blob: 8663c5c63da95db2d8ab9a8cd40bcb68a51f910d [file] [log] [blame]
Ben Chengba4fc8b2009-06-01 13:00:29 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "Dalvik.h"
Dan Bornsteindf4daaf2010-12-01 14:23:44 -080018#include "libdex/DexOpcodes.h"
Ben Cheng00603072010-10-28 11:13:58 -070019#include "libdex/DexCatch.h"
Ben Chengba4fc8b2009-06-01 13:00:29 -070020#include "interp/Jit.h"
21#include "CompilerInternals.h"
Ben Cheng7a2697d2010-06-07 13:44:23 -070022#include "Dataflow.h"
Ben Chengba4fc8b2009-06-01 13:00:29 -070023
Ben Cheng00603072010-10-28 11:13:58 -070024static inline bool contentIsInsn(const u2 *codePtr) {
25 u2 instr = *codePtr;
26 Opcode opcode = instr & 0xff;
27
28 /*
29 * Since the low 8-bit in metadata may look like OP_NOP, we need to check
30 * both the low and whole sub-word to determine whether it is code or data.
31 */
32 return (opcode != OP_NOP || instr == 0);
33}
34
Ben Chengba4fc8b2009-06-01 13:00:29 -070035/*
36 * Parse an instruction, return the length of the instruction
37 */
38static inline int parseInsn(const u2 *codePtr, DecodedInstruction *decInsn,
39 bool printMe)
40{
Ben Cheng00603072010-10-28 11:13:58 -070041 // Don't parse instruction data
42 if (!contentIsInsn(codePtr)) {
43 return 0;
44 }
45
Ben Chengba4fc8b2009-06-01 13:00:29 -070046 u2 instr = *codePtr;
Dan Bornstein9a1f8162010-12-01 17:02:26 -080047 Opcode opcode = dexOpcodeFromCodeUnit(instr);
Ben Chengba4fc8b2009-06-01 13:00:29 -070048
Dan Bornstein54322392010-11-17 14:16:56 -080049 dexDecodeInstruction(codePtr, decInsn);
Ben Chengba4fc8b2009-06-01 13:00:29 -070050 if (printMe) {
Ben Cheng7a2697d2010-06-07 13:44:23 -070051 char *decodedString = dvmCompilerGetDalvikDisassembly(decInsn, NULL);
Ben Chengccd6c012009-10-15 14:52:45 -070052 LOGD("%p: %#06x %s\n", codePtr, opcode, decodedString);
Ben Chengba4fc8b2009-06-01 13:00:29 -070053 }
Ben Cheng00603072010-10-28 11:13:58 -070054 return dexGetWidthFromOpcode(opcode);
Ben Chengba4fc8b2009-06-01 13:00:29 -070055}
56
Ben Cheng9c147b82009-10-07 16:41:46 -070057#define UNKNOWN_TARGET 0xffffffff
58
Ben Chengba4fc8b2009-06-01 13:00:29 -070059/*
60 * Identify block-ending instructions and collect supplemental information
61 * regarding the following instructions.
62 */
63static inline bool findBlockBoundary(const Method *caller, MIR *insn,
64 unsigned int curOffset,
65 unsigned int *target, bool *isInvoke,
66 const Method **callee)
67{
Dan Bornstein9a1f8162010-12-01 17:02:26 -080068 switch (insn->dalvikInsn.opcode) {
Ben Chengba4fc8b2009-06-01 13:00:29 -070069 /* Target is not compile-time constant */
70 case OP_RETURN_VOID:
71 case OP_RETURN:
72 case OP_RETURN_WIDE:
73 case OP_RETURN_OBJECT:
74 case OP_THROW:
Ben Cheng9c147b82009-10-07 16:41:46 -070075 *target = UNKNOWN_TARGET;
76 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -070077 case OP_INVOKE_VIRTUAL:
78 case OP_INVOKE_VIRTUAL_RANGE:
jeffhao71eee1f2011-01-04 14:18:54 -080079 case OP_INVOKE_VIRTUAL_JUMBO:
Ben Chengba4fc8b2009-06-01 13:00:29 -070080 case OP_INVOKE_INTERFACE:
81 case OP_INVOKE_INTERFACE_RANGE:
jeffhao71eee1f2011-01-04 14:18:54 -080082 case OP_INVOKE_INTERFACE_JUMBO:
Ben Chengba4fc8b2009-06-01 13:00:29 -070083 case OP_INVOKE_VIRTUAL_QUICK:
84 case OP_INVOKE_VIRTUAL_QUICK_RANGE:
85 *isInvoke = true;
86 break;
87 case OP_INVOKE_SUPER:
jeffhao71eee1f2011-01-04 14:18:54 -080088 case OP_INVOKE_SUPER_RANGE:
89 case OP_INVOKE_SUPER_JUMBO: {
Ben Chengba4fc8b2009-06-01 13:00:29 -070090 int mIndex = caller->clazz->pDvmDex->
91 pResMethods[insn->dalvikInsn.vB]->methodIndex;
92 const Method *calleeMethod =
93 caller->clazz->super->vtable[mIndex];
94
Ben Cheng8b258bf2009-06-24 17:27:07 -070095 if (calleeMethod && !dvmIsNativeMethod(calleeMethod)) {
Ben Chengba4fc8b2009-06-01 13:00:29 -070096 *target = (unsigned int) calleeMethod->insns;
97 }
98 *isInvoke = true;
99 *callee = calleeMethod;
100 break;
101 }
102 case OP_INVOKE_STATIC:
jeffhao71eee1f2011-01-04 14:18:54 -0800103 case OP_INVOKE_STATIC_RANGE:
104 case OP_INVOKE_STATIC_JUMBO: {
Ben Chengba4fc8b2009-06-01 13:00:29 -0700105 const Method *calleeMethod =
106 caller->clazz->pDvmDex->pResMethods[insn->dalvikInsn.vB];
107
Ben Cheng8b258bf2009-06-24 17:27:07 -0700108 if (calleeMethod && !dvmIsNativeMethod(calleeMethod)) {
Ben Chengba4fc8b2009-06-01 13:00:29 -0700109 *target = (unsigned int) calleeMethod->insns;
110 }
111 *isInvoke = true;
112 *callee = calleeMethod;
113 break;
114 }
115 case OP_INVOKE_SUPER_QUICK:
116 case OP_INVOKE_SUPER_QUICK_RANGE: {
117 const Method *calleeMethod =
118 caller->clazz->super->vtable[insn->dalvikInsn.vB];
119
Ben Cheng8b258bf2009-06-24 17:27:07 -0700120 if (calleeMethod && !dvmIsNativeMethod(calleeMethod)) {
Ben Chengba4fc8b2009-06-01 13:00:29 -0700121 *target = (unsigned int) calleeMethod->insns;
122 }
123 *isInvoke = true;
124 *callee = calleeMethod;
125 break;
126 }
127 case OP_INVOKE_DIRECT:
jeffhao71eee1f2011-01-04 14:18:54 -0800128 case OP_INVOKE_DIRECT_RANGE:
129 case OP_INVOKE_DIRECT_JUMBO: {
Ben Chengba4fc8b2009-06-01 13:00:29 -0700130 const Method *calleeMethod =
131 caller->clazz->pDvmDex->pResMethods[insn->dalvikInsn.vB];
Ben Cheng8b258bf2009-06-24 17:27:07 -0700132 if (calleeMethod && !dvmIsNativeMethod(calleeMethod)) {
Ben Chengba4fc8b2009-06-01 13:00:29 -0700133 *target = (unsigned int) calleeMethod->insns;
134 }
135 *isInvoke = true;
136 *callee = calleeMethod;
137 break;
138 }
139 case OP_GOTO:
140 case OP_GOTO_16:
141 case OP_GOTO_32:
142 *target = curOffset + (int) insn->dalvikInsn.vA;
143 break;
144
145 case OP_IF_EQ:
146 case OP_IF_NE:
147 case OP_IF_LT:
148 case OP_IF_GE:
149 case OP_IF_GT:
150 case OP_IF_LE:
151 *target = curOffset + (int) insn->dalvikInsn.vC;
152 break;
153
154 case OP_IF_EQZ:
155 case OP_IF_NEZ:
156 case OP_IF_LTZ:
157 case OP_IF_GEZ:
158 case OP_IF_GTZ:
159 case OP_IF_LEZ:
160 *target = curOffset + (int) insn->dalvikInsn.vB;
161 break;
162
163 default:
164 return false;
Ben Cheng9c147b82009-10-07 16:41:46 -0700165 }
166 return true;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700167}
168
Bill Buzbee324b3ac2009-12-04 13:17:36 -0800169static inline bool isGoto(MIR *insn)
170{
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800171 switch (insn->dalvikInsn.opcode) {
Bill Buzbee324b3ac2009-12-04 13:17:36 -0800172 case OP_GOTO:
173 case OP_GOTO_16:
174 case OP_GOTO_32:
175 return true;
176 default:
177 return false;
178 }
179}
180
Ben Chengba4fc8b2009-06-01 13:00:29 -0700181/*
Bill Buzbee324b3ac2009-12-04 13:17:36 -0800182 * Identify unconditional branch instructions
Ben Chengba4fc8b2009-06-01 13:00:29 -0700183 */
184static inline bool isUnconditionalBranch(MIR *insn)
185{
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800186 switch (insn->dalvikInsn.opcode) {
Ben Chengba4fc8b2009-06-01 13:00:29 -0700187 case OP_RETURN_VOID:
188 case OP_RETURN:
189 case OP_RETURN_WIDE:
190 case OP_RETURN_OBJECT:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700191 return true;
192 default:
Bill Buzbee324b3ac2009-12-04 13:17:36 -0800193 return isGoto(insn);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700194 }
195}
196
197/*
Ben Cheng8b258bf2009-06-24 17:27:07 -0700198 * dvmHashTableLookup() callback
199 */
200static int compareMethod(const CompilerMethodStats *m1,
201 const CompilerMethodStats *m2)
202{
203 return (int) m1->method - (int) m2->method;
204}
205
206/*
Ben Cheng7a2697d2010-06-07 13:44:23 -0700207 * Analyze the body of the method to collect high-level information regarding
208 * inlining:
209 * - is empty method?
210 * - is getter/setter?
211 * - can throw exception?
212 *
213 * Currently the inliner only handles getters and setters. When its capability
214 * becomes more sophisticated more information will be retrieved here.
215 */
216static int analyzeInlineTarget(DecodedInstruction *dalvikInsn, int attributes,
217 int offset)
218{
Dan Bornsteine4852762010-12-02 12:45:00 -0800219 int flags = dexGetFlagsFromOpcode(dalvikInsn->opcode);
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800220 int dalvikOpcode = dalvikInsn->opcode;
Ben Cheng7a2697d2010-06-07 13:44:23 -0700221
Dan Bornstein0759f522010-11-30 14:58:53 -0800222 if (flags & kInstrInvoke) {
Ben Cheng7a2697d2010-06-07 13:44:23 -0700223 attributes &= ~METHOD_IS_LEAF;
224 }
225
226 if (!(flags & kInstrCanReturn)) {
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800227 if (!(dvmCompilerDataFlowAttributes[dalvikOpcode] &
Ben Cheng7a2697d2010-06-07 13:44:23 -0700228 DF_IS_GETTER)) {
229 attributes &= ~METHOD_IS_GETTER;
230 }
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800231 if (!(dvmCompilerDataFlowAttributes[dalvikOpcode] &
Ben Cheng7a2697d2010-06-07 13:44:23 -0700232 DF_IS_SETTER)) {
233 attributes &= ~METHOD_IS_SETTER;
234 }
235 }
236
237 /*
238 * The expected instruction sequence is setter will never return value and
239 * getter will also do. Clear the bits if the behavior is discovered
240 * otherwise.
241 */
242 if (flags & kInstrCanReturn) {
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800243 if (dalvikOpcode == OP_RETURN_VOID) {
Ben Cheng7a2697d2010-06-07 13:44:23 -0700244 attributes &= ~METHOD_IS_GETTER;
245 }
246 else {
247 attributes &= ~METHOD_IS_SETTER;
248 }
249 }
250
251 if (flags & kInstrCanThrow) {
252 attributes &= ~METHOD_IS_THROW_FREE;
253 }
254
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800255 if (offset == 0 && dalvikOpcode == OP_RETURN_VOID) {
Ben Cheng7a2697d2010-06-07 13:44:23 -0700256 attributes |= METHOD_IS_EMPTY;
257 }
258
Ben Cheng34dc7962010-08-26 14:56:31 -0700259 /*
260 * Check if this opcode is selected for single stepping.
261 * If so, don't inline the callee as there is no stack frame for the
262 * interpreter to single-step through the instruction.
263 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800264 if (SINGLE_STEP_OP(dalvikOpcode)) {
Ben Cheng34dc7962010-08-26 14:56:31 -0700265 attributes &= ~(METHOD_IS_GETTER | METHOD_IS_SETTER);
266 }
267
Ben Cheng7a2697d2010-06-07 13:44:23 -0700268 return attributes;
269}
270
271/*
Ben Cheng8b258bf2009-06-24 17:27:07 -0700272 * Analyze each method whose traces are ever compiled. Collect a variety of
273 * statistics like the ratio of exercised vs overall code and code bloat
Ben Cheng7a2697d2010-06-07 13:44:23 -0700274 * ratios. If isCallee is true, also analyze each instruction in more details
275 * to see if it is suitable for inlining.
Ben Cheng8b258bf2009-06-24 17:27:07 -0700276 */
Ben Cheng7a2697d2010-06-07 13:44:23 -0700277CompilerMethodStats *dvmCompilerAnalyzeMethodBody(const Method *method,
278 bool isCallee)
Ben Cheng8b258bf2009-06-24 17:27:07 -0700279{
280 const DexCode *dexCode = dvmGetMethodCode(method);
281 const u2 *codePtr = dexCode->insns;
282 const u2 *codeEnd = dexCode->insns + dexCode->insnsSize;
283 int insnSize = 0;
284 int hashValue = dvmComputeUtf8Hash(method->name);
285
286 CompilerMethodStats dummyMethodEntry; // For hash table lookup
287 CompilerMethodStats *realMethodEntry; // For hash table storage
288
289 /* For lookup only */
290 dummyMethodEntry.method = method;
Ben Chengcfdeca32011-01-14 11:36:46 -0800291 realMethodEntry = (CompilerMethodStats *)
292 dvmHashTableLookup(gDvmJit.methodStatsTable,
293 hashValue,
294 &dummyMethodEntry,
295 (HashCompareFunc) compareMethod,
296 false);
Ben Cheng8b258bf2009-06-24 17:27:07 -0700297
Ben Cheng7a2697d2010-06-07 13:44:23 -0700298 /* This method has never been analyzed before - create an entry */
299 if (realMethodEntry == NULL) {
300 realMethodEntry =
301 (CompilerMethodStats *) calloc(1, sizeof(CompilerMethodStats));
302 realMethodEntry->method = method;
303
304 dvmHashTableLookup(gDvmJit.methodStatsTable, hashValue,
305 realMethodEntry,
306 (HashCompareFunc) compareMethod,
307 true);
Ben Cheng8b258bf2009-06-24 17:27:07 -0700308 }
309
Ben Cheng7a2697d2010-06-07 13:44:23 -0700310 /* This method is invoked as a callee and has been analyzed - just return */
311 if ((isCallee == true) && (realMethodEntry->attributes & METHOD_IS_CALLEE))
312 return realMethodEntry;
Ben Cheng8b258bf2009-06-24 17:27:07 -0700313
Ben Cheng7a2697d2010-06-07 13:44:23 -0700314 /*
315 * Similarly, return if this method has been compiled before as a hot
316 * method already.
317 */
318 if ((isCallee == false) &&
319 (realMethodEntry->attributes & METHOD_IS_HOT))
320 return realMethodEntry;
321
322 int attributes;
323
324 /* Method hasn't been analyzed for the desired purpose yet */
325 if (isCallee) {
326 /* Aggressively set the attributes until proven otherwise */
327 attributes = METHOD_IS_LEAF | METHOD_IS_THROW_FREE | METHOD_IS_CALLEE |
328 METHOD_IS_GETTER | METHOD_IS_SETTER;
329 } else {
330 attributes = METHOD_IS_HOT;
331 }
Ben Cheng8b258bf2009-06-24 17:27:07 -0700332
333 /* Count the number of instructions */
334 while (codePtr < codeEnd) {
335 DecodedInstruction dalvikInsn;
336 int width = parseInsn(codePtr, &dalvikInsn, false);
337
338 /* Terminate when the data section is seen */
339 if (width == 0)
340 break;
341
Ben Cheng7a2697d2010-06-07 13:44:23 -0700342 if (isCallee) {
343 attributes = analyzeInlineTarget(&dalvikInsn, attributes, insnSize);
344 }
345
Ben Cheng8b258bf2009-06-24 17:27:07 -0700346 insnSize += width;
347 codePtr += width;
348 }
349
Ben Cheng7a2697d2010-06-07 13:44:23 -0700350 /*
351 * Only handle simple getters/setters with one instruction followed by
352 * return
353 */
354 if ((attributes & (METHOD_IS_GETTER | METHOD_IS_SETTER)) &&
355 (insnSize != 3)) {
356 attributes &= ~(METHOD_IS_GETTER | METHOD_IS_SETTER);
357 }
358
Ben Cheng8b258bf2009-06-24 17:27:07 -0700359 realMethodEntry->dalvikSize = insnSize * 2;
Ben Cheng7a2697d2010-06-07 13:44:23 -0700360 realMethodEntry->attributes |= attributes;
361
362#if 0
363 /* Uncomment the following to explore various callee patterns */
364 if (attributes & METHOD_IS_THROW_FREE) {
365 LOGE("%s%s is inlinable%s", method->clazz->descriptor, method->name,
366 (attributes & METHOD_IS_EMPTY) ? " empty" : "");
367 }
368
369 if (attributes & METHOD_IS_LEAF) {
370 LOGE("%s%s is leaf %d%s", method->clazz->descriptor, method->name,
371 insnSize, insnSize < 5 ? " (small)" : "");
372 }
373
374 if (attributes & (METHOD_IS_GETTER | METHOD_IS_SETTER)) {
375 LOGE("%s%s is %s", method->clazz->descriptor, method->name,
376 attributes & METHOD_IS_GETTER ? "getter": "setter");
377 }
378 if (attributes ==
379 (METHOD_IS_LEAF | METHOD_IS_THROW_FREE | METHOD_IS_CALLEE)) {
380 LOGE("%s%s is inlinable non setter/getter", method->clazz->descriptor,
381 method->name);
382 }
383#endif
384
Ben Cheng8b258bf2009-06-24 17:27:07 -0700385 return realMethodEntry;
386}
387
388/*
Ben Cheng33672452010-01-12 14:59:30 -0800389 * Crawl the stack of the thread that requesed compilation to see if any of the
390 * ancestors are on the blacklist.
391 */
Andy McFadden953a0ed2010-09-17 15:48:38 -0700392static bool filterMethodByCallGraph(Thread *thread, const char *curMethodName)
Ben Cheng33672452010-01-12 14:59:30 -0800393{
394 /* Crawl the Dalvik stack frames and compare the method name*/
395 StackSaveArea *ssaPtr = ((StackSaveArea *) thread->curFrame) - 1;
396 while (ssaPtr != ((StackSaveArea *) NULL) - 1) {
397 const Method *method = ssaPtr->method;
398 if (method) {
399 int hashValue = dvmComputeUtf8Hash(method->name);
400 bool found =
401 dvmHashTableLookup(gDvmJit.methodTable, hashValue,
402 (char *) method->name,
403 (HashCompareFunc) strcmp, false) !=
404 NULL;
405 if (found) {
406 LOGD("Method %s (--> %s) found on the JIT %s list",
407 method->name, curMethodName,
408 gDvmJit.includeSelectedMethod ? "white" : "black");
409 return true;
410 }
411
412 }
413 ssaPtr = ((StackSaveArea *) ssaPtr->prevFrame) - 1;
414 };
415 return false;
416}
417
418/*
Ben Chengba4fc8b2009-06-01 13:00:29 -0700419 * Main entry point to start trace compilation. Basic blocks are constructed
420 * first and they will be passed to the codegen routines to convert Dalvik
421 * bytecode into machine code.
422 */
Bill Buzbee716f1202009-07-23 13:22:09 -0700423bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
Ben Cheng4a419582010-08-04 13:23:09 -0700424 JitTranslationInfo *info, jmp_buf *bailPtr,
425 int optHints)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700426{
427 const DexCode *dexCode = dvmGetMethodCode(desc->method);
428 const JitTraceRun* currRun = &desc->trace[0];
Ben Cheng385828e2011-03-04 16:48:33 -0800429 unsigned int curOffset = currRun->info.frag.startOffset;
430 unsigned int numInsts = currRun->info.frag.numInsts;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700431 const u2 *codePtr = dexCode->insns + curOffset;
Ben Cheng8b258bf2009-06-24 17:27:07 -0700432 int traceSize = 0; // # of half-words
Ben Chengba4fc8b2009-06-01 13:00:29 -0700433 const u2 *startCodePtr = codePtr;
Ben Cheng00603072010-10-28 11:13:58 -0700434 BasicBlock *curBB, *entryCodeBB;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700435 int numBlocks = 0;
436 static int compilationId;
437 CompilationUnit cUnit;
Ben Cheng00603072010-10-28 11:13:58 -0700438 GrowableList *blockList;
Ben Cheng1357e942010-02-10 17:21:39 -0800439#if defined(WITH_JIT_TUNING)
Ben Cheng8b258bf2009-06-24 17:27:07 -0700440 CompilerMethodStats *methodStats;
Ben Cheng1357e942010-02-10 17:21:39 -0800441#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -0700442
Bill Buzbee964a7b02010-01-28 12:54:19 -0800443 /* If we've already compiled this trace, just return success */
Ben Chengcfdeca32011-01-14 11:36:46 -0800444 if (dvmJitGetTraceAddr(startCodePtr) && !info->discardResult) {
Ben Cheng7a2697d2010-06-07 13:44:23 -0700445 /*
446 * Make sure the codeAddress is NULL so that it won't clobber the
447 * existing entry.
448 */
449 info->codeAddress = NULL;
Bill Buzbee964a7b02010-01-28 12:54:19 -0800450 return true;
451 }
452
buzbee18fba342011-01-19 15:31:15 -0800453 /* If the work order is stale, discard it */
454 if (info->cacheVersion != gDvmJit.cacheVersion) {
455 return false;
456 }
457
Ben Chenge9695e52009-06-16 16:11:47 -0700458 compilationId++;
Ben Cheng8b258bf2009-06-24 17:27:07 -0700459 memset(&cUnit, 0, sizeof(CompilationUnit));
460
Ben Cheng1357e942010-02-10 17:21:39 -0800461#if defined(WITH_JIT_TUNING)
Ben Cheng8b258bf2009-06-24 17:27:07 -0700462 /* Locate the entry to store compilation statistics for this method */
Ben Cheng7a2697d2010-06-07 13:44:23 -0700463 methodStats = dvmCompilerAnalyzeMethodBody(desc->method, false);
Ben Cheng1357e942010-02-10 17:21:39 -0800464#endif
Ben Chenge9695e52009-06-16 16:11:47 -0700465
Bill Buzbeefc519dc2010-03-06 23:30:57 -0800466 /* Set the recover buffer pointer */
467 cUnit.bailPtr = bailPtr;
468
Ben Chengba4fc8b2009-06-01 13:00:29 -0700469 /* Initialize the printMe flag */
470 cUnit.printMe = gDvmJit.printMe;
471
Ben Cheng7a2697d2010-06-07 13:44:23 -0700472 /* Setup the method */
473 cUnit.method = desc->method;
474
475 /* Initialize the PC reconstruction list */
476 dvmInitGrowableList(&cUnit.pcReconstructionList, 8);
477
Ben Cheng00603072010-10-28 11:13:58 -0700478 /* Initialize the basic block list */
479 blockList = &cUnit.blockList;
480 dvmInitGrowableList(blockList, 8);
481
Ben Chengba4fc8b2009-06-01 13:00:29 -0700482 /* Identify traces that we don't want to compile */
483 if (gDvmJit.methodTable) {
484 int len = strlen(desc->method->clazz->descriptor) +
485 strlen(desc->method->name) + 1;
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800486 char *fullSignature = (char *)dvmCompilerNew(len, true);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700487 strcpy(fullSignature, desc->method->clazz->descriptor);
488 strcat(fullSignature, desc->method->name);
489
490 int hashValue = dvmComputeUtf8Hash(fullSignature);
491
492 /*
493 * Doing three levels of screening to see whether we want to skip
494 * compiling this method
495 */
496
497 /* First, check the full "class;method" signature */
498 bool methodFound =
499 dvmHashTableLookup(gDvmJit.methodTable, hashValue,
500 fullSignature, (HashCompareFunc) strcmp,
501 false) !=
502 NULL;
503
504 /* Full signature not found - check the enclosing class */
505 if (methodFound == false) {
506 int hashValue = dvmComputeUtf8Hash(desc->method->clazz->descriptor);
507 methodFound =
508 dvmHashTableLookup(gDvmJit.methodTable, hashValue,
509 (char *) desc->method->clazz->descriptor,
510 (HashCompareFunc) strcmp, false) !=
511 NULL;
512 /* Enclosing class not found - check the method name */
513 if (methodFound == false) {
514 int hashValue = dvmComputeUtf8Hash(desc->method->name);
515 methodFound =
516 dvmHashTableLookup(gDvmJit.methodTable, hashValue,
517 (char *) desc->method->name,
518 (HashCompareFunc) strcmp, false) !=
519 NULL;
Ben Cheng33672452010-01-12 14:59:30 -0800520
521 /*
522 * Debug by call-graph is enabled. Check if the debug list
523 * covers any methods on the VM stack.
524 */
525 if (methodFound == false && gDvmJit.checkCallGraph == true) {
526 methodFound =
527 filterMethodByCallGraph(info->requestingThread,
528 desc->method->name);
529 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700530 }
531 }
532
533 /*
534 * Under the following conditions, the trace will be *conservatively*
535 * compiled by only containing single-step instructions to and from the
536 * interpreter.
537 * 1) If includeSelectedMethod == false, the method matches the full or
538 * partial signature stored in the hash table.
539 *
540 * 2) If includeSelectedMethod == true, the method does not match the
541 * full and partial signature stored in the hash table.
542 */
543 if (gDvmJit.includeSelectedMethod != methodFound) {
544 cUnit.allSingleStep = true;
545 } else {
546 /* Compile the trace as normal */
547
548 /* Print the method we cherry picked */
549 if (gDvmJit.includeSelectedMethod == true) {
550 cUnit.printMe = true;
551 }
552 }
553 }
554
Ben Cheng4238ec22009-08-24 16:32:22 -0700555 /* Allocate the entry block */
Ben Cheng00603072010-10-28 11:13:58 -0700556 curBB = dvmCompilerNewBB(kTraceEntryBlock, numBlocks++);
557 dvmInsertGrowableList(blockList, (intptr_t) curBB);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700558 curBB->startOffset = curOffset;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700559
Ben Cheng00603072010-10-28 11:13:58 -0700560 entryCodeBB = dvmCompilerNewBB(kDalvikByteCode, numBlocks++);
561 dvmInsertGrowableList(blockList, (intptr_t) entryCodeBB);
562 entryCodeBB->startOffset = curOffset;
563 curBB->fallThrough = entryCodeBB;
564 curBB = entryCodeBB;
Ben Cheng4238ec22009-08-24 16:32:22 -0700565
Ben Chengba4fc8b2009-06-01 13:00:29 -0700566 if (cUnit.printMe) {
567 LOGD("--------\nCompiler: Building trace for %s, offset 0x%x\n",
568 desc->method->name, curOffset);
569 }
570
Ben Cheng1efc9c52009-06-08 18:25:27 -0700571 /*
572 * Analyze the trace descriptor and include up to the maximal number
573 * of Dalvik instructions into the IR.
574 */
575 while (1) {
Ben Chengba4fc8b2009-06-01 13:00:29 -0700576 MIR *insn;
577 int width;
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800578 insn = (MIR *)dvmCompilerNew(sizeof(MIR), true);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700579 insn->offset = curOffset;
580 width = parseInsn(codePtr, &insn->dalvikInsn, cUnit.printMe);
Ben Cheng8b258bf2009-06-24 17:27:07 -0700581
582 /* The trace should never incude instruction data */
583 assert(width);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700584 insn->width = width;
585 traceSize += width;
586 dvmCompilerAppendMIR(curBB, insn);
Ben Cheng1efc9c52009-06-08 18:25:27 -0700587 cUnit.numInsts++;
Ben Cheng7a2697d2010-06-07 13:44:23 -0700588
Dan Bornsteine4852762010-12-02 12:45:00 -0800589 int flags = dexGetFlagsFromOpcode(insn->dalvikInsn.opcode);
Ben Cheng7a2697d2010-06-07 13:44:23 -0700590
Dan Bornstein0759f522010-11-30 14:58:53 -0800591 if (flags & kInstrInvoke) {
Ben Cheng385828e2011-03-04 16:48:33 -0800592 const Method *calleeMethod = (const Method *)
593 currRun[JIT_TRACE_CUR_METHOD].info.meta;
Ben Cheng7a2697d2010-06-07 13:44:23 -0700594 assert(numInsts == 1);
595 CallsiteInfo *callsiteInfo =
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800596 (CallsiteInfo *)dvmCompilerNew(sizeof(CallsiteInfo), true);
Ben Cheng385828e2011-03-04 16:48:33 -0800597 callsiteInfo->classDescriptor = (const char *)
598 currRun[JIT_TRACE_CLASS_DESC].info.meta;
599 callsiteInfo->classLoader = (Object *)
600 currRun[JIT_TRACE_CLASS_LOADER].info.meta;
Ben Chengcfdeca32011-01-14 11:36:46 -0800601 callsiteInfo->method = calleeMethod;
Ben Cheng7a2697d2010-06-07 13:44:23 -0700602 insn->meta.callsiteInfo = callsiteInfo;
603 }
604
Ben Cheng1efc9c52009-06-08 18:25:27 -0700605 /* Instruction limit reached - terminate the trace here */
606 if (cUnit.numInsts >= numMaxInsts) {
607 break;
608 }
609 if (--numInsts == 0) {
Ben Cheng385828e2011-03-04 16:48:33 -0800610 if (currRun->info.frag.runEnd) {
Ben Cheng1efc9c52009-06-08 18:25:27 -0700611 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700612 } else {
Ben Cheng7a2697d2010-06-07 13:44:23 -0700613 /* Advance to the next trace description (ie non-meta info) */
614 do {
615 currRun++;
Ben Cheng385828e2011-03-04 16:48:33 -0800616 } while (!currRun->isCode);
Ben Cheng7a2697d2010-06-07 13:44:23 -0700617
618 /* Dummy end-of-run marker seen */
Ben Cheng385828e2011-03-04 16:48:33 -0800619 if (currRun->info.frag.numInsts == 0) {
Ben Cheng7a2697d2010-06-07 13:44:23 -0700620 break;
621 }
622
Ben Cheng00603072010-10-28 11:13:58 -0700623 curBB = dvmCompilerNewBB(kDalvikByteCode, numBlocks++);
624 dvmInsertGrowableList(blockList, (intptr_t) curBB);
Ben Cheng385828e2011-03-04 16:48:33 -0800625 curOffset = currRun->info.frag.startOffset;
626 numInsts = currRun->info.frag.numInsts;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700627 curBB->startOffset = curOffset;
628 codePtr = dexCode->insns + curOffset;
629 }
630 } else {
631 curOffset += width;
632 codePtr += width;
633 }
634 }
635
Ben Cheng1357e942010-02-10 17:21:39 -0800636#if defined(WITH_JIT_TUNING)
Ben Cheng8b258bf2009-06-24 17:27:07 -0700637 /* Convert # of half-word to bytes */
638 methodStats->compiledDalvikSize += traceSize * 2;
Ben Cheng1357e942010-02-10 17:21:39 -0800639#endif
Ben Cheng8b258bf2009-06-24 17:27:07 -0700640
Ben Chengba4fc8b2009-06-01 13:00:29 -0700641 /*
642 * Now scan basic blocks containing real code to connect the
643 * taken/fallthrough links. Also create chaining cells for code not included
644 * in the trace.
645 */
Ben Cheng00603072010-10-28 11:13:58 -0700646 size_t blockId;
647 for (blockId = 0; blockId < blockList->numUsed; blockId++) {
648 curBB = (BasicBlock *) dvmGrowableListGetElement(blockList, blockId);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700649 MIR *lastInsn = curBB->lastMIRInsn;
buzbee2e152ba2010-12-15 16:32:35 -0800650 BasicBlock *backwardCell;
Ben Cheng4238ec22009-08-24 16:32:22 -0700651 /* Skip empty blocks */
Ben Chengba4fc8b2009-06-01 13:00:29 -0700652 if (lastInsn == NULL) {
Ben Cheng4238ec22009-08-24 16:32:22 -0700653 continue;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700654 }
655 curOffset = lastInsn->offset;
656 unsigned int targetOffset = curOffset;
657 unsigned int fallThroughOffset = curOffset + lastInsn->width;
658 bool isInvoke = false;
659 const Method *callee = NULL;
660
661 findBlockBoundary(desc->method, curBB->lastMIRInsn, curOffset,
662 &targetOffset, &isInvoke, &callee);
663
664 /* Link the taken and fallthrough blocks */
665 BasicBlock *searchBB;
666
Dan Bornsteine4852762010-12-02 12:45:00 -0800667 int flags = dexGetFlagsFromOpcode(lastInsn->dalvikInsn.opcode);
Ben Cheng7a2697d2010-06-07 13:44:23 -0700668
669 if (flags & kInstrInvoke) {
670 cUnit.hasInvoke = true;
671 }
672
Ben Chengba4fc8b2009-06-01 13:00:29 -0700673 /* No backward branch in the trace - start searching the next BB */
Ben Cheng00603072010-10-28 11:13:58 -0700674 size_t searchBlockId;
675 for (searchBlockId = blockId+1; searchBlockId < blockList->numUsed;
676 searchBlockId++) {
677 searchBB = (BasicBlock *) dvmGrowableListGetElement(blockList,
678 searchBlockId);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700679 if (targetOffset == searchBB->startOffset) {
680 curBB->taken = searchBB;
Ben Cheng7ab74e12011-02-03 14:02:06 -0800681 dvmCompilerSetBit(searchBB->predecessors, curBB->id);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700682 }
683 if (fallThroughOffset == searchBB->startOffset) {
684 curBB->fallThrough = searchBB;
Ben Cheng7ab74e12011-02-03 14:02:06 -0800685 dvmCompilerSetBit(searchBB->predecessors, curBB->id);
Ben Cheng7a2697d2010-06-07 13:44:23 -0700686
687 /*
688 * Fallthrough block of an invoke instruction needs to be
689 * aligned to 4-byte boundary (alignment instruction to be
690 * inserted later.
691 */
692 if (flags & kInstrInvoke) {
693 searchBB->isFallThroughFromInvoke = true;
694 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700695 }
696 }
697
Ben Cheng1efc9c52009-06-08 18:25:27 -0700698 /*
699 * Some blocks are ended by non-control-flow-change instructions,
700 * currently only due to trace length constraint. In this case we need
701 * to generate an explicit branch at the end of the block to jump to
702 * the chaining cell.
703 */
704 curBB->needFallThroughBranch =
Ben Cheng17f15ce2009-07-27 16:21:52 -0700705 ((flags & (kInstrCanBranch | kInstrCanSwitch | kInstrCanReturn |
Dan Bornstein0759f522010-11-30 14:58:53 -0800706 kInstrInvoke)) == 0);
Ben Cheng17f15ce2009-07-27 16:21:52 -0700707
Ben Cheng4a419582010-08-04 13:23:09 -0700708 /* Only form a loop if JIT_OPT_NO_LOOP is not set */
Ben Cheng4238ec22009-08-24 16:32:22 -0700709 if (curBB->taken == NULL &&
710 curBB->fallThrough == NULL &&
711 flags == (kInstrCanBranch | kInstrCanContinue) &&
Ben Cheng00603072010-10-28 11:13:58 -0700712 fallThroughOffset == entryCodeBB->startOffset &&
Ben Cheng4a419582010-08-04 13:23:09 -0700713 JIT_OPT_NO_LOOP != (optHints & JIT_OPT_NO_LOOP)) {
Ben Cheng0fd31e42009-09-03 14:40:16 -0700714 BasicBlock *loopBranch = curBB;
715 BasicBlock *exitBB;
716 BasicBlock *exitChainingCell;
Ben Cheng4238ec22009-08-24 16:32:22 -0700717
718 if (cUnit.printMe) {
719 LOGD("Natural loop detected!");
720 }
Ben Cheng00603072010-10-28 11:13:58 -0700721 exitBB = dvmCompilerNewBB(kTraceExitBlock, numBlocks++);
722 dvmInsertGrowableList(blockList, (intptr_t) exitBB);
Ben Cheng0fd31e42009-09-03 14:40:16 -0700723 exitBB->startOffset = targetOffset;
Ben Cheng0fd31e42009-09-03 14:40:16 -0700724 exitBB->needFallThroughBranch = true;
Ben Cheng4238ec22009-08-24 16:32:22 -0700725
Ben Cheng0fd31e42009-09-03 14:40:16 -0700726 loopBranch->taken = exitBB;
Ben Cheng7ab74e12011-02-03 14:02:06 -0800727 dvmCompilerSetBit(exitBB->predecessors, loopBranch->id);
buzbee2e152ba2010-12-15 16:32:35 -0800728 backwardCell =
Ben Cheng00603072010-10-28 11:13:58 -0700729 dvmCompilerNewBB(kChainingCellBackwardBranch, numBlocks++);
730 dvmInsertGrowableList(blockList, (intptr_t) backwardCell);
731 backwardCell->startOffset = entryCodeBB->startOffset;
Ben Cheng0fd31e42009-09-03 14:40:16 -0700732 loopBranch->fallThrough = backwardCell;
Ben Cheng7ab74e12011-02-03 14:02:06 -0800733 dvmCompilerSetBit(backwardCell->predecessors, loopBranch->id);
Ben Cheng0fd31e42009-09-03 14:40:16 -0700734
735 /* Create the chaining cell as the fallthrough of the exit block */
Ben Cheng00603072010-10-28 11:13:58 -0700736 exitChainingCell = dvmCompilerNewBB(kChainingCellNormal,
737 numBlocks++);
738 dvmInsertGrowableList(blockList, (intptr_t) exitChainingCell);
Ben Cheng0fd31e42009-09-03 14:40:16 -0700739 exitChainingCell->startOffset = targetOffset;
Ben Cheng0fd31e42009-09-03 14:40:16 -0700740
741 exitBB->fallThrough = exitChainingCell;
Ben Cheng7ab74e12011-02-03 14:02:06 -0800742 dvmCompilerSetBit(exitChainingCell->predecessors, exitBB->id);
Ben Cheng0fd31e42009-09-03 14:40:16 -0700743
Ben Cheng4238ec22009-08-24 16:32:22 -0700744 cUnit.hasLoop = true;
745 }
746
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800747 if (lastInsn->dalvikInsn.opcode == OP_PACKED_SWITCH ||
748 lastInsn->dalvikInsn.opcode == OP_SPARSE_SWITCH) {
Ben Cheng6c10a972009-10-29 14:39:18 -0700749 int i;
750 const u2 *switchData = desc->method->insns + lastInsn->offset +
751 lastInsn->dalvikInsn.vB;
752 int size = switchData[1];
753 int maxChains = MIN(size, MAX_CHAINED_SWITCH_CASES);
754
755 /*
756 * Generate the landing pad for cases whose ranks are higher than
757 * MAX_CHAINED_SWITCH_CASES. The code will re-enter the interpreter
758 * through the NoChain point.
759 */
760 if (maxChains != size) {
761 cUnit.switchOverflowPad =
762 desc->method->insns + lastInsn->offset;
763 }
764
765 s4 *targets = (s4 *) (switchData + 2 +
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800766 (lastInsn->dalvikInsn.opcode == OP_PACKED_SWITCH ?
Ben Cheng6c10a972009-10-29 14:39:18 -0700767 2 : size * 2));
768
769 /* One chaining cell for the first MAX_CHAINED_SWITCH_CASES cases */
770 for (i = 0; i < maxChains; i++) {
Ben Cheng00603072010-10-28 11:13:58 -0700771 BasicBlock *caseChain = dvmCompilerNewBB(kChainingCellNormal,
772 numBlocks++);
773 dvmInsertGrowableList(blockList, (intptr_t) caseChain);
Ben Cheng6c10a972009-10-29 14:39:18 -0700774 caseChain->startOffset = lastInsn->offset + targets[i];
Ben Cheng6c10a972009-10-29 14:39:18 -0700775 }
776
777 /* One more chaining cell for the default case */
Ben Cheng00603072010-10-28 11:13:58 -0700778 BasicBlock *caseChain = dvmCompilerNewBB(kChainingCellNormal,
779 numBlocks++);
780 dvmInsertGrowableList(blockList, (intptr_t) caseChain);
Ben Cheng6c10a972009-10-29 14:39:18 -0700781 caseChain->startOffset = lastInsn->offset + lastInsn->width;
Ben Cheng6d576092009-09-01 17:01:58 -0700782 /* Fallthrough block not included in the trace */
Ben Cheng6c10a972009-10-29 14:39:18 -0700783 } else if (!isUnconditionalBranch(lastInsn) &&
784 curBB->fallThrough == NULL) {
Ben Cheng00603072010-10-28 11:13:58 -0700785 BasicBlock *fallThroughBB;
Ben Cheng6d576092009-09-01 17:01:58 -0700786 /*
787 * If the chaining cell is after an invoke or
788 * instruction that cannot change the control flow, request a hot
789 * chaining cell.
790 */
791 if (isInvoke || curBB->needFallThroughBranch) {
Ben Cheng00603072010-10-28 11:13:58 -0700792 fallThroughBB = dvmCompilerNewBB(kChainingCellHot, numBlocks++);
Ben Cheng6d576092009-09-01 17:01:58 -0700793 } else {
Ben Cheng00603072010-10-28 11:13:58 -0700794 fallThroughBB = dvmCompilerNewBB(kChainingCellNormal,
795 numBlocks++);
Ben Cheng6d576092009-09-01 17:01:58 -0700796 }
Ben Cheng00603072010-10-28 11:13:58 -0700797 dvmInsertGrowableList(blockList, (intptr_t) fallThroughBB);
798 fallThroughBB->startOffset = fallThroughOffset;
799 curBB->fallThrough = fallThroughBB;
Ben Cheng7ab74e12011-02-03 14:02:06 -0800800 dvmCompilerSetBit(fallThroughBB->predecessors, curBB->id);
Ben Cheng6d576092009-09-01 17:01:58 -0700801 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700802 /* Target block not included in the trace */
Ben Cheng38329f52009-07-07 14:19:20 -0700803 if (curBB->taken == NULL &&
Bill Buzbee324b3ac2009-12-04 13:17:36 -0800804 (isGoto(lastInsn) || isInvoke ||
805 (targetOffset != UNKNOWN_TARGET && targetOffset != curOffset))) {
Ben Cheng7e2c3c72010-12-22 16:40:46 -0800806 BasicBlock *newBB = NULL;
Ben Cheng1efc9c52009-06-08 18:25:27 -0700807 if (isInvoke) {
Ben Cheng38329f52009-07-07 14:19:20 -0700808 /* Monomorphic callee */
809 if (callee) {
Ben Cheng7e2c3c72010-12-22 16:40:46 -0800810 /* JNI call doesn't need a chaining cell */
811 if (!dvmIsNativeMethod(callee)) {
812 newBB = dvmCompilerNewBB(kChainingCellInvokeSingleton,
813 numBlocks++);
814 newBB->startOffset = 0;
815 newBB->containingMethod = callee;
816 }
Ben Cheng38329f52009-07-07 14:19:20 -0700817 /* Will resolve at runtime */
818 } else {
Ben Cheng00603072010-10-28 11:13:58 -0700819 newBB = dvmCompilerNewBB(kChainingCellInvokePredicted,
820 numBlocks++);
Ben Cheng38329f52009-07-07 14:19:20 -0700821 newBB->startOffset = 0;
822 }
Ben Cheng1efc9c52009-06-08 18:25:27 -0700823 /* For unconditional branches, request a hot chaining cell */
824 } else {
Jeff Hao97319a82009-08-12 16:57:15 -0700825#if !defined(WITH_SELF_VERIFICATION)
Dan Bornsteinc2b486f2010-11-12 16:07:16 -0800826 newBB = dvmCompilerNewBB(dexIsGoto(flags) ?
Bill Buzbee1465db52009-09-23 17:17:35 -0700827 kChainingCellHot :
Ben Cheng00603072010-10-28 11:13:58 -0700828 kChainingCellNormal,
829 numBlocks++);
Ben Cheng38329f52009-07-07 14:19:20 -0700830 newBB->startOffset = targetOffset;
Jeff Hao97319a82009-08-12 16:57:15 -0700831#else
832 /* Handle branches that branch back into the block */
833 if (targetOffset >= curBB->firstMIRInsn->offset &&
834 targetOffset <= curBB->lastMIRInsn->offset) {
Ben Cheng00603072010-10-28 11:13:58 -0700835 newBB = dvmCompilerNewBB(kChainingCellBackwardBranch,
836 numBlocks++);
Jeff Hao97319a82009-08-12 16:57:15 -0700837 } else {
Dan Bornsteinc2b486f2010-11-12 16:07:16 -0800838 newBB = dvmCompilerNewBB(dexIsGoto(flags) ?
Bill Buzbee1465db52009-09-23 17:17:35 -0700839 kChainingCellHot :
Ben Cheng00603072010-10-28 11:13:58 -0700840 kChainingCellNormal,
841 numBlocks++);
Jeff Hao97319a82009-08-12 16:57:15 -0700842 }
843 newBB->startOffset = targetOffset;
844#endif
Ben Cheng1efc9c52009-06-08 18:25:27 -0700845 }
Ben Cheng7e2c3c72010-12-22 16:40:46 -0800846 if (newBB) {
847 curBB->taken = newBB;
Ben Cheng7ab74e12011-02-03 14:02:06 -0800848 dvmCompilerSetBit(newBB->predecessors, curBB->id);
Ben Cheng7e2c3c72010-12-22 16:40:46 -0800849 dvmInsertGrowableList(blockList, (intptr_t) newBB);
850 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700851 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700852 }
853
854 /* Now create a special block to host PC reconstruction code */
Ben Cheng00603072010-10-28 11:13:58 -0700855 curBB = dvmCompilerNewBB(kPCReconstruction, numBlocks++);
856 dvmInsertGrowableList(blockList, (intptr_t) curBB);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700857
858 /* And one final block that publishes the PC and raise the exception */
Ben Cheng00603072010-10-28 11:13:58 -0700859 curBB = dvmCompilerNewBB(kExceptionHandling, numBlocks++);
860 dvmInsertGrowableList(blockList, (intptr_t) curBB);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700861
862 if (cUnit.printMe) {
Ben Cheng00603072010-10-28 11:13:58 -0700863 char* signature =
864 dexProtoCopyMethodDescriptor(&desc->method->prototype);
Elliott Hughescc6fac82010-07-02 13:38:44 -0700865 LOGD("TRACEINFO (%d): 0x%08x %s%s.%s 0x%x %d of %d, %d blocks",
Ben Chenge9695e52009-06-16 16:11:47 -0700866 compilationId,
Ben Chengba4fc8b2009-06-01 13:00:29 -0700867 (intptr_t) desc->method->insns,
868 desc->method->clazz->descriptor,
869 desc->method->name,
Elliott Hughescc6fac82010-07-02 13:38:44 -0700870 signature,
Ben Cheng385828e2011-03-04 16:48:33 -0800871 desc->trace[0].info.frag.startOffset,
Ben Chengba4fc8b2009-06-01 13:00:29 -0700872 traceSize,
873 dexCode->insnsSize,
874 numBlocks);
Elliott Hughescc6fac82010-07-02 13:38:44 -0700875 free(signature);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700876 }
877
Ben Chengba4fc8b2009-06-01 13:00:29 -0700878 cUnit.traceDesc = desc;
879 cUnit.numBlocks = numBlocks;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700880
Ben Cheng7a2697d2010-06-07 13:44:23 -0700881 /* Set the instruction set to use (NOTE: later components may change it) */
882 cUnit.instructionSet = dvmCompilerInstructionSet();
883
884 /* Inline transformation @ the MIR level */
885 if (cUnit.hasInvoke && !(gDvmJit.disableOpt & (1 << kMethodInlining))) {
Ben Chengcfdeca32011-01-14 11:36:46 -0800886 dvmCompilerInlineMIR(&cUnit, info);
Ben Cheng7a2697d2010-06-07 13:44:23 -0700887 }
888
Ben Cheng00603072010-10-28 11:13:58 -0700889 cUnit.numDalvikRegisters = cUnit.method->registersSize;
890
Ben Cheng4238ec22009-08-24 16:32:22 -0700891 /* Preparation for SSA conversion */
892 dvmInitializeSSAConversion(&cUnit);
893
894 if (cUnit.hasLoop) {
Ben Cheng4a419582010-08-04 13:23:09 -0700895 /*
896 * Loop is not optimizable (for example lack of a single induction
897 * variable), punt and recompile the trace with loop optimization
898 * disabled.
899 */
900 bool loopOpt = dvmCompilerLoopOpt(&cUnit);
901 if (loopOpt == false) {
902 if (cUnit.printMe) {
903 LOGD("Loop is not optimizable - retry codegen");
904 }
905 /* Reset the compiler resource pool */
906 dvmCompilerArenaReset();
907 return dvmCompileTrace(desc, cUnit.numInsts, info, bailPtr,
908 optHints | JIT_OPT_NO_LOOP);
909 }
Ben Cheng4238ec22009-08-24 16:32:22 -0700910 }
911 else {
912 dvmCompilerNonLoopAnalysis(&cUnit);
913 }
914
Bill Buzbee1465db52009-09-23 17:17:35 -0700915 dvmCompilerInitializeRegAlloc(&cUnit); // Needs to happen after SSA naming
916
Ben Chengba4fc8b2009-06-01 13:00:29 -0700917 if (cUnit.printMe) {
918 dvmCompilerDumpCompilationUnit(&cUnit);
919 }
920
buzbee23d95d02010-12-14 13:16:43 -0800921 /* Allocate Registers using simple local allocation scheme */
922 dvmCompilerLocalRegAlloc(&cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700923
Ben Chengba4fc8b2009-06-01 13:00:29 -0700924 /* Convert MIR to LIR, etc. */
925 dvmCompilerMIR2LIR(&cUnit);
926
buzbeebff121a2010-08-04 15:25:06 -0700927 /* Convert LIR into machine code. Loop for recoverable retries */
928 do {
929 dvmCompilerAssembleLIR(&cUnit, info);
930 cUnit.assemblerRetries++;
931 if (cUnit.printMe && cUnit.assemblerStatus != kSuccess)
932 LOGD("Assembler abort #%d on %d",cUnit.assemblerRetries,
933 cUnit.assemblerStatus);
934 } while (cUnit.assemblerStatus == kRetryAll);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700935
936 if (cUnit.printMe) {
Ben Chengcfdeca32011-01-14 11:36:46 -0800937 LOGD("Trace Dalvik PC: %p", startCodePtr);
buzbeebff121a2010-08-04 15:25:06 -0700938 dvmCompilerCodegenDump(&cUnit);
Ben Cheng1efc9c52009-06-08 18:25:27 -0700939 LOGD("End %s%s, %d Dalvik instructions",
940 desc->method->clazz->descriptor, desc->method->name,
941 cUnit.numInsts);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700942 }
943
buzbeebff121a2010-08-04 15:25:06 -0700944 if (cUnit.assemblerStatus == kRetryHalve) {
Ben Cheng385828e2011-03-04 16:48:33 -0800945 /* Reset the compiler resource pool before retry */
946 dvmCompilerArenaReset();
947
buzbeebff121a2010-08-04 15:25:06 -0700948 /* Halve the instruction count and start from the top */
Ben Cheng4a419582010-08-04 13:23:09 -0700949 return dvmCompileTrace(desc, cUnit.numInsts / 2, info, bailPtr,
950 optHints);
Ben Cheng1efc9c52009-06-08 18:25:27 -0700951 }
buzbeebff121a2010-08-04 15:25:06 -0700952
Ben Cheng385828e2011-03-04 16:48:33 -0800953 /*
954 * If this trace uses class objects as constants,
955 * dvmJitInstallClassObjectPointers will switch the thread state
956 * to running and look up the class pointers using the descriptor/loader
957 * tuple stored in the callsite info structure. We need to make this window
958 * as short as possible since it is blocking GC.
959 */
960 if (cUnit.hasClassLiterals && info->codeAddress) {
961 dvmJitInstallClassObjectPointers(&cUnit, (char *) info->codeAddress);
962 }
963
964 /*
965 * Since callsiteinfo is allocated from the arena, delay the reset until
966 * class pointers are resolved.
967 */
968 dvmCompilerArenaReset();
969
buzbeebff121a2010-08-04 15:25:06 -0700970 assert(cUnit.assemblerStatus == kSuccess);
971#if defined(WITH_JIT_TUNING)
972 methodStats->nativeSize += cUnit.totalSize;
973#endif
Ben Cheng00603072010-10-28 11:13:58 -0700974
buzbeebff121a2010-08-04 15:25:06 -0700975 return info->codeAddress != NULL;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700976}
977
978/*
Ben Cheng7a2697d2010-06-07 13:44:23 -0700979 * Since we are including instructions from possibly a cold method into the
980 * current trace, we need to make sure that all the associated information
981 * with the callee is properly initialized. If not, we punt on this inline
982 * target.
983 *
Ben Cheng34dc7962010-08-26 14:56:31 -0700984 * TODO: volatile instructions will be handled later.
Ben Cheng7a2697d2010-06-07 13:44:23 -0700985 */
986bool dvmCompilerCanIncludeThisInstruction(const Method *method,
987 const DecodedInstruction *insn)
988{
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800989 switch (insn->opcode) {
Ben Cheng7a2697d2010-06-07 13:44:23 -0700990 case OP_NEW_INSTANCE:
jeffhao71eee1f2011-01-04 14:18:54 -0800991 case OP_NEW_INSTANCE_JUMBO:
992 case OP_CHECK_CAST:
993 case OP_CHECK_CAST_JUMBO: {
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800994 ClassObject *classPtr = (ClassObject *)(void*)
Ben Cheng7a2697d2010-06-07 13:44:23 -0700995 (method->clazz->pDvmDex->pResClasses[insn->vB]);
996
997 /* Class hasn't been initialized yet */
998 if (classPtr == NULL) {
999 return false;
1000 }
1001 return true;
1002 }
Ben Cheng7a2697d2010-06-07 13:44:23 -07001003 case OP_SGET:
jeffhao71eee1f2011-01-04 14:18:54 -08001004 case OP_SGET_JUMBO:
Ben Cheng7a2697d2010-06-07 13:44:23 -07001005 case OP_SGET_WIDE:
jeffhao71eee1f2011-01-04 14:18:54 -08001006 case OP_SGET_WIDE_JUMBO:
1007 case OP_SGET_OBJECT:
1008 case OP_SGET_OBJECT_JUMBO:
1009 case OP_SGET_BOOLEAN:
1010 case OP_SGET_BOOLEAN_JUMBO:
1011 case OP_SGET_BYTE:
1012 case OP_SGET_BYTE_JUMBO:
1013 case OP_SGET_CHAR:
1014 case OP_SGET_CHAR_JUMBO:
1015 case OP_SGET_SHORT:
1016 case OP_SGET_SHORT_JUMBO:
Ben Cheng7a2697d2010-06-07 13:44:23 -07001017 case OP_SPUT:
jeffhao71eee1f2011-01-04 14:18:54 -08001018 case OP_SPUT_JUMBO:
1019 case OP_SPUT_WIDE:
1020 case OP_SPUT_WIDE_JUMBO:
1021 case OP_SPUT_OBJECT:
1022 case OP_SPUT_OBJECT_JUMBO:
1023 case OP_SPUT_BOOLEAN:
1024 case OP_SPUT_BOOLEAN_JUMBO:
1025 case OP_SPUT_BYTE:
1026 case OP_SPUT_BYTE_JUMBO:
1027 case OP_SPUT_CHAR:
1028 case OP_SPUT_CHAR_JUMBO:
1029 case OP_SPUT_SHORT:
1030 case OP_SPUT_SHORT_JUMBO: {
Ben Cheng7a2697d2010-06-07 13:44:23 -07001031 void *fieldPtr = (void*)
1032 (method->clazz->pDvmDex->pResFields[insn->vB]);
1033
1034 if (fieldPtr == NULL) {
1035 return false;
1036 }
1037 return true;
1038 }
1039 case OP_INVOKE_SUPER:
jeffhao71eee1f2011-01-04 14:18:54 -08001040 case OP_INVOKE_SUPER_RANGE:
1041 case OP_INVOKE_SUPER_JUMBO: {
Ben Cheng7a2697d2010-06-07 13:44:23 -07001042 int mIndex = method->clazz->pDvmDex->
1043 pResMethods[insn->vB]->methodIndex;
1044 const Method *calleeMethod = method->clazz->super->vtable[mIndex];
1045 if (calleeMethod == NULL) {
1046 return false;
1047 }
1048 return true;
1049 }
1050 case OP_INVOKE_SUPER_QUICK:
1051 case OP_INVOKE_SUPER_QUICK_RANGE: {
1052 const Method *calleeMethod = method->clazz->super->vtable[insn->vB];
1053 if (calleeMethod == NULL) {
1054 return false;
1055 }
1056 return true;
1057 }
1058 case OP_INVOKE_STATIC:
1059 case OP_INVOKE_STATIC_RANGE:
jeffhao71eee1f2011-01-04 14:18:54 -08001060 case OP_INVOKE_STATIC_JUMBO:
Ben Cheng7a2697d2010-06-07 13:44:23 -07001061 case OP_INVOKE_DIRECT:
jeffhao71eee1f2011-01-04 14:18:54 -08001062 case OP_INVOKE_DIRECT_RANGE:
1063 case OP_INVOKE_DIRECT_JUMBO: {
Ben Cheng7a2697d2010-06-07 13:44:23 -07001064 const Method *calleeMethod =
1065 method->clazz->pDvmDex->pResMethods[insn->vB];
1066 if (calleeMethod == NULL) {
1067 return false;
1068 }
1069 return true;
1070 }
jeffhao71eee1f2011-01-04 14:18:54 -08001071 case OP_CONST_CLASS:
1072 case OP_CONST_CLASS_JUMBO: {
Ben Cheng7a2697d2010-06-07 13:44:23 -07001073 void *classPtr = (void*)
1074 (method->clazz->pDvmDex->pResClasses[insn->vB]);
1075
1076 if (classPtr == NULL) {
1077 return false;
1078 }
1079 return true;
1080 }
1081 case OP_CONST_STRING_JUMBO:
1082 case OP_CONST_STRING: {
1083 void *strPtr = (void*)
1084 (method->clazz->pDvmDex->pResStrings[insn->vB]);
1085
1086 if (strPtr == NULL) {
1087 return false;
1088 }
1089 return true;
1090 }
1091 default:
1092 return true;
1093 }
1094}
1095
Ben Cheng00603072010-10-28 11:13:58 -07001096/* Split an existing block from the specified code offset into two */
1097static BasicBlock *splitBlock(CompilationUnit *cUnit,
1098 unsigned int codeOffset,
1099 BasicBlock *origBlock)
1100{
1101 MIR *insn = origBlock->firstMIRInsn;
1102 while (insn) {
1103 if (insn->offset == codeOffset) break;
1104 insn = insn->next;
1105 }
1106 if (insn == NULL) {
1107 LOGE("Break split failed");
1108 dvmAbort();
1109 }
1110 BasicBlock *bottomBlock = dvmCompilerNewBB(kDalvikByteCode,
1111 cUnit->numBlocks++);
1112 dvmInsertGrowableList(&cUnit->blockList, (intptr_t) bottomBlock);
1113
1114 bottomBlock->startOffset = codeOffset;
1115 bottomBlock->firstMIRInsn = insn;
1116 bottomBlock->lastMIRInsn = origBlock->lastMIRInsn;
1117
Ben Cheng00603072010-10-28 11:13:58 -07001118 /* Handle the taken path */
1119 bottomBlock->taken = origBlock->taken;
1120 if (bottomBlock->taken) {
1121 origBlock->taken = NULL;
1122 dvmCompilerClearBit(bottomBlock->taken->predecessors, origBlock->id);
1123 dvmCompilerSetBit(bottomBlock->taken->predecessors, bottomBlock->id);
1124 }
1125
1126 /* Handle the fallthrough path */
1127 bottomBlock->fallThrough = origBlock->fallThrough;
1128 origBlock->fallThrough = bottomBlock;
1129 dvmCompilerSetBit(bottomBlock->predecessors, origBlock->id);
1130 if (bottomBlock->fallThrough) {
1131 dvmCompilerClearBit(bottomBlock->fallThrough->predecessors,
1132 origBlock->id);
1133 dvmCompilerSetBit(bottomBlock->fallThrough->predecessors,
1134 bottomBlock->id);
1135 }
1136
1137 /* Handle the successor list */
1138 if (origBlock->successorBlockList.blockListType != kNotUsed) {
1139 bottomBlock->successorBlockList = origBlock->successorBlockList;
1140 origBlock->successorBlockList.blockListType = kNotUsed;
1141 GrowableListIterator iterator;
1142
1143 dvmGrowableListIteratorInit(&bottomBlock->successorBlockList.blocks,
1144 &iterator);
1145 while (true) {
Ben Cheng7a02cb12010-12-15 14:18:31 -08001146 SuccessorBlockInfo *successorBlockInfo =
1147 (SuccessorBlockInfo *) dvmGrowableListIteratorNext(&iterator);
1148 if (successorBlockInfo == NULL) break;
1149 BasicBlock *bb = successorBlockInfo->block;
Ben Cheng00603072010-10-28 11:13:58 -07001150 dvmCompilerClearBit(bb->predecessors, origBlock->id);
1151 dvmCompilerSetBit(bb->predecessors, bottomBlock->id);
1152 }
1153 }
1154
1155 origBlock->lastMIRInsn = insn->prev;
Ben Cheng00603072010-10-28 11:13:58 -07001156
1157 insn->prev->next = NULL;
1158 insn->prev = NULL;
1159 return bottomBlock;
1160}
1161
1162/*
1163 * Given a code offset, find out the block that starts with it. If the offset
1164 * is in the middle of an existing block, split it into two.
1165 */
1166static BasicBlock *findBlock(CompilationUnit *cUnit,
1167 unsigned int codeOffset,
1168 bool split, bool create)
1169{
1170 GrowableList *blockList = &cUnit->blockList;
1171 BasicBlock *bb;
1172 unsigned int i;
1173
1174 for (i = 0; i < blockList->numUsed; i++) {
1175 bb = (BasicBlock *) blockList->elemList[i];
1176 if (bb->blockType != kDalvikByteCode) continue;
1177 if (bb->startOffset == codeOffset) return bb;
1178 /* Check if a branch jumps into the middle of an existing block */
1179 if ((split == true) && (codeOffset > bb->startOffset) &&
1180 (bb->lastMIRInsn != NULL) &&
1181 (codeOffset <= bb->lastMIRInsn->offset)) {
1182 BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb);
1183 return newBB;
1184 }
1185 }
1186 if (create) {
1187 bb = dvmCompilerNewBB(kDalvikByteCode, cUnit->numBlocks++);
1188 dvmInsertGrowableList(&cUnit->blockList, (intptr_t) bb);
1189 bb->startOffset = codeOffset;
1190 return bb;
1191 }
1192 return NULL;
1193}
1194
1195/* Dump the CFG into a DOT graph */
1196void dumpCFG(CompilationUnit *cUnit, const char *dirPrefix)
1197{
1198 const Method *method = cUnit->method;
1199 FILE *file;
1200 char* signature = dexProtoCopyMethodDescriptor(&method->prototype);
1201 char *fileName = (char *) dvmCompilerNew(
1202 strlen(dirPrefix) +
1203 strlen(method->clazz->descriptor) +
1204 strlen(method->name) +
1205 strlen(signature) +
1206 strlen(".dot") + 1, true);
1207 sprintf(fileName, "%s%s%s%s.dot", dirPrefix,
1208 method->clazz->descriptor, method->name, signature);
1209 free(signature);
1210
1211 /*
1212 * Convert the special characters into a filesystem- and shell-friendly
1213 * format.
1214 */
1215 int i;
1216 for (i = strlen(dirPrefix); fileName[i]; i++) {
1217 if (fileName[i] == '/') {
1218 fileName[i] = '_';
1219 } else if (fileName[i] == ';') {
1220 fileName[i] = '#';
1221 } else if (fileName[i] == '$') {
1222 fileName[i] = '+';
1223 } else if (fileName[i] == '(' || fileName[i] == ')') {
1224 fileName[i] = '@';
1225 } else if (fileName[i] == '<' || fileName[i] == '>') {
1226 fileName[i] = '=';
1227 }
1228 }
1229 file = fopen(fileName, "w");
1230 if (file == NULL) {
1231 return;
1232 }
1233 fprintf(file, "digraph G {\n");
1234
1235 fprintf(file, " rankdir=TB\n");
1236
1237 int numReachableBlocks = cUnit->numReachableBlocks;
1238 int idx;
1239 const GrowableList *blockList = &cUnit->blockList;
1240
1241 for (idx = 0; idx < numReachableBlocks; idx++) {
1242 int blockIdx = cUnit->dfsOrder.elemList[idx];
1243 BasicBlock *bb = (BasicBlock *) dvmGrowableListGetElement(blockList,
1244 blockIdx);
1245 if (bb == NULL) break;
1246 if (bb->blockType == kMethodEntryBlock) {
1247 fprintf(file, " entry [shape=Mdiamond];\n");
1248 } else if (bb->blockType == kMethodExitBlock) {
1249 fprintf(file, " exit [shape=Mdiamond];\n");
1250 } else if (bb->blockType == kDalvikByteCode) {
Ben Cheng7a02cb12010-12-15 14:18:31 -08001251 fprintf(file, " block%04x [shape=record,label = \"{ \\\n",
1252 bb->startOffset);
Ben Cheng00603072010-10-28 11:13:58 -07001253 const MIR *mir;
1254 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
1255 fprintf(file, " {%04x %s\\l}%s\\\n", mir->offset,
1256 dvmCompilerFullDisassembler(cUnit, mir),
1257 mir->next ? " | " : " ");
1258 }
1259 fprintf(file, " }\"];\n\n");
1260 } else if (bb->blockType == kExceptionHandling) {
1261 char blockName[BLOCK_NAME_LEN];
1262
1263 dvmGetBlockName(bb, blockName);
1264 fprintf(file, " %s [shape=invhouse];\n", blockName);
1265 }
1266
1267 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
1268
1269 if (bb->taken) {
1270 dvmGetBlockName(bb, blockName1);
1271 dvmGetBlockName(bb->taken, blockName2);
1272 fprintf(file, " %s:s -> %s:n [style=dotted]\n",
1273 blockName1, blockName2);
1274 }
1275 if (bb->fallThrough) {
1276 dvmGetBlockName(bb, blockName1);
1277 dvmGetBlockName(bb->fallThrough, blockName2);
1278 fprintf(file, " %s:s -> %s:n\n", blockName1, blockName2);
1279 }
1280
1281 if (bb->successorBlockList.blockListType != kNotUsed) {
1282 fprintf(file, " succ%04x [shape=%s,label = \"{ \\\n",
1283 bb->startOffset,
1284 (bb->successorBlockList.blockListType == kCatch) ?
1285 "Mrecord" : "record");
1286 GrowableListIterator iterator;
1287 dvmGrowableListIteratorInit(&bb->successorBlockList.blocks,
1288 &iterator);
Ben Cheng7a02cb12010-12-15 14:18:31 -08001289 SuccessorBlockInfo *successorBlockInfo =
1290 (SuccessorBlockInfo *) dvmGrowableListIteratorNext(&iterator);
Ben Cheng00603072010-10-28 11:13:58 -07001291
1292 int succId = 0;
1293 while (true) {
Ben Cheng7a02cb12010-12-15 14:18:31 -08001294 if (successorBlockInfo == NULL) break;
1295
1296 BasicBlock *destBlock = successorBlockInfo->block;
1297 SuccessorBlockInfo *nextSuccessorBlockInfo =
1298 (SuccessorBlockInfo *) dvmGrowableListIteratorNext(&iterator);
1299
1300 fprintf(file, " {<f%d> %04x: %04x\\l}%s\\\n",
Ben Cheng00603072010-10-28 11:13:58 -07001301 succId++,
Ben Cheng7a02cb12010-12-15 14:18:31 -08001302 successorBlockInfo->key,
Ben Cheng00603072010-10-28 11:13:58 -07001303 destBlock->startOffset,
Ben Cheng7a02cb12010-12-15 14:18:31 -08001304 (nextSuccessorBlockInfo != NULL) ? " | " : " ");
1305
1306 successorBlockInfo = nextSuccessorBlockInfo;
Ben Cheng00603072010-10-28 11:13:58 -07001307 }
1308 fprintf(file, " }\"];\n\n");
1309
1310 dvmGetBlockName(bb, blockName1);
1311 fprintf(file, " %s:s -> succ%04x:n [style=dashed]\n",
1312 blockName1, bb->startOffset);
1313
1314 if (bb->successorBlockList.blockListType == kPackedSwitch ||
1315 bb->successorBlockList.blockListType == kSparseSwitch) {
1316
1317 dvmGrowableListIteratorInit(&bb->successorBlockList.blocks,
1318 &iterator);
1319
1320 succId = 0;
1321 while (true) {
Ben Cheng7a02cb12010-12-15 14:18:31 -08001322 SuccessorBlockInfo *successorBlockInfo =
1323 (SuccessorBlockInfo *)
1324 dvmGrowableListIteratorNext(&iterator);
1325 if (successorBlockInfo == NULL) break;
1326
1327 BasicBlock *destBlock = successorBlockInfo->block;
Ben Cheng00603072010-10-28 11:13:58 -07001328
1329 dvmGetBlockName(destBlock, blockName2);
1330 fprintf(file, " succ%04x:f%d:e -> %s:n\n",
1331 bb->startOffset, succId++,
1332 blockName2);
1333 }
1334 }
1335 }
1336 fprintf(file, "\n");
1337
1338 /*
1339 * If we need to debug the dominator tree, uncomment the following code
1340 */
1341#if 0
1342 dvmGetBlockName(bb, blockName1);
1343 fprintf(file, " cfg%s [label=\"%s\", shape=none];\n",
1344 blockName1, blockName1);
1345 if (bb->iDom) {
1346 dvmGetBlockName(bb->iDom, blockName2);
1347 fprintf(file, " cfg%s:s -> cfg%s:n\n\n",
1348 blockName2, blockName1);
1349 }
1350#endif
1351 }
1352 fprintf(file, "}\n");
1353 fclose(file);
1354}
1355
1356/* Verify if all the successor is connected with all the claimed predecessors */
1357static bool verifyPredInfo(CompilationUnit *cUnit, BasicBlock *bb)
1358{
1359 BitVectorIterator bvIterator;
1360
1361 dvmBitVectorIteratorInit(bb->predecessors, &bvIterator);
1362 while (true) {
1363 int blockIdx = dvmBitVectorIteratorNext(&bvIterator);
1364 if (blockIdx == -1) break;
1365 BasicBlock *predBB = (BasicBlock *)
1366 dvmGrowableListGetElement(&cUnit->blockList, blockIdx);
1367 bool found = false;
1368 if (predBB->taken == bb) {
1369 found = true;
1370 } else if (predBB->fallThrough == bb) {
1371 found = true;
1372 } else if (predBB->successorBlockList.blockListType != kNotUsed) {
1373 GrowableListIterator iterator;
1374 dvmGrowableListIteratorInit(&predBB->successorBlockList.blocks,
1375 &iterator);
1376 while (true) {
Ben Cheng7a02cb12010-12-15 14:18:31 -08001377 SuccessorBlockInfo *successorBlockInfo =
1378 (SuccessorBlockInfo *)
1379 dvmGrowableListIteratorNext(&iterator);
1380 if (successorBlockInfo == NULL) break;
1381 BasicBlock *succBB = successorBlockInfo->block;
Ben Cheng00603072010-10-28 11:13:58 -07001382 if (succBB == bb) {
1383 found = true;
1384 break;
1385 }
1386 }
1387 }
1388 if (found == false) {
1389 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
1390 dvmGetBlockName(bb, blockName1);
1391 dvmGetBlockName(predBB, blockName2);
1392 dumpCFG(cUnit, "/data/tombstones/");
1393 LOGE("Successor %s not found from %s",
1394 blockName1, blockName2);
1395 dvmAbort();
1396 }
1397 }
1398 return true;
1399}
1400
1401/* Identify code range in try blocks and set up the empty catch blocks */
1402static void processTryCatchBlocks(CompilationUnit *cUnit)
1403{
1404 const Method *meth = cUnit->method;
1405 const DexCode *pCode = dvmGetMethodCode(meth);
1406 int triesSize = pCode->triesSize;
1407 int i;
1408 int offset;
1409
1410 if (triesSize == 0) {
1411 return;
1412 }
1413
1414 const DexTry *pTries = dexGetTries(pCode);
1415 BitVector *tryBlockAddr = cUnit->tryBlockAddr;
1416
1417 /* Mark all the insn offsets in Try blocks */
1418 for (i = 0; i < triesSize; i++) {
1419 const DexTry* pTry = &pTries[i];
1420 /* all in 16-bit units */
1421 int startOffset = pTry->startAddr;
1422 int endOffset = startOffset + pTry->insnCount;
1423
1424 for (offset = startOffset; offset < endOffset; offset++) {
1425 dvmCompilerSetBit(tryBlockAddr, offset);
1426 }
1427 }
1428
1429 /* Iterate over each of the handlers to enqueue the empty Catch blocks */
1430 offset = dexGetFirstHandlerOffset(pCode);
1431 int handlersSize = dexGetHandlersSize(pCode);
1432
1433 for (i = 0; i < handlersSize; i++) {
1434 DexCatchIterator iterator;
1435 dexCatchIteratorInit(&iterator, pCode, offset);
1436
1437 for (;;) {
1438 DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
1439
1440 if (handler == NULL) {
1441 break;
1442 }
1443
Ben Cheng7a02cb12010-12-15 14:18:31 -08001444 /*
1445 * Create dummy catch blocks first. Since these are created before
1446 * other blocks are processed, "split" is specified as false.
1447 */
1448 findBlock(cUnit, handler->address,
1449 /* split */
1450 false,
1451 /* create */
1452 true);
Ben Cheng00603072010-10-28 11:13:58 -07001453 }
1454
1455 offset = dexCatchIteratorGetEndOffset(&iterator, pCode);
1456 }
1457}
1458
1459/* Process instructions with the kInstrCanBranch flag */
1460static void processCanBranch(CompilationUnit *cUnit, BasicBlock *curBlock,
1461 MIR *insn, int curOffset, int width, int flags,
1462 const u2* codePtr, const u2* codeEnd)
1463{
1464 int target = curOffset;
1465 switch (insn->dalvikInsn.opcode) {
1466 case OP_GOTO:
1467 case OP_GOTO_16:
1468 case OP_GOTO_32:
1469 target += (int) insn->dalvikInsn.vA;
1470 break;
1471 case OP_IF_EQ:
1472 case OP_IF_NE:
1473 case OP_IF_LT:
1474 case OP_IF_GE:
1475 case OP_IF_GT:
1476 case OP_IF_LE:
1477 target += (int) insn->dalvikInsn.vC;
1478 break;
1479 case OP_IF_EQZ:
1480 case OP_IF_NEZ:
1481 case OP_IF_LTZ:
1482 case OP_IF_GEZ:
1483 case OP_IF_GTZ:
1484 case OP_IF_LEZ:
1485 target += (int) insn->dalvikInsn.vB;
1486 break;
1487 default:
1488 LOGE("Unexpected opcode(%d) with kInstrCanBranch set",
1489 insn->dalvikInsn.opcode);
1490 dvmAbort();
1491 }
1492 BasicBlock *takenBlock = findBlock(cUnit, target,
1493 /* split */
1494 true,
1495 /* create */
1496 true);
1497 curBlock->taken = takenBlock;
1498 dvmCompilerSetBit(takenBlock->predecessors, curBlock->id);
1499
1500 /* Always terminate the current block for conditional branches */
1501 if (flags & kInstrCanContinue) {
1502 BasicBlock *fallthroughBlock = findBlock(cUnit,
1503 curOffset + width,
1504 /* split */
1505 false,
1506 /* create */
1507 true);
1508 curBlock->fallThrough = fallthroughBlock;
1509 dvmCompilerSetBit(fallthroughBlock->predecessors, curBlock->id);
1510 } else if (codePtr < codeEnd) {
1511 /* Create a fallthrough block for real instructions (incl. OP_NOP) */
1512 if (contentIsInsn(codePtr)) {
1513 findBlock(cUnit, curOffset + width,
1514 /* split */
1515 false,
1516 /* create */
1517 true);
1518 }
1519 }
1520}
1521
1522/* Process instructions with the kInstrCanSwitch flag */
1523static void processCanSwitch(CompilationUnit *cUnit, BasicBlock *curBlock,
1524 MIR *insn, int curOffset, int width, int flags)
1525{
1526 u2 *switchData= (u2 *) (cUnit->method->insns + curOffset +
1527 insn->dalvikInsn.vB);
1528 int size;
Ben Cheng7a02cb12010-12-15 14:18:31 -08001529 int *keyTable;
Ben Cheng00603072010-10-28 11:13:58 -07001530 int *targetTable;
1531 int i;
Ben Cheng7a02cb12010-12-15 14:18:31 -08001532 int firstKey;
Ben Cheng00603072010-10-28 11:13:58 -07001533
1534 /*
1535 * Packed switch data format:
1536 * ushort ident = 0x0100 magic value
1537 * ushort size number of entries in the table
1538 * int first_key first (and lowest) switch case value
1539 * int targets[size] branch targets, relative to switch opcode
1540 *
1541 * Total size is (4+size*2) 16-bit code units.
1542 */
1543 if (insn->dalvikInsn.opcode == OP_PACKED_SWITCH) {
1544 assert(switchData[0] == kPackedSwitchSignature);
1545 size = switchData[1];
Ben Cheng7a02cb12010-12-15 14:18:31 -08001546 firstKey = switchData[2] | (switchData[3] << 16);
Ben Cheng00603072010-10-28 11:13:58 -07001547 targetTable = (int *) &switchData[4];
Ben Cheng7a02cb12010-12-15 14:18:31 -08001548 keyTable = NULL; // Make the compiler happy
Ben Cheng00603072010-10-28 11:13:58 -07001549 /*
1550 * Sparse switch data format:
1551 * ushort ident = 0x0200 magic value
1552 * ushort size number of entries in the table; > 0
1553 * int keys[size] keys, sorted low-to-high; 32-bit aligned
1554 * int targets[size] branch targets, relative to switch opcode
1555 *
1556 * Total size is (2+size*4) 16-bit code units.
1557 */
1558 } else {
1559 assert(switchData[0] == kSparseSwitchSignature);
1560 size = switchData[1];
Ben Cheng7a02cb12010-12-15 14:18:31 -08001561 keyTable = (int *) &switchData[2];
Ben Cheng00603072010-10-28 11:13:58 -07001562 targetTable = (int *) &switchData[2 + size*2];
Ben Cheng7a02cb12010-12-15 14:18:31 -08001563 firstKey = 0; // To make the compiler happy
Ben Cheng00603072010-10-28 11:13:58 -07001564 }
1565
1566 if (curBlock->successorBlockList.blockListType != kNotUsed) {
1567 LOGE("Successor block list already in use: %d",
1568 curBlock->successorBlockList.blockListType);
1569 dvmAbort();
1570 }
1571 curBlock->successorBlockList.blockListType =
1572 (insn->dalvikInsn.opcode == OP_PACKED_SWITCH) ?
1573 kPackedSwitch : kSparseSwitch;
1574 dvmInitGrowableList(&curBlock->successorBlockList.blocks, size);
1575
1576 for (i = 0; i < size; i++) {
1577 BasicBlock *caseBlock = findBlock(cUnit, curOffset + targetTable[i],
1578 /* split */
1579 true,
1580 /* create */
1581 true);
Ben Cheng7a02cb12010-12-15 14:18:31 -08001582 SuccessorBlockInfo *successorBlockInfo =
1583 (SuccessorBlockInfo *) dvmCompilerNew(sizeof(SuccessorBlockInfo),
1584 false);
1585 successorBlockInfo->block = caseBlock;
1586 successorBlockInfo->key = (insn->dalvikInsn.opcode == OP_PACKED_SWITCH)?
1587 firstKey + i : keyTable[i];
Ben Cheng00603072010-10-28 11:13:58 -07001588 dvmInsertGrowableList(&curBlock->successorBlockList.blocks,
Ben Cheng7a02cb12010-12-15 14:18:31 -08001589 (intptr_t) successorBlockInfo);
Ben Cheng00603072010-10-28 11:13:58 -07001590 dvmCompilerSetBit(caseBlock->predecessors, curBlock->id);
1591 }
1592
1593 /* Fall-through case */
1594 BasicBlock *fallthroughBlock = findBlock(cUnit,
1595 curOffset + width,
1596 /* split */
1597 false,
1598 /* create */
1599 true);
1600 curBlock->fallThrough = fallthroughBlock;
1601 dvmCompilerSetBit(fallthroughBlock->predecessors, curBlock->id);
1602}
1603
1604/* Process instructions with the kInstrCanThrow flag */
1605static void processCanThrow(CompilationUnit *cUnit, BasicBlock *curBlock,
1606 MIR *insn, int curOffset, int width, int flags,
1607 BitVector *tryBlockAddr, const u2 *codePtr,
1608 const u2* codeEnd)
1609{
1610 const Method *method = cUnit->method;
1611 const DexCode *dexCode = dvmGetMethodCode(method);
1612
Ben Cheng00603072010-10-28 11:13:58 -07001613 /* In try block */
1614 if (dvmIsBitSet(tryBlockAddr, curOffset)) {
1615 DexCatchIterator iterator;
1616
1617 if (!dexFindCatchHandler(&iterator, dexCode, curOffset)) {
1618 LOGE("Catch block not found in dexfile for insn %x in %s",
1619 curOffset, method->name);
1620 dvmAbort();
1621
1622 }
1623 if (curBlock->successorBlockList.blockListType != kNotUsed) {
1624 LOGE("Successor block list already in use: %d",
1625 curBlock->successorBlockList.blockListType);
1626 dvmAbort();
1627 }
1628 curBlock->successorBlockList.blockListType = kCatch;
1629 dvmInitGrowableList(&curBlock->successorBlockList.blocks, 2);
1630
1631 for (;;) {
1632 DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
1633
1634 if (handler == NULL) {
1635 break;
1636 }
1637
1638 BasicBlock *catchBlock = findBlock(cUnit, handler->address,
1639 /* split */
1640 false,
1641 /* create */
1642 false);
1643
Ben Cheng7a02cb12010-12-15 14:18:31 -08001644 SuccessorBlockInfo *successorBlockInfo =
1645 (SuccessorBlockInfo *) dvmCompilerNew(sizeof(SuccessorBlockInfo),
1646 false);
1647 successorBlockInfo->block = catchBlock;
1648 successorBlockInfo->key = handler->typeIdx;
Ben Cheng00603072010-10-28 11:13:58 -07001649 dvmInsertGrowableList(&curBlock->successorBlockList.blocks,
Ben Cheng7a02cb12010-12-15 14:18:31 -08001650 (intptr_t) successorBlockInfo);
Ben Cheng00603072010-10-28 11:13:58 -07001651 dvmCompilerSetBit(catchBlock->predecessors, curBlock->id);
1652 }
1653 } else {
1654 BasicBlock *ehBlock = dvmCompilerNewBB(kExceptionHandling,
1655 cUnit->numBlocks++);
1656 curBlock->taken = ehBlock;
1657 dvmInsertGrowableList(&cUnit->blockList, (intptr_t) ehBlock);
1658 ehBlock->startOffset = curOffset;
1659 dvmCompilerSetBit(ehBlock->predecessors, curBlock->id);
1660 }
1661
1662 /*
1663 * Force the current block to terminate.
1664 *
1665 * Data may be present before codeEnd, so we need to parse it to know
1666 * whether it is code or data.
1667 */
1668 if (codePtr < codeEnd) {
1669 /* Create a fallthrough block for real instructions (incl. OP_NOP) */
1670 if (contentIsInsn(codePtr)) {
1671 BasicBlock *fallthroughBlock = findBlock(cUnit,
1672 curOffset + width,
1673 /* split */
1674 false,
1675 /* create */
1676 true);
1677 /*
1678 * OP_THROW and OP_THROW_VERIFICATION_ERROR are unconditional
1679 * branches.
1680 */
1681 if (insn->dalvikInsn.opcode != OP_THROW_VERIFICATION_ERROR &&
1682 insn->dalvikInsn.opcode != OP_THROW) {
1683 curBlock->fallThrough = fallthroughBlock;
1684 dvmCompilerSetBit(fallthroughBlock->predecessors, curBlock->id);
1685 }
1686 }
1687 }
1688}
1689
Ben Cheng7a2697d2010-06-07 13:44:23 -07001690/*
Ben Chengba4fc8b2009-06-01 13:00:29 -07001691 * Similar to dvmCompileTrace, but the entity processed here is the whole
1692 * method.
1693 *
1694 * TODO: implementation will be revisited when the trace builder can provide
1695 * whole-method traces.
1696 */
Ben Chengcfdeca32011-01-14 11:36:46 -08001697bool dvmCompileMethod(const Method *method, JitTranslationInfo *info)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001698{
Ben Cheng00603072010-10-28 11:13:58 -07001699 CompilationUnit cUnit;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001700 const DexCode *dexCode = dvmGetMethodCode(method);
1701 const u2 *codePtr = dexCode->insns;
1702 const u2 *codeEnd = dexCode->insns + dexCode->insnsSize;
Ben Cheng00603072010-10-28 11:13:58 -07001703 int numBlocks = 0;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001704 unsigned int curOffset = 0;
1705
Ben Chengcfdeca32011-01-14 11:36:46 -08001706 /* Method already compiled */
1707 if (dvmJitGetMethodAddr(codePtr)) {
1708 info->codeAddress = NULL;
1709 return false;
1710 }
1711
Ben Cheng00603072010-10-28 11:13:58 -07001712 memset(&cUnit, 0, sizeof(cUnit));
1713 cUnit.method = method;
Ben Cheng7a2697d2010-06-07 13:44:23 -07001714
Ben Chengcfdeca32011-01-14 11:36:46 -08001715 cUnit.methodJitMode = true;
1716
Ben Cheng00603072010-10-28 11:13:58 -07001717 /* Initialize the block list */
1718 dvmInitGrowableList(&cUnit.blockList, 4);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001719
Ben Chengcfdeca32011-01-14 11:36:46 -08001720 /*
1721 * FIXME - PC reconstruction list won't be needed after the codegen routines
1722 * are enhanced to true method mode.
1723 */
1724 /* Initialize the PC reconstruction list */
1725 dvmInitGrowableList(&cUnit.pcReconstructionList, 8);
1726
Ben Chengba4fc8b2009-06-01 13:00:29 -07001727 /* Allocate the bit-vector to track the beginning of basic blocks */
Ben Cheng00603072010-10-28 11:13:58 -07001728 BitVector *tryBlockAddr = dvmCompilerAllocBitVector(dexCode->insnsSize,
1729 true /* expandable */);
1730 cUnit.tryBlockAddr = tryBlockAddr;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001731
Ben Cheng00603072010-10-28 11:13:58 -07001732 /* Create the default entry and exit blocks and enter them to the list */
1733 BasicBlock *entryBlock = dvmCompilerNewBB(kMethodEntryBlock, numBlocks++);
1734 BasicBlock *exitBlock = dvmCompilerNewBB(kMethodExitBlock, numBlocks++);
1735
1736 cUnit.entryBlock = entryBlock;
1737 cUnit.exitBlock = exitBlock;
1738
1739 dvmInsertGrowableList(&cUnit.blockList, (intptr_t) entryBlock);
1740 dvmInsertGrowableList(&cUnit.blockList, (intptr_t) exitBlock);
1741
1742 /* Current block to record parsed instructions */
1743 BasicBlock *curBlock = dvmCompilerNewBB(kDalvikByteCode, numBlocks++);
1744 curBlock->startOffset = 0;
1745 dvmInsertGrowableList(&cUnit.blockList, (intptr_t) curBlock);
1746 entryBlock->fallThrough = curBlock;
1747 dvmCompilerSetBit(curBlock->predecessors, entryBlock->id);
Ben Cheng7a2697d2010-06-07 13:44:23 -07001748
Ben Chengba4fc8b2009-06-01 13:00:29 -07001749 /*
Ben Cheng00603072010-10-28 11:13:58 -07001750 * Store back the number of blocks since new blocks may be created of
1751 * accessing cUnit.
Ben Chengba4fc8b2009-06-01 13:00:29 -07001752 */
Ben Cheng00603072010-10-28 11:13:58 -07001753 cUnit.numBlocks = numBlocks;
1754
1755 /* Identify code range in try blocks and set up the empty catch blocks */
1756 processTryCatchBlocks(&cUnit);
1757
1758 /* Parse all instructions and put them into containing basic blocks */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001759 while (codePtr < codeEnd) {
Ben Cheng00603072010-10-28 11:13:58 -07001760 MIR *insn = (MIR *) dvmCompilerNew(sizeof(MIR), true);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001761 insn->offset = curOffset;
1762 int width = parseInsn(codePtr, &insn->dalvikInsn, false);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001763 insn->width = width;
1764
Ben Cheng8b258bf2009-06-24 17:27:07 -07001765 /* Terminate when the data section is seen */
1766 if (width == 0)
1767 break;
Ben Cheng7a2697d2010-06-07 13:44:23 -07001768
Ben Cheng00603072010-10-28 11:13:58 -07001769 dvmCompilerAppendMIR(curBlock, insn);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001770
1771 codePtr += width;
Ben Cheng00603072010-10-28 11:13:58 -07001772 int flags = dexGetFlagsFromOpcode(insn->dalvikInsn.opcode);
1773
1774 if (flags & kInstrCanBranch) {
1775 processCanBranch(&cUnit, curBlock, insn, curOffset, width, flags,
1776 codePtr, codeEnd);
1777 } else if (flags & kInstrCanReturn) {
1778 curBlock->fallThrough = exitBlock;
1779 dvmCompilerSetBit(exitBlock->predecessors, curBlock->id);
1780 /*
1781 * Terminate the current block if there are instructions
1782 * afterwards.
1783 */
1784 if (codePtr < codeEnd) {
1785 /*
1786 * Create a fallthrough block for real instructions
1787 * (incl. OP_NOP).
1788 */
1789 if (contentIsInsn(codePtr)) {
1790 findBlock(&cUnit, curOffset + width,
1791 /* split */
1792 false,
1793 /* create */
1794 true);
1795 }
1796 }
1797 } else if (flags & kInstrCanThrow) {
1798 processCanThrow(&cUnit, curBlock, insn, curOffset, width, flags,
1799 tryBlockAddr, codePtr, codeEnd);
1800 } else if (flags & kInstrCanSwitch) {
1801 processCanSwitch(&cUnit, curBlock, insn, curOffset, width, flags);
1802 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001803 curOffset += width;
Ben Cheng00603072010-10-28 11:13:58 -07001804 BasicBlock *nextBlock = findBlock(&cUnit, curOffset,
1805 /* split */
1806 false,
1807 /* create */
1808 false);
1809 if (nextBlock) {
1810 /*
1811 * The next instruction could be the target of a previously parsed
1812 * forward branch so a block is already created. If the current
1813 * instruction is not an unconditional branch, connect them through
1814 * the fall-through link.
1815 */
1816 assert(curBlock->fallThrough == NULL ||
1817 curBlock->fallThrough == nextBlock ||
1818 curBlock->fallThrough == exitBlock);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001819
Ben Cheng00603072010-10-28 11:13:58 -07001820 if ((curBlock->fallThrough == NULL) &&
Ben Cheng20d7e6c2011-02-18 17:12:42 -08001821 (flags & kInstrCanContinue)) {
Ben Cheng00603072010-10-28 11:13:58 -07001822 curBlock->fallThrough = nextBlock;
1823 dvmCompilerSetBit(nextBlock->predecessors, curBlock->id);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001824 }
Ben Cheng00603072010-10-28 11:13:58 -07001825 curBlock = nextBlock;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001826 }
1827 }
1828
Ben Chengcfdeca32011-01-14 11:36:46 -08001829 if (cUnit.printMe) {
1830 dvmCompilerDumpCompilationUnit(&cUnit);
1831 }
1832
Ben Cheng00603072010-10-28 11:13:58 -07001833 /* Adjust this value accordingly once inlining is performed */
1834 cUnit.numDalvikRegisters = cUnit.method->registersSize;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001835
Ben Cheng00603072010-10-28 11:13:58 -07001836 /* Verify if all blocks are connected as claimed */
1837 /* FIXME - to be disabled in the future */
1838 dvmCompilerDataFlowAnalysisDispatcher(&cUnit, verifyPredInfo,
1839 kAllNodes,
1840 false /* isIterative */);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001841
Ben Chengba4fc8b2009-06-01 13:00:29 -07001842
Ben Cheng00603072010-10-28 11:13:58 -07001843 /* Perform SSA transformation for the whole method */
1844 dvmCompilerMethodSSATransformation(&cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001845
Ben Chengcfdeca32011-01-14 11:36:46 -08001846 dvmCompilerInitializeRegAlloc(&cUnit); // Needs to happen after SSA naming
Ben Chengba4fc8b2009-06-01 13:00:29 -07001847
Ben Chengcfdeca32011-01-14 11:36:46 -08001848 /* Allocate Registers using simple local allocation scheme */
1849 dvmCompilerLocalRegAlloc(&cUnit);
1850
1851 /* Convert MIR to LIR, etc. */
1852 dvmCompilerMethodMIR2LIR(&cUnit);
1853
1854 // Debugging only
1855 //dumpCFG(&cUnit, "/data/tombstones/");
1856
1857 /* Method is not empty */
1858 if (cUnit.firstLIRInsn) {
1859 /* Convert LIR into machine code. Loop for recoverable retries */
1860 do {
1861 dvmCompilerAssembleLIR(&cUnit, info);
1862 cUnit.assemblerRetries++;
1863 if (cUnit.printMe && cUnit.assemblerStatus != kSuccess)
1864 LOGD("Assembler abort #%d on %d",cUnit.assemblerRetries,
1865 cUnit.assemblerStatus);
1866 } while (cUnit.assemblerStatus == kRetryAll);
1867
1868 if (cUnit.printMe) {
1869 dvmCompilerCodegenDump(&cUnit);
1870 }
1871
1872 if (info->codeAddress) {
1873 dvmJitSetCodeAddr(dexCode->insns, info->codeAddress,
1874 info->instructionSet, true, 0);
1875 /*
1876 * Clear the codeAddress for the enclosing trace to reuse the info
1877 */
1878 info->codeAddress = NULL;
1879 }
1880 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001881
Ben Cheng00603072010-10-28 11:13:58 -07001882 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001883}