blob: 3c579c40648ae24c726f54d305aa52d9da27dd29 [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) |
buzbeead8f15e2012-06-18 14:49:45 -070055#if defined(ART_USE_QUICK_COMPILER)
56 //(1 << kDebugDumpBitcodeFile) |
Bill Buzbeec9f40dd2012-08-15 11:35:25 -070057 //(1 << kDebugVerifyBitcode) |
buzbeead8f15e2012-06-18 14:49:45 -070058#endif
Bill Buzbeea114add2012-05-03 15:00:40 -070059 0;
buzbeece302932011-10-04 14:32:18 -070060
buzbee31a4a6f2012-02-28 15:36:15 -080061inline bool contentIsInsn(const u2* codePtr) {
Bill Buzbeea114add2012-05-03 15:00:40 -070062 u2 instr = *codePtr;
63 Instruction::Code opcode = (Instruction::Code)(instr & 0xff);
buzbee67bf8852011-08-17 17:51:35 -070064
Bill Buzbeea114add2012-05-03 15:00:40 -070065 /*
66 * Since the low 8-bit in metadata may look like NOP, we need to check
67 * both the low and whole sub-word to determine whether it is code or data.
68 */
69 return (opcode != Instruction::NOP || instr == 0);
buzbee67bf8852011-08-17 17:51:35 -070070}
71
72/*
73 * Parse an instruction, return the length of the instruction
74 */
buzbee31a4a6f2012-02-28 15:36:15 -080075inline int parseInsn(CompilationUnit* cUnit, const u2* codePtr,
Bill Buzbeea114add2012-05-03 15:00:40 -070076 DecodedInstruction* decoded_instruction, bool printMe)
buzbee67bf8852011-08-17 17:51:35 -070077{
Elliott Hughesadb8c672012-03-06 16:49:32 -080078 // Don't parse instruction data
79 if (!contentIsInsn(codePtr)) {
80 return 0;
81 }
buzbee67bf8852011-08-17 17:51:35 -070082
Elliott Hughesadb8c672012-03-06 16:49:32 -080083 const Instruction* instruction = Instruction::At(codePtr);
84 *decoded_instruction = DecodedInstruction(instruction);
buzbee67bf8852011-08-17 17:51:35 -070085
Elliott Hughesadb8c672012-03-06 16:49:32 -080086 if (printMe) {
Bill Buzbeea114add2012-05-03 15:00:40 -070087 char* decodedString = oatGetDalvikDisassembly(cUnit, *decoded_instruction,
88 NULL);
89 LOG(INFO) << codePtr << ": 0x"
90 << std::hex << static_cast<int>(decoded_instruction->opcode)
Elliott Hughesadb8c672012-03-06 16:49:32 -080091 << " " << decodedString;
92 }
93 return instruction->SizeInCodeUnits();
buzbee67bf8852011-08-17 17:51:35 -070094}
95
96#define UNKNOWN_TARGET 0xffffffff
97
Elliott Hughesadb8c672012-03-06 16:49:32 -080098inline bool isGoto(MIR* insn) {
99 switch (insn->dalvikInsn.opcode) {
100 case Instruction::GOTO:
101 case Instruction::GOTO_16:
102 case Instruction::GOTO_32:
103 return true;
104 default:
105 return false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700106 }
buzbee67bf8852011-08-17 17:51:35 -0700107}
108
109/*
110 * Identify unconditional branch instructions
111 */
Elliott Hughesadb8c672012-03-06 16:49:32 -0800112inline bool isUnconditionalBranch(MIR* insn) {
113 switch (insn->dalvikInsn.opcode) {
114 case Instruction::RETURN_VOID:
115 case Instruction::RETURN:
116 case Instruction::RETURN_WIDE:
117 case Instruction::RETURN_OBJECT:
118 return true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700119 default:
120 return isGoto(insn);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800121 }
buzbee67bf8852011-08-17 17:51:35 -0700122}
123
124/* Split an existing block from the specified code offset into two */
buzbee31a4a6f2012-02-28 15:36:15 -0800125BasicBlock *splitBlock(CompilationUnit* cUnit, unsigned int codeOffset,
Bill Buzbeea114add2012-05-03 15:00:40 -0700126 BasicBlock* origBlock, BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700127{
Bill Buzbeea114add2012-05-03 15:00:40 -0700128 MIR* insn = origBlock->firstMIRInsn;
129 while (insn) {
130 if (insn->offset == codeOffset) break;
131 insn = insn->next;
132 }
133 if (insn == NULL) {
134 LOG(FATAL) << "Break split failed";
135 }
136 BasicBlock *bottomBlock = oatNewBB(cUnit, kDalvikByteCode,
137 cUnit->numBlocks++);
138 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700139
Bill Buzbeea114add2012-05-03 15:00:40 -0700140 bottomBlock->startOffset = codeOffset;
141 bottomBlock->firstMIRInsn = insn;
142 bottomBlock->lastMIRInsn = origBlock->lastMIRInsn;
buzbee67bf8852011-08-17 17:51:35 -0700143
Bill Buzbeea114add2012-05-03 15:00:40 -0700144 /* Add it to the quick lookup cache */
145 cUnit->blockMap.Put(bottomBlock->startOffset, bottomBlock);
buzbee5b537102012-01-17 17:33:47 -0800146
Bill Buzbeea114add2012-05-03 15:00:40 -0700147 /* Handle the taken path */
148 bottomBlock->taken = origBlock->taken;
149 if (bottomBlock->taken) {
150 origBlock->taken = NULL;
151 oatDeleteGrowableList(bottomBlock->taken->predecessors,
buzbeeba938cb2012-02-03 14:47:55 -0800152 (intptr_t)origBlock);
Bill Buzbeea114add2012-05-03 15:00:40 -0700153 oatInsertGrowableList(cUnit, bottomBlock->taken->predecessors,
154 (intptr_t)bottomBlock);
155 }
156
157 /* Handle the fallthrough path */
Bill Buzbeea114add2012-05-03 15:00:40 -0700158 bottomBlock->fallThrough = origBlock->fallThrough;
159 origBlock->fallThrough = bottomBlock;
Bill Buzbeea114add2012-05-03 15:00:40 -0700160 oatInsertGrowableList(cUnit, bottomBlock->predecessors,
161 (intptr_t)origBlock);
162 if (bottomBlock->fallThrough) {
163 oatDeleteGrowableList(bottomBlock->fallThrough->predecessors,
164 (intptr_t)origBlock);
165 oatInsertGrowableList(cUnit, bottomBlock->fallThrough->predecessors,
166 (intptr_t)bottomBlock);
167 }
168
169 /* Handle the successor list */
170 if (origBlock->successorBlockList.blockListType != kNotUsed) {
171 bottomBlock->successorBlockList = origBlock->successorBlockList;
172 origBlock->successorBlockList.blockListType = kNotUsed;
173 GrowableListIterator iterator;
174
175 oatGrowableListIteratorInit(&bottomBlock->successorBlockList.blocks,
176 &iterator);
177 while (true) {
178 SuccessorBlockInfo *successorBlockInfo =
179 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
180 if (successorBlockInfo == NULL) break;
181 BasicBlock *bb = successorBlockInfo->block;
182 oatDeleteGrowableList(bb->predecessors, (intptr_t)origBlock);
183 oatInsertGrowableList(cUnit, bb->predecessors, (intptr_t)bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700184 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700185 }
buzbee67bf8852011-08-17 17:51:35 -0700186
Bill Buzbeea114add2012-05-03 15:00:40 -0700187 origBlock->lastMIRInsn = insn->prev;
buzbee67bf8852011-08-17 17:51:35 -0700188
Bill Buzbeea114add2012-05-03 15:00:40 -0700189 insn->prev->next = NULL;
190 insn->prev = NULL;
191 /*
192 * Update the immediate predecessor block pointer so that outgoing edges
193 * can be applied to the proper block.
194 */
195 if (immedPredBlockP) {
196 DCHECK_EQ(*immedPredBlockP, origBlock);
197 *immedPredBlockP = bottomBlock;
198 }
199 return bottomBlock;
buzbee67bf8852011-08-17 17:51:35 -0700200}
201
202/*
203 * Given a code offset, find out the block that starts with it. If the offset
buzbee9ab05de2012-01-18 15:43:48 -0800204 * is in the middle of an existing block, split it into two. If immedPredBlockP
205 * is not non-null and is the block being split, update *immedPredBlockP to
206 * point to the bottom block so that outgoing edges can be set up properly
207 * (by the caller)
buzbee5b537102012-01-17 17:33:47 -0800208 * Utilizes a map for fast lookup of the typical cases.
buzbee67bf8852011-08-17 17:51:35 -0700209 */
buzbee31a4a6f2012-02-28 15:36:15 -0800210BasicBlock *findBlock(CompilationUnit* cUnit, unsigned int codeOffset,
211 bool split, bool create, BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700212{
Bill Buzbeea114add2012-05-03 15:00:40 -0700213 GrowableList* blockList = &cUnit->blockList;
214 BasicBlock* bb;
215 unsigned int i;
216 SafeMap<unsigned int, BasicBlock*>::iterator it;
buzbee67bf8852011-08-17 17:51:35 -0700217
Bill Buzbeea114add2012-05-03 15:00:40 -0700218 it = cUnit->blockMap.find(codeOffset);
219 if (it != cUnit->blockMap.end()) {
220 return it->second;
221 } else if (!create) {
222 return NULL;
223 }
224
225 if (split) {
226 for (i = 0; i < blockList->numUsed; i++) {
227 bb = (BasicBlock *) blockList->elemList[i];
228 if (bb->blockType != kDalvikByteCode) continue;
229 /* Check if a branch jumps into the middle of an existing block */
230 if ((codeOffset > bb->startOffset) && (bb->lastMIRInsn != NULL) &&
231 (codeOffset <= bb->lastMIRInsn->offset)) {
232 BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb,
233 bb == *immedPredBlockP ?
234 immedPredBlockP : NULL);
235 return newBB;
236 }
buzbee5b537102012-01-17 17:33:47 -0800237 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700238 }
buzbee5b537102012-01-17 17:33:47 -0800239
Bill Buzbeea114add2012-05-03 15:00:40 -0700240 /* Create a new one */
241 bb = oatNewBB(cUnit, kDalvikByteCode, cUnit->numBlocks++);
242 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) bb);
243 bb->startOffset = codeOffset;
244 cUnit->blockMap.Put(bb->startOffset, bb);
245 return bb;
buzbee67bf8852011-08-17 17:51:35 -0700246}
247
buzbeef58c12c2012-07-03 15:06:29 -0700248/* Find existing block */
249BasicBlock* oatFindBlock(CompilationUnit* cUnit, unsigned int codeOffset)
250{
251 return findBlock(cUnit, codeOffset, false, false, NULL);
252}
253
buzbeead8f15e2012-06-18 14:49:45 -0700254/* Turn method name into a legal Linux file name */
255void oatReplaceSpecialChars(std::string& str)
256{
257 static const struct { const char before; const char after; } match[] =
258 {{'/','-'}, {';','#'}, {' ','#'}, {'$','+'},
259 {'(','@'}, {')','@'}, {'<','='}, {'>','='}};
260 for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) {
261 std::replace(str.begin(), str.end(), match[i].before, match[i].after);
262 }
263}
264
buzbee67bf8852011-08-17 17:51:35 -0700265/* Dump the CFG into a DOT graph */
266void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix)
267{
Bill Buzbeea114add2012-05-03 15:00:40 -0700268 FILE* file;
buzbeead8f15e2012-06-18 14:49:45 -0700269 std::string fname(PrettyMethod(cUnit->method_idx, *cUnit->dex_file));
270 oatReplaceSpecialChars(fname);
271 fname = StringPrintf("%s%s%x.dot", dirPrefix, fname.c_str(),
272 cUnit->entryBlock->fallThrough->startOffset);
273 file = fopen(fname.c_str(), "w");
Bill Buzbeea114add2012-05-03 15:00:40 -0700274 if (file == NULL) {
275 return;
276 }
277 fprintf(file, "digraph G {\n");
278
279 fprintf(file, " rankdir=TB\n");
280
281 int numReachableBlocks = cUnit->numReachableBlocks;
282 int idx;
283 const GrowableList *blockList = &cUnit->blockList;
284
285 for (idx = 0; idx < numReachableBlocks; idx++) {
286 int blockIdx = cUnit->dfsOrder.elemList[idx];
287 BasicBlock *bb = (BasicBlock *) oatGrowableListGetElement(blockList,
288 blockIdx);
289 if (bb == NULL) break;
290 if (bb->blockType == kEntryBlock) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700291 fprintf(file, " entry_%d [shape=Mdiamond];\n", bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700292 } else if (bb->blockType == kExitBlock) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700293 fprintf(file, " exit_%d [shape=Mdiamond];\n", bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700294 } else if (bb->blockType == kDalvikByteCode) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700295 fprintf(file, " block%04x_%d [shape=record,label = \"{ \\\n",
296 bb->startOffset, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700297 const MIR *mir;
298 fprintf(file, " {block id %d\\l}%s\\\n", bb->id,
299 bb->firstMIRInsn ? " | " : " ");
300 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
301 fprintf(file, " {%04x %s\\l}%s\\\n", mir->offset,
302 mir->ssaRep ? oatFullDisassembler(cUnit, mir) :
303 Instruction::Name(mir->dalvikInsn.opcode),
304 mir->next ? " | " : " ");
305 }
306 fprintf(file, " }\"];\n\n");
307 } else if (bb->blockType == kExceptionHandling) {
308 char blockName[BLOCK_NAME_LEN];
309
310 oatGetBlockName(bb, blockName);
311 fprintf(file, " %s [shape=invhouse];\n", blockName);
buzbee67bf8852011-08-17 17:51:35 -0700312 }
buzbee67bf8852011-08-17 17:51:35 -0700313
Bill Buzbeea114add2012-05-03 15:00:40 -0700314 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
buzbee67bf8852011-08-17 17:51:35 -0700315
Bill Buzbeea114add2012-05-03 15:00:40 -0700316 if (bb->taken) {
317 oatGetBlockName(bb, blockName1);
318 oatGetBlockName(bb->taken, blockName2);
319 fprintf(file, " %s:s -> %s:n [style=dotted]\n",
320 blockName1, blockName2);
buzbee67bf8852011-08-17 17:51:35 -0700321 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700322 if (bb->fallThrough) {
323 oatGetBlockName(bb, blockName1);
324 oatGetBlockName(bb->fallThrough, blockName2);
325 fprintf(file, " %s:s -> %s:n\n", blockName1, blockName2);
326 }
327
328 if (bb->successorBlockList.blockListType != kNotUsed) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700329 fprintf(file, " succ%04x_%d [shape=%s,label = \"{ \\\n",
330 bb->startOffset, bb->id,
Bill Buzbeea114add2012-05-03 15:00:40 -0700331 (bb->successorBlockList.blockListType == kCatch) ?
332 "Mrecord" : "record");
333 GrowableListIterator iterator;
334 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
335 &iterator);
336 SuccessorBlockInfo *successorBlockInfo =
337 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
338
339 int succId = 0;
340 while (true) {
341 if (successorBlockInfo == NULL) break;
342
343 BasicBlock *destBlock = successorBlockInfo->block;
344 SuccessorBlockInfo *nextSuccessorBlockInfo =
345 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
346
347 fprintf(file, " {<f%d> %04x: %04x\\l}%s\\\n",
348 succId++,
349 successorBlockInfo->key,
350 destBlock->startOffset,
351 (nextSuccessorBlockInfo != NULL) ? " | " : " ");
352
353 successorBlockInfo = nextSuccessorBlockInfo;
354 }
355 fprintf(file, " }\"];\n\n");
356
357 oatGetBlockName(bb, blockName1);
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700358 fprintf(file, " %s:s -> succ%04x_%d:n [style=dashed]\n",
359 blockName1, bb->startOffset, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700360
361 if (bb->successorBlockList.blockListType == kPackedSwitch ||
362 bb->successorBlockList.blockListType == kSparseSwitch) {
363
364 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
365 &iterator);
366
367 succId = 0;
368 while (true) {
369 SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
370 oatGrowableListIteratorNext(&iterator);
371 if (successorBlockInfo == NULL) break;
372
373 BasicBlock *destBlock = successorBlockInfo->block;
374
375 oatGetBlockName(destBlock, blockName2);
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700376 fprintf(file, " succ%04x_%d:f%d:e -> %s:n\n", bb->startOffset,
377 bb->id, succId++, blockName2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700378 }
379 }
380 }
381 fprintf(file, "\n");
382
383 /* Display the dominator tree */
384 oatGetBlockName(bb, blockName1);
385 fprintf(file, " cfg%s [label=\"%s\", shape=none];\n",
386 blockName1, blockName1);
387 if (bb->iDom) {
388 oatGetBlockName(bb->iDom, blockName2);
389 fprintf(file, " cfg%s:s -> cfg%s:n\n\n", blockName2, blockName1);
390 }
391 }
392 fprintf(file, "}\n");
393 fclose(file);
buzbee67bf8852011-08-17 17:51:35 -0700394}
395
396/* Verify if all the successor is connected with all the claimed predecessors */
buzbee31a4a6f2012-02-28 15:36:15 -0800397bool verifyPredInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700398{
Bill Buzbeea114add2012-05-03 15:00:40 -0700399 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700400
Bill Buzbeea114add2012-05-03 15:00:40 -0700401 oatGrowableListIteratorInit(bb->predecessors, &iter);
402 while (true) {
403 BasicBlock *predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
404 if (!predBB) break;
405 bool found = false;
406 if (predBB->taken == bb) {
407 found = true;
408 } else if (predBB->fallThrough == bb) {
409 found = true;
410 } else if (predBB->successorBlockList.blockListType != kNotUsed) {
411 GrowableListIterator iterator;
412 oatGrowableListIteratorInit(&predBB->successorBlockList.blocks,
413 &iterator);
414 while (true) {
415 SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
416 oatGrowableListIteratorNext(&iterator);
417 if (successorBlockInfo == NULL) break;
418 BasicBlock *succBB = successorBlockInfo->block;
419 if (succBB == bb) {
buzbee67bf8852011-08-17 17:51:35 -0700420 found = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700421 break;
buzbee67bf8852011-08-17 17:51:35 -0700422 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700423 }
buzbee67bf8852011-08-17 17:51:35 -0700424 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700425 if (found == false) {
426 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
427 oatGetBlockName(bb, blockName1);
428 oatGetBlockName(predBB, blockName2);
429 oatDumpCFG(cUnit, "/sdcard/cfg/");
430 LOG(FATAL) << "Successor " << blockName1 << "not found from "
431 << blockName2;
432 }
433 }
434 return true;
buzbee67bf8852011-08-17 17:51:35 -0700435}
436
437/* Identify code range in try blocks and set up the empty catch blocks */
buzbee31a4a6f2012-02-28 15:36:15 -0800438void processTryCatchBlocks(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700439{
Bill Buzbeea114add2012-05-03 15:00:40 -0700440 const DexFile::CodeItem* code_item = cUnit->code_item;
441 int triesSize = code_item->tries_size_;
442 int offset;
buzbee67bf8852011-08-17 17:51:35 -0700443
Bill Buzbeea114add2012-05-03 15:00:40 -0700444 if (triesSize == 0) {
445 return;
446 }
447
448 ArenaBitVector* tryBlockAddr = cUnit->tryBlockAddr;
449
450 for (int i = 0; i < triesSize; i++) {
451 const DexFile::TryItem* pTry =
452 DexFile::GetTryItems(*code_item, i);
453 int startOffset = pTry->start_addr_;
454 int endOffset = startOffset + pTry->insn_count_;
455 for (offset = startOffset; offset < endOffset; offset++) {
456 oatSetBit(cUnit, tryBlockAddr, offset);
buzbee67bf8852011-08-17 17:51:35 -0700457 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700458 }
buzbee67bf8852011-08-17 17:51:35 -0700459
Bill Buzbeea114add2012-05-03 15:00:40 -0700460 // Iterate over each of the handlers to enqueue the empty Catch blocks
461 const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item, 0);
462 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
463 for (uint32_t idx = 0; idx < handlers_size; idx++) {
464 CatchHandlerIterator iterator(handlers_ptr);
465 for (; iterator.HasNext(); iterator.Next()) {
466 uint32_t address = iterator.GetHandlerAddress();
467 findBlock(cUnit, address, false /* split */, true /*create*/,
468 /* immedPredBlockP */ NULL);
buzbee67bf8852011-08-17 17:51:35 -0700469 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700470 handlers_ptr = iterator.EndDataPointer();
471 }
buzbee67bf8852011-08-17 17:51:35 -0700472}
473
Elliott Hughesadb8c672012-03-06 16:49:32 -0800474/* Process instructions with the kBranch flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800475BasicBlock* processCanBranch(CompilationUnit* cUnit, BasicBlock* curBlock,
Bill Buzbeea114add2012-05-03 15:00:40 -0700476 MIR* insn, int curOffset, int width, int flags,
477 const u2* codePtr, const u2* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700478{
Bill Buzbeea114add2012-05-03 15:00:40 -0700479 int target = curOffset;
480 switch (insn->dalvikInsn.opcode) {
481 case Instruction::GOTO:
482 case Instruction::GOTO_16:
483 case Instruction::GOTO_32:
484 target += (int) insn->dalvikInsn.vA;
485 break;
486 case Instruction::IF_EQ:
487 case Instruction::IF_NE:
488 case Instruction::IF_LT:
489 case Instruction::IF_GE:
490 case Instruction::IF_GT:
491 case Instruction::IF_LE:
492 target += (int) insn->dalvikInsn.vC;
493 break;
494 case Instruction::IF_EQZ:
495 case Instruction::IF_NEZ:
496 case Instruction::IF_LTZ:
497 case Instruction::IF_GEZ:
498 case Instruction::IF_GTZ:
499 case Instruction::IF_LEZ:
500 target += (int) insn->dalvikInsn.vB;
501 break;
502 default:
503 LOG(FATAL) << "Unexpected opcode(" << (int)insn->dalvikInsn.opcode
504 << ") with kBranch set";
505 }
506 BasicBlock *takenBlock = findBlock(cUnit, target,
507 /* split */
508 true,
509 /* create */
510 true,
511 /* immedPredBlockP */
512 &curBlock);
513 curBlock->taken = takenBlock;
514 oatInsertGrowableList(cUnit, takenBlock->predecessors, (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700515
Bill Buzbeea114add2012-05-03 15:00:40 -0700516 /* Always terminate the current block for conditional branches */
517 if (flags & Instruction::kContinue) {
518 BasicBlock *fallthroughBlock = findBlock(cUnit,
519 curOffset + width,
520 /*
521 * If the method is processed
522 * in sequential order from the
523 * beginning, we don't need to
524 * specify split for continue
525 * blocks. However, this
526 * routine can be called by
527 * compileLoop, which starts
528 * parsing the method from an
529 * arbitrary address in the
530 * method body.
531 */
532 true,
533 /* create */
534 true,
535 /* immedPredBlockP */
536 &curBlock);
537 curBlock->fallThrough = fallthroughBlock;
538 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
539 (intptr_t)curBlock);
540 } else if (codePtr < codeEnd) {
541 /* Create a fallthrough block for real instructions (incl. NOP) */
542 if (contentIsInsn(codePtr)) {
543 findBlock(cUnit, curOffset + width,
544 /* split */
545 false,
546 /* create */
547 true,
548 /* immedPredBlockP */
549 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700550 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700551 }
552 return curBlock;
buzbee67bf8852011-08-17 17:51:35 -0700553}
554
Elliott Hughesadb8c672012-03-06 16:49:32 -0800555/* Process instructions with the kSwitch flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800556void processCanSwitch(CompilationUnit* cUnit, BasicBlock* curBlock,
557 MIR* insn, int curOffset, int width, int flags)
buzbee67bf8852011-08-17 17:51:35 -0700558{
Bill Buzbeea114add2012-05-03 15:00:40 -0700559 u2* switchData= (u2 *) (cUnit->insns + curOffset + insn->dalvikInsn.vB);
560 int size;
561 int* keyTable;
562 int* targetTable;
563 int i;
564 int firstKey;
buzbee67bf8852011-08-17 17:51:35 -0700565
Bill Buzbeea114add2012-05-03 15:00:40 -0700566 /*
567 * Packed switch data format:
568 * ushort ident = 0x0100 magic value
569 * ushort size number of entries in the table
570 * int first_key first (and lowest) switch case value
571 * int targets[size] branch targets, relative to switch opcode
572 *
573 * Total size is (4+size*2) 16-bit code units.
574 */
575 if (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) {
576 DCHECK_EQ(static_cast<int>(switchData[0]),
577 static_cast<int>(Instruction::kPackedSwitchSignature));
578 size = switchData[1];
579 firstKey = switchData[2] | (switchData[3] << 16);
580 targetTable = (int *) &switchData[4];
581 keyTable = NULL; // Make the compiler happy
582 /*
583 * Sparse switch data format:
584 * ushort ident = 0x0200 magic value
585 * ushort size number of entries in the table; > 0
586 * int keys[size] keys, sorted low-to-high; 32-bit aligned
587 * int targets[size] branch targets, relative to switch opcode
588 *
589 * Total size is (2+size*4) 16-bit code units.
590 */
591 } else {
592 DCHECK_EQ(static_cast<int>(switchData[0]),
593 static_cast<int>(Instruction::kSparseSwitchSignature));
594 size = switchData[1];
595 keyTable = (int *) &switchData[2];
596 targetTable = (int *) &switchData[2 + size*2];
597 firstKey = 0; // To make the compiler happy
598 }
buzbee67bf8852011-08-17 17:51:35 -0700599
Bill Buzbeea114add2012-05-03 15:00:40 -0700600 if (curBlock->successorBlockList.blockListType != kNotUsed) {
601 LOG(FATAL) << "Successor block list already in use: "
602 << (int)curBlock->successorBlockList.blockListType;
603 }
604 curBlock->successorBlockList.blockListType =
605 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
606 kPackedSwitch : kSparseSwitch;
607 oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, size,
608 kListSuccessorBlocks);
609
610 for (i = 0; i < size; i++) {
611 BasicBlock *caseBlock = findBlock(cUnit, curOffset + targetTable[i],
612 /* split */
613 true,
614 /* create */
615 true,
616 /* immedPredBlockP */
617 &curBlock);
618 SuccessorBlockInfo *successorBlockInfo =
619 (SuccessorBlockInfo *) oatNew(cUnit, sizeof(SuccessorBlockInfo),
620 false, kAllocSuccessor);
621 successorBlockInfo->block = caseBlock;
622 successorBlockInfo->key =
Elliott Hughesadb8c672012-03-06 16:49:32 -0800623 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
Bill Buzbeea114add2012-05-03 15:00:40 -0700624 firstKey + i : keyTable[i];
625 oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
626 (intptr_t) successorBlockInfo);
627 oatInsertGrowableList(cUnit, caseBlock->predecessors,
buzbeeba938cb2012-02-03 14:47:55 -0800628 (intptr_t)curBlock);
Bill Buzbeea114add2012-05-03 15:00:40 -0700629 }
630
631 /* Fall-through case */
632 BasicBlock* fallthroughBlock = findBlock(cUnit,
633 curOffset + width,
634 /* split */
635 false,
636 /* create */
637 true,
638 /* immedPredBlockP */
639 NULL);
640 curBlock->fallThrough = fallthroughBlock;
641 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
642 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700643}
644
Elliott Hughesadb8c672012-03-06 16:49:32 -0800645/* Process instructions with the kThrow flag */
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700646BasicBlock* processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock,
647 MIR* insn, int curOffset, int width, int flags,
648 ArenaBitVector* tryBlockAddr, const u2* codePtr,
649 const u2* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700650{
Bill Buzbeea114add2012-05-03 15:00:40 -0700651 const DexFile::CodeItem* code_item = cUnit->code_item;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700652 bool inTryBlock = oatIsBitSet(tryBlockAddr, curOffset);
buzbee67bf8852011-08-17 17:51:35 -0700653
Bill Buzbeea114add2012-05-03 15:00:40 -0700654 /* In try block */
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700655 if (inTryBlock) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700656 CatchHandlerIterator iterator(*code_item, curOffset);
buzbee67bf8852011-08-17 17:51:35 -0700657
Bill Buzbeea114add2012-05-03 15:00:40 -0700658 if (curBlock->successorBlockList.blockListType != kNotUsed) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700659 LOG(INFO) << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
Bill Buzbeea114add2012-05-03 15:00:40 -0700660 LOG(FATAL) << "Successor block list already in use: "
661 << (int)curBlock->successorBlockList.blockListType;
buzbee67bf8852011-08-17 17:51:35 -0700662 }
663
Bill Buzbeea114add2012-05-03 15:00:40 -0700664 curBlock->successorBlockList.blockListType = kCatch;
665 oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, 2,
666 kListSuccessorBlocks);
667
668 for (;iterator.HasNext(); iterator.Next()) {
669 BasicBlock *catchBlock = findBlock(cUnit, iterator.GetHandlerAddress(),
670 false /* split*/,
671 false /* creat */,
672 NULL /* immedPredBlockP */);
673 catchBlock->catchEntry = true;
674 SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
675 oatNew(cUnit, sizeof(SuccessorBlockInfo), false, kAllocSuccessor);
676 successorBlockInfo->block = catchBlock;
677 successorBlockInfo->key = iterator.GetHandlerTypeIndex();
678 oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
679 (intptr_t) successorBlockInfo);
680 oatInsertGrowableList(cUnit, catchBlock->predecessors,
681 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700682 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700683 } else {
684 BasicBlock *ehBlock = oatNewBB(cUnit, kExceptionHandling,
685 cUnit->numBlocks++);
686 curBlock->taken = ehBlock;
687 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) ehBlock);
688 ehBlock->startOffset = curOffset;
689 oatInsertGrowableList(cUnit, ehBlock->predecessors, (intptr_t)curBlock);
690 }
691
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700692 if (insn->dalvikInsn.opcode == Instruction::THROW){
693 if ((codePtr < codeEnd) && contentIsInsn(codePtr)) {
694 // Force creation of new block following THROW via side-effect
695 findBlock(cUnit, curOffset + width, /* split */ false,
696 /* create */ true, /* immedPredBlockP */ NULL);
697 }
698 if (!inTryBlock) {
699 // Don't split a THROW that can't rethrow - we're done.
700 return curBlock;
Bill Buzbeea114add2012-05-03 15:00:40 -0700701 }
702 }
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700703
704 /*
705 * Split the potentially-throwing instruction into two parts.
706 * The first half will be a pseudo-op that captures the exception
707 * edges and terminates the basic block. It always falls through.
708 * Then, create a new basic block that begins with the throwing instruction
709 * (minus exceptions). Note: this new basic block must NOT be entered into
710 * the blockMap. If the potentially-throwing instruction is the target of a
711 * future branch, we need to find the check psuedo half. The new
712 * basic block containing the work portion of the instruction should
713 * only be entered via fallthrough from the block containing the
714 * pseudo exception edge MIR. Note also that this new block is
715 * not automatically terminated after the work portion, and may
716 * contain following instructions.
717 */
718 BasicBlock *newBlock = oatNewBB(cUnit, kDalvikByteCode, cUnit->numBlocks++);
719 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t)newBlock);
720 newBlock->startOffset = insn->offset;
721 curBlock->fallThrough = newBlock;
722 oatInsertGrowableList(cUnit, newBlock->predecessors, (intptr_t)curBlock);
723 MIR* newInsn = (MIR*)oatNew(cUnit, sizeof(MIR), true, kAllocMIR);
724 *newInsn = *insn;
725 insn->dalvikInsn.opcode =
726 static_cast<Instruction::Code>(kMirOpCheck);
727 // Associate the two halves
728 insn->meta.throwInsn = newInsn;
729 newInsn->meta.throwInsn = insn;
730 oatAppendMIR(newBlock, newInsn);
731 return newBlock;
buzbee67bf8852011-08-17 17:51:35 -0700732}
733
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800734void oatInit(CompilationUnit* cUnit, const Compiler& compiler) {
735 if (!oatArchInit()) {
736 LOG(FATAL) << "Failed to initialize oat";
737 }
738 if (!oatHeapInit(cUnit)) {
739 LOG(FATAL) << "Failed to initialize oat heap";
740 }
741}
742
Elliott Hughes3fa1b7e2012-03-13 17:06:22 -0700743CompiledMethod* oatCompileMethod(Compiler& compiler,
744 const DexFile::CodeItem* code_item,
Ian Rogers08f753d2012-08-24 14:35:25 -0700745 uint32_t access_flags, InvokeType invoke_type,
746 uint32_t method_idx,
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700747 jobject class_loader,
Elliott Hughes3fa1b7e2012-03-13 17:06:22 -0700748 const DexFile& dex_file)
buzbee67bf8852011-08-17 17:51:35 -0700749{
Bill Buzbeea114add2012-05-03 15:00:40 -0700750 VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
Brian Carlstrom94496d32011-08-22 09:22:47 -0700751
Bill Buzbeea114add2012-05-03 15:00:40 -0700752 const u2* codePtr = code_item->insns_;
753 const u2* codeEnd = code_item->insns_ + code_item->insns_size_in_code_units_;
754 int numBlocks = 0;
755 unsigned int curOffset = 0;
buzbee67bf8852011-08-17 17:51:35 -0700756
Bill Buzbeea114add2012-05-03 15:00:40 -0700757 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
758 UniquePtr<CompilationUnit> cUnit(new CompilationUnit);
buzbeeba938cb2012-02-03 14:47:55 -0800759
Bill Buzbeea114add2012-05-03 15:00:40 -0700760 oatInit(cUnit.get(), compiler);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800761
Bill Buzbeea114add2012-05-03 15:00:40 -0700762 cUnit->compiler = &compiler;
763 cUnit->class_linker = class_linker;
764 cUnit->dex_file = &dex_file;
Bill Buzbeea114add2012-05-03 15:00:40 -0700765 cUnit->method_idx = method_idx;
766 cUnit->code_item = code_item;
767 cUnit->access_flags = access_flags;
Ian Rogers08f753d2012-08-24 14:35:25 -0700768 cUnit->invoke_type = invoke_type;
Bill Buzbeea114add2012-05-03 15:00:40 -0700769 cUnit->shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
770 cUnit->instructionSet = compiler.GetInstructionSet();
771 cUnit->insns = code_item->insns_;
772 cUnit->insnsSize = code_item->insns_size_in_code_units_;
773 cUnit->numIns = code_item->ins_size_;
774 cUnit->numRegs = code_item->registers_size_ - cUnit->numIns;
775 cUnit->numOuts = code_item->outs_size_;
buzbee2cfc6392012-05-07 14:51:40 -0700776#if defined(ART_USE_QUICK_COMPILER)
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700777 DCHECK((cUnit->instructionSet == kThumb2) ||
778 (cUnit->instructionSet == kX86) ||
779 (cUnit->instructionSet == kMips));
780 if (cUnit->instructionSet == kThumb2) {
781 // TODO: remove this once x86 is tested
buzbee85eee022012-07-16 22:12:38 -0700782 cUnit->genBitcode = true;
783 }
buzbee2a83e8f2012-07-13 16:42:30 -0700784#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700785 /* Adjust this value accordingly once inlining is performed */
786 cUnit->numDalvikRegisters = code_item->registers_size_;
787 // TODO: set this from command line
788 cUnit->compilerFlipMatch = false;
789 bool useMatch = !cUnit->compilerMethodMatch.empty();
790 bool match = useMatch && (cUnit->compilerFlipMatch ^
791 (PrettyMethod(method_idx, dex_file).find(cUnit->compilerMethodMatch) !=
792 std::string::npos));
793 if (!useMatch || match) {
794 cUnit->disableOpt = kCompilerOptimizerDisableFlags;
795 cUnit->enableDebug = kCompilerDebugFlags;
796 cUnit->printMe = VLOG_IS_ON(compiler) ||
797 (cUnit->enableDebug & (1 << kDebugVerbose));
798 }
buzbee2cfc6392012-05-07 14:51:40 -0700799#if defined(ART_USE_QUICK_COMPILER)
buzbee6969d502012-06-15 16:40:31 -0700800 if (cUnit->genBitcode) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700801 //cUnit->enableDebug |= (1 << kDebugVerifyBitcode);
buzbee2a83e8f2012-07-13 16:42:30 -0700802 //cUnit->printMe = true;
803 //cUnit->enableDebug |= (1 << kDebugDumpBitcodeFile);
buzbee6969d502012-06-15 16:40:31 -0700804 }
buzbee2cfc6392012-05-07 14:51:40 -0700805#endif
jeffhao7fbee072012-08-24 17:56:54 -0700806 if (cUnit->instructionSet == kMips) {
807 // Disable some optimizations for mips for now
808 cUnit->disableOpt |= (
809 (1 << kLoadStoreElimination) |
810 (1 << kLoadHoisting) |
811 (1 << kSuppressLoads) |
812 (1 << kNullCheckElimination) |
813 (1 << kPromoteRegs) |
814 (1 << kTrackLiveTemps) |
815 (1 << kSkipLargeMethodOptimization) |
816 (1 << kSafeOptimizations) |
817 (1 << kBBOpt) |
818 (1 << kMatch) |
819 (1 << kPromoteCompilerTemps));
820 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700821 /* Are we generating code for the debugger? */
822 if (compiler.IsDebuggingSupported()) {
823 cUnit->genDebugger = true;
824 // Yes, disable most optimizations
825 cUnit->disableOpt |= (
826 (1 << kLoadStoreElimination) |
827 (1 << kLoadHoisting) |
828 (1 << kSuppressLoads) |
829 (1 << kPromoteRegs) |
830 (1 << kBBOpt) |
831 (1 << kMatch) |
832 (1 << kTrackLiveTemps));
833 }
834
835 /* Gathering opcode stats? */
836 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
837 cUnit->opcodeCount = (int*)oatNew(cUnit.get(),
838 kNumPackedOpcodes * sizeof(int), true, kAllocMisc);
839 }
840
841 /* Assume non-throwing leaf */
842 cUnit->attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE);
843
844 /* Initialize the block list, estimate size based on insnsSize */
845 oatInitGrowableList(cUnit.get(), &cUnit->blockList, cUnit->insnsSize,
846 kListBlockList);
847
848 /* Initialize the switchTables list */
849 oatInitGrowableList(cUnit.get(), &cUnit->switchTables, 4,
850 kListSwitchTables);
851
852 /* Intialize the fillArrayData list */
853 oatInitGrowableList(cUnit.get(), &cUnit->fillArrayData, 4,
854 kListFillArrayData);
855
856 /* Intialize the throwLaunchpads list, estimate size based on insnsSize */
857 oatInitGrowableList(cUnit.get(), &cUnit->throwLaunchpads, cUnit->insnsSize,
858 kListThrowLaunchPads);
859
860 /* Intialize the instrinsicLaunchpads list */
861 oatInitGrowableList(cUnit.get(), &cUnit->intrinsicLaunchpads, 4,
862 kListMisc);
863
864
865 /* Intialize the suspendLaunchpads list */
866 oatInitGrowableList(cUnit.get(), &cUnit->suspendLaunchpads, 2048,
867 kListSuspendLaunchPads);
868
869 /* Allocate the bit-vector to track the beginning of basic blocks */
870 ArenaBitVector *tryBlockAddr = oatAllocBitVector(cUnit.get(),
871 cUnit->insnsSize,
872 true /* expandable */);
873 cUnit->tryBlockAddr = tryBlockAddr;
874
875 /* Create the default entry and exit blocks and enter them to the list */
876 BasicBlock *entryBlock = oatNewBB(cUnit.get(), kEntryBlock, numBlocks++);
877 BasicBlock *exitBlock = oatNewBB(cUnit.get(), kExitBlock, numBlocks++);
878
879 cUnit->entryBlock = entryBlock;
880 cUnit->exitBlock = exitBlock;
881
882 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) entryBlock);
883 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) exitBlock);
884
885 /* Current block to record parsed instructions */
886 BasicBlock *curBlock = oatNewBB(cUnit.get(), kDalvikByteCode, numBlocks++);
887 curBlock->startOffset = 0;
888 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) curBlock);
889 /* Add first block to the fast lookup cache */
890 cUnit->blockMap.Put(curBlock->startOffset, curBlock);
891 entryBlock->fallThrough = curBlock;
892 oatInsertGrowableList(cUnit.get(), curBlock->predecessors,
893 (intptr_t)entryBlock);
894
895 /*
896 * Store back the number of blocks since new blocks may be created of
897 * accessing cUnit.
898 */
899 cUnit->numBlocks = numBlocks;
900
901 /* Identify code range in try blocks and set up the empty catch blocks */
902 processTryCatchBlocks(cUnit.get());
903
904 /* Set up for simple method detection */
905 int numPatterns = sizeof(specialPatterns)/sizeof(specialPatterns[0]);
906 bool livePattern = (numPatterns > 0) && !(cUnit->disableOpt & (1 << kMatch));
Elliott Hughesabe64aa2012-05-30 17:34:45 -0700907 bool* deadPattern = (bool*)oatNew(cUnit.get(), sizeof(bool) * numPatterns, true,
Bill Buzbeea114add2012-05-03 15:00:40 -0700908 kAllocMisc);
909 SpecialCaseHandler specialCase = kNoHandler;
910 int patternPos = 0;
911
912 /* Parse all instructions and put them into containing basic blocks */
913 while (codePtr < codeEnd) {
914 MIR *insn = (MIR *) oatNew(cUnit.get(), sizeof(MIR), true, kAllocMIR);
915 insn->offset = curOffset;
916 int width = parseInsn(cUnit.get(), codePtr, &insn->dalvikInsn, false);
917 insn->width = width;
918 Instruction::Code opcode = insn->dalvikInsn.opcode;
919 if (cUnit->opcodeCount != NULL) {
920 cUnit->opcodeCount[static_cast<int>(opcode)]++;
buzbee44b412b2012-02-04 08:50:53 -0800921 }
922
Bill Buzbeea114add2012-05-03 15:00:40 -0700923 /* Terminate when the data section is seen */
924 if (width == 0)
925 break;
926
927 /* Possible simple method? */
928 if (livePattern) {
929 livePattern = false;
930 specialCase = kNoHandler;
931 for (int i = 0; i < numPatterns; i++) {
932 if (!deadPattern[i]) {
933 if (specialPatterns[i].opcodes[patternPos] == opcode) {
934 livePattern = true;
935 specialCase = specialPatterns[i].handlerCode;
936 } else {
937 deadPattern[i] = true;
938 }
939 }
940 }
941 patternPos++;
buzbeea7c12682012-03-19 13:13:53 -0700942 }
943
Bill Buzbeea114add2012-05-03 15:00:40 -0700944 oatAppendMIR(curBlock, insn);
buzbeecefd1872011-09-09 09:59:52 -0700945
Bill Buzbeea114add2012-05-03 15:00:40 -0700946 codePtr += width;
947 int flags = Instruction::Flags(insn->dalvikInsn.opcode);
buzbee67bf8852011-08-17 17:51:35 -0700948
Bill Buzbeea114add2012-05-03 15:00:40 -0700949 int dfFlags = oatDataFlowAttributes[insn->dalvikInsn.opcode];
buzbee67bf8852011-08-17 17:51:35 -0700950
Bill Buzbeea114add2012-05-03 15:00:40 -0700951 if (dfFlags & DF_HAS_DEFS) {
buzbeebff24652012-05-06 16:22:05 -0700952 cUnit->defCount += (dfFlags & DF_A_WIDE) ? 2 : 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700953 }
buzbee67bf8852011-08-17 17:51:35 -0700954
Bill Buzbeea114add2012-05-03 15:00:40 -0700955 if (flags & Instruction::kBranch) {
956 curBlock = processCanBranch(cUnit.get(), curBlock, insn, curOffset,
957 width, flags, codePtr, codeEnd);
958 } else if (flags & Instruction::kReturn) {
959 curBlock->fallThrough = exitBlock;
960 oatInsertGrowableList(cUnit.get(), exitBlock->predecessors,
961 (intptr_t)curBlock);
962 /*
963 * Terminate the current block if there are instructions
964 * afterwards.
965 */
966 if (codePtr < codeEnd) {
967 /*
968 * Create a fallthrough block for real instructions
969 * (incl. NOP).
970 */
971 if (contentIsInsn(codePtr)) {
972 findBlock(cUnit.get(), curOffset + width,
973 /* split */
974 false,
975 /* create */
976 true,
977 /* immedPredBlockP */
978 NULL);
979 }
980 }
981 } else if (flags & Instruction::kThrow) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700982 curBlock = processCanThrow(cUnit.get(), curBlock, insn, curOffset,
983 width, flags, tryBlockAddr, codePtr, codeEnd);
Bill Buzbeea114add2012-05-03 15:00:40 -0700984 } else if (flags & Instruction::kSwitch) {
985 processCanSwitch(cUnit.get(), curBlock, insn, curOffset, width, flags);
986 }
987 curOffset += width;
988 BasicBlock *nextBlock = findBlock(cUnit.get(), curOffset,
989 /* split */
990 false,
991 /* create */
992 false,
993 /* immedPredBlockP */
994 NULL);
995 if (nextBlock) {
996 /*
997 * The next instruction could be the target of a previously parsed
998 * forward branch so a block is already created. If the current
999 * instruction is not an unconditional branch, connect them through
1000 * the fall-through link.
1001 */
1002 DCHECK(curBlock->fallThrough == NULL ||
1003 curBlock->fallThrough == nextBlock ||
1004 curBlock->fallThrough == exitBlock);
buzbee5ade1d22011-09-09 14:44:52 -07001005
Bill Buzbeea114add2012-05-03 15:00:40 -07001006 if ((curBlock->fallThrough == NULL) && (flags & Instruction::kContinue)) {
1007 curBlock->fallThrough = nextBlock;
1008 oatInsertGrowableList(cUnit.get(), nextBlock->predecessors,
1009 (intptr_t)curBlock);
1010 }
1011 curBlock = nextBlock;
1012 }
1013 }
buzbeefc9e6fa2012-03-23 15:14:29 -07001014
Bill Buzbeea114add2012-05-03 15:00:40 -07001015 if (!(cUnit->disableOpt & (1 << kSkipLargeMethodOptimization))) {
1016 if ((cUnit->numBlocks > MANY_BLOCKS) ||
1017 ((cUnit->numBlocks > MANY_BLOCKS_INITIALIZER) &&
1018 PrettyMethod(method_idx, dex_file, false).find("init>") !=
1019 std::string::npos)) {
1020 cUnit->qdMode = true;
1021 }
1022 }
buzbeefc9e6fa2012-03-23 15:14:29 -07001023
buzbee2cfc6392012-05-07 14:51:40 -07001024#if defined(ART_USE_QUICK_COMPILER)
1025 if (cUnit->genBitcode) {
1026 // Bitcode generation requires full dataflow analysis, no qdMode
1027 cUnit->qdMode = false;
1028 }
1029#endif
1030
Bill Buzbeea114add2012-05-03 15:00:40 -07001031 if (cUnit->qdMode) {
1032 cUnit->disableDataflow = true;
1033 // Disable optimization which require dataflow/ssa
1034 cUnit->disableOpt |=
1035 (1 << kNullCheckElimination) |
1036 (1 << kBBOpt) |
1037 (1 << kPromoteRegs);
1038 if (cUnit->printMe) {
1039 LOG(INFO) << "QD mode enabled: "
1040 << PrettyMethod(method_idx, dex_file)
1041 << " too big: " << cUnit->numBlocks;
1042 }
1043 }
buzbeec1f45042011-09-21 16:03:19 -07001044
Bill Buzbeea114add2012-05-03 15:00:40 -07001045 if (cUnit->printMe) {
1046 oatDumpCompilationUnit(cUnit.get());
1047 }
buzbee67bf8852011-08-17 17:51:35 -07001048
Bill Buzbeea114add2012-05-03 15:00:40 -07001049 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
1050 /* Verify if all blocks are connected as claimed */
1051 oatDataFlowAnalysisDispatcher(cUnit.get(), verifyPredInfo, kAllNodes,
1052 false /* isIterative */);
1053 }
buzbee67bf8852011-08-17 17:51:35 -07001054
Bill Buzbeea114add2012-05-03 15:00:40 -07001055 /* Perform SSA transformation for the whole method */
1056 oatMethodSSATransformation(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001057
buzbee2cfc6392012-05-07 14:51:40 -07001058 /* Do constant propagation */
1059 // TODO: Probably need to make these expandable to support new ssa names
1060 // introducted during MIR optimization passes
1061 cUnit->isConstantV = oatAllocBitVector(cUnit.get(), cUnit->numSSARegs,
1062 false /* not expandable */);
1063 cUnit->constantValues =
1064 (int*)oatNew(cUnit.get(), sizeof(int) * cUnit->numSSARegs, true,
1065 kAllocDFInfo);
1066 oatDataFlowAnalysisDispatcher(cUnit.get(), oatDoConstantPropagation,
1067 kAllNodes,
1068 false /* isIterative */);
1069
Bill Buzbeea114add2012-05-03 15:00:40 -07001070 /* Detect loops */
1071 oatMethodLoopDetection(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001072
Bill Buzbeea114add2012-05-03 15:00:40 -07001073 /* Count uses */
1074 oatMethodUseCount(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001075
Bill Buzbeea114add2012-05-03 15:00:40 -07001076 /* Perform null check elimination */
1077 oatMethodNullCheckElimination(cUnit.get());
1078
1079 /* Do some basic block optimizations */
1080 oatMethodBasicBlockOptimization(cUnit.get());
1081
1082 oatInitializeRegAlloc(cUnit.get()); // Needs to happen after SSA naming
1083
1084 /* Allocate Registers using simple local allocation scheme */
1085 oatSimpleRegAlloc(cUnit.get());
1086
buzbee2cfc6392012-05-07 14:51:40 -07001087#if defined(ART_USE_QUICK_COMPILER)
1088 /* Go the LLVM path? */
1089 if (cUnit->genBitcode) {
1090 // MIR->Bitcode
1091 oatMethodMIR2Bitcode(cUnit.get());
1092 // Bitcode->LIR
1093 oatMethodBitcode2LIR(cUnit.get());
1094 } else {
1095#endif
1096 if (specialCase != kNoHandler) {
1097 /*
1098 * Custom codegen for special cases. If for any reason the
1099 * special codegen doesn't succeed, cUnit->firstLIRInsn will
1100 * set to NULL;
1101 */
1102 oatSpecialMIR2LIR(cUnit.get(), specialCase);
1103 }
buzbee67bf8852011-08-17 17:51:35 -07001104
buzbee2cfc6392012-05-07 14:51:40 -07001105 /* Convert MIR to LIR, etc. */
1106 if (cUnit->firstLIRInsn == NULL) {
1107 oatMethodMIR2LIR(cUnit.get());
1108 }
1109#if defined(ART_USE_QUICK_COMPILER)
Bill Buzbeea114add2012-05-03 15:00:40 -07001110 }
buzbee2cfc6392012-05-07 14:51:40 -07001111#endif
buzbee67bf8852011-08-17 17:51:35 -07001112
Bill Buzbeea114add2012-05-03 15:00:40 -07001113 // Debugging only
1114 if (cUnit->enableDebug & (1 << kDebugDumpCFG)) {
1115 oatDumpCFG(cUnit.get(), "/sdcard/cfg/");
1116 }
buzbee16da88c2012-03-20 10:38:17 -07001117
Bill Buzbeea114add2012-05-03 15:00:40 -07001118 /* Method is not empty */
1119 if (cUnit->firstLIRInsn) {
buzbee67bf8852011-08-17 17:51:35 -07001120
Bill Buzbeea114add2012-05-03 15:00:40 -07001121 // mark the targets of switch statement case labels
1122 oatProcessSwitchTables(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001123
Bill Buzbeea114add2012-05-03 15:00:40 -07001124 /* Convert LIR into machine code. */
1125 oatAssembleLIR(cUnit.get());
buzbee99ba9642012-01-25 14:23:14 -08001126
Elliott Hughes3b6baaa2011-10-14 19:13:56 -07001127 if (cUnit->printMe) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001128 oatCodegenDump(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001129 }
1130
Bill Buzbeea114add2012-05-03 15:00:40 -07001131 if (cUnit->opcodeCount != NULL) {
1132 LOG(INFO) << "Opcode Count";
1133 for (int i = 0; i < kNumPackedOpcodes; i++) {
1134 if (cUnit->opcodeCount[i] != 0) {
1135 LOG(INFO) << "-C- "
1136 << Instruction::Name(static_cast<Instruction::Code>(i))
1137 << " " << cUnit->opcodeCount[i];
buzbee67bf8852011-08-17 17:51:35 -07001138 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001139 }
1140 }
1141 }
buzbeea7c12682012-03-19 13:13:53 -07001142
Bill Buzbeea114add2012-05-03 15:00:40 -07001143 // Combine vmap tables - core regs, then fp regs - into vmapTable
1144 std::vector<uint16_t> vmapTable;
buzbeeca7a5e42012-08-20 11:12:18 -07001145 // Core regs may have been inserted out of order - sort first
1146 std::sort(cUnit->coreVmapTable.begin(), cUnit->coreVmapTable.end());
Bill Buzbeea114add2012-05-03 15:00:40 -07001147 for (size_t i = 0 ; i < cUnit->coreVmapTable.size(); i++) {
buzbeeca7a5e42012-08-20 11:12:18 -07001148 // Copy, stripping out the phys register sort key
1149 vmapTable.push_back(~(-1 << VREG_NUM_WIDTH) & cUnit->coreVmapTable[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001150 }
1151 // If we have a frame, push a marker to take place of lr
1152 if (cUnit->frameSize > 0) {
1153 vmapTable.push_back(INVALID_VREG);
1154 } else {
1155 DCHECK_EQ(__builtin_popcount(cUnit->coreSpillMask), 0);
1156 DCHECK_EQ(__builtin_popcount(cUnit->fpSpillMask), 0);
1157 }
buzbeeca7a5e42012-08-20 11:12:18 -07001158 // Combine vmap tables - core regs, then fp regs. fp regs already sorted
Bill Buzbeea114add2012-05-03 15:00:40 -07001159 for (uint32_t i = 0; i < cUnit->fpVmapTable.size(); i++) {
1160 vmapTable.push_back(cUnit->fpVmapTable[i]);
1161 }
1162 CompiledMethod* result =
1163 new CompiledMethod(cUnit->instructionSet, cUnit->codeBuffer,
1164 cUnit->frameSize, cUnit->coreSpillMask,
1165 cUnit->fpSpillMask, cUnit->mappingTable, vmapTable);
buzbee67bf8852011-08-17 17:51:35 -07001166
Bill Buzbeea114add2012-05-03 15:00:40 -07001167 VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file)
1168 << " (" << (cUnit->codeBuffer.size() * sizeof(cUnit->codeBuffer[0]))
1169 << " bytes)";
buzbee5abfa3e2012-01-31 17:01:43 -08001170
1171#ifdef WITH_MEMSTATS
Bill Buzbeea114add2012-05-03 15:00:40 -07001172 if (cUnit->enableDebug & (1 << kDebugShowMemoryUsage)) {
1173 oatDumpMemStats(cUnit.get());
1174 }
buzbee5abfa3e2012-01-31 17:01:43 -08001175#endif
buzbee67bf8852011-08-17 17:51:35 -07001176
Bill Buzbeea114add2012-05-03 15:00:40 -07001177 oatArenaReset(cUnit.get());
buzbeeba938cb2012-02-03 14:47:55 -08001178
Bill Buzbeea114add2012-05-03 15:00:40 -07001179 return result;
buzbee67bf8852011-08-17 17:51:35 -07001180}
1181
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001182} // namespace art
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001183
Bill Buzbeea114add2012-05-03 15:00:40 -07001184extern "C" art::CompiledMethod*
1185 ArtCompileMethod(art::Compiler& compiler,
1186 const art::DexFile::CodeItem* code_item,
Ian Rogers08f753d2012-08-24 14:35:25 -07001187 uint32_t access_flags, art::InvokeType invoke_type,
1188 uint32_t method_idx, jobject class_loader,
Bill Buzbeea114add2012-05-03 15:00:40 -07001189 const art::DexFile& dex_file)
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001190{
1191 CHECK_EQ(compiler.GetInstructionSet(), art::oatInstructionSet());
Ian Rogers08f753d2012-08-24 14:35:25 -07001192 return art::oatCompileMethod(compiler, code_item, access_flags, invoke_type,
1193 method_idx, class_loader, dex_file);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001194}