blob: 8c403c599e41710099b9fe3246918d5c008b9b30 [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
buzbee692be802012-08-29 15:52:59 -070026#if defined(ART_USE_QUICK_COMPILER)
27QuickCompiler::QuickCompiler(art::Compiler* compiler)
28 : compiler_(compiler) {
29 // Create context, module, intrinsic helper & ir builder
30 llvm_context_.reset(new llvm::LLVMContext());
31 llvm_module_.reset(new llvm::Module("art", *llvm_context_));
32 llvm::StructType::create(*llvm_context_, "JavaObject");
33 llvm::StructType::create(*llvm_context_, "Method");
34 llvm::StructType::create(*llvm_context_, "Thread");
35 intrinsic_helper_.reset( new greenland::IntrinsicHelper(*llvm_context_, *llvm_module_));
36 ir_builder_.reset(new greenland::IRBuilder(*llvm_context_, *llvm_module_, *intrinsic_helper_));
37}
38
39QuickCompiler::~QuickCompiler() {
40}
41
42extern "C" void ArtInitQuickCompilerContext(art::Compiler& compiler) {
43 CHECK(compiler.GetCompilerContext() == NULL);
44 QuickCompiler* quickCompiler = new QuickCompiler(&compiler);
45 compiler.SetCompilerContext(quickCompiler);
46}
47
48extern "C" void ArtUnInitQuickCompilerContext(art::Compiler& compiler) {
49 delete reinterpret_cast<QuickCompiler*>(compiler.GetCompilerContext());
50 compiler.SetCompilerContext(NULL);
51}
52#endif
53
buzbeece302932011-10-04 14:32:18 -070054/* Default optimizer/debug setting for the compiler. */
Elliott Hughese52e49b2012-04-02 16:05:44 -070055static uint32_t kCompilerOptimizerDisableFlags = 0 | // Disable specific optimizations
Bill Buzbeea114add2012-05-03 15:00:40 -070056 //(1 << kLoadStoreElimination) |
57 //(1 << kLoadHoisting) |
58 //(1 << kSuppressLoads) |
59 //(1 << kNullCheckElimination) |
60 //(1 << kPromoteRegs) |
61 //(1 << kTrackLiveTemps) |
62 //(1 << kSkipLargeMethodOptimization) |
63 //(1 << kSafeOptimizations) |
64 //(1 << kBBOpt) |
65 //(1 << kMatch) |
66 //(1 << kPromoteCompilerTemps) |
67 0;
buzbeece302932011-10-04 14:32:18 -070068
Elliott Hughese52e49b2012-04-02 16:05:44 -070069static uint32_t kCompilerDebugFlags = 0 | // Enable debug/testing modes
Bill Buzbeea114add2012-05-03 15:00:40 -070070 //(1 << kDebugDisplayMissingTargets) |
71 //(1 << kDebugVerbose) |
72 //(1 << kDebugDumpCFG) |
73 //(1 << kDebugSlowFieldPath) |
74 //(1 << kDebugSlowInvokePath) |
75 //(1 << kDebugSlowStringPath) |
76 //(1 << kDebugSlowestFieldPath) |
77 //(1 << kDebugSlowestStringPath) |
78 //(1 << kDebugExerciseResolveMethod) |
79 //(1 << kDebugVerifyDataflow) |
80 //(1 << kDebugShowMemoryUsage) |
81 //(1 << kDebugShowNops) |
82 //(1 << kDebugCountOpcodes) |
buzbeead8f15e2012-06-18 14:49:45 -070083#if defined(ART_USE_QUICK_COMPILER)
84 //(1 << kDebugDumpBitcodeFile) |
Bill Buzbeec9f40dd2012-08-15 11:35:25 -070085 //(1 << kDebugVerifyBitcode) |
buzbeead8f15e2012-06-18 14:49:45 -070086#endif
Bill Buzbeea114add2012-05-03 15:00:40 -070087 0;
buzbeece302932011-10-04 14:32:18 -070088
buzbee31a4a6f2012-02-28 15:36:15 -080089inline bool contentIsInsn(const u2* codePtr) {
Bill Buzbeea114add2012-05-03 15:00:40 -070090 u2 instr = *codePtr;
91 Instruction::Code opcode = (Instruction::Code)(instr & 0xff);
buzbee67bf8852011-08-17 17:51:35 -070092
Bill Buzbeea114add2012-05-03 15:00:40 -070093 /*
94 * Since the low 8-bit in metadata may look like NOP, we need to check
95 * both the low and whole sub-word to determine whether it is code or data.
96 */
97 return (opcode != Instruction::NOP || instr == 0);
buzbee67bf8852011-08-17 17:51:35 -070098}
99
100/*
101 * Parse an instruction, return the length of the instruction
102 */
buzbee31a4a6f2012-02-28 15:36:15 -0800103inline int parseInsn(CompilationUnit* cUnit, const u2* codePtr,
Bill Buzbeea114add2012-05-03 15:00:40 -0700104 DecodedInstruction* decoded_instruction, bool printMe)
buzbee67bf8852011-08-17 17:51:35 -0700105{
Elliott Hughesadb8c672012-03-06 16:49:32 -0800106 // Don't parse instruction data
107 if (!contentIsInsn(codePtr)) {
108 return 0;
109 }
buzbee67bf8852011-08-17 17:51:35 -0700110
Elliott Hughesadb8c672012-03-06 16:49:32 -0800111 const Instruction* instruction = Instruction::At(codePtr);
112 *decoded_instruction = DecodedInstruction(instruction);
buzbee67bf8852011-08-17 17:51:35 -0700113
Elliott Hughesadb8c672012-03-06 16:49:32 -0800114 if (printMe) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700115 char* decodedString = oatGetDalvikDisassembly(cUnit, *decoded_instruction,
116 NULL);
117 LOG(INFO) << codePtr << ": 0x"
118 << std::hex << static_cast<int>(decoded_instruction->opcode)
Elliott Hughesadb8c672012-03-06 16:49:32 -0800119 << " " << decodedString;
120 }
121 return instruction->SizeInCodeUnits();
buzbee67bf8852011-08-17 17:51:35 -0700122}
123
124#define UNKNOWN_TARGET 0xffffffff
125
Elliott Hughesadb8c672012-03-06 16:49:32 -0800126inline bool isGoto(MIR* insn) {
127 switch (insn->dalvikInsn.opcode) {
128 case Instruction::GOTO:
129 case Instruction::GOTO_16:
130 case Instruction::GOTO_32:
131 return true;
132 default:
133 return false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700134 }
buzbee67bf8852011-08-17 17:51:35 -0700135}
136
137/*
138 * Identify unconditional branch instructions
139 */
Elliott Hughesadb8c672012-03-06 16:49:32 -0800140inline bool isUnconditionalBranch(MIR* insn) {
141 switch (insn->dalvikInsn.opcode) {
142 case Instruction::RETURN_VOID:
143 case Instruction::RETURN:
144 case Instruction::RETURN_WIDE:
145 case Instruction::RETURN_OBJECT:
146 return true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700147 default:
148 return isGoto(insn);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800149 }
buzbee67bf8852011-08-17 17:51:35 -0700150}
151
152/* Split an existing block from the specified code offset into two */
buzbee31a4a6f2012-02-28 15:36:15 -0800153BasicBlock *splitBlock(CompilationUnit* cUnit, unsigned int codeOffset,
Bill Buzbeea114add2012-05-03 15:00:40 -0700154 BasicBlock* origBlock, BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700155{
Bill Buzbeea114add2012-05-03 15:00:40 -0700156 MIR* insn = origBlock->firstMIRInsn;
157 while (insn) {
158 if (insn->offset == codeOffset) break;
159 insn = insn->next;
160 }
161 if (insn == NULL) {
162 LOG(FATAL) << "Break split failed";
163 }
164 BasicBlock *bottomBlock = oatNewBB(cUnit, kDalvikByteCode,
165 cUnit->numBlocks++);
166 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700167
Bill Buzbeea114add2012-05-03 15:00:40 -0700168 bottomBlock->startOffset = codeOffset;
169 bottomBlock->firstMIRInsn = insn;
170 bottomBlock->lastMIRInsn = origBlock->lastMIRInsn;
buzbee67bf8852011-08-17 17:51:35 -0700171
Bill Buzbeea114add2012-05-03 15:00:40 -0700172 /* Add it to the quick lookup cache */
173 cUnit->blockMap.Put(bottomBlock->startOffset, bottomBlock);
buzbee5b537102012-01-17 17:33:47 -0800174
Bill Buzbeea114add2012-05-03 15:00:40 -0700175 /* Handle the taken path */
176 bottomBlock->taken = origBlock->taken;
177 if (bottomBlock->taken) {
178 origBlock->taken = NULL;
179 oatDeleteGrowableList(bottomBlock->taken->predecessors,
buzbeeba938cb2012-02-03 14:47:55 -0800180 (intptr_t)origBlock);
Bill Buzbeea114add2012-05-03 15:00:40 -0700181 oatInsertGrowableList(cUnit, bottomBlock->taken->predecessors,
182 (intptr_t)bottomBlock);
183 }
184
185 /* Handle the fallthrough path */
Bill Buzbeea114add2012-05-03 15:00:40 -0700186 bottomBlock->fallThrough = origBlock->fallThrough;
187 origBlock->fallThrough = bottomBlock;
Bill Buzbeea114add2012-05-03 15:00:40 -0700188 oatInsertGrowableList(cUnit, bottomBlock->predecessors,
189 (intptr_t)origBlock);
190 if (bottomBlock->fallThrough) {
191 oatDeleteGrowableList(bottomBlock->fallThrough->predecessors,
192 (intptr_t)origBlock);
193 oatInsertGrowableList(cUnit, bottomBlock->fallThrough->predecessors,
194 (intptr_t)bottomBlock);
195 }
196
197 /* Handle the successor list */
198 if (origBlock->successorBlockList.blockListType != kNotUsed) {
199 bottomBlock->successorBlockList = origBlock->successorBlockList;
200 origBlock->successorBlockList.blockListType = kNotUsed;
201 GrowableListIterator iterator;
202
203 oatGrowableListIteratorInit(&bottomBlock->successorBlockList.blocks,
204 &iterator);
205 while (true) {
206 SuccessorBlockInfo *successorBlockInfo =
207 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
208 if (successorBlockInfo == NULL) break;
209 BasicBlock *bb = successorBlockInfo->block;
210 oatDeleteGrowableList(bb->predecessors, (intptr_t)origBlock);
211 oatInsertGrowableList(cUnit, bb->predecessors, (intptr_t)bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700212 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700213 }
buzbee67bf8852011-08-17 17:51:35 -0700214
Bill Buzbeea114add2012-05-03 15:00:40 -0700215 origBlock->lastMIRInsn = insn->prev;
buzbee67bf8852011-08-17 17:51:35 -0700216
Bill Buzbeea114add2012-05-03 15:00:40 -0700217 insn->prev->next = NULL;
218 insn->prev = NULL;
219 /*
220 * Update the immediate predecessor block pointer so that outgoing edges
221 * can be applied to the proper block.
222 */
223 if (immedPredBlockP) {
224 DCHECK_EQ(*immedPredBlockP, origBlock);
225 *immedPredBlockP = bottomBlock;
226 }
227 return bottomBlock;
buzbee67bf8852011-08-17 17:51:35 -0700228}
229
230/*
231 * Given a code offset, find out the block that starts with it. If the offset
buzbee9ab05de2012-01-18 15:43:48 -0800232 * is in the middle of an existing block, split it into two. If immedPredBlockP
233 * is not non-null and is the block being split, update *immedPredBlockP to
234 * point to the bottom block so that outgoing edges can be set up properly
235 * (by the caller)
buzbee5b537102012-01-17 17:33:47 -0800236 * Utilizes a map for fast lookup of the typical cases.
buzbee67bf8852011-08-17 17:51:35 -0700237 */
buzbee31a4a6f2012-02-28 15:36:15 -0800238BasicBlock *findBlock(CompilationUnit* cUnit, unsigned int codeOffset,
239 bool split, bool create, BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700240{
Bill Buzbeea114add2012-05-03 15:00:40 -0700241 GrowableList* blockList = &cUnit->blockList;
242 BasicBlock* bb;
243 unsigned int i;
244 SafeMap<unsigned int, BasicBlock*>::iterator it;
buzbee67bf8852011-08-17 17:51:35 -0700245
Bill Buzbeea114add2012-05-03 15:00:40 -0700246 it = cUnit->blockMap.find(codeOffset);
247 if (it != cUnit->blockMap.end()) {
248 return it->second;
249 } else if (!create) {
250 return NULL;
251 }
252
253 if (split) {
254 for (i = 0; i < blockList->numUsed; i++) {
255 bb = (BasicBlock *) blockList->elemList[i];
256 if (bb->blockType != kDalvikByteCode) continue;
257 /* Check if a branch jumps into the middle of an existing block */
258 if ((codeOffset > bb->startOffset) && (bb->lastMIRInsn != NULL) &&
259 (codeOffset <= bb->lastMIRInsn->offset)) {
260 BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb,
261 bb == *immedPredBlockP ?
262 immedPredBlockP : NULL);
263 return newBB;
264 }
buzbee5b537102012-01-17 17:33:47 -0800265 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700266 }
buzbee5b537102012-01-17 17:33:47 -0800267
Bill Buzbeea114add2012-05-03 15:00:40 -0700268 /* Create a new one */
269 bb = oatNewBB(cUnit, kDalvikByteCode, cUnit->numBlocks++);
270 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) bb);
271 bb->startOffset = codeOffset;
272 cUnit->blockMap.Put(bb->startOffset, bb);
273 return bb;
buzbee67bf8852011-08-17 17:51:35 -0700274}
275
buzbeef58c12c2012-07-03 15:06:29 -0700276/* Find existing block */
277BasicBlock* oatFindBlock(CompilationUnit* cUnit, unsigned int codeOffset)
278{
279 return findBlock(cUnit, codeOffset, false, false, NULL);
280}
281
buzbeead8f15e2012-06-18 14:49:45 -0700282/* Turn method name into a legal Linux file name */
283void oatReplaceSpecialChars(std::string& str)
284{
285 static const struct { const char before; const char after; } match[] =
286 {{'/','-'}, {';','#'}, {' ','#'}, {'$','+'},
287 {'(','@'}, {')','@'}, {'<','='}, {'>','='}};
288 for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) {
289 std::replace(str.begin(), str.end(), match[i].before, match[i].after);
290 }
291}
292
buzbee67bf8852011-08-17 17:51:35 -0700293/* Dump the CFG into a DOT graph */
294void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix)
295{
Bill Buzbeea114add2012-05-03 15:00:40 -0700296 FILE* file;
buzbeead8f15e2012-06-18 14:49:45 -0700297 std::string fname(PrettyMethod(cUnit->method_idx, *cUnit->dex_file));
298 oatReplaceSpecialChars(fname);
299 fname = StringPrintf("%s%s%x.dot", dirPrefix, fname.c_str(),
300 cUnit->entryBlock->fallThrough->startOffset);
301 file = fopen(fname.c_str(), "w");
Bill Buzbeea114add2012-05-03 15:00:40 -0700302 if (file == NULL) {
303 return;
304 }
305 fprintf(file, "digraph G {\n");
306
307 fprintf(file, " rankdir=TB\n");
308
309 int numReachableBlocks = cUnit->numReachableBlocks;
310 int idx;
311 const GrowableList *blockList = &cUnit->blockList;
312
313 for (idx = 0; idx < numReachableBlocks; idx++) {
314 int blockIdx = cUnit->dfsOrder.elemList[idx];
315 BasicBlock *bb = (BasicBlock *) oatGrowableListGetElement(blockList,
316 blockIdx);
317 if (bb == NULL) break;
318 if (bb->blockType == kEntryBlock) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700319 fprintf(file, " entry_%d [shape=Mdiamond];\n", bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700320 } else if (bb->blockType == kExitBlock) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700321 fprintf(file, " exit_%d [shape=Mdiamond];\n", bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700322 } else if (bb->blockType == kDalvikByteCode) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700323 fprintf(file, " block%04x_%d [shape=record,label = \"{ \\\n",
324 bb->startOffset, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700325 const MIR *mir;
326 fprintf(file, " {block id %d\\l}%s\\\n", bb->id,
327 bb->firstMIRInsn ? " | " : " ");
328 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
329 fprintf(file, " {%04x %s\\l}%s\\\n", mir->offset,
330 mir->ssaRep ? oatFullDisassembler(cUnit, mir) :
331 Instruction::Name(mir->dalvikInsn.opcode),
332 mir->next ? " | " : " ");
333 }
334 fprintf(file, " }\"];\n\n");
335 } else if (bb->blockType == kExceptionHandling) {
336 char blockName[BLOCK_NAME_LEN];
337
338 oatGetBlockName(bb, blockName);
339 fprintf(file, " %s [shape=invhouse];\n", blockName);
buzbee67bf8852011-08-17 17:51:35 -0700340 }
buzbee67bf8852011-08-17 17:51:35 -0700341
Bill Buzbeea114add2012-05-03 15:00:40 -0700342 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
buzbee67bf8852011-08-17 17:51:35 -0700343
Bill Buzbeea114add2012-05-03 15:00:40 -0700344 if (bb->taken) {
345 oatGetBlockName(bb, blockName1);
346 oatGetBlockName(bb->taken, blockName2);
347 fprintf(file, " %s:s -> %s:n [style=dotted]\n",
348 blockName1, blockName2);
buzbee67bf8852011-08-17 17:51:35 -0700349 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700350 if (bb->fallThrough) {
351 oatGetBlockName(bb, blockName1);
352 oatGetBlockName(bb->fallThrough, blockName2);
353 fprintf(file, " %s:s -> %s:n\n", blockName1, blockName2);
354 }
355
356 if (bb->successorBlockList.blockListType != kNotUsed) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700357 fprintf(file, " succ%04x_%d [shape=%s,label = \"{ \\\n",
358 bb->startOffset, bb->id,
Bill Buzbeea114add2012-05-03 15:00:40 -0700359 (bb->successorBlockList.blockListType == kCatch) ?
360 "Mrecord" : "record");
361 GrowableListIterator iterator;
362 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
363 &iterator);
364 SuccessorBlockInfo *successorBlockInfo =
365 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
366
367 int succId = 0;
368 while (true) {
369 if (successorBlockInfo == NULL) break;
370
371 BasicBlock *destBlock = successorBlockInfo->block;
372 SuccessorBlockInfo *nextSuccessorBlockInfo =
373 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
374
375 fprintf(file, " {<f%d> %04x: %04x\\l}%s\\\n",
376 succId++,
377 successorBlockInfo->key,
378 destBlock->startOffset,
379 (nextSuccessorBlockInfo != NULL) ? " | " : " ");
380
381 successorBlockInfo = nextSuccessorBlockInfo;
382 }
383 fprintf(file, " }\"];\n\n");
384
385 oatGetBlockName(bb, blockName1);
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700386 fprintf(file, " %s:s -> succ%04x_%d:n [style=dashed]\n",
387 blockName1, bb->startOffset, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700388
389 if (bb->successorBlockList.blockListType == kPackedSwitch ||
390 bb->successorBlockList.blockListType == kSparseSwitch) {
391
392 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
393 &iterator);
394
395 succId = 0;
396 while (true) {
397 SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
398 oatGrowableListIteratorNext(&iterator);
399 if (successorBlockInfo == NULL) break;
400
401 BasicBlock *destBlock = successorBlockInfo->block;
402
403 oatGetBlockName(destBlock, blockName2);
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700404 fprintf(file, " succ%04x_%d:f%d:e -> %s:n\n", bb->startOffset,
405 bb->id, succId++, blockName2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700406 }
407 }
408 }
409 fprintf(file, "\n");
410
411 /* Display the dominator tree */
412 oatGetBlockName(bb, blockName1);
413 fprintf(file, " cfg%s [label=\"%s\", shape=none];\n",
414 blockName1, blockName1);
415 if (bb->iDom) {
416 oatGetBlockName(bb->iDom, blockName2);
417 fprintf(file, " cfg%s:s -> cfg%s:n\n\n", blockName2, blockName1);
418 }
419 }
420 fprintf(file, "}\n");
421 fclose(file);
buzbee67bf8852011-08-17 17:51:35 -0700422}
423
424/* Verify if all the successor is connected with all the claimed predecessors */
buzbee31a4a6f2012-02-28 15:36:15 -0800425bool verifyPredInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700426{
Bill Buzbeea114add2012-05-03 15:00:40 -0700427 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700428
Bill Buzbeea114add2012-05-03 15:00:40 -0700429 oatGrowableListIteratorInit(bb->predecessors, &iter);
430 while (true) {
431 BasicBlock *predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
432 if (!predBB) break;
433 bool found = false;
434 if (predBB->taken == bb) {
435 found = true;
436 } else if (predBB->fallThrough == bb) {
437 found = true;
438 } else if (predBB->successorBlockList.blockListType != kNotUsed) {
439 GrowableListIterator iterator;
440 oatGrowableListIteratorInit(&predBB->successorBlockList.blocks,
441 &iterator);
442 while (true) {
443 SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
444 oatGrowableListIteratorNext(&iterator);
445 if (successorBlockInfo == NULL) break;
446 BasicBlock *succBB = successorBlockInfo->block;
447 if (succBB == bb) {
buzbee67bf8852011-08-17 17:51:35 -0700448 found = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700449 break;
buzbee67bf8852011-08-17 17:51:35 -0700450 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700451 }
buzbee67bf8852011-08-17 17:51:35 -0700452 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700453 if (found == false) {
454 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
455 oatGetBlockName(bb, blockName1);
456 oatGetBlockName(predBB, blockName2);
457 oatDumpCFG(cUnit, "/sdcard/cfg/");
458 LOG(FATAL) << "Successor " << blockName1 << "not found from "
459 << blockName2;
460 }
461 }
462 return true;
buzbee67bf8852011-08-17 17:51:35 -0700463}
464
465/* Identify code range in try blocks and set up the empty catch blocks */
buzbee31a4a6f2012-02-28 15:36:15 -0800466void processTryCatchBlocks(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700467{
Bill Buzbeea114add2012-05-03 15:00:40 -0700468 const DexFile::CodeItem* code_item = cUnit->code_item;
469 int triesSize = code_item->tries_size_;
470 int offset;
buzbee67bf8852011-08-17 17:51:35 -0700471
Bill Buzbeea114add2012-05-03 15:00:40 -0700472 if (triesSize == 0) {
473 return;
474 }
475
476 ArenaBitVector* tryBlockAddr = cUnit->tryBlockAddr;
477
478 for (int i = 0; i < triesSize; i++) {
479 const DexFile::TryItem* pTry =
480 DexFile::GetTryItems(*code_item, i);
481 int startOffset = pTry->start_addr_;
482 int endOffset = startOffset + pTry->insn_count_;
483 for (offset = startOffset; offset < endOffset; offset++) {
484 oatSetBit(cUnit, tryBlockAddr, offset);
buzbee67bf8852011-08-17 17:51:35 -0700485 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700486 }
buzbee67bf8852011-08-17 17:51:35 -0700487
Bill Buzbeea114add2012-05-03 15:00:40 -0700488 // Iterate over each of the handlers to enqueue the empty Catch blocks
489 const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item, 0);
490 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
491 for (uint32_t idx = 0; idx < handlers_size; idx++) {
492 CatchHandlerIterator iterator(handlers_ptr);
493 for (; iterator.HasNext(); iterator.Next()) {
494 uint32_t address = iterator.GetHandlerAddress();
495 findBlock(cUnit, address, false /* split */, true /*create*/,
496 /* immedPredBlockP */ NULL);
buzbee67bf8852011-08-17 17:51:35 -0700497 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700498 handlers_ptr = iterator.EndDataPointer();
499 }
buzbee67bf8852011-08-17 17:51:35 -0700500}
501
Elliott Hughesadb8c672012-03-06 16:49:32 -0800502/* Process instructions with the kBranch flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800503BasicBlock* processCanBranch(CompilationUnit* cUnit, BasicBlock* curBlock,
Bill Buzbeea114add2012-05-03 15:00:40 -0700504 MIR* insn, int curOffset, int width, int flags,
505 const u2* codePtr, const u2* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700506{
Bill Buzbeea114add2012-05-03 15:00:40 -0700507 int target = curOffset;
508 switch (insn->dalvikInsn.opcode) {
509 case Instruction::GOTO:
510 case Instruction::GOTO_16:
511 case Instruction::GOTO_32:
512 target += (int) insn->dalvikInsn.vA;
513 break;
514 case Instruction::IF_EQ:
515 case Instruction::IF_NE:
516 case Instruction::IF_LT:
517 case Instruction::IF_GE:
518 case Instruction::IF_GT:
519 case Instruction::IF_LE:
520 target += (int) insn->dalvikInsn.vC;
521 break;
522 case Instruction::IF_EQZ:
523 case Instruction::IF_NEZ:
524 case Instruction::IF_LTZ:
525 case Instruction::IF_GEZ:
526 case Instruction::IF_GTZ:
527 case Instruction::IF_LEZ:
528 target += (int) insn->dalvikInsn.vB;
529 break;
530 default:
531 LOG(FATAL) << "Unexpected opcode(" << (int)insn->dalvikInsn.opcode
532 << ") with kBranch set";
533 }
534 BasicBlock *takenBlock = findBlock(cUnit, target,
535 /* split */
536 true,
537 /* create */
538 true,
539 /* immedPredBlockP */
540 &curBlock);
541 curBlock->taken = takenBlock;
542 oatInsertGrowableList(cUnit, takenBlock->predecessors, (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700543
Bill Buzbeea114add2012-05-03 15:00:40 -0700544 /* Always terminate the current block for conditional branches */
545 if (flags & Instruction::kContinue) {
546 BasicBlock *fallthroughBlock = findBlock(cUnit,
547 curOffset + width,
548 /*
549 * If the method is processed
550 * in sequential order from the
551 * beginning, we don't need to
552 * specify split for continue
553 * blocks. However, this
554 * routine can be called by
555 * compileLoop, which starts
556 * parsing the method from an
557 * arbitrary address in the
558 * method body.
559 */
560 true,
561 /* create */
562 true,
563 /* immedPredBlockP */
564 &curBlock);
565 curBlock->fallThrough = fallthroughBlock;
566 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
567 (intptr_t)curBlock);
568 } else if (codePtr < codeEnd) {
569 /* Create a fallthrough block for real instructions (incl. NOP) */
570 if (contentIsInsn(codePtr)) {
571 findBlock(cUnit, curOffset + width,
572 /* split */
573 false,
574 /* create */
575 true,
576 /* immedPredBlockP */
577 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700578 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700579 }
580 return curBlock;
buzbee67bf8852011-08-17 17:51:35 -0700581}
582
Elliott Hughesadb8c672012-03-06 16:49:32 -0800583/* Process instructions with the kSwitch flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800584void processCanSwitch(CompilationUnit* cUnit, BasicBlock* curBlock,
585 MIR* insn, int curOffset, int width, int flags)
buzbee67bf8852011-08-17 17:51:35 -0700586{
Bill Buzbeea114add2012-05-03 15:00:40 -0700587 u2* switchData= (u2 *) (cUnit->insns + curOffset + insn->dalvikInsn.vB);
588 int size;
589 int* keyTable;
590 int* targetTable;
591 int i;
592 int firstKey;
buzbee67bf8852011-08-17 17:51:35 -0700593
Bill Buzbeea114add2012-05-03 15:00:40 -0700594 /*
595 * Packed switch data format:
596 * ushort ident = 0x0100 magic value
597 * ushort size number of entries in the table
598 * int first_key first (and lowest) switch case value
599 * int targets[size] branch targets, relative to switch opcode
600 *
601 * Total size is (4+size*2) 16-bit code units.
602 */
603 if (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) {
604 DCHECK_EQ(static_cast<int>(switchData[0]),
605 static_cast<int>(Instruction::kPackedSwitchSignature));
606 size = switchData[1];
607 firstKey = switchData[2] | (switchData[3] << 16);
608 targetTable = (int *) &switchData[4];
609 keyTable = NULL; // Make the compiler happy
610 /*
611 * Sparse switch data format:
612 * ushort ident = 0x0200 magic value
613 * ushort size number of entries in the table; > 0
614 * int keys[size] keys, sorted low-to-high; 32-bit aligned
615 * int targets[size] branch targets, relative to switch opcode
616 *
617 * Total size is (2+size*4) 16-bit code units.
618 */
619 } else {
620 DCHECK_EQ(static_cast<int>(switchData[0]),
621 static_cast<int>(Instruction::kSparseSwitchSignature));
622 size = switchData[1];
623 keyTable = (int *) &switchData[2];
624 targetTable = (int *) &switchData[2 + size*2];
625 firstKey = 0; // To make the compiler happy
626 }
buzbee67bf8852011-08-17 17:51:35 -0700627
Bill Buzbeea114add2012-05-03 15:00:40 -0700628 if (curBlock->successorBlockList.blockListType != kNotUsed) {
629 LOG(FATAL) << "Successor block list already in use: "
630 << (int)curBlock->successorBlockList.blockListType;
631 }
632 curBlock->successorBlockList.blockListType =
633 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
634 kPackedSwitch : kSparseSwitch;
635 oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, size,
636 kListSuccessorBlocks);
637
638 for (i = 0; i < size; i++) {
639 BasicBlock *caseBlock = findBlock(cUnit, curOffset + targetTable[i],
640 /* split */
641 true,
642 /* create */
643 true,
644 /* immedPredBlockP */
645 &curBlock);
646 SuccessorBlockInfo *successorBlockInfo =
647 (SuccessorBlockInfo *) oatNew(cUnit, sizeof(SuccessorBlockInfo),
648 false, kAllocSuccessor);
649 successorBlockInfo->block = caseBlock;
650 successorBlockInfo->key =
Elliott Hughesadb8c672012-03-06 16:49:32 -0800651 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
Bill Buzbeea114add2012-05-03 15:00:40 -0700652 firstKey + i : keyTable[i];
653 oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
654 (intptr_t) successorBlockInfo);
655 oatInsertGrowableList(cUnit, caseBlock->predecessors,
buzbeeba938cb2012-02-03 14:47:55 -0800656 (intptr_t)curBlock);
Bill Buzbeea114add2012-05-03 15:00:40 -0700657 }
658
659 /* Fall-through case */
660 BasicBlock* fallthroughBlock = findBlock(cUnit,
661 curOffset + width,
662 /* split */
663 false,
664 /* create */
665 true,
666 /* immedPredBlockP */
667 NULL);
668 curBlock->fallThrough = fallthroughBlock;
669 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
670 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700671}
672
Elliott Hughesadb8c672012-03-06 16:49:32 -0800673/* Process instructions with the kThrow flag */
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700674BasicBlock* processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock,
675 MIR* insn, int curOffset, int width, int flags,
676 ArenaBitVector* tryBlockAddr, const u2* codePtr,
677 const u2* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700678{
Bill Buzbeea114add2012-05-03 15:00:40 -0700679 const DexFile::CodeItem* code_item = cUnit->code_item;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700680 bool inTryBlock = oatIsBitSet(tryBlockAddr, curOffset);
buzbee67bf8852011-08-17 17:51:35 -0700681
Bill Buzbeea114add2012-05-03 15:00:40 -0700682 /* In try block */
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700683 if (inTryBlock) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700684 CatchHandlerIterator iterator(*code_item, curOffset);
buzbee67bf8852011-08-17 17:51:35 -0700685
Bill Buzbeea114add2012-05-03 15:00:40 -0700686 if (curBlock->successorBlockList.blockListType != kNotUsed) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700687 LOG(INFO) << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
Bill Buzbeea114add2012-05-03 15:00:40 -0700688 LOG(FATAL) << "Successor block list already in use: "
689 << (int)curBlock->successorBlockList.blockListType;
buzbee67bf8852011-08-17 17:51:35 -0700690 }
691
Bill Buzbeea114add2012-05-03 15:00:40 -0700692 curBlock->successorBlockList.blockListType = kCatch;
693 oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, 2,
694 kListSuccessorBlocks);
695
696 for (;iterator.HasNext(); iterator.Next()) {
697 BasicBlock *catchBlock = findBlock(cUnit, iterator.GetHandlerAddress(),
698 false /* split*/,
699 false /* creat */,
700 NULL /* immedPredBlockP */);
701 catchBlock->catchEntry = true;
702 SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
703 oatNew(cUnit, sizeof(SuccessorBlockInfo), false, kAllocSuccessor);
704 successorBlockInfo->block = catchBlock;
705 successorBlockInfo->key = iterator.GetHandlerTypeIndex();
706 oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
707 (intptr_t) successorBlockInfo);
708 oatInsertGrowableList(cUnit, catchBlock->predecessors,
709 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700710 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700711 } else {
712 BasicBlock *ehBlock = oatNewBB(cUnit, kExceptionHandling,
713 cUnit->numBlocks++);
714 curBlock->taken = ehBlock;
715 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) ehBlock);
716 ehBlock->startOffset = curOffset;
717 oatInsertGrowableList(cUnit, ehBlock->predecessors, (intptr_t)curBlock);
718 }
719
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700720 if (insn->dalvikInsn.opcode == Instruction::THROW){
721 if ((codePtr < codeEnd) && contentIsInsn(codePtr)) {
722 // Force creation of new block following THROW via side-effect
723 findBlock(cUnit, curOffset + width, /* split */ false,
724 /* create */ true, /* immedPredBlockP */ NULL);
725 }
726 if (!inTryBlock) {
727 // Don't split a THROW that can't rethrow - we're done.
728 return curBlock;
Bill Buzbeea114add2012-05-03 15:00:40 -0700729 }
730 }
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700731
732 /*
733 * Split the potentially-throwing instruction into two parts.
734 * The first half will be a pseudo-op that captures the exception
735 * edges and terminates the basic block. It always falls through.
736 * Then, create a new basic block that begins with the throwing instruction
737 * (minus exceptions). Note: this new basic block must NOT be entered into
738 * the blockMap. If the potentially-throwing instruction is the target of a
739 * future branch, we need to find the check psuedo half. The new
740 * basic block containing the work portion of the instruction should
741 * only be entered via fallthrough from the block containing the
742 * pseudo exception edge MIR. Note also that this new block is
743 * not automatically terminated after the work portion, and may
744 * contain following instructions.
745 */
746 BasicBlock *newBlock = oatNewBB(cUnit, kDalvikByteCode, cUnit->numBlocks++);
747 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t)newBlock);
748 newBlock->startOffset = insn->offset;
749 curBlock->fallThrough = newBlock;
750 oatInsertGrowableList(cUnit, newBlock->predecessors, (intptr_t)curBlock);
751 MIR* newInsn = (MIR*)oatNew(cUnit, sizeof(MIR), true, kAllocMIR);
752 *newInsn = *insn;
753 insn->dalvikInsn.opcode =
754 static_cast<Instruction::Code>(kMirOpCheck);
755 // Associate the two halves
756 insn->meta.throwInsn = newInsn;
757 newInsn->meta.throwInsn = insn;
758 oatAppendMIR(newBlock, newInsn);
759 return newBlock;
buzbee67bf8852011-08-17 17:51:35 -0700760}
761
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800762void oatInit(CompilationUnit* cUnit, const Compiler& compiler) {
763 if (!oatArchInit()) {
764 LOG(FATAL) << "Failed to initialize oat";
765 }
766 if (!oatHeapInit(cUnit)) {
767 LOG(FATAL) << "Failed to initialize oat heap";
768 }
769}
770
Elliott Hughes3fa1b7e2012-03-13 17:06:22 -0700771CompiledMethod* oatCompileMethod(Compiler& compiler,
772 const DexFile::CodeItem* code_item,
Ian Rogers08f753d2012-08-24 14:35:25 -0700773 uint32_t access_flags, InvokeType invoke_type,
774 uint32_t method_idx,
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700775 jobject class_loader,
Elliott Hughes3fa1b7e2012-03-13 17:06:22 -0700776 const DexFile& dex_file)
buzbee67bf8852011-08-17 17:51:35 -0700777{
Bill Buzbeea114add2012-05-03 15:00:40 -0700778 VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
Brian Carlstrom94496d32011-08-22 09:22:47 -0700779
Bill Buzbeea114add2012-05-03 15:00:40 -0700780 const u2* codePtr = code_item->insns_;
781 const u2* codeEnd = code_item->insns_ + code_item->insns_size_in_code_units_;
782 int numBlocks = 0;
783 unsigned int curOffset = 0;
buzbee67bf8852011-08-17 17:51:35 -0700784
Bill Buzbeea114add2012-05-03 15:00:40 -0700785 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
786 UniquePtr<CompilationUnit> cUnit(new CompilationUnit);
buzbeeba938cb2012-02-03 14:47:55 -0800787
Bill Buzbeea114add2012-05-03 15:00:40 -0700788 oatInit(cUnit.get(), compiler);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800789
Bill Buzbeea114add2012-05-03 15:00:40 -0700790 cUnit->compiler = &compiler;
791 cUnit->class_linker = class_linker;
792 cUnit->dex_file = &dex_file;
Bill Buzbeea114add2012-05-03 15:00:40 -0700793 cUnit->method_idx = method_idx;
794 cUnit->code_item = code_item;
795 cUnit->access_flags = access_flags;
Ian Rogers08f753d2012-08-24 14:35:25 -0700796 cUnit->invoke_type = invoke_type;
Bill Buzbeea114add2012-05-03 15:00:40 -0700797 cUnit->shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
798 cUnit->instructionSet = compiler.GetInstructionSet();
799 cUnit->insns = code_item->insns_;
800 cUnit->insnsSize = code_item->insns_size_in_code_units_;
801 cUnit->numIns = code_item->ins_size_;
802 cUnit->numRegs = code_item->registers_size_ - cUnit->numIns;
803 cUnit->numOuts = code_item->outs_size_;
buzbee2cfc6392012-05-07 14:51:40 -0700804#if defined(ART_USE_QUICK_COMPILER)
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700805 DCHECK((cUnit->instructionSet == kThumb2) ||
806 (cUnit->instructionSet == kX86) ||
807 (cUnit->instructionSet == kMips));
808 if (cUnit->instructionSet == kThumb2) {
809 // TODO: remove this once x86 is tested
buzbee85eee022012-07-16 22:12:38 -0700810 cUnit->genBitcode = true;
811 }
buzbee2a83e8f2012-07-13 16:42:30 -0700812#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700813 /* Adjust this value accordingly once inlining is performed */
814 cUnit->numDalvikRegisters = code_item->registers_size_;
815 // TODO: set this from command line
816 cUnit->compilerFlipMatch = false;
817 bool useMatch = !cUnit->compilerMethodMatch.empty();
818 bool match = useMatch && (cUnit->compilerFlipMatch ^
819 (PrettyMethod(method_idx, dex_file).find(cUnit->compilerMethodMatch) !=
820 std::string::npos));
821 if (!useMatch || match) {
822 cUnit->disableOpt = kCompilerOptimizerDisableFlags;
823 cUnit->enableDebug = kCompilerDebugFlags;
824 cUnit->printMe = VLOG_IS_ON(compiler) ||
825 (cUnit->enableDebug & (1 << kDebugVerbose));
826 }
buzbee2cfc6392012-05-07 14:51:40 -0700827#if defined(ART_USE_QUICK_COMPILER)
buzbee6969d502012-06-15 16:40:31 -0700828 if (cUnit->genBitcode) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700829 //cUnit->enableDebug |= (1 << kDebugVerifyBitcode);
buzbee2a83e8f2012-07-13 16:42:30 -0700830 //cUnit->printMe = true;
831 //cUnit->enableDebug |= (1 << kDebugDumpBitcodeFile);
buzbee6969d502012-06-15 16:40:31 -0700832 }
buzbee2cfc6392012-05-07 14:51:40 -0700833#endif
jeffhao7fbee072012-08-24 17:56:54 -0700834 if (cUnit->instructionSet == kMips) {
835 // Disable some optimizations for mips for now
836 cUnit->disableOpt |= (
837 (1 << kLoadStoreElimination) |
838 (1 << kLoadHoisting) |
839 (1 << kSuppressLoads) |
840 (1 << kNullCheckElimination) |
841 (1 << kPromoteRegs) |
842 (1 << kTrackLiveTemps) |
843 (1 << kSkipLargeMethodOptimization) |
844 (1 << kSafeOptimizations) |
845 (1 << kBBOpt) |
846 (1 << kMatch) |
847 (1 << kPromoteCompilerTemps));
848 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700849 /* Are we generating code for the debugger? */
850 if (compiler.IsDebuggingSupported()) {
851 cUnit->genDebugger = true;
852 // Yes, disable most optimizations
853 cUnit->disableOpt |= (
854 (1 << kLoadStoreElimination) |
855 (1 << kLoadHoisting) |
856 (1 << kSuppressLoads) |
857 (1 << kPromoteRegs) |
858 (1 << kBBOpt) |
859 (1 << kMatch) |
860 (1 << kTrackLiveTemps));
861 }
862
863 /* Gathering opcode stats? */
864 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
865 cUnit->opcodeCount = (int*)oatNew(cUnit.get(),
866 kNumPackedOpcodes * sizeof(int), true, kAllocMisc);
867 }
868
869 /* Assume non-throwing leaf */
870 cUnit->attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE);
871
872 /* Initialize the block list, estimate size based on insnsSize */
873 oatInitGrowableList(cUnit.get(), &cUnit->blockList, cUnit->insnsSize,
874 kListBlockList);
875
876 /* Initialize the switchTables list */
877 oatInitGrowableList(cUnit.get(), &cUnit->switchTables, 4,
878 kListSwitchTables);
879
880 /* Intialize the fillArrayData list */
881 oatInitGrowableList(cUnit.get(), &cUnit->fillArrayData, 4,
882 kListFillArrayData);
883
884 /* Intialize the throwLaunchpads list, estimate size based on insnsSize */
885 oatInitGrowableList(cUnit.get(), &cUnit->throwLaunchpads, cUnit->insnsSize,
886 kListThrowLaunchPads);
887
888 /* Intialize the instrinsicLaunchpads list */
889 oatInitGrowableList(cUnit.get(), &cUnit->intrinsicLaunchpads, 4,
890 kListMisc);
891
892
893 /* Intialize the suspendLaunchpads list */
894 oatInitGrowableList(cUnit.get(), &cUnit->suspendLaunchpads, 2048,
895 kListSuspendLaunchPads);
896
897 /* Allocate the bit-vector to track the beginning of basic blocks */
898 ArenaBitVector *tryBlockAddr = oatAllocBitVector(cUnit.get(),
899 cUnit->insnsSize,
900 true /* expandable */);
901 cUnit->tryBlockAddr = tryBlockAddr;
902
903 /* Create the default entry and exit blocks and enter them to the list */
904 BasicBlock *entryBlock = oatNewBB(cUnit.get(), kEntryBlock, numBlocks++);
905 BasicBlock *exitBlock = oatNewBB(cUnit.get(), kExitBlock, numBlocks++);
906
907 cUnit->entryBlock = entryBlock;
908 cUnit->exitBlock = exitBlock;
909
910 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) entryBlock);
911 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) exitBlock);
912
913 /* Current block to record parsed instructions */
914 BasicBlock *curBlock = oatNewBB(cUnit.get(), kDalvikByteCode, numBlocks++);
915 curBlock->startOffset = 0;
916 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) curBlock);
917 /* Add first block to the fast lookup cache */
918 cUnit->blockMap.Put(curBlock->startOffset, curBlock);
919 entryBlock->fallThrough = curBlock;
920 oatInsertGrowableList(cUnit.get(), curBlock->predecessors,
921 (intptr_t)entryBlock);
922
923 /*
924 * Store back the number of blocks since new blocks may be created of
925 * accessing cUnit.
926 */
927 cUnit->numBlocks = numBlocks;
928
929 /* Identify code range in try blocks and set up the empty catch blocks */
930 processTryCatchBlocks(cUnit.get());
931
932 /* Set up for simple method detection */
933 int numPatterns = sizeof(specialPatterns)/sizeof(specialPatterns[0]);
934 bool livePattern = (numPatterns > 0) && !(cUnit->disableOpt & (1 << kMatch));
Elliott Hughesabe64aa2012-05-30 17:34:45 -0700935 bool* deadPattern = (bool*)oatNew(cUnit.get(), sizeof(bool) * numPatterns, true,
Bill Buzbeea114add2012-05-03 15:00:40 -0700936 kAllocMisc);
937 SpecialCaseHandler specialCase = kNoHandler;
938 int patternPos = 0;
939
940 /* Parse all instructions and put them into containing basic blocks */
941 while (codePtr < codeEnd) {
942 MIR *insn = (MIR *) oatNew(cUnit.get(), sizeof(MIR), true, kAllocMIR);
943 insn->offset = curOffset;
944 int width = parseInsn(cUnit.get(), codePtr, &insn->dalvikInsn, false);
945 insn->width = width;
946 Instruction::Code opcode = insn->dalvikInsn.opcode;
947 if (cUnit->opcodeCount != NULL) {
948 cUnit->opcodeCount[static_cast<int>(opcode)]++;
buzbee44b412b2012-02-04 08:50:53 -0800949 }
950
Bill Buzbeea114add2012-05-03 15:00:40 -0700951 /* Terminate when the data section is seen */
952 if (width == 0)
953 break;
954
955 /* Possible simple method? */
956 if (livePattern) {
957 livePattern = false;
958 specialCase = kNoHandler;
959 for (int i = 0; i < numPatterns; i++) {
960 if (!deadPattern[i]) {
961 if (specialPatterns[i].opcodes[patternPos] == opcode) {
962 livePattern = true;
963 specialCase = specialPatterns[i].handlerCode;
964 } else {
965 deadPattern[i] = true;
966 }
967 }
968 }
969 patternPos++;
buzbeea7c12682012-03-19 13:13:53 -0700970 }
971
Bill Buzbeea114add2012-05-03 15:00:40 -0700972 oatAppendMIR(curBlock, insn);
buzbeecefd1872011-09-09 09:59:52 -0700973
Bill Buzbeea114add2012-05-03 15:00:40 -0700974 codePtr += width;
975 int flags = Instruction::Flags(insn->dalvikInsn.opcode);
buzbee67bf8852011-08-17 17:51:35 -0700976
Bill Buzbeea114add2012-05-03 15:00:40 -0700977 int dfFlags = oatDataFlowAttributes[insn->dalvikInsn.opcode];
buzbee67bf8852011-08-17 17:51:35 -0700978
Bill Buzbeea114add2012-05-03 15:00:40 -0700979 if (dfFlags & DF_HAS_DEFS) {
buzbeebff24652012-05-06 16:22:05 -0700980 cUnit->defCount += (dfFlags & DF_A_WIDE) ? 2 : 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700981 }
buzbee67bf8852011-08-17 17:51:35 -0700982
Bill Buzbeea114add2012-05-03 15:00:40 -0700983 if (flags & Instruction::kBranch) {
984 curBlock = processCanBranch(cUnit.get(), curBlock, insn, curOffset,
985 width, flags, codePtr, codeEnd);
986 } else if (flags & Instruction::kReturn) {
987 curBlock->fallThrough = exitBlock;
988 oatInsertGrowableList(cUnit.get(), exitBlock->predecessors,
989 (intptr_t)curBlock);
990 /*
991 * Terminate the current block if there are instructions
992 * afterwards.
993 */
994 if (codePtr < codeEnd) {
995 /*
996 * Create a fallthrough block for real instructions
997 * (incl. NOP).
998 */
999 if (contentIsInsn(codePtr)) {
1000 findBlock(cUnit.get(), curOffset + width,
1001 /* split */
1002 false,
1003 /* create */
1004 true,
1005 /* immedPredBlockP */
1006 NULL);
1007 }
1008 }
1009 } else if (flags & Instruction::kThrow) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -07001010 curBlock = processCanThrow(cUnit.get(), curBlock, insn, curOffset,
1011 width, flags, tryBlockAddr, codePtr, codeEnd);
Bill Buzbeea114add2012-05-03 15:00:40 -07001012 } else if (flags & Instruction::kSwitch) {
1013 processCanSwitch(cUnit.get(), curBlock, insn, curOffset, width, flags);
1014 }
1015 curOffset += width;
1016 BasicBlock *nextBlock = findBlock(cUnit.get(), curOffset,
1017 /* split */
1018 false,
1019 /* create */
1020 false,
1021 /* immedPredBlockP */
1022 NULL);
1023 if (nextBlock) {
1024 /*
1025 * The next instruction could be the target of a previously parsed
1026 * forward branch so a block is already created. If the current
1027 * instruction is not an unconditional branch, connect them through
1028 * the fall-through link.
1029 */
1030 DCHECK(curBlock->fallThrough == NULL ||
1031 curBlock->fallThrough == nextBlock ||
1032 curBlock->fallThrough == exitBlock);
buzbee5ade1d22011-09-09 14:44:52 -07001033
Bill Buzbeea114add2012-05-03 15:00:40 -07001034 if ((curBlock->fallThrough == NULL) && (flags & Instruction::kContinue)) {
1035 curBlock->fallThrough = nextBlock;
1036 oatInsertGrowableList(cUnit.get(), nextBlock->predecessors,
1037 (intptr_t)curBlock);
1038 }
1039 curBlock = nextBlock;
1040 }
1041 }
buzbeefc9e6fa2012-03-23 15:14:29 -07001042
Bill Buzbeea114add2012-05-03 15:00:40 -07001043 if (!(cUnit->disableOpt & (1 << kSkipLargeMethodOptimization))) {
1044 if ((cUnit->numBlocks > MANY_BLOCKS) ||
1045 ((cUnit->numBlocks > MANY_BLOCKS_INITIALIZER) &&
1046 PrettyMethod(method_idx, dex_file, false).find("init>") !=
1047 std::string::npos)) {
1048 cUnit->qdMode = true;
1049 }
1050 }
buzbeefc9e6fa2012-03-23 15:14:29 -07001051
buzbee2cfc6392012-05-07 14:51:40 -07001052#if defined(ART_USE_QUICK_COMPILER)
1053 if (cUnit->genBitcode) {
1054 // Bitcode generation requires full dataflow analysis, no qdMode
1055 cUnit->qdMode = false;
1056 }
1057#endif
1058
Bill Buzbeea114add2012-05-03 15:00:40 -07001059 if (cUnit->qdMode) {
1060 cUnit->disableDataflow = true;
1061 // Disable optimization which require dataflow/ssa
1062 cUnit->disableOpt |=
1063 (1 << kNullCheckElimination) |
1064 (1 << kBBOpt) |
1065 (1 << kPromoteRegs);
1066 if (cUnit->printMe) {
1067 LOG(INFO) << "QD mode enabled: "
1068 << PrettyMethod(method_idx, dex_file)
1069 << " too big: " << cUnit->numBlocks;
1070 }
1071 }
buzbeec1f45042011-09-21 16:03:19 -07001072
Bill Buzbeea114add2012-05-03 15:00:40 -07001073 if (cUnit->printMe) {
1074 oatDumpCompilationUnit(cUnit.get());
1075 }
buzbee67bf8852011-08-17 17:51:35 -07001076
Bill Buzbeea114add2012-05-03 15:00:40 -07001077 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
1078 /* Verify if all blocks are connected as claimed */
1079 oatDataFlowAnalysisDispatcher(cUnit.get(), verifyPredInfo, kAllNodes,
1080 false /* isIterative */);
1081 }
buzbee67bf8852011-08-17 17:51:35 -07001082
Bill Buzbeea114add2012-05-03 15:00:40 -07001083 /* Perform SSA transformation for the whole method */
1084 oatMethodSSATransformation(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001085
buzbee2cfc6392012-05-07 14:51:40 -07001086 /* Do constant propagation */
1087 // TODO: Probably need to make these expandable to support new ssa names
1088 // introducted during MIR optimization passes
1089 cUnit->isConstantV = oatAllocBitVector(cUnit.get(), cUnit->numSSARegs,
1090 false /* not expandable */);
1091 cUnit->constantValues =
1092 (int*)oatNew(cUnit.get(), sizeof(int) * cUnit->numSSARegs, true,
1093 kAllocDFInfo);
1094 oatDataFlowAnalysisDispatcher(cUnit.get(), oatDoConstantPropagation,
1095 kAllNodes,
1096 false /* isIterative */);
1097
Bill Buzbeea114add2012-05-03 15:00:40 -07001098 /* Detect loops */
1099 oatMethodLoopDetection(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001100
Bill Buzbeea114add2012-05-03 15:00:40 -07001101 /* Count uses */
1102 oatMethodUseCount(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001103
Bill Buzbeea114add2012-05-03 15:00:40 -07001104 /* Perform null check elimination */
1105 oatMethodNullCheckElimination(cUnit.get());
1106
1107 /* Do some basic block optimizations */
1108 oatMethodBasicBlockOptimization(cUnit.get());
1109
1110 oatInitializeRegAlloc(cUnit.get()); // Needs to happen after SSA naming
1111
1112 /* Allocate Registers using simple local allocation scheme */
1113 oatSimpleRegAlloc(cUnit.get());
1114
buzbee2cfc6392012-05-07 14:51:40 -07001115#if defined(ART_USE_QUICK_COMPILER)
1116 /* Go the LLVM path? */
1117 if (cUnit->genBitcode) {
1118 // MIR->Bitcode
1119 oatMethodMIR2Bitcode(cUnit.get());
1120 // Bitcode->LIR
1121 oatMethodBitcode2LIR(cUnit.get());
1122 } else {
1123#endif
1124 if (specialCase != kNoHandler) {
1125 /*
1126 * Custom codegen for special cases. If for any reason the
1127 * special codegen doesn't succeed, cUnit->firstLIRInsn will
1128 * set to NULL;
1129 */
1130 oatSpecialMIR2LIR(cUnit.get(), specialCase);
1131 }
buzbee67bf8852011-08-17 17:51:35 -07001132
buzbee2cfc6392012-05-07 14:51:40 -07001133 /* Convert MIR to LIR, etc. */
1134 if (cUnit->firstLIRInsn == NULL) {
1135 oatMethodMIR2LIR(cUnit.get());
1136 }
1137#if defined(ART_USE_QUICK_COMPILER)
Bill Buzbeea114add2012-05-03 15:00:40 -07001138 }
buzbee2cfc6392012-05-07 14:51:40 -07001139#endif
buzbee67bf8852011-08-17 17:51:35 -07001140
Bill Buzbeea114add2012-05-03 15:00:40 -07001141 // Debugging only
1142 if (cUnit->enableDebug & (1 << kDebugDumpCFG)) {
1143 oatDumpCFG(cUnit.get(), "/sdcard/cfg/");
1144 }
buzbee16da88c2012-03-20 10:38:17 -07001145
Bill Buzbeea114add2012-05-03 15:00:40 -07001146 /* Method is not empty */
1147 if (cUnit->firstLIRInsn) {
buzbee67bf8852011-08-17 17:51:35 -07001148
Bill Buzbeea114add2012-05-03 15:00:40 -07001149 // mark the targets of switch statement case labels
1150 oatProcessSwitchTables(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001151
Bill Buzbeea114add2012-05-03 15:00:40 -07001152 /* Convert LIR into machine code. */
1153 oatAssembleLIR(cUnit.get());
buzbee99ba9642012-01-25 14:23:14 -08001154
Elliott Hughes3b6baaa2011-10-14 19:13:56 -07001155 if (cUnit->printMe) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001156 oatCodegenDump(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001157 }
1158
Bill Buzbeea114add2012-05-03 15:00:40 -07001159 if (cUnit->opcodeCount != NULL) {
1160 LOG(INFO) << "Opcode Count";
1161 for (int i = 0; i < kNumPackedOpcodes; i++) {
1162 if (cUnit->opcodeCount[i] != 0) {
1163 LOG(INFO) << "-C- "
1164 << Instruction::Name(static_cast<Instruction::Code>(i))
1165 << " " << cUnit->opcodeCount[i];
buzbee67bf8852011-08-17 17:51:35 -07001166 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001167 }
1168 }
1169 }
buzbeea7c12682012-03-19 13:13:53 -07001170
Bill Buzbeea114add2012-05-03 15:00:40 -07001171 // Combine vmap tables - core regs, then fp regs - into vmapTable
1172 std::vector<uint16_t> vmapTable;
buzbeeca7a5e42012-08-20 11:12:18 -07001173 // Core regs may have been inserted out of order - sort first
1174 std::sort(cUnit->coreVmapTable.begin(), cUnit->coreVmapTable.end());
Bill Buzbeea114add2012-05-03 15:00:40 -07001175 for (size_t i = 0 ; i < cUnit->coreVmapTable.size(); i++) {
buzbeeca7a5e42012-08-20 11:12:18 -07001176 // Copy, stripping out the phys register sort key
1177 vmapTable.push_back(~(-1 << VREG_NUM_WIDTH) & cUnit->coreVmapTable[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001178 }
1179 // If we have a frame, push a marker to take place of lr
1180 if (cUnit->frameSize > 0) {
1181 vmapTable.push_back(INVALID_VREG);
1182 } else {
1183 DCHECK_EQ(__builtin_popcount(cUnit->coreSpillMask), 0);
1184 DCHECK_EQ(__builtin_popcount(cUnit->fpSpillMask), 0);
1185 }
buzbeeca7a5e42012-08-20 11:12:18 -07001186 // Combine vmap tables - core regs, then fp regs. fp regs already sorted
Bill Buzbeea114add2012-05-03 15:00:40 -07001187 for (uint32_t i = 0; i < cUnit->fpVmapTable.size(); i++) {
1188 vmapTable.push_back(cUnit->fpVmapTable[i]);
1189 }
1190 CompiledMethod* result =
1191 new CompiledMethod(cUnit->instructionSet, cUnit->codeBuffer,
1192 cUnit->frameSize, cUnit->coreSpillMask,
1193 cUnit->fpSpillMask, cUnit->mappingTable, vmapTable);
buzbee67bf8852011-08-17 17:51:35 -07001194
Bill Buzbeea114add2012-05-03 15:00:40 -07001195 VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file)
1196 << " (" << (cUnit->codeBuffer.size() * sizeof(cUnit->codeBuffer[0]))
1197 << " bytes)";
buzbee5abfa3e2012-01-31 17:01:43 -08001198
1199#ifdef WITH_MEMSTATS
Bill Buzbeea114add2012-05-03 15:00:40 -07001200 if (cUnit->enableDebug & (1 << kDebugShowMemoryUsage)) {
1201 oatDumpMemStats(cUnit.get());
1202 }
buzbee5abfa3e2012-01-31 17:01:43 -08001203#endif
buzbee67bf8852011-08-17 17:51:35 -07001204
Bill Buzbeea114add2012-05-03 15:00:40 -07001205 oatArenaReset(cUnit.get());
buzbeeba938cb2012-02-03 14:47:55 -08001206
Bill Buzbeea114add2012-05-03 15:00:40 -07001207 return result;
buzbee67bf8852011-08-17 17:51:35 -07001208}
1209
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001210} // namespace art
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001211
Bill Buzbeea114add2012-05-03 15:00:40 -07001212extern "C" art::CompiledMethod*
1213 ArtCompileMethod(art::Compiler& compiler,
1214 const art::DexFile::CodeItem* code_item,
Ian Rogers08f753d2012-08-24 14:35:25 -07001215 uint32_t access_flags, art::InvokeType invoke_type,
1216 uint32_t method_idx, jobject class_loader,
Bill Buzbeea114add2012-05-03 15:00:40 -07001217 const art::DexFile& dex_file)
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001218{
1219 CHECK_EQ(compiler.GetInstructionSet(), art::oatInstructionSet());
Ian Rogers08f753d2012-08-24 14:35:25 -07001220 return art::oatCompileMethod(compiler, code_item, access_flags, invoke_type,
1221 method_idx, class_loader, dex_file);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001222}