blob: dce9b8bd14736c60e5cc5ad67a381d93697a5b28 [file] [log] [blame]
buzbee67bf8852011-08-17 17:51:35 -07001/*
2 * Copyright (C) 2011 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"
18#include "CompilerInternals.h"
19#include "Dataflow.h"
Ian Rogers0571d352011-11-03 19:51:38 -070020#include "leb128.h"
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070021#include "object.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070022#include "runtime.h"
buzbee67bf8852011-08-17 17:51:35 -070023
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080024namespace art {
25
buzbeece302932011-10-04 14:32:18 -070026/* Default optimizer/debug setting for the compiler. */
Elliott Hughese52e49b2012-04-02 16:05:44 -070027static uint32_t kCompilerOptimizerDisableFlags = 0 | // Disable specific optimizations
Bill Buzbeea114add2012-05-03 15:00:40 -070028 //(1 << kLoadStoreElimination) |
29 //(1 << kLoadHoisting) |
30 //(1 << kSuppressLoads) |
31 //(1 << kNullCheckElimination) |
32 //(1 << kPromoteRegs) |
33 //(1 << kTrackLiveTemps) |
34 //(1 << kSkipLargeMethodOptimization) |
35 //(1 << kSafeOptimizations) |
36 //(1 << kBBOpt) |
37 //(1 << kMatch) |
38 //(1 << kPromoteCompilerTemps) |
39 0;
buzbeece302932011-10-04 14:32:18 -070040
Elliott Hughese52e49b2012-04-02 16:05:44 -070041static uint32_t kCompilerDebugFlags = 0 | // Enable debug/testing modes
Bill Buzbeea114add2012-05-03 15:00:40 -070042 //(1 << kDebugDisplayMissingTargets) |
43 //(1 << kDebugVerbose) |
44 //(1 << kDebugDumpCFG) |
45 //(1 << kDebugSlowFieldPath) |
46 //(1 << kDebugSlowInvokePath) |
47 //(1 << kDebugSlowStringPath) |
48 //(1 << kDebugSlowestFieldPath) |
49 //(1 << kDebugSlowestStringPath) |
50 //(1 << kDebugExerciseResolveMethod) |
51 //(1 << kDebugVerifyDataflow) |
52 //(1 << kDebugShowMemoryUsage) |
53 //(1 << kDebugShowNops) |
54 //(1 << kDebugCountOpcodes) |
55 0;
buzbeece302932011-10-04 14:32:18 -070056
buzbee31a4a6f2012-02-28 15:36:15 -080057inline bool contentIsInsn(const u2* codePtr) {
Bill Buzbeea114add2012-05-03 15:00:40 -070058 u2 instr = *codePtr;
59 Instruction::Code opcode = (Instruction::Code)(instr & 0xff);
buzbee67bf8852011-08-17 17:51:35 -070060
Bill Buzbeea114add2012-05-03 15:00:40 -070061 /*
62 * Since the low 8-bit in metadata may look like NOP, we need to check
63 * both the low and whole sub-word to determine whether it is code or data.
64 */
65 return (opcode != Instruction::NOP || instr == 0);
buzbee67bf8852011-08-17 17:51:35 -070066}
67
68/*
69 * Parse an instruction, return the length of the instruction
70 */
buzbee31a4a6f2012-02-28 15:36:15 -080071inline int parseInsn(CompilationUnit* cUnit, const u2* codePtr,
Bill Buzbeea114add2012-05-03 15:00:40 -070072 DecodedInstruction* decoded_instruction, bool printMe)
buzbee67bf8852011-08-17 17:51:35 -070073{
Elliott Hughesadb8c672012-03-06 16:49:32 -080074 // Don't parse instruction data
75 if (!contentIsInsn(codePtr)) {
76 return 0;
77 }
buzbee67bf8852011-08-17 17:51:35 -070078
Elliott Hughesadb8c672012-03-06 16:49:32 -080079 const Instruction* instruction = Instruction::At(codePtr);
80 *decoded_instruction = DecodedInstruction(instruction);
buzbee67bf8852011-08-17 17:51:35 -070081
Elliott Hughesadb8c672012-03-06 16:49:32 -080082 if (printMe) {
Bill Buzbeea114add2012-05-03 15:00:40 -070083 char* decodedString = oatGetDalvikDisassembly(cUnit, *decoded_instruction,
84 NULL);
85 LOG(INFO) << codePtr << ": 0x"
86 << std::hex << static_cast<int>(decoded_instruction->opcode)
Elliott Hughesadb8c672012-03-06 16:49:32 -080087 << " " << decodedString;
88 }
89 return instruction->SizeInCodeUnits();
buzbee67bf8852011-08-17 17:51:35 -070090}
91
92#define UNKNOWN_TARGET 0xffffffff
93
Elliott Hughesadb8c672012-03-06 16:49:32 -080094inline bool isGoto(MIR* insn) {
95 switch (insn->dalvikInsn.opcode) {
96 case Instruction::GOTO:
97 case Instruction::GOTO_16:
98 case Instruction::GOTO_32:
99 return true;
100 default:
101 return false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700102 }
buzbee67bf8852011-08-17 17:51:35 -0700103}
104
105/*
106 * Identify unconditional branch instructions
107 */
Elliott Hughesadb8c672012-03-06 16:49:32 -0800108inline bool isUnconditionalBranch(MIR* insn) {
109 switch (insn->dalvikInsn.opcode) {
110 case Instruction::RETURN_VOID:
111 case Instruction::RETURN:
112 case Instruction::RETURN_WIDE:
113 case Instruction::RETURN_OBJECT:
114 return true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700115 default:
116 return isGoto(insn);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800117 }
buzbee67bf8852011-08-17 17:51:35 -0700118}
119
120/* Split an existing block from the specified code offset into two */
buzbee31a4a6f2012-02-28 15:36:15 -0800121BasicBlock *splitBlock(CompilationUnit* cUnit, unsigned int codeOffset,
Bill Buzbeea114add2012-05-03 15:00:40 -0700122 BasicBlock* origBlock, BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700123{
Bill Buzbeea114add2012-05-03 15:00:40 -0700124 MIR* insn = origBlock->firstMIRInsn;
125 while (insn) {
126 if (insn->offset == codeOffset) break;
127 insn = insn->next;
128 }
129 if (insn == NULL) {
130 LOG(FATAL) << "Break split failed";
131 }
132 BasicBlock *bottomBlock = oatNewBB(cUnit, kDalvikByteCode,
133 cUnit->numBlocks++);
134 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700135
Bill Buzbeea114add2012-05-03 15:00:40 -0700136 bottomBlock->startOffset = codeOffset;
137 bottomBlock->firstMIRInsn = insn;
138 bottomBlock->lastMIRInsn = origBlock->lastMIRInsn;
buzbee67bf8852011-08-17 17:51:35 -0700139
Bill Buzbeea114add2012-05-03 15:00:40 -0700140 /* Add it to the quick lookup cache */
141 cUnit->blockMap.Put(bottomBlock->startOffset, bottomBlock);
buzbee5b537102012-01-17 17:33:47 -0800142
Bill Buzbeea114add2012-05-03 15:00:40 -0700143 /* Handle the taken path */
144 bottomBlock->taken = origBlock->taken;
145 if (bottomBlock->taken) {
146 origBlock->taken = NULL;
147 oatDeleteGrowableList(bottomBlock->taken->predecessors,
buzbeeba938cb2012-02-03 14:47:55 -0800148 (intptr_t)origBlock);
Bill Buzbeea114add2012-05-03 15:00:40 -0700149 oatInsertGrowableList(cUnit, bottomBlock->taken->predecessors,
150 (intptr_t)bottomBlock);
151 }
152
153 /* Handle the fallthrough path */
154 bottomBlock->needFallThroughBranch = origBlock->needFallThroughBranch;
155 bottomBlock->fallThrough = origBlock->fallThrough;
156 origBlock->fallThrough = bottomBlock;
157 origBlock->needFallThroughBranch = true;
158 oatInsertGrowableList(cUnit, bottomBlock->predecessors,
159 (intptr_t)origBlock);
160 if (bottomBlock->fallThrough) {
161 oatDeleteGrowableList(bottomBlock->fallThrough->predecessors,
162 (intptr_t)origBlock);
163 oatInsertGrowableList(cUnit, bottomBlock->fallThrough->predecessors,
164 (intptr_t)bottomBlock);
165 }
166
167 /* Handle the successor list */
168 if (origBlock->successorBlockList.blockListType != kNotUsed) {
169 bottomBlock->successorBlockList = origBlock->successorBlockList;
170 origBlock->successorBlockList.blockListType = kNotUsed;
171 GrowableListIterator iterator;
172
173 oatGrowableListIteratorInit(&bottomBlock->successorBlockList.blocks,
174 &iterator);
175 while (true) {
176 SuccessorBlockInfo *successorBlockInfo =
177 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
178 if (successorBlockInfo == NULL) break;
179 BasicBlock *bb = successorBlockInfo->block;
180 oatDeleteGrowableList(bb->predecessors, (intptr_t)origBlock);
181 oatInsertGrowableList(cUnit, bb->predecessors, (intptr_t)bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700182 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700183 }
buzbee67bf8852011-08-17 17:51:35 -0700184
Bill Buzbeea114add2012-05-03 15:00:40 -0700185 origBlock->lastMIRInsn = insn->prev;
buzbee67bf8852011-08-17 17:51:35 -0700186
Bill Buzbeea114add2012-05-03 15:00:40 -0700187 insn->prev->next = NULL;
188 insn->prev = NULL;
189 /*
190 * Update the immediate predecessor block pointer so that outgoing edges
191 * can be applied to the proper block.
192 */
193 if (immedPredBlockP) {
194 DCHECK_EQ(*immedPredBlockP, origBlock);
195 *immedPredBlockP = bottomBlock;
196 }
197 return bottomBlock;
buzbee67bf8852011-08-17 17:51:35 -0700198}
199
200/*
201 * Given a code offset, find out the block that starts with it. If the offset
buzbee9ab05de2012-01-18 15:43:48 -0800202 * is in the middle of an existing block, split it into two. If immedPredBlockP
203 * is not non-null and is the block being split, update *immedPredBlockP to
204 * point to the bottom block so that outgoing edges can be set up properly
205 * (by the caller)
buzbee5b537102012-01-17 17:33:47 -0800206 * Utilizes a map for fast lookup of the typical cases.
buzbee67bf8852011-08-17 17:51:35 -0700207 */
buzbee31a4a6f2012-02-28 15:36:15 -0800208BasicBlock *findBlock(CompilationUnit* cUnit, unsigned int codeOffset,
209 bool split, bool create, BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700210{
Bill Buzbeea114add2012-05-03 15:00:40 -0700211 GrowableList* blockList = &cUnit->blockList;
212 BasicBlock* bb;
213 unsigned int i;
214 SafeMap<unsigned int, BasicBlock*>::iterator it;
buzbee67bf8852011-08-17 17:51:35 -0700215
Bill Buzbeea114add2012-05-03 15:00:40 -0700216 it = cUnit->blockMap.find(codeOffset);
217 if (it != cUnit->blockMap.end()) {
218 return it->second;
219 } else if (!create) {
220 return NULL;
221 }
222
223 if (split) {
224 for (i = 0; i < blockList->numUsed; i++) {
225 bb = (BasicBlock *) blockList->elemList[i];
226 if (bb->blockType != kDalvikByteCode) continue;
227 /* Check if a branch jumps into the middle of an existing block */
228 if ((codeOffset > bb->startOffset) && (bb->lastMIRInsn != NULL) &&
229 (codeOffset <= bb->lastMIRInsn->offset)) {
230 BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb,
231 bb == *immedPredBlockP ?
232 immedPredBlockP : NULL);
233 return newBB;
234 }
buzbee5b537102012-01-17 17:33:47 -0800235 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700236 }
buzbee5b537102012-01-17 17:33:47 -0800237
Bill Buzbeea114add2012-05-03 15:00:40 -0700238 /* Create a new one */
239 bb = oatNewBB(cUnit, kDalvikByteCode, cUnit->numBlocks++);
240 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) bb);
241 bb->startOffset = codeOffset;
242 cUnit->blockMap.Put(bb->startOffset, bb);
243 return bb;
buzbee67bf8852011-08-17 17:51:35 -0700244}
245
246/* Dump the CFG into a DOT graph */
247void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix)
248{
Bill Buzbeea114add2012-05-03 15:00:40 -0700249 FILE* file;
250 std::string name(PrettyMethod(cUnit->method_idx, *cUnit->dex_file));
251 char startOffset[80];
252 sprintf(startOffset, "_%x", cUnit->entryBlock->fallThrough->startOffset);
253 char* fileName = (char*) oatNew(cUnit, strlen(dirPrefix) +
254 name.length() + strlen(".dot") + 1,
255 true, kAllocDebugInfo);
256 sprintf(fileName, "%s%s%s.dot", dirPrefix, name.c_str(), startOffset);
buzbee67bf8852011-08-17 17:51:35 -0700257
Bill Buzbeea114add2012-05-03 15:00:40 -0700258 /*
259 * Convert the special characters into a filesystem- and shell-friendly
260 * format.
261 */
262 int i;
263 for (i = strlen(dirPrefix); fileName[i]; i++) {
264 if (fileName[i] == '/') {
265 fileName[i] = '_';
266 } else if (fileName[i] == ';') {
267 fileName[i] = '#';
268 } else if (fileName[i] == '$') {
269 fileName[i] = '+';
270 } else if (fileName[i] == '(' || fileName[i] == ')') {
271 fileName[i] = '@';
272 } else if (fileName[i] == '<' || fileName[i] == '>') {
273 fileName[i] = '=';
buzbee67bf8852011-08-17 17:51:35 -0700274 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700275 }
276 file = fopen(fileName, "w");
277 if (file == NULL) {
278 return;
279 }
280 fprintf(file, "digraph G {\n");
281
282 fprintf(file, " rankdir=TB\n");
283
284 int numReachableBlocks = cUnit->numReachableBlocks;
285 int idx;
286 const GrowableList *blockList = &cUnit->blockList;
287
288 for (idx = 0; idx < numReachableBlocks; idx++) {
289 int blockIdx = cUnit->dfsOrder.elemList[idx];
290 BasicBlock *bb = (BasicBlock *) oatGrowableListGetElement(blockList,
291 blockIdx);
292 if (bb == NULL) break;
293 if (bb->blockType == kEntryBlock) {
294 fprintf(file, " entry [shape=Mdiamond];\n");
295 } else if (bb->blockType == kExitBlock) {
296 fprintf(file, " exit [shape=Mdiamond];\n");
297 } else if (bb->blockType == kDalvikByteCode) {
298 fprintf(file, " block%04x [shape=record,label = \"{ \\\n",
299 bb->startOffset);
300 const MIR *mir;
301 fprintf(file, " {block id %d\\l}%s\\\n", bb->id,
302 bb->firstMIRInsn ? " | " : " ");
303 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
304 fprintf(file, " {%04x %s\\l}%s\\\n", mir->offset,
305 mir->ssaRep ? oatFullDisassembler(cUnit, mir) :
306 Instruction::Name(mir->dalvikInsn.opcode),
307 mir->next ? " | " : " ");
308 }
309 fprintf(file, " }\"];\n\n");
310 } else if (bb->blockType == kExceptionHandling) {
311 char blockName[BLOCK_NAME_LEN];
312
313 oatGetBlockName(bb, blockName);
314 fprintf(file, " %s [shape=invhouse];\n", blockName);
buzbee67bf8852011-08-17 17:51:35 -0700315 }
buzbee67bf8852011-08-17 17:51:35 -0700316
Bill Buzbeea114add2012-05-03 15:00:40 -0700317 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
buzbee67bf8852011-08-17 17:51:35 -0700318
Bill Buzbeea114add2012-05-03 15:00:40 -0700319 if (bb->taken) {
320 oatGetBlockName(bb, blockName1);
321 oatGetBlockName(bb->taken, blockName2);
322 fprintf(file, " %s:s -> %s:n [style=dotted]\n",
323 blockName1, blockName2);
buzbee67bf8852011-08-17 17:51:35 -0700324 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700325 if (bb->fallThrough) {
326 oatGetBlockName(bb, blockName1);
327 oatGetBlockName(bb->fallThrough, blockName2);
328 fprintf(file, " %s:s -> %s:n\n", blockName1, blockName2);
329 }
330
331 if (bb->successorBlockList.blockListType != kNotUsed) {
332 fprintf(file, " succ%04x [shape=%s,label = \"{ \\\n",
333 bb->startOffset,
334 (bb->successorBlockList.blockListType == kCatch) ?
335 "Mrecord" : "record");
336 GrowableListIterator iterator;
337 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
338 &iterator);
339 SuccessorBlockInfo *successorBlockInfo =
340 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
341
342 int succId = 0;
343 while (true) {
344 if (successorBlockInfo == NULL) break;
345
346 BasicBlock *destBlock = successorBlockInfo->block;
347 SuccessorBlockInfo *nextSuccessorBlockInfo =
348 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
349
350 fprintf(file, " {<f%d> %04x: %04x\\l}%s\\\n",
351 succId++,
352 successorBlockInfo->key,
353 destBlock->startOffset,
354 (nextSuccessorBlockInfo != NULL) ? " | " : " ");
355
356 successorBlockInfo = nextSuccessorBlockInfo;
357 }
358 fprintf(file, " }\"];\n\n");
359
360 oatGetBlockName(bb, blockName1);
361 fprintf(file, " %s:s -> succ%04x:n [style=dashed]\n",
362 blockName1, bb->startOffset);
363
364 if (bb->successorBlockList.blockListType == kPackedSwitch ||
365 bb->successorBlockList.blockListType == kSparseSwitch) {
366
367 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
368 &iterator);
369
370 succId = 0;
371 while (true) {
372 SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
373 oatGrowableListIteratorNext(&iterator);
374 if (successorBlockInfo == NULL) break;
375
376 BasicBlock *destBlock = successorBlockInfo->block;
377
378 oatGetBlockName(destBlock, blockName2);
379 fprintf(file, " succ%04x:f%d:e -> %s:n\n", bb->startOffset,
380 succId++, blockName2);
381 }
382 }
383 }
384 fprintf(file, "\n");
385
386 /* Display the dominator tree */
387 oatGetBlockName(bb, blockName1);
388 fprintf(file, " cfg%s [label=\"%s\", shape=none];\n",
389 blockName1, blockName1);
390 if (bb->iDom) {
391 oatGetBlockName(bb->iDom, blockName2);
392 fprintf(file, " cfg%s:s -> cfg%s:n\n\n", blockName2, blockName1);
393 }
394 }
395 fprintf(file, "}\n");
396 fclose(file);
buzbee67bf8852011-08-17 17:51:35 -0700397}
398
399/* Verify if all the successor is connected with all the claimed predecessors */
buzbee31a4a6f2012-02-28 15:36:15 -0800400bool verifyPredInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700401{
Bill Buzbeea114add2012-05-03 15:00:40 -0700402 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700403
Bill Buzbeea114add2012-05-03 15:00:40 -0700404 oatGrowableListIteratorInit(bb->predecessors, &iter);
405 while (true) {
406 BasicBlock *predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
407 if (!predBB) break;
408 bool found = false;
409 if (predBB->taken == bb) {
410 found = true;
411 } else if (predBB->fallThrough == bb) {
412 found = true;
413 } else if (predBB->successorBlockList.blockListType != kNotUsed) {
414 GrowableListIterator iterator;
415 oatGrowableListIteratorInit(&predBB->successorBlockList.blocks,
416 &iterator);
417 while (true) {
418 SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
419 oatGrowableListIteratorNext(&iterator);
420 if (successorBlockInfo == NULL) break;
421 BasicBlock *succBB = successorBlockInfo->block;
422 if (succBB == bb) {
buzbee67bf8852011-08-17 17:51:35 -0700423 found = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700424 break;
buzbee67bf8852011-08-17 17:51:35 -0700425 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700426 }
buzbee67bf8852011-08-17 17:51:35 -0700427 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700428 if (found == false) {
429 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
430 oatGetBlockName(bb, blockName1);
431 oatGetBlockName(predBB, blockName2);
432 oatDumpCFG(cUnit, "/sdcard/cfg/");
433 LOG(FATAL) << "Successor " << blockName1 << "not found from "
434 << blockName2;
435 }
436 }
437 return true;
buzbee67bf8852011-08-17 17:51:35 -0700438}
439
440/* Identify code range in try blocks and set up the empty catch blocks */
buzbee31a4a6f2012-02-28 15:36:15 -0800441void processTryCatchBlocks(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700442{
Bill Buzbeea114add2012-05-03 15:00:40 -0700443 const DexFile::CodeItem* code_item = cUnit->code_item;
444 int triesSize = code_item->tries_size_;
445 int offset;
buzbee67bf8852011-08-17 17:51:35 -0700446
Bill Buzbeea114add2012-05-03 15:00:40 -0700447 if (triesSize == 0) {
448 return;
449 }
450
451 ArenaBitVector* tryBlockAddr = cUnit->tryBlockAddr;
452
453 for (int i = 0; i < triesSize; i++) {
454 const DexFile::TryItem* pTry =
455 DexFile::GetTryItems(*code_item, i);
456 int startOffset = pTry->start_addr_;
457 int endOffset = startOffset + pTry->insn_count_;
458 for (offset = startOffset; offset < endOffset; offset++) {
459 oatSetBit(cUnit, tryBlockAddr, offset);
buzbee67bf8852011-08-17 17:51:35 -0700460 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700461 }
buzbee67bf8852011-08-17 17:51:35 -0700462
Bill Buzbeea114add2012-05-03 15:00:40 -0700463 // Iterate over each of the handlers to enqueue the empty Catch blocks
464 const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item, 0);
465 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
466 for (uint32_t idx = 0; idx < handlers_size; idx++) {
467 CatchHandlerIterator iterator(handlers_ptr);
468 for (; iterator.HasNext(); iterator.Next()) {
469 uint32_t address = iterator.GetHandlerAddress();
470 findBlock(cUnit, address, false /* split */, true /*create*/,
471 /* immedPredBlockP */ NULL);
buzbee67bf8852011-08-17 17:51:35 -0700472 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700473 handlers_ptr = iterator.EndDataPointer();
474 }
buzbee67bf8852011-08-17 17:51:35 -0700475}
476
Elliott Hughesadb8c672012-03-06 16:49:32 -0800477/* Process instructions with the kBranch flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800478BasicBlock* processCanBranch(CompilationUnit* cUnit, BasicBlock* curBlock,
Bill Buzbeea114add2012-05-03 15:00:40 -0700479 MIR* insn, int curOffset, int width, int flags,
480 const u2* codePtr, const u2* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700481{
Bill Buzbeea114add2012-05-03 15:00:40 -0700482 int target = curOffset;
483 switch (insn->dalvikInsn.opcode) {
484 case Instruction::GOTO:
485 case Instruction::GOTO_16:
486 case Instruction::GOTO_32:
487 target += (int) insn->dalvikInsn.vA;
488 break;
489 case Instruction::IF_EQ:
490 case Instruction::IF_NE:
491 case Instruction::IF_LT:
492 case Instruction::IF_GE:
493 case Instruction::IF_GT:
494 case Instruction::IF_LE:
495 target += (int) insn->dalvikInsn.vC;
496 break;
497 case Instruction::IF_EQZ:
498 case Instruction::IF_NEZ:
499 case Instruction::IF_LTZ:
500 case Instruction::IF_GEZ:
501 case Instruction::IF_GTZ:
502 case Instruction::IF_LEZ:
503 target += (int) insn->dalvikInsn.vB;
504 break;
505 default:
506 LOG(FATAL) << "Unexpected opcode(" << (int)insn->dalvikInsn.opcode
507 << ") with kBranch set";
508 }
509 BasicBlock *takenBlock = findBlock(cUnit, target,
510 /* split */
511 true,
512 /* create */
513 true,
514 /* immedPredBlockP */
515 &curBlock);
516 curBlock->taken = takenBlock;
517 oatInsertGrowableList(cUnit, takenBlock->predecessors, (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700518
Bill Buzbeea114add2012-05-03 15:00:40 -0700519 /* Always terminate the current block for conditional branches */
520 if (flags & Instruction::kContinue) {
521 BasicBlock *fallthroughBlock = findBlock(cUnit,
522 curOffset + width,
523 /*
524 * If the method is processed
525 * in sequential order from the
526 * beginning, we don't need to
527 * specify split for continue
528 * blocks. However, this
529 * routine can be called by
530 * compileLoop, which starts
531 * parsing the method from an
532 * arbitrary address in the
533 * method body.
534 */
535 true,
536 /* create */
537 true,
538 /* immedPredBlockP */
539 &curBlock);
540 curBlock->fallThrough = fallthroughBlock;
541 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
542 (intptr_t)curBlock);
543 } else if (codePtr < codeEnd) {
544 /* Create a fallthrough block for real instructions (incl. NOP) */
545 if (contentIsInsn(codePtr)) {
546 findBlock(cUnit, curOffset + width,
547 /* split */
548 false,
549 /* create */
550 true,
551 /* immedPredBlockP */
552 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700553 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700554 }
555 return curBlock;
buzbee67bf8852011-08-17 17:51:35 -0700556}
557
Elliott Hughesadb8c672012-03-06 16:49:32 -0800558/* Process instructions with the kSwitch flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800559void processCanSwitch(CompilationUnit* cUnit, BasicBlock* curBlock,
560 MIR* insn, int curOffset, int width, int flags)
buzbee67bf8852011-08-17 17:51:35 -0700561{
Bill Buzbeea114add2012-05-03 15:00:40 -0700562 u2* switchData= (u2 *) (cUnit->insns + curOffset + insn->dalvikInsn.vB);
563 int size;
564 int* keyTable;
565 int* targetTable;
566 int i;
567 int firstKey;
buzbee67bf8852011-08-17 17:51:35 -0700568
Bill Buzbeea114add2012-05-03 15:00:40 -0700569 /*
570 * Packed switch data format:
571 * ushort ident = 0x0100 magic value
572 * ushort size number of entries in the table
573 * int first_key first (and lowest) switch case value
574 * int targets[size] branch targets, relative to switch opcode
575 *
576 * Total size is (4+size*2) 16-bit code units.
577 */
578 if (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) {
579 DCHECK_EQ(static_cast<int>(switchData[0]),
580 static_cast<int>(Instruction::kPackedSwitchSignature));
581 size = switchData[1];
582 firstKey = switchData[2] | (switchData[3] << 16);
583 targetTable = (int *) &switchData[4];
584 keyTable = NULL; // Make the compiler happy
585 /*
586 * Sparse switch data format:
587 * ushort ident = 0x0200 magic value
588 * ushort size number of entries in the table; > 0
589 * int keys[size] keys, sorted low-to-high; 32-bit aligned
590 * int targets[size] branch targets, relative to switch opcode
591 *
592 * Total size is (2+size*4) 16-bit code units.
593 */
594 } else {
595 DCHECK_EQ(static_cast<int>(switchData[0]),
596 static_cast<int>(Instruction::kSparseSwitchSignature));
597 size = switchData[1];
598 keyTable = (int *) &switchData[2];
599 targetTable = (int *) &switchData[2 + size*2];
600 firstKey = 0; // To make the compiler happy
601 }
buzbee67bf8852011-08-17 17:51:35 -0700602
Bill Buzbeea114add2012-05-03 15:00:40 -0700603 if (curBlock->successorBlockList.blockListType != kNotUsed) {
604 LOG(FATAL) << "Successor block list already in use: "
605 << (int)curBlock->successorBlockList.blockListType;
606 }
607 curBlock->successorBlockList.blockListType =
608 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
609 kPackedSwitch : kSparseSwitch;
610 oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, size,
611 kListSuccessorBlocks);
612
613 for (i = 0; i < size; i++) {
614 BasicBlock *caseBlock = findBlock(cUnit, curOffset + targetTable[i],
615 /* split */
616 true,
617 /* create */
618 true,
619 /* immedPredBlockP */
620 &curBlock);
621 SuccessorBlockInfo *successorBlockInfo =
622 (SuccessorBlockInfo *) oatNew(cUnit, sizeof(SuccessorBlockInfo),
623 false, kAllocSuccessor);
624 successorBlockInfo->block = caseBlock;
625 successorBlockInfo->key =
Elliott Hughesadb8c672012-03-06 16:49:32 -0800626 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
Bill Buzbeea114add2012-05-03 15:00:40 -0700627 firstKey + i : keyTable[i];
628 oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
629 (intptr_t) successorBlockInfo);
630 oatInsertGrowableList(cUnit, caseBlock->predecessors,
buzbeeba938cb2012-02-03 14:47:55 -0800631 (intptr_t)curBlock);
Bill Buzbeea114add2012-05-03 15:00:40 -0700632 }
633
634 /* Fall-through case */
635 BasicBlock* fallthroughBlock = findBlock(cUnit,
636 curOffset + width,
637 /* split */
638 false,
639 /* create */
640 true,
641 /* immedPredBlockP */
642 NULL);
643 curBlock->fallThrough = fallthroughBlock;
644 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
645 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700646}
647
Elliott Hughesadb8c672012-03-06 16:49:32 -0800648/* Process instructions with the kThrow flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800649void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock, MIR* insn,
650 int curOffset, int width, int flags,
651 ArenaBitVector* tryBlockAddr, const u2* codePtr,
652 const u2* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700653{
Bill Buzbeea114add2012-05-03 15:00:40 -0700654 const DexFile::CodeItem* code_item = cUnit->code_item;
buzbee67bf8852011-08-17 17:51:35 -0700655
Bill Buzbeea114add2012-05-03 15:00:40 -0700656 /* In try block */
657 if (oatIsBitSet(tryBlockAddr, curOffset)) {
658 CatchHandlerIterator iterator(*code_item, curOffset);
buzbee67bf8852011-08-17 17:51:35 -0700659
Bill Buzbeea114add2012-05-03 15:00:40 -0700660 if (curBlock->successorBlockList.blockListType != kNotUsed) {
661 LOG(FATAL) << "Successor block list already in use: "
662 << (int)curBlock->successorBlockList.blockListType;
buzbee67bf8852011-08-17 17:51:35 -0700663 }
664
Bill Buzbeea114add2012-05-03 15:00:40 -0700665 curBlock->successorBlockList.blockListType = kCatch;
666 oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, 2,
667 kListSuccessorBlocks);
668
669 for (;iterator.HasNext(); iterator.Next()) {
670 BasicBlock *catchBlock = findBlock(cUnit, iterator.GetHandlerAddress(),
671 false /* split*/,
672 false /* creat */,
673 NULL /* immedPredBlockP */);
674 catchBlock->catchEntry = true;
675 SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
676 oatNew(cUnit, sizeof(SuccessorBlockInfo), false, kAllocSuccessor);
677 successorBlockInfo->block = catchBlock;
678 successorBlockInfo->key = iterator.GetHandlerTypeIndex();
679 oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
680 (intptr_t) successorBlockInfo);
681 oatInsertGrowableList(cUnit, catchBlock->predecessors,
682 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700683 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700684 } else {
685 BasicBlock *ehBlock = oatNewBB(cUnit, kExceptionHandling,
686 cUnit->numBlocks++);
687 curBlock->taken = ehBlock;
688 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) ehBlock);
689 ehBlock->startOffset = curOffset;
690 oatInsertGrowableList(cUnit, ehBlock->predecessors, (intptr_t)curBlock);
691 }
692
693 /*
694 * Force the current block to terminate.
695 *
696 * Data may be present before codeEnd, so we need to parse it to know
697 * whether it is code or data.
698 */
699 if (codePtr < codeEnd) {
700 /* Create a fallthrough block for real instructions (incl. NOP) */
701 if (contentIsInsn(codePtr)) {
702 BasicBlock *fallthroughBlock = findBlock(cUnit,
703 curOffset + width,
704 /* split */
705 false,
706 /* create */
707 true,
708 /* immedPredBlockP */
709 NULL);
710 /*
711 * THROW is an unconditional branch. NOTE:
712 * THROW_VERIFICATION_ERROR is also an unconditional
713 * branch, but we shouldn't treat it as such until we have
714 * a dead code elimination pass (which won't be important
715 * until inlining w/ constant propogation is implemented.
716 */
717 if (insn->dalvikInsn.opcode != Instruction::THROW) {
718 curBlock->fallThrough = fallthroughBlock;
719 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
720 (intptr_t)curBlock);
721 }
722 }
723 }
buzbee67bf8852011-08-17 17:51:35 -0700724}
725
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800726void oatInit(CompilationUnit* cUnit, const Compiler& compiler) {
727 if (!oatArchInit()) {
728 LOG(FATAL) << "Failed to initialize oat";
729 }
730 if (!oatHeapInit(cUnit)) {
731 LOG(FATAL) << "Failed to initialize oat heap";
732 }
733}
734
Elliott Hughes3fa1b7e2012-03-13 17:06:22 -0700735CompiledMethod* oatCompileMethod(Compiler& compiler,
736 const DexFile::CodeItem* code_item,
737 uint32_t access_flags, uint32_t method_idx,
738 const ClassLoader* class_loader,
739 const DexFile& dex_file)
buzbee67bf8852011-08-17 17:51:35 -0700740{
Bill Buzbeea114add2012-05-03 15:00:40 -0700741 VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
Brian Carlstrom94496d32011-08-22 09:22:47 -0700742
Bill Buzbeea114add2012-05-03 15:00:40 -0700743 const u2* codePtr = code_item->insns_;
744 const u2* codeEnd = code_item->insns_ + code_item->insns_size_in_code_units_;
745 int numBlocks = 0;
746 unsigned int curOffset = 0;
buzbee67bf8852011-08-17 17:51:35 -0700747
Bill Buzbeea114add2012-05-03 15:00:40 -0700748 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
749 UniquePtr<CompilationUnit> cUnit(new CompilationUnit);
buzbeeba938cb2012-02-03 14:47:55 -0800750
Bill Buzbeea114add2012-05-03 15:00:40 -0700751 oatInit(cUnit.get(), compiler);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800752
Bill Buzbeea114add2012-05-03 15:00:40 -0700753 cUnit->compiler = &compiler;
754 cUnit->class_linker = class_linker;
755 cUnit->dex_file = &dex_file;
756 cUnit->dex_cache = class_linker->FindDexCache(dex_file);
757 cUnit->method_idx = method_idx;
758 cUnit->code_item = code_item;
759 cUnit->access_flags = access_flags;
760 cUnit->shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
761 cUnit->instructionSet = compiler.GetInstructionSet();
762 cUnit->insns = code_item->insns_;
763 cUnit->insnsSize = code_item->insns_size_in_code_units_;
764 cUnit->numIns = code_item->ins_size_;
765 cUnit->numRegs = code_item->registers_size_ - cUnit->numIns;
766 cUnit->numOuts = code_item->outs_size_;
767 /* Adjust this value accordingly once inlining is performed */
768 cUnit->numDalvikRegisters = code_item->registers_size_;
769 // TODO: set this from command line
770 cUnit->compilerFlipMatch = false;
771 bool useMatch = !cUnit->compilerMethodMatch.empty();
772 bool match = useMatch && (cUnit->compilerFlipMatch ^
773 (PrettyMethod(method_idx, dex_file).find(cUnit->compilerMethodMatch) !=
774 std::string::npos));
775 if (!useMatch || match) {
776 cUnit->disableOpt = kCompilerOptimizerDisableFlags;
777 cUnit->enableDebug = kCompilerDebugFlags;
778 cUnit->printMe = VLOG_IS_ON(compiler) ||
779 (cUnit->enableDebug & (1 << kDebugVerbose));
780 }
781 if (cUnit->instructionSet == kX86) {
782 // Disable optimizations on X86 for now
783 cUnit->disableOpt = -1;
784 }
785 /* Are we generating code for the debugger? */
786 if (compiler.IsDebuggingSupported()) {
787 cUnit->genDebugger = true;
788 // Yes, disable most optimizations
789 cUnit->disableOpt |= (
790 (1 << kLoadStoreElimination) |
791 (1 << kLoadHoisting) |
792 (1 << kSuppressLoads) |
793 (1 << kPromoteRegs) |
794 (1 << kBBOpt) |
795 (1 << kMatch) |
796 (1 << kTrackLiveTemps));
797 }
798
799 /* Gathering opcode stats? */
800 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
801 cUnit->opcodeCount = (int*)oatNew(cUnit.get(),
802 kNumPackedOpcodes * sizeof(int), true, kAllocMisc);
803 }
804
805 /* Assume non-throwing leaf */
806 cUnit->attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE);
807
808 /* Initialize the block list, estimate size based on insnsSize */
809 oatInitGrowableList(cUnit.get(), &cUnit->blockList, cUnit->insnsSize,
810 kListBlockList);
811
812 /* Initialize the switchTables list */
813 oatInitGrowableList(cUnit.get(), &cUnit->switchTables, 4,
814 kListSwitchTables);
815
816 /* Intialize the fillArrayData list */
817 oatInitGrowableList(cUnit.get(), &cUnit->fillArrayData, 4,
818 kListFillArrayData);
819
820 /* Intialize the throwLaunchpads list, estimate size based on insnsSize */
821 oatInitGrowableList(cUnit.get(), &cUnit->throwLaunchpads, cUnit->insnsSize,
822 kListThrowLaunchPads);
823
824 /* Intialize the instrinsicLaunchpads list */
825 oatInitGrowableList(cUnit.get(), &cUnit->intrinsicLaunchpads, 4,
826 kListMisc);
827
828
829 /* Intialize the suspendLaunchpads list */
830 oatInitGrowableList(cUnit.get(), &cUnit->suspendLaunchpads, 2048,
831 kListSuspendLaunchPads);
832
833 /* Allocate the bit-vector to track the beginning of basic blocks */
834 ArenaBitVector *tryBlockAddr = oatAllocBitVector(cUnit.get(),
835 cUnit->insnsSize,
836 true /* expandable */);
837 cUnit->tryBlockAddr = tryBlockAddr;
838
839 /* Create the default entry and exit blocks and enter them to the list */
840 BasicBlock *entryBlock = oatNewBB(cUnit.get(), kEntryBlock, numBlocks++);
841 BasicBlock *exitBlock = oatNewBB(cUnit.get(), kExitBlock, numBlocks++);
842
843 cUnit->entryBlock = entryBlock;
844 cUnit->exitBlock = exitBlock;
845
846 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) entryBlock);
847 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) exitBlock);
848
849 /* Current block to record parsed instructions */
850 BasicBlock *curBlock = oatNewBB(cUnit.get(), kDalvikByteCode, numBlocks++);
851 curBlock->startOffset = 0;
852 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) curBlock);
853 /* Add first block to the fast lookup cache */
854 cUnit->blockMap.Put(curBlock->startOffset, curBlock);
855 entryBlock->fallThrough = curBlock;
856 oatInsertGrowableList(cUnit.get(), curBlock->predecessors,
857 (intptr_t)entryBlock);
858
859 /*
860 * Store back the number of blocks since new blocks may be created of
861 * accessing cUnit.
862 */
863 cUnit->numBlocks = numBlocks;
864
865 /* Identify code range in try blocks and set up the empty catch blocks */
866 processTryCatchBlocks(cUnit.get());
867
868 /* Set up for simple method detection */
869 int numPatterns = sizeof(specialPatterns)/sizeof(specialPatterns[0]);
870 bool livePattern = (numPatterns > 0) && !(cUnit->disableOpt & (1 << kMatch));
871 bool* deadPattern = (bool*)oatNew(cUnit.get(), sizeof(bool) * numPatterns,
872 kAllocMisc);
873 SpecialCaseHandler specialCase = kNoHandler;
874 int patternPos = 0;
875
876 /* Parse all instructions and put them into containing basic blocks */
877 while (codePtr < codeEnd) {
878 MIR *insn = (MIR *) oatNew(cUnit.get(), sizeof(MIR), true, kAllocMIR);
879 insn->offset = curOffset;
880 int width = parseInsn(cUnit.get(), codePtr, &insn->dalvikInsn, false);
881 insn->width = width;
882 Instruction::Code opcode = insn->dalvikInsn.opcode;
883 if (cUnit->opcodeCount != NULL) {
884 cUnit->opcodeCount[static_cast<int>(opcode)]++;
buzbee44b412b2012-02-04 08:50:53 -0800885 }
886
Bill Buzbeea114add2012-05-03 15:00:40 -0700887 /* Terminate when the data section is seen */
888 if (width == 0)
889 break;
890
891 /* Possible simple method? */
892 if (livePattern) {
893 livePattern = false;
894 specialCase = kNoHandler;
895 for (int i = 0; i < numPatterns; i++) {
896 if (!deadPattern[i]) {
897 if (specialPatterns[i].opcodes[patternPos] == opcode) {
898 livePattern = true;
899 specialCase = specialPatterns[i].handlerCode;
900 } else {
901 deadPattern[i] = true;
902 }
903 }
904 }
905 patternPos++;
buzbeea7c12682012-03-19 13:13:53 -0700906 }
907
Bill Buzbeea114add2012-05-03 15:00:40 -0700908 oatAppendMIR(curBlock, insn);
buzbeecefd1872011-09-09 09:59:52 -0700909
Bill Buzbeea114add2012-05-03 15:00:40 -0700910 codePtr += width;
911 int flags = Instruction::Flags(insn->dalvikInsn.opcode);
buzbee67bf8852011-08-17 17:51:35 -0700912
Bill Buzbeea114add2012-05-03 15:00:40 -0700913 int dfFlags = oatDataFlowAttributes[insn->dalvikInsn.opcode];
buzbee67bf8852011-08-17 17:51:35 -0700914
Bill Buzbeea114add2012-05-03 15:00:40 -0700915 if (dfFlags & DF_HAS_DEFS) {
916 cUnit->defCount += (dfFlags & DF_DA_WIDE) ? 2 : 1;
917 }
buzbee67bf8852011-08-17 17:51:35 -0700918
Bill Buzbeea114add2012-05-03 15:00:40 -0700919 if (flags & Instruction::kBranch) {
920 curBlock = processCanBranch(cUnit.get(), curBlock, insn, curOffset,
921 width, flags, codePtr, codeEnd);
922 } else if (flags & Instruction::kReturn) {
923 curBlock->fallThrough = exitBlock;
924 oatInsertGrowableList(cUnit.get(), exitBlock->predecessors,
925 (intptr_t)curBlock);
926 /*
927 * Terminate the current block if there are instructions
928 * afterwards.
929 */
930 if (codePtr < codeEnd) {
931 /*
932 * Create a fallthrough block for real instructions
933 * (incl. NOP).
934 */
935 if (contentIsInsn(codePtr)) {
936 findBlock(cUnit.get(), curOffset + width,
937 /* split */
938 false,
939 /* create */
940 true,
941 /* immedPredBlockP */
942 NULL);
943 }
944 }
945 } else if (flags & Instruction::kThrow) {
946 processCanThrow(cUnit.get(), curBlock, insn, curOffset, width, flags,
947 tryBlockAddr, codePtr, codeEnd);
948 } else if (flags & Instruction::kSwitch) {
949 processCanSwitch(cUnit.get(), curBlock, insn, curOffset, width, flags);
950 }
951 curOffset += width;
952 BasicBlock *nextBlock = findBlock(cUnit.get(), curOffset,
953 /* split */
954 false,
955 /* create */
956 false,
957 /* immedPredBlockP */
958 NULL);
959 if (nextBlock) {
960 /*
961 * The next instruction could be the target of a previously parsed
962 * forward branch so a block is already created. If the current
963 * instruction is not an unconditional branch, connect them through
964 * the fall-through link.
965 */
966 DCHECK(curBlock->fallThrough == NULL ||
967 curBlock->fallThrough == nextBlock ||
968 curBlock->fallThrough == exitBlock);
buzbee5ade1d22011-09-09 14:44:52 -0700969
Bill Buzbeea114add2012-05-03 15:00:40 -0700970 if ((curBlock->fallThrough == NULL) && (flags & Instruction::kContinue)) {
971 curBlock->fallThrough = nextBlock;
972 oatInsertGrowableList(cUnit.get(), nextBlock->predecessors,
973 (intptr_t)curBlock);
974 }
975 curBlock = nextBlock;
976 }
977 }
buzbeefc9e6fa2012-03-23 15:14:29 -0700978
Bill Buzbeea114add2012-05-03 15:00:40 -0700979 if (!(cUnit->disableOpt & (1 << kSkipLargeMethodOptimization))) {
980 if ((cUnit->numBlocks > MANY_BLOCKS) ||
981 ((cUnit->numBlocks > MANY_BLOCKS_INITIALIZER) &&
982 PrettyMethod(method_idx, dex_file, false).find("init>") !=
983 std::string::npos)) {
984 cUnit->qdMode = true;
985 }
986 }
buzbeefc9e6fa2012-03-23 15:14:29 -0700987
Bill Buzbeea114add2012-05-03 15:00:40 -0700988 if (cUnit->qdMode) {
989 cUnit->disableDataflow = true;
990 // Disable optimization which require dataflow/ssa
991 cUnit->disableOpt |=
992 (1 << kNullCheckElimination) |
993 (1 << kBBOpt) |
994 (1 << kPromoteRegs);
995 if (cUnit->printMe) {
996 LOG(INFO) << "QD mode enabled: "
997 << PrettyMethod(method_idx, dex_file)
998 << " too big: " << cUnit->numBlocks;
999 }
1000 }
buzbeec1f45042011-09-21 16:03:19 -07001001
Bill Buzbeea114add2012-05-03 15:00:40 -07001002 if (cUnit->printMe) {
1003 oatDumpCompilationUnit(cUnit.get());
1004 }
buzbee67bf8852011-08-17 17:51:35 -07001005
Bill Buzbeea114add2012-05-03 15:00:40 -07001006 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
1007 /* Verify if all blocks are connected as claimed */
1008 oatDataFlowAnalysisDispatcher(cUnit.get(), verifyPredInfo, kAllNodes,
1009 false /* isIterative */);
1010 }
buzbee67bf8852011-08-17 17:51:35 -07001011
Bill Buzbeea114add2012-05-03 15:00:40 -07001012 /* Perform SSA transformation for the whole method */
1013 oatMethodSSATransformation(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001014
Bill Buzbeea114add2012-05-03 15:00:40 -07001015 /* Detect loops */
1016 oatMethodLoopDetection(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001017
Bill Buzbeea114add2012-05-03 15:00:40 -07001018 /* Count uses */
1019 oatMethodUseCount(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001020
Bill Buzbeea114add2012-05-03 15:00:40 -07001021 /* Perform null check elimination */
1022 oatMethodNullCheckElimination(cUnit.get());
1023
1024 /* Do some basic block optimizations */
1025 oatMethodBasicBlockOptimization(cUnit.get());
1026
1027 oatInitializeRegAlloc(cUnit.get()); // Needs to happen after SSA naming
1028
1029 /* Allocate Registers using simple local allocation scheme */
1030 oatSimpleRegAlloc(cUnit.get());
1031
1032 if (specialCase != kNoHandler) {
buzbee67bf8852011-08-17 17:51:35 -07001033 /*
Bill Buzbeea114add2012-05-03 15:00:40 -07001034 * Custom codegen for special cases. If for any reason the
1035 * special codegen doesn't success, cUnit->firstLIRInsn will
1036 * set to NULL;
buzbee67bf8852011-08-17 17:51:35 -07001037 */
Bill Buzbeea114add2012-05-03 15:00:40 -07001038 oatSpecialMIR2LIR(cUnit.get(), specialCase);
1039 }
buzbee67bf8852011-08-17 17:51:35 -07001040
Bill Buzbeea114add2012-05-03 15:00:40 -07001041 /* Convert MIR to LIR, etc. */
1042 if (cUnit->firstLIRInsn == NULL) {
1043 oatMethodMIR2LIR(cUnit.get());
1044 }
buzbee67bf8852011-08-17 17:51:35 -07001045
Bill Buzbeea114add2012-05-03 15:00:40 -07001046 // Debugging only
1047 if (cUnit->enableDebug & (1 << kDebugDumpCFG)) {
1048 oatDumpCFG(cUnit.get(), "/sdcard/cfg/");
1049 }
buzbee16da88c2012-03-20 10:38:17 -07001050
Bill Buzbeea114add2012-05-03 15:00:40 -07001051 /* Method is not empty */
1052 if (cUnit->firstLIRInsn) {
buzbee67bf8852011-08-17 17:51:35 -07001053
Bill Buzbeea114add2012-05-03 15:00:40 -07001054 // mark the targets of switch statement case labels
1055 oatProcessSwitchTables(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001056
Bill Buzbeea114add2012-05-03 15:00:40 -07001057 /* Convert LIR into machine code. */
1058 oatAssembleLIR(cUnit.get());
buzbee99ba9642012-01-25 14:23:14 -08001059
Elliott Hughes3b6baaa2011-10-14 19:13:56 -07001060 if (cUnit->printMe) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001061 oatCodegenDump(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001062 }
1063
Bill Buzbeea114add2012-05-03 15:00:40 -07001064 if (cUnit->opcodeCount != NULL) {
1065 LOG(INFO) << "Opcode Count";
1066 for (int i = 0; i < kNumPackedOpcodes; i++) {
1067 if (cUnit->opcodeCount[i] != 0) {
1068 LOG(INFO) << "-C- "
1069 << Instruction::Name(static_cast<Instruction::Code>(i))
1070 << " " << cUnit->opcodeCount[i];
buzbee67bf8852011-08-17 17:51:35 -07001071 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001072 }
1073 }
1074 }
buzbeea7c12682012-03-19 13:13:53 -07001075
Bill Buzbeea114add2012-05-03 15:00:40 -07001076 // Combine vmap tables - core regs, then fp regs - into vmapTable
1077 std::vector<uint16_t> vmapTable;
1078 for (size_t i = 0 ; i < cUnit->coreVmapTable.size(); i++) {
1079 vmapTable.push_back(cUnit->coreVmapTable[i]);
1080 }
1081 // If we have a frame, push a marker to take place of lr
1082 if (cUnit->frameSize > 0) {
1083 vmapTable.push_back(INVALID_VREG);
1084 } else {
1085 DCHECK_EQ(__builtin_popcount(cUnit->coreSpillMask), 0);
1086 DCHECK_EQ(__builtin_popcount(cUnit->fpSpillMask), 0);
1087 }
1088 // Combine vmap tables - core regs, then fp regs
1089 for (uint32_t i = 0; i < cUnit->fpVmapTable.size(); i++) {
1090 vmapTable.push_back(cUnit->fpVmapTable[i]);
1091 }
1092 CompiledMethod* result =
1093 new CompiledMethod(cUnit->instructionSet, cUnit->codeBuffer,
1094 cUnit->frameSize, cUnit->coreSpillMask,
1095 cUnit->fpSpillMask, cUnit->mappingTable, vmapTable);
buzbee67bf8852011-08-17 17:51:35 -07001096
Bill Buzbeea114add2012-05-03 15:00:40 -07001097 VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file)
1098 << " (" << (cUnit->codeBuffer.size() * sizeof(cUnit->codeBuffer[0]))
1099 << " bytes)";
buzbee5abfa3e2012-01-31 17:01:43 -08001100
1101#ifdef WITH_MEMSTATS
Bill Buzbeea114add2012-05-03 15:00:40 -07001102 if (cUnit->enableDebug & (1 << kDebugShowMemoryUsage)) {
1103 oatDumpMemStats(cUnit.get());
1104 }
buzbee5abfa3e2012-01-31 17:01:43 -08001105#endif
buzbee67bf8852011-08-17 17:51:35 -07001106
Bill Buzbeea114add2012-05-03 15:00:40 -07001107 oatArenaReset(cUnit.get());
buzbeeba938cb2012-02-03 14:47:55 -08001108
Bill Buzbeea114add2012-05-03 15:00:40 -07001109 return result;
buzbee67bf8852011-08-17 17:51:35 -07001110}
1111
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001112} // namespace art
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001113
Bill Buzbeea114add2012-05-03 15:00:40 -07001114extern "C" art::CompiledMethod*
1115 ArtCompileMethod(art::Compiler& compiler,
1116 const art::DexFile::CodeItem* code_item,
1117 uint32_t access_flags, uint32_t method_idx,
1118 const art::ClassLoader* class_loader,
1119 const art::DexFile& dex_file)
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001120{
1121 CHECK_EQ(compiler.GetInstructionSet(), art::oatInstructionSet());
Bill Buzbeea114add2012-05-03 15:00:40 -07001122 return art::oatCompileMethod(compiler, code_item, access_flags, method_idx,
1123 class_loader, dex_file);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001124}