blob: 6ccccd2f28392ed4d3340a849ecee86a1c605f15 [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"
buzbeec143c552011-08-20 17:38:58 -070020#include "constants.h"
Ian Rogers0571d352011-11-03 19:51:38 -070021#include "leb128.h"
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070022#include "object.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070023#include "runtime.h"
buzbee67bf8852011-08-17 17:51:35 -070024
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080025namespace art {
26
buzbeece302932011-10-04 14:32:18 -070027/* Default optimizer/debug setting for the compiler. */
28uint32_t compilerOptimizerDisableFlags = 0 | // Disable specific optimizations
buzbee67bc2362011-10-11 18:08:40 -070029 //(1 << kLoadStoreElimination) |
30 //(1 << kLoadHoisting) |
31 //(1 << kSuppressLoads) |
32 //(1 << kNullCheckElimination) |
buzbee769fde12012-01-05 17:35:23 -080033 //(1 << kPromoteRegs) |
34 //(1 << kTrackLiveTemps) |
buzbee99ba9642012-01-25 14:23:14 -080035 //(1 << kSkipLargeMethodOptimization) |
buzbee86a4bce2012-03-06 18:15:00 -080036 //(1 << kSafeOptimizations) |
buzbee239c4e72012-03-16 08:42:29 -070037 //(1 << kBBOpt) |
buzbee9c044ce2012-03-18 13:24:07 -070038 //(1 << kPromoteCompilerTemps) |
buzbeece302932011-10-04 14:32:18 -070039 0;
40
41uint32_t compilerDebugFlags = 0 | // Enable debug/testing modes
buzbeee3de7492011-10-05 13:37:17 -070042 //(1 << kDebugDisplayMissingTargets) |
buzbeece302932011-10-04 14:32:18 -070043 //(1 << kDebugVerbose) |
44 //(1 << kDebugDumpCFG) |
45 //(1 << kDebugSlowFieldPath) |
46 //(1 << kDebugSlowInvokePath) |
47 //(1 << kDebugSlowStringPath) |
48 //(1 << kDebugSlowestFieldPath) |
49 //(1 << kDebugSlowestStringPath) |
buzbee34c77ad2012-01-11 13:01:32 -080050 //(1 << kDebugExerciseResolveMethod) |
buzbee5b537102012-01-17 17:33:47 -080051 //(1 << kDebugVerifyDataflow) |
buzbee5abfa3e2012-01-31 17:01:43 -080052 //(1 << kDebugShowMemoryUsage) |
buzbee86a4bce2012-03-06 18:15:00 -080053 //(1 << kDebugShowNops) |
buzbeece302932011-10-04 14:32:18 -070054 0;
55
buzbee31a4a6f2012-02-28 15:36:15 -080056inline bool contentIsInsn(const u2* codePtr) {
buzbee67bf8852011-08-17 17:51:35 -070057 u2 instr = *codePtr;
Elliott Hughesadb8c672012-03-06 16:49:32 -080058 Instruction::Code opcode = (Instruction::Code)(instr & 0xff);
buzbee67bf8852011-08-17 17:51:35 -070059
60 /*
Elliott Hughesadb8c672012-03-06 16:49:32 -080061 * Since the low 8-bit in metadata may look like NOP, we need to check
buzbee67bf8852011-08-17 17:51:35 -070062 * both the low and whole sub-word to determine whether it is code or data.
63 */
Elliott Hughesadb8c672012-03-06 16:49:32 -080064 return (opcode != Instruction::NOP || instr == 0);
buzbee67bf8852011-08-17 17:51:35 -070065}
66
67/*
68 * Parse an instruction, return the length of the instruction
69 */
buzbee31a4a6f2012-02-28 15:36:15 -080070inline int parseInsn(CompilationUnit* cUnit, const u2* codePtr,
Elliott Hughesadb8c672012-03-06 16:49:32 -080071 DecodedInstruction* decoded_instruction, bool printMe)
buzbee67bf8852011-08-17 17:51:35 -070072{
Elliott Hughesadb8c672012-03-06 16:49:32 -080073 // Don't parse instruction data
74 if (!contentIsInsn(codePtr)) {
75 return 0;
76 }
buzbee67bf8852011-08-17 17:51:35 -070077
Elliott Hughesadb8c672012-03-06 16:49:32 -080078 const Instruction* instruction = Instruction::At(codePtr);
79 *decoded_instruction = DecodedInstruction(instruction);
buzbee67bf8852011-08-17 17:51:35 -070080
Elliott Hughesadb8c672012-03-06 16:49:32 -080081 if (printMe) {
82 char* decodedString = oatGetDalvikDisassembly(cUnit, *decoded_instruction, NULL);
83 LOG(INFO) << codePtr << ": 0x" << std::hex << static_cast<int>(decoded_instruction->opcode)
84 << " " << decodedString;
85 }
86 return instruction->SizeInCodeUnits();
buzbee67bf8852011-08-17 17:51:35 -070087}
88
89#define UNKNOWN_TARGET 0xffffffff
90
Elliott Hughesadb8c672012-03-06 16:49:32 -080091inline bool isGoto(MIR* insn) {
92 switch (insn->dalvikInsn.opcode) {
93 case Instruction::GOTO:
94 case Instruction::GOTO_16:
95 case Instruction::GOTO_32:
96 return true;
97 default:
98 return false;
buzbee67bf8852011-08-17 17:51:35 -070099 }
100}
101
102/*
103 * Identify unconditional branch instructions
104 */
Elliott Hughesadb8c672012-03-06 16:49:32 -0800105inline bool isUnconditionalBranch(MIR* insn) {
106 switch (insn->dalvikInsn.opcode) {
107 case Instruction::RETURN_VOID:
108 case Instruction::RETURN:
109 case Instruction::RETURN_WIDE:
110 case Instruction::RETURN_OBJECT:
111 return true;
112 default:
113 return isGoto(insn);
114 }
buzbee67bf8852011-08-17 17:51:35 -0700115}
116
117/* Split an existing block from the specified code offset into two */
buzbee31a4a6f2012-02-28 15:36:15 -0800118BasicBlock *splitBlock(CompilationUnit* cUnit, unsigned int codeOffset,
119 BasicBlock* origBlock, BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700120{
121 MIR* insn = origBlock->firstMIRInsn;
122 while (insn) {
123 if (insn->offset == codeOffset) break;
124 insn = insn->next;
125 }
126 if (insn == NULL) {
127 LOG(FATAL) << "Break split failed";
128 }
buzbee5abfa3e2012-01-31 17:01:43 -0800129 BasicBlock *bottomBlock = oatNewBB(cUnit, kDalvikByteCode,
130 cUnit->numBlocks++);
buzbeeba938cb2012-02-03 14:47:55 -0800131 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700132
133 bottomBlock->startOffset = codeOffset;
134 bottomBlock->firstMIRInsn = insn;
135 bottomBlock->lastMIRInsn = origBlock->lastMIRInsn;
136
buzbee5b537102012-01-17 17:33:47 -0800137 /* Add it to the quick lookup cache */
138 cUnit->blockMap.insert(std::make_pair(bottomBlock->startOffset,
139 bottomBlock));
140
buzbee67bf8852011-08-17 17:51:35 -0700141 /* Handle the taken path */
142 bottomBlock->taken = origBlock->taken;
143 if (bottomBlock->taken) {
144 origBlock->taken = NULL;
buzbee5abfa3e2012-01-31 17:01:43 -0800145 oatDeleteGrowableList(bottomBlock->taken->predecessors,
146 (intptr_t)origBlock);
buzbeeba938cb2012-02-03 14:47:55 -0800147 oatInsertGrowableList(cUnit, bottomBlock->taken->predecessors,
buzbee5abfa3e2012-01-31 17:01:43 -0800148 (intptr_t)bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700149 }
150
151 /* Handle the fallthrough path */
152 bottomBlock->needFallThroughBranch = origBlock->needFallThroughBranch;
153 bottomBlock->fallThrough = origBlock->fallThrough;
154 origBlock->fallThrough = bottomBlock;
155 origBlock->needFallThroughBranch = true;
buzbeeba938cb2012-02-03 14:47:55 -0800156 oatInsertGrowableList(cUnit, bottomBlock->predecessors,
157 (intptr_t)origBlock);
buzbee67bf8852011-08-17 17:51:35 -0700158 if (bottomBlock->fallThrough) {
buzbee5abfa3e2012-01-31 17:01:43 -0800159 oatDeleteGrowableList(bottomBlock->fallThrough->predecessors,
160 (intptr_t)origBlock);
buzbeeba938cb2012-02-03 14:47:55 -0800161 oatInsertGrowableList(cUnit, bottomBlock->fallThrough->predecessors,
buzbee5abfa3e2012-01-31 17:01:43 -0800162 (intptr_t)bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700163 }
164
165 /* Handle the successor list */
166 if (origBlock->successorBlockList.blockListType != kNotUsed) {
167 bottomBlock->successorBlockList = origBlock->successorBlockList;
168 origBlock->successorBlockList.blockListType = kNotUsed;
169 GrowableListIterator iterator;
170
171 oatGrowableListIteratorInit(&bottomBlock->successorBlockList.blocks,
172 &iterator);
173 while (true) {
174 SuccessorBlockInfo *successorBlockInfo =
175 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
176 if (successorBlockInfo == NULL) break;
177 BasicBlock *bb = successorBlockInfo->block;
buzbee5abfa3e2012-01-31 17:01:43 -0800178 oatDeleteGrowableList(bb->predecessors, (intptr_t)origBlock);
buzbeeba938cb2012-02-03 14:47:55 -0800179 oatInsertGrowableList(cUnit, bb->predecessors,
180 (intptr_t)bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700181 }
182 }
183
184 origBlock->lastMIRInsn = insn->prev;
185
186 insn->prev->next = NULL;
187 insn->prev = NULL;
buzbee9ab05de2012-01-18 15:43:48 -0800188 /*
189 * Update the immediate predecessor block pointer so that outgoing edges
190 * can be applied to the proper block.
191 */
192 if (immedPredBlockP) {
193 DCHECK_EQ(*immedPredBlockP, origBlock);
194 *immedPredBlockP = bottomBlock;
195 }
buzbee67bf8852011-08-17 17:51:35 -0700196 return bottomBlock;
197}
198
199/*
200 * Given a code offset, find out the block that starts with it. If the offset
buzbee9ab05de2012-01-18 15:43:48 -0800201 * is in the middle of an existing block, split it into two. If immedPredBlockP
202 * is not non-null and is the block being split, update *immedPredBlockP to
203 * point to the bottom block so that outgoing edges can be set up properly
204 * (by the caller)
buzbee5b537102012-01-17 17:33:47 -0800205 * Utilizes a map for fast lookup of the typical cases.
buzbee67bf8852011-08-17 17:51:35 -0700206 */
buzbee31a4a6f2012-02-28 15:36:15 -0800207BasicBlock *findBlock(CompilationUnit* cUnit, unsigned int codeOffset,
208 bool split, bool create, BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700209{
210 GrowableList* blockList = &cUnit->blockList;
211 BasicBlock* bb;
212 unsigned int i;
buzbee5b537102012-01-17 17:33:47 -0800213 std::map<unsigned int, BasicBlock*>::iterator it;
buzbee67bf8852011-08-17 17:51:35 -0700214
buzbee5b537102012-01-17 17:33:47 -0800215 it = cUnit->blockMap.find(codeOffset);
216 if (it != cUnit->blockMap.end()) {
217 return it->second;
218 } else if (!create) {
219 return NULL;
220 }
221
222 if (split) {
223 for (i = 0; i < blockList->numUsed; i++) {
224 bb = (BasicBlock *) blockList->elemList[i];
225 if (bb->blockType != kDalvikByteCode) continue;
226 /* Check if a branch jumps into the middle of an existing block */
227 if ((codeOffset > bb->startOffset) && (bb->lastMIRInsn != NULL) &&
228 (codeOffset <= bb->lastMIRInsn->offset)) {
229 BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb,
230 bb == *immedPredBlockP ?
231 immedPredBlockP : NULL);
232 return newBB;
233 }
buzbee67bf8852011-08-17 17:51:35 -0700234 }
235 }
buzbee5b537102012-01-17 17:33:47 -0800236
237 /* Create a new one */
buzbee5abfa3e2012-01-31 17:01:43 -0800238 bb = oatNewBB(cUnit, kDalvikByteCode, cUnit->numBlocks++);
buzbeeba938cb2012-02-03 14:47:55 -0800239 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) bb);
buzbee5b537102012-01-17 17:33:47 -0800240 bb->startOffset = codeOffset;
241 cUnit->blockMap.insert(std::make_pair(bb->startOffset, bb));
242 return bb;
buzbee67bf8852011-08-17 17:51:35 -0700243}
244
245/* Dump the CFG into a DOT graph */
246void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix)
247{
buzbee67bf8852011-08-17 17:51:35 -0700248 FILE* file;
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800249 std::string name(PrettyMethod(cUnit->method_idx, *cUnit->dex_file));
buzbee67bf8852011-08-17 17:51:35 -0700250 char startOffset[80];
251 sprintf(startOffset, "_%x", cUnit->entryBlock->fallThrough->startOffset);
buzbeeba938cb2012-02-03 14:47:55 -0800252 char* fileName = (char*) oatNew(cUnit,
buzbeec143c552011-08-20 17:38:58 -0700253 strlen(dirPrefix) +
254 name.length() +
buzbee5abfa3e2012-01-31 17:01:43 -0800255 strlen(".dot") + 1, true, kAllocDebugInfo);
buzbeec143c552011-08-20 17:38:58 -0700256 sprintf(fileName, "%s%s%s.dot", dirPrefix, name.c_str(), startOffset);
buzbee67bf8852011-08-17 17:51:35 -0700257
258 /*
259 * Convert the special characters into a filesystem- and shell-friendly
260 * format.
261 */
262 int i;
263 for (i = strlen(dirPrefix); fileName[i]; i++) {
264 if (fileName[i] == '/') {
265 fileName[i] = '_';
266 } else if (fileName[i] == ';') {
267 fileName[i] = '#';
268 } else if (fileName[i] == '$') {
269 fileName[i] = '+';
270 } else if (fileName[i] == '(' || fileName[i] == ')') {
271 fileName[i] = '@';
272 } else if (fileName[i] == '<' || fileName[i] == '>') {
273 fileName[i] = '=';
274 }
275 }
276 file = fopen(fileName, "w");
277 if (file == NULL) {
278 return;
279 }
280 fprintf(file, "digraph G {\n");
281
282 fprintf(file, " rankdir=TB\n");
283
284 int numReachableBlocks = cUnit->numReachableBlocks;
285 int idx;
286 const GrowableList *blockList = &cUnit->blockList;
287
288 for (idx = 0; idx < numReachableBlocks; idx++) {
289 int blockIdx = cUnit->dfsOrder.elemList[idx];
290 BasicBlock *bb = (BasicBlock *) oatGrowableListGetElement(blockList,
291 blockIdx);
292 if (bb == NULL) break;
293 if (bb->blockType == kEntryBlock) {
294 fprintf(file, " entry [shape=Mdiamond];\n");
295 } else if (bb->blockType == kExitBlock) {
296 fprintf(file, " exit [shape=Mdiamond];\n");
297 } else if (bb->blockType == kDalvikByteCode) {
298 fprintf(file, " block%04x [shape=record,label = \"{ \\\n",
299 bb->startOffset);
300 const MIR *mir;
301 fprintf(file, " {block id %d\\l}%s\\\n", bb->id,
302 bb->firstMIRInsn ? " | " : " ");
303 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
304 fprintf(file, " {%04x %s\\l}%s\\\n", mir->offset,
Elliott Hughesadb8c672012-03-06 16:49:32 -0800305 mir->ssaRep ? oatFullDisassembler(cUnit, mir) : Instruction::Name(mir->dalvikInsn.opcode),
buzbee67bf8852011-08-17 17:51:35 -0700306 mir->next ? " | " : " ");
307 }
308 fprintf(file, " }\"];\n\n");
309 } else if (bb->blockType == kExceptionHandling) {
310 char blockName[BLOCK_NAME_LEN];
311
312 oatGetBlockName(bb, blockName);
313 fprintf(file, " %s [shape=invhouse];\n", blockName);
314 }
315
316 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
317
318 if (bb->taken) {
319 oatGetBlockName(bb, blockName1);
320 oatGetBlockName(bb->taken, blockName2);
321 fprintf(file, " %s:s -> %s:n [style=dotted]\n",
322 blockName1, blockName2);
323 }
324 if (bb->fallThrough) {
325 oatGetBlockName(bb, blockName1);
326 oatGetBlockName(bb->fallThrough, blockName2);
327 fprintf(file, " %s:s -> %s:n\n", blockName1, blockName2);
328 }
329
330 if (bb->successorBlockList.blockListType != kNotUsed) {
331 fprintf(file, " succ%04x [shape=%s,label = \"{ \\\n",
332 bb->startOffset,
333 (bb->successorBlockList.blockListType == kCatch) ?
334 "Mrecord" : "record");
335 GrowableListIterator iterator;
336 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
337 &iterator);
338 SuccessorBlockInfo *successorBlockInfo =
339 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
340
341 int succId = 0;
342 while (true) {
343 if (successorBlockInfo == NULL) break;
344
345 BasicBlock *destBlock = successorBlockInfo->block;
346 SuccessorBlockInfo *nextSuccessorBlockInfo =
347 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
348
349 fprintf(file, " {<f%d> %04x: %04x\\l}%s\\\n",
350 succId++,
351 successorBlockInfo->key,
352 destBlock->startOffset,
353 (nextSuccessorBlockInfo != NULL) ? " | " : " ");
354
355 successorBlockInfo = nextSuccessorBlockInfo;
356 }
357 fprintf(file, " }\"];\n\n");
358
359 oatGetBlockName(bb, blockName1);
360 fprintf(file, " %s:s -> succ%04x:n [style=dashed]\n",
361 blockName1, bb->startOffset);
362
363 if (bb->successorBlockList.blockListType == kPackedSwitch ||
364 bb->successorBlockList.blockListType == kSparseSwitch) {
365
366 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
367 &iterator);
368
369 succId = 0;
370 while (true) {
371 SuccessorBlockInfo *successorBlockInfo =
372 (SuccessorBlockInfo *)
373 oatGrowableListIteratorNext(&iterator);
374 if (successorBlockInfo == NULL) break;
375
376 BasicBlock *destBlock = successorBlockInfo->block;
377
378 oatGetBlockName(destBlock, blockName2);
379 fprintf(file, " succ%04x:f%d:e -> %s:n\n",
380 bb->startOffset, succId++,
381 blockName2);
382 }
383 }
384 }
385 fprintf(file, "\n");
386
buzbeece302932011-10-04 14:32:18 -0700387 /* Display the dominator tree */
buzbee67bf8852011-08-17 17:51:35 -0700388 oatGetBlockName(bb, blockName1);
389 fprintf(file, " cfg%s [label=\"%s\", shape=none];\n",
390 blockName1, blockName1);
391 if (bb->iDom) {
392 oatGetBlockName(bb->iDom, blockName2);
393 fprintf(file, " cfg%s:s -> cfg%s:n\n\n",
394 blockName2, blockName1);
395 }
buzbee67bf8852011-08-17 17:51:35 -0700396 }
397 fprintf(file, "}\n");
398 fclose(file);
399}
400
401/* Verify if all the successor is connected with all the claimed predecessors */
buzbee31a4a6f2012-02-28 15:36:15 -0800402bool verifyPredInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700403{
buzbee5abfa3e2012-01-31 17:01:43 -0800404 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700405
buzbee5abfa3e2012-01-31 17:01:43 -0800406 oatGrowableListIteratorInit(bb->predecessors, &iter);
buzbee67bf8852011-08-17 17:51:35 -0700407 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800408 BasicBlock *predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
409 if (!predBB) break;
buzbee67bf8852011-08-17 17:51:35 -0700410 bool found = false;
411 if (predBB->taken == bb) {
412 found = true;
413 } else if (predBB->fallThrough == bb) {
414 found = true;
415 } else if (predBB->successorBlockList.blockListType != kNotUsed) {
416 GrowableListIterator iterator;
417 oatGrowableListIteratorInit(&predBB->successorBlockList.blocks,
418 &iterator);
419 while (true) {
420 SuccessorBlockInfo *successorBlockInfo =
421 (SuccessorBlockInfo *)
422 oatGrowableListIteratorNext(&iterator);
423 if (successorBlockInfo == NULL) break;
424 BasicBlock *succBB = successorBlockInfo->block;
425 if (succBB == bb) {
426 found = true;
427 break;
428 }
429 }
430 }
431 if (found == false) {
432 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
433 oatGetBlockName(bb, blockName1);
434 oatGetBlockName(predBB, blockName2);
435 oatDumpCFG(cUnit, "/sdcard/cfg/");
436 LOG(FATAL) << "Successor " << blockName1 << "not found from "
437 << blockName2;
438 }
439 }
440 return true;
441}
442
443/* Identify code range in try blocks and set up the empty catch blocks */
buzbee31a4a6f2012-02-28 15:36:15 -0800444void processTryCatchBlocks(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700445{
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800446 const DexFile::CodeItem* code_item = cUnit->code_item;
buzbeee9a72f62011-09-04 17:59:07 -0700447 int triesSize = code_item->tries_size_;
buzbee67bf8852011-08-17 17:51:35 -0700448 int offset;
449
450 if (triesSize == 0) {
451 return;
452 }
453
buzbee67bf8852011-08-17 17:51:35 -0700454 ArenaBitVector* tryBlockAddr = cUnit->tryBlockAddr;
455
buzbeee9a72f62011-09-04 17:59:07 -0700456 for (int i = 0; i < triesSize; i++) {
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800457 const DexFile::TryItem* pTry =
458 DexFile::GetTryItems(*code_item, i);
buzbeee9a72f62011-09-04 17:59:07 -0700459 int startOffset = pTry->start_addr_;
460 int endOffset = startOffset + pTry->insn_count_;
buzbee67bf8852011-08-17 17:51:35 -0700461 for (offset = startOffset; offset < endOffset; offset++) {
buzbeeba938cb2012-02-03 14:47:55 -0800462 oatSetBit(cUnit, tryBlockAddr, offset);
buzbee67bf8852011-08-17 17:51:35 -0700463 }
464 }
465
buzbeee9a72f62011-09-04 17:59:07 -0700466 // Iterate over each of the handlers to enqueue the empty Catch blocks
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800467 const byte* handlers_ptr =
468 DexFile::GetCatchHandlerData(*code_item, 0);
469 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
buzbeee9a72f62011-09-04 17:59:07 -0700470 for (uint32_t idx = 0; idx < handlers_size; idx++) {
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800471 CatchHandlerIterator iterator(handlers_ptr);
Ian Rogers0571d352011-11-03 19:51:38 -0700472 for (; iterator.HasNext(); iterator.Next()) {
473 uint32_t address = iterator.GetHandlerAddress();
buzbee9ab05de2012-01-18 15:43:48 -0800474 findBlock(cUnit, address, false /* split */, true /*create*/,
475 /* immedPredBlockP */ NULL);
buzbee67bf8852011-08-17 17:51:35 -0700476 }
Ian Rogers0571d352011-11-03 19:51:38 -0700477 handlers_ptr = iterator.EndDataPointer();
buzbee67bf8852011-08-17 17:51:35 -0700478 }
479}
480
Elliott Hughesadb8c672012-03-06 16:49:32 -0800481/* Process instructions with the kBranch flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800482BasicBlock* processCanBranch(CompilationUnit* cUnit, BasicBlock* curBlock,
483 MIR* insn, int curOffset, int width, int flags,
484 const u2* codePtr, const u2* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700485{
486 int target = curOffset;
487 switch (insn->dalvikInsn.opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800488 case Instruction::GOTO:
489 case Instruction::GOTO_16:
490 case Instruction::GOTO_32:
buzbee67bf8852011-08-17 17:51:35 -0700491 target += (int) insn->dalvikInsn.vA;
492 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800493 case Instruction::IF_EQ:
494 case Instruction::IF_NE:
495 case Instruction::IF_LT:
496 case Instruction::IF_GE:
497 case Instruction::IF_GT:
498 case Instruction::IF_LE:
buzbee67bf8852011-08-17 17:51:35 -0700499 target += (int) insn->dalvikInsn.vC;
500 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800501 case Instruction::IF_EQZ:
502 case Instruction::IF_NEZ:
503 case Instruction::IF_LTZ:
504 case Instruction::IF_GEZ:
505 case Instruction::IF_GTZ:
506 case Instruction::IF_LEZ:
buzbee67bf8852011-08-17 17:51:35 -0700507 target += (int) insn->dalvikInsn.vB;
508 break;
509 default:
510 LOG(FATAL) << "Unexpected opcode(" << (int)insn->dalvikInsn.opcode
Elliott Hughesadb8c672012-03-06 16:49:32 -0800511 << ") with kBranch set";
buzbee67bf8852011-08-17 17:51:35 -0700512 }
513 BasicBlock *takenBlock = findBlock(cUnit, target,
514 /* split */
515 true,
516 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800517 true,
518 /* immedPredBlockP */
519 &curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700520 curBlock->taken = takenBlock;
buzbeeba938cb2012-02-03 14:47:55 -0800521 oatInsertGrowableList(cUnit, takenBlock->predecessors, (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700522
523 /* Always terminate the current block for conditional branches */
Elliott Hughesadb8c672012-03-06 16:49:32 -0800524 if (flags & Instruction::kContinue) {
buzbee67bf8852011-08-17 17:51:35 -0700525 BasicBlock *fallthroughBlock = findBlock(cUnit,
526 curOffset + width,
527 /*
528 * If the method is processed
529 * in sequential order from the
530 * beginning, we don't need to
531 * specify split for continue
532 * blocks. However, this
533 * routine can be called by
534 * compileLoop, which starts
535 * parsing the method from an
536 * arbitrary address in the
537 * method body.
538 */
539 true,
540 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800541 true,
542 /* immedPredBlockP */
543 &curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700544 curBlock->fallThrough = fallthroughBlock;
buzbeeba938cb2012-02-03 14:47:55 -0800545 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
buzbee5abfa3e2012-01-31 17:01:43 -0800546 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700547 } else if (codePtr < codeEnd) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800548 /* Create a fallthrough block for real instructions (incl. NOP) */
buzbee67bf8852011-08-17 17:51:35 -0700549 if (contentIsInsn(codePtr)) {
550 findBlock(cUnit, curOffset + width,
551 /* split */
552 false,
553 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800554 true,
555 /* immedPredBlockP */
556 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700557 }
558 }
buzbeee941e2c2011-12-05 12:38:17 -0800559 return curBlock;
buzbee67bf8852011-08-17 17:51:35 -0700560}
561
Elliott Hughesadb8c672012-03-06 16:49:32 -0800562/* Process instructions with the kSwitch flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800563void processCanSwitch(CompilationUnit* cUnit, BasicBlock* curBlock,
564 MIR* insn, int curOffset, int width, int flags)
buzbee67bf8852011-08-17 17:51:35 -0700565{
566 u2* switchData= (u2 *) (cUnit->insns + curOffset +
567 insn->dalvikInsn.vB);
568 int size;
569 int* keyTable;
570 int* targetTable;
571 int i;
572 int firstKey;
573
574 /*
575 * Packed switch data format:
576 * ushort ident = 0x0100 magic value
577 * ushort size number of entries in the table
578 * int first_key first (and lowest) switch case value
579 * int targets[size] branch targets, relative to switch opcode
580 *
581 * Total size is (4+size*2) 16-bit code units.
582 */
Elliott Hughesadb8c672012-03-06 16:49:32 -0800583 if (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) {
584 DCHECK_EQ(static_cast<int>(switchData[0]), static_cast<int>(Instruction::kPackedSwitchSignature));
buzbee67bf8852011-08-17 17:51:35 -0700585 size = switchData[1];
586 firstKey = switchData[2] | (switchData[3] << 16);
587 targetTable = (int *) &switchData[4];
588 keyTable = NULL; // Make the compiler happy
589 /*
590 * Sparse switch data format:
591 * ushort ident = 0x0200 magic value
592 * ushort size number of entries in the table; > 0
593 * int keys[size] keys, sorted low-to-high; 32-bit aligned
594 * int targets[size] branch targets, relative to switch opcode
595 *
596 * Total size is (2+size*4) 16-bit code units.
597 */
598 } else {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800599 DCHECK_EQ(static_cast<int>(switchData[0]), static_cast<int>(Instruction::kSparseSwitchSignature));
buzbee67bf8852011-08-17 17:51:35 -0700600 size = switchData[1];
601 keyTable = (int *) &switchData[2];
602 targetTable = (int *) &switchData[2 + size*2];
603 firstKey = 0; // To make the compiler happy
604 }
605
606 if (curBlock->successorBlockList.blockListType != kNotUsed) {
607 LOG(FATAL) << "Successor block list already in use: " <<
608 (int)curBlock->successorBlockList.blockListType;
609 }
610 curBlock->successorBlockList.blockListType =
Elliott Hughesadb8c672012-03-06 16:49:32 -0800611 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
buzbee67bf8852011-08-17 17:51:35 -0700612 kPackedSwitch : kSparseSwitch;
buzbeeba938cb2012-02-03 14:47:55 -0800613 oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, size,
buzbee5abfa3e2012-01-31 17:01:43 -0800614 kListSuccessorBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700615
616 for (i = 0; i < size; i++) {
617 BasicBlock *caseBlock = findBlock(cUnit, curOffset + targetTable[i],
618 /* split */
619 true,
620 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800621 true,
622 /* immedPredBlockP */
623 &curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700624 SuccessorBlockInfo *successorBlockInfo =
buzbeeba938cb2012-02-03 14:47:55 -0800625 (SuccessorBlockInfo *) oatNew(cUnit, sizeof(SuccessorBlockInfo),
626 false, kAllocSuccessor);
buzbee67bf8852011-08-17 17:51:35 -0700627 successorBlockInfo->block = caseBlock;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800628 successorBlockInfo->key = (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH)?
buzbee67bf8852011-08-17 17:51:35 -0700629 firstKey + i : keyTable[i];
buzbeeba938cb2012-02-03 14:47:55 -0800630 oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
buzbee67bf8852011-08-17 17:51:35 -0700631 (intptr_t) successorBlockInfo);
buzbeeba938cb2012-02-03 14:47:55 -0800632 oatInsertGrowableList(cUnit, caseBlock->predecessors,
633 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700634 }
635
636 /* Fall-through case */
637 BasicBlock* fallthroughBlock = findBlock(cUnit,
638 curOffset + width,
639 /* split */
640 false,
641 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800642 true,
643 /* immedPredBlockP */
644 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700645 curBlock->fallThrough = fallthroughBlock;
buzbeeba938cb2012-02-03 14:47:55 -0800646 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
647 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700648}
649
Elliott Hughesadb8c672012-03-06 16:49:32 -0800650/* Process instructions with the kThrow flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800651void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock, MIR* insn,
652 int curOffset, int width, int flags,
653 ArenaBitVector* tryBlockAddr, const u2* codePtr,
654 const u2* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700655{
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800656 const DexFile::CodeItem* code_item = cUnit->code_item;
buzbee67bf8852011-08-17 17:51:35 -0700657
658 /* In try block */
659 if (oatIsBitSet(tryBlockAddr, curOffset)) {
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800660 CatchHandlerIterator iterator(*code_item, curOffset);
buzbee67bf8852011-08-17 17:51:35 -0700661
buzbee67bf8852011-08-17 17:51:35 -0700662 if (curBlock->successorBlockList.blockListType != kNotUsed) {
663 LOG(FATAL) << "Successor block list already in use: " <<
664 (int)curBlock->successorBlockList.blockListType;
665 }
buzbeee9a72f62011-09-04 17:59:07 -0700666
buzbee67bf8852011-08-17 17:51:35 -0700667 curBlock->successorBlockList.blockListType = kCatch;
buzbeeba938cb2012-02-03 14:47:55 -0800668 oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, 2,
buzbee5abfa3e2012-01-31 17:01:43 -0800669 kListSuccessorBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700670
Ian Rogers0571d352011-11-03 19:51:38 -0700671 for (;iterator.HasNext(); iterator.Next()) {
672 BasicBlock *catchBlock = findBlock(cUnit, iterator.GetHandlerAddress(),
buzbeee9a72f62011-09-04 17:59:07 -0700673 false /* split*/,
buzbee9ab05de2012-01-18 15:43:48 -0800674 false /* creat */,
675 NULL /* immedPredBlockP */);
buzbee43a36422011-09-14 14:00:13 -0700676 catchBlock->catchEntry = true;
buzbeeba938cb2012-02-03 14:47:55 -0800677 SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
678 oatNew(cUnit, sizeof(SuccessorBlockInfo), false,
679 kAllocSuccessor);
buzbee67bf8852011-08-17 17:51:35 -0700680 successorBlockInfo->block = catchBlock;
Ian Rogers0571d352011-11-03 19:51:38 -0700681 successorBlockInfo->key = iterator.GetHandlerTypeIndex();
buzbeeba938cb2012-02-03 14:47:55 -0800682 oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
buzbee67bf8852011-08-17 17:51:35 -0700683 (intptr_t) successorBlockInfo);
buzbeeba938cb2012-02-03 14:47:55 -0800684 oatInsertGrowableList(cUnit, catchBlock->predecessors,
685 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700686 }
687 } else {
buzbee5abfa3e2012-01-31 17:01:43 -0800688 BasicBlock *ehBlock = oatNewBB(cUnit, kExceptionHandling,
689 cUnit->numBlocks++);
buzbee67bf8852011-08-17 17:51:35 -0700690 curBlock->taken = ehBlock;
buzbeeba938cb2012-02-03 14:47:55 -0800691 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) ehBlock);
buzbee67bf8852011-08-17 17:51:35 -0700692 ehBlock->startOffset = curOffset;
buzbeeba938cb2012-02-03 14:47:55 -0800693 oatInsertGrowableList(cUnit, ehBlock->predecessors, (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700694 }
695
696 /*
697 * Force the current block to terminate.
698 *
699 * Data may be present before codeEnd, so we need to parse it to know
700 * whether it is code or data.
701 */
702 if (codePtr < codeEnd) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800703 /* Create a fallthrough block for real instructions (incl. NOP) */
buzbee67bf8852011-08-17 17:51:35 -0700704 if (contentIsInsn(codePtr)) {
705 BasicBlock *fallthroughBlock = findBlock(cUnit,
706 curOffset + width,
707 /* split */
708 false,
709 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800710 true,
711 /* immedPredBlockP */
712 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700713 /*
Elliott Hughesadb8c672012-03-06 16:49:32 -0800714 * THROW is an unconditional branch. NOTE:
715 * THROW_VERIFICATION_ERROR is also an unconditional
buzbee510c6052011-10-27 10:47:20 -0700716 * branch, but we shouldn't treat it as such until we have
717 * a dead code elimination pass (which won't be important
718 * until inlining w/ constant propogation is implemented.
buzbee67bf8852011-08-17 17:51:35 -0700719 */
Elliott Hughesadb8c672012-03-06 16:49:32 -0800720 if (insn->dalvikInsn.opcode != Instruction::THROW) {
buzbee67bf8852011-08-17 17:51:35 -0700721 curBlock->fallThrough = fallthroughBlock;
buzbeeba938cb2012-02-03 14:47:55 -0800722 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
buzbee5abfa3e2012-01-31 17:01:43 -0800723 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700724 }
725 }
726 }
727}
728
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800729void oatInit(CompilationUnit* cUnit, const Compiler& compiler) {
730 if (!oatArchInit()) {
731 LOG(FATAL) << "Failed to initialize oat";
732 }
733 if (!oatHeapInit(cUnit)) {
734 LOG(FATAL) << "Failed to initialize oat heap";
735 }
736}
737
Elliott Hughes3fa1b7e2012-03-13 17:06:22 -0700738CompiledMethod* oatCompileMethod(Compiler& compiler,
739 const DexFile::CodeItem* code_item,
740 uint32_t access_flags, uint32_t method_idx,
741 const ClassLoader* class_loader,
742 const DexFile& dex_file)
buzbee67bf8852011-08-17 17:51:35 -0700743{
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800744 VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
Brian Carlstrom94496d32011-08-22 09:22:47 -0700745
buzbeec143c552011-08-20 17:38:58 -0700746 const u2* codePtr = code_item->insns_;
Ian Rogersd81871c2011-10-03 13:57:23 -0700747 const u2* codeEnd = code_item->insns_ + code_item->insns_size_in_code_units_;
buzbee67bf8852011-08-17 17:51:35 -0700748 int numBlocks = 0;
749 unsigned int curOffset = 0;
750
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800751 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700752 UniquePtr<CompilationUnit> cUnit(new CompilationUnit);
753 memset(cUnit.get(), 0, sizeof(*cUnit));
buzbeeba938cb2012-02-03 14:47:55 -0800754
755 oatInit(cUnit.get(), compiler);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800756
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700757 cUnit->compiler = &compiler;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800758 cUnit->class_linker = class_linker;
759 cUnit->dex_file = &dex_file;
760 cUnit->dex_cache = class_linker->FindDexCache(dex_file);
761 cUnit->method_idx = method_idx;
762 cUnit->code_item = code_item;
763 cUnit->access_flags = access_flags;
764 cUnit->shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800765 cUnit->instructionSet = compiler.GetInstructionSet();
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700766 cUnit->insns = code_item->insns_;
Ian Rogersd81871c2011-10-03 13:57:23 -0700767 cUnit->insnsSize = code_item->insns_size_in_code_units_;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800768 cUnit->numIns = code_item->ins_size_;
769 cUnit->numRegs = code_item->registers_size_ - cUnit->numIns;
770 cUnit->numOuts = code_item->outs_size_;
771 /* Adjust this value accordingly once inlining is performed */
772 cUnit->numDalvikRegisters = code_item->registers_size_;
buzbee5b537102012-01-17 17:33:47 -0800773 cUnit->blockMap = std::map<unsigned int, BasicBlock*>();
774 cUnit->blockMap.clear();
buzbee85d8c1e2012-01-27 15:52:35 -0800775 cUnit->boundaryMap = std::map<unsigned int, LIR*>();
776 cUnit->boundaryMap.clear();
buzbeeba938cb2012-02-03 14:47:55 -0800777 // TODO: set these from command line
778 cUnit->compilerMethodMatch = new std::string("");
779 cUnit->compilerFlipMatch = false;
780 bool useMatch = cUnit->compilerMethodMatch->length() != 0;
781 bool match = useMatch && (cUnit->compilerFlipMatch ^
782 (PrettyMethod(method_idx, dex_file).find(*cUnit->compilerMethodMatch)
783 != std::string::npos));
buzbeece302932011-10-04 14:32:18 -0700784 if (!useMatch || match) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700785 cUnit->disableOpt = compilerOptimizerDisableFlags;
786 cUnit->enableDebug = compilerDebugFlags;
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800787 cUnit->printMe = VLOG_IS_ON(compiler) || (cUnit->enableDebug & (1 << kDebugVerbose));
buzbeece302932011-10-04 14:32:18 -0700788 }
buzbee44b412b2012-02-04 08:50:53 -0800789 /* Are we generating code for the debugger? */
Elliott Hughesde6e4cf2012-02-27 14:46:06 -0800790 if (compiler.IsDebuggingSupported()) {
buzbee44b412b2012-02-04 08:50:53 -0800791 cUnit->genDebugger = true;
792 // Yes, disable most optimizations
793 cUnit->disableOpt |= (
794 (1 << kLoadStoreElimination) |
795 (1 << kLoadHoisting) |
796 (1 << kSuppressLoads) |
797 (1 << kPromoteRegs) |
buzbeeb37c9992012-03-18 21:28:43 -0700798 (1 << kBBOpt) |
buzbee44b412b2012-02-04 08:50:53 -0800799 (1 << kTrackLiveTemps));
800 }
801
buzbeecefd1872011-09-09 09:59:52 -0700802 /* Assume non-throwing leaf */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700803 cUnit->attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE);
buzbeecefd1872011-09-09 09:59:52 -0700804
buzbee5abfa3e2012-01-31 17:01:43 -0800805 /* Initialize the block list, estimate size based on insnsSize */
buzbeeba938cb2012-02-03 14:47:55 -0800806 oatInitGrowableList(cUnit.get(), &cUnit->blockList, cUnit->insnsSize,
807 kListBlockList);
buzbee67bf8852011-08-17 17:51:35 -0700808
809 /* Initialize the switchTables list */
buzbeeba938cb2012-02-03 14:47:55 -0800810 oatInitGrowableList(cUnit.get(), &cUnit->switchTables, 4,
811 kListSwitchTables);
buzbee67bf8852011-08-17 17:51:35 -0700812
813 /* Intialize the fillArrayData list */
buzbeeba938cb2012-02-03 14:47:55 -0800814 oatInitGrowableList(cUnit.get(), &cUnit->fillArrayData, 4,
815 kListFillArrayData);
buzbee67bf8852011-08-17 17:51:35 -0700816
buzbee5abfa3e2012-01-31 17:01:43 -0800817 /* Intialize the throwLaunchpads list, estimate size based on insnsSize */
buzbeeba938cb2012-02-03 14:47:55 -0800818 oatInitGrowableList(cUnit.get(), &cUnit->throwLaunchpads, cUnit->insnsSize,
buzbee5abfa3e2012-01-31 17:01:43 -0800819 kListThrowLaunchPads);
buzbee5ade1d22011-09-09 14:44:52 -0700820
buzbeec1f45042011-09-21 16:03:19 -0700821 /* Intialize the suspendLaunchpads list */
buzbeeba938cb2012-02-03 14:47:55 -0800822 oatInitGrowableList(cUnit.get(), &cUnit->suspendLaunchpads, 2048,
buzbee5abfa3e2012-01-31 17:01:43 -0800823 kListSuspendLaunchPads);
buzbeec1f45042011-09-21 16:03:19 -0700824
buzbee67bf8852011-08-17 17:51:35 -0700825 /* Allocate the bit-vector to track the beginning of basic blocks */
buzbeeba938cb2012-02-03 14:47:55 -0800826 ArenaBitVector *tryBlockAddr = oatAllocBitVector(cUnit.get(),
827 cUnit->insnsSize,
buzbee67bf8852011-08-17 17:51:35 -0700828 true /* expandable */);
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700829 cUnit->tryBlockAddr = tryBlockAddr;
buzbee67bf8852011-08-17 17:51:35 -0700830
831 /* Create the default entry and exit blocks and enter them to the list */
buzbee5abfa3e2012-01-31 17:01:43 -0800832 BasicBlock *entryBlock = oatNewBB(cUnit.get(), kEntryBlock, numBlocks++);
833 BasicBlock *exitBlock = oatNewBB(cUnit.get(), kExitBlock, numBlocks++);
buzbee67bf8852011-08-17 17:51:35 -0700834
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700835 cUnit->entryBlock = entryBlock;
836 cUnit->exitBlock = exitBlock;
buzbee67bf8852011-08-17 17:51:35 -0700837
buzbeeba938cb2012-02-03 14:47:55 -0800838 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) entryBlock);
839 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) exitBlock);
buzbee67bf8852011-08-17 17:51:35 -0700840
841 /* Current block to record parsed instructions */
buzbee5abfa3e2012-01-31 17:01:43 -0800842 BasicBlock *curBlock = oatNewBB(cUnit.get(), kDalvikByteCode, numBlocks++);
buzbee67bf8852011-08-17 17:51:35 -0700843 curBlock->startOffset = 0;
buzbeeba938cb2012-02-03 14:47:55 -0800844 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) curBlock);
buzbee5b537102012-01-17 17:33:47 -0800845 /* Add first block to the fast lookup cache */
846 cUnit->blockMap.insert(std::make_pair(curBlock->startOffset, curBlock));
buzbee67bf8852011-08-17 17:51:35 -0700847 entryBlock->fallThrough = curBlock;
buzbeeba938cb2012-02-03 14:47:55 -0800848 oatInsertGrowableList(cUnit.get(), curBlock->predecessors,
849 (intptr_t)entryBlock);
buzbee67bf8852011-08-17 17:51:35 -0700850
851 /*
852 * Store back the number of blocks since new blocks may be created of
853 * accessing cUnit.
854 */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700855 cUnit->numBlocks = numBlocks;
buzbee67bf8852011-08-17 17:51:35 -0700856
857 /* Identify code range in try blocks and set up the empty catch blocks */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700858 processTryCatchBlocks(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700859
860 /* Parse all instructions and put them into containing basic blocks */
861 while (codePtr < codeEnd) {
buzbeeba938cb2012-02-03 14:47:55 -0800862 MIR *insn = (MIR *) oatNew(cUnit.get(), sizeof(MIR), true, kAllocMIR);
buzbee67bf8852011-08-17 17:51:35 -0700863 insn->offset = curOffset;
buzbeeba938cb2012-02-03 14:47:55 -0800864 int width = parseInsn(cUnit.get(), codePtr, &insn->dalvikInsn, false);
buzbee67bf8852011-08-17 17:51:35 -0700865 insn->width = width;
866
867 /* Terminate when the data section is seen */
868 if (width == 0)
869 break;
870
871 oatAppendMIR(curBlock, insn);
872
873 codePtr += width;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800874 int flags = Instruction::Flags(insn->dalvikInsn.opcode);
buzbee67bf8852011-08-17 17:51:35 -0700875
buzbee5abfa3e2012-01-31 17:01:43 -0800876 int dfFlags = oatDataFlowAttributes[insn->dalvikInsn.opcode];
877
878 if (dfFlags & DF_HAS_DEFS) {
879 cUnit->defCount += (dfFlags & DF_DA_WIDE) ? 2 : 1;
880 }
buzbee99ba9642012-01-25 14:23:14 -0800881
Elliott Hughesadb8c672012-03-06 16:49:32 -0800882 if (flags & Instruction::kBranch) {
buzbeee941e2c2011-12-05 12:38:17 -0800883 curBlock = processCanBranch(cUnit.get(), curBlock, insn, curOffset,
884 width, flags, codePtr, codeEnd);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800885 } else if (flags & Instruction::kReturn) {
buzbee67bf8852011-08-17 17:51:35 -0700886 curBlock->fallThrough = exitBlock;
buzbeeba938cb2012-02-03 14:47:55 -0800887 oatInsertGrowableList(cUnit.get(), exitBlock->predecessors,
888 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700889 /*
890 * Terminate the current block if there are instructions
891 * afterwards.
892 */
893 if (codePtr < codeEnd) {
894 /*
895 * Create a fallthrough block for real instructions
Elliott Hughesadb8c672012-03-06 16:49:32 -0800896 * (incl. NOP).
buzbee67bf8852011-08-17 17:51:35 -0700897 */
898 if (contentIsInsn(codePtr)) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700899 findBlock(cUnit.get(), curOffset + width,
buzbee67bf8852011-08-17 17:51:35 -0700900 /* split */
901 false,
902 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800903 true,
904 /* immedPredBlockP */
905 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700906 }
907 }
Elliott Hughesadb8c672012-03-06 16:49:32 -0800908 } else if (flags & Instruction::kThrow) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700909 processCanThrow(cUnit.get(), curBlock, insn, curOffset, width, flags,
buzbee67bf8852011-08-17 17:51:35 -0700910 tryBlockAddr, codePtr, codeEnd);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800911 } else if (flags & Instruction::kSwitch) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700912 processCanSwitch(cUnit.get(), curBlock, insn, curOffset, width, flags);
buzbee67bf8852011-08-17 17:51:35 -0700913 }
914 curOffset += width;
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700915 BasicBlock *nextBlock = findBlock(cUnit.get(), curOffset,
buzbee67bf8852011-08-17 17:51:35 -0700916 /* split */
917 false,
918 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800919 false,
920 /* immedPredBlockP */
921 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700922 if (nextBlock) {
923 /*
924 * The next instruction could be the target of a previously parsed
925 * forward branch so a block is already created. If the current
926 * instruction is not an unconditional branch, connect them through
927 * the fall-through link.
928 */
buzbeeed3e9302011-09-23 17:34:19 -0700929 DCHECK(curBlock->fallThrough == NULL ||
buzbee67bf8852011-08-17 17:51:35 -0700930 curBlock->fallThrough == nextBlock ||
931 curBlock->fallThrough == exitBlock);
932
Elliott Hughesadb8c672012-03-06 16:49:32 -0800933 if ((curBlock->fallThrough == NULL) && (flags & Instruction::kContinue)) {
buzbee67bf8852011-08-17 17:51:35 -0700934 curBlock->fallThrough = nextBlock;
buzbeeba938cb2012-02-03 14:47:55 -0800935 oatInsertGrowableList(cUnit.get(), nextBlock->predecessors,
buzbee5abfa3e2012-01-31 17:01:43 -0800936 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700937 }
938 curBlock = nextBlock;
939 }
940 }
941
buzbee5abfa3e2012-01-31 17:01:43 -0800942 if (!(cUnit->disableOpt & (1 << kSkipLargeMethodOptimization))) {
buzbee99ba9642012-01-25 14:23:14 -0800943 if ((cUnit->numBlocks > MANY_BLOCKS) ||
944 ((cUnit->numBlocks > MANY_BLOCKS_INITIALIZER) &&
945 PrettyMethod(method_idx, dex_file).find("init>") !=
946 std::string::npos)) {
947 cUnit->disableDataflow = true;
948 // Disable optimization which require dataflow/ssa
949 cUnit->disableOpt |=
950 (1 << kNullCheckElimination) |
buzbeeb37c9992012-03-18 21:28:43 -0700951 (1 << kBBOpt) |
buzbee99ba9642012-01-25 14:23:14 -0800952 (1 << kPromoteRegs);
953 if (cUnit->printMe) {
954 LOG(INFO) << "Compiler: " << PrettyMethod(method_idx, dex_file)
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800955 << " too big: " << cUnit->numBlocks;
buzbee99ba9642012-01-25 14:23:14 -0800956 }
957 }
958 }
959
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700960 if (cUnit->printMe) {
961 oatDumpCompilationUnit(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700962 }
963
buzbee5b537102012-01-17 17:33:47 -0800964 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
965 /* Verify if all blocks are connected as claimed */
buzbee5abfa3e2012-01-31 17:01:43 -0800966 oatDataFlowAnalysisDispatcher(cUnit.get(), verifyPredInfo, kAllNodes,
967 false /* isIterative */);
buzbee5b537102012-01-17 17:33:47 -0800968 }
buzbee67bf8852011-08-17 17:51:35 -0700969
970 /* Perform SSA transformation for the whole method */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700971 oatMethodSSATransformation(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700972
buzbee239c4e72012-03-16 08:42:29 -0700973 /* Detect loops */
974 oatMethodLoopDetection(cUnit.get());
975
976 /* Count uses */
977 oatMethodUseCount(cUnit.get());
978
buzbee43a36422011-09-14 14:00:13 -0700979 /* Perform null check elimination */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700980 oatMethodNullCheckElimination(cUnit.get());
buzbee43a36422011-09-14 14:00:13 -0700981
buzbeee1965672012-03-11 18:39:19 -0700982 /* Do some basic block optimizations */
983 oatMethodBasicBlockOptimization(cUnit.get());
buzbeee1965672012-03-11 18:39:19 -0700984
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700985 oatInitializeRegAlloc(cUnit.get()); // Needs to happen after SSA naming
buzbee67bf8852011-08-17 17:51:35 -0700986
987 /* Allocate Registers using simple local allocation scheme */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700988 oatSimpleRegAlloc(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700989
990 /* Convert MIR to LIR, etc. */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700991 oatMethodMIR2LIR(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700992
993 // Debugging only
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700994 if (cUnit->enableDebug & (1 << kDebugDumpCFG)) {
995 oatDumpCFG(cUnit.get(), "/sdcard/cfg/");
buzbeeec5adf32011-09-11 15:25:43 -0700996 }
buzbee67bf8852011-08-17 17:51:35 -0700997
998 /* Method is not empty */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700999 if (cUnit->firstLIRInsn) {
buzbee67bf8852011-08-17 17:51:35 -07001000
1001 // mark the targets of switch statement case labels
Elliott Hughes3b6baaa2011-10-14 19:13:56 -07001002 oatProcessSwitchTables(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001003
1004 /* Convert LIR into machine code. */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -07001005 oatAssembleLIR(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001006
Elliott Hughes3b6baaa2011-10-14 19:13:56 -07001007 if (cUnit->printMe) {
1008 oatCodegenDump(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001009 }
1010 }
1011
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001012 // Combine vmap tables - core regs, then fp regs - into vmapTable
1013 std::vector<uint16_t> vmapTable;
Elliott Hughes3b6baaa2011-10-14 19:13:56 -07001014 for (size_t i = 0 ; i < cUnit->coreVmapTable.size(); i++) {
1015 vmapTable.push_back(cUnit->coreVmapTable[i]);
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001016 }
Ian Rogersf7d9ad32012-03-13 18:45:39 -07001017 // Add a marker to take place of lr
1018 vmapTable.push_back(INVALID_VREG);
buzbeec41e5b52011-09-23 12:46:19 -07001019 // Combine vmap tables - core regs, then fp regs
Elliott Hughes3b6baaa2011-10-14 19:13:56 -07001020 for (uint32_t i = 0; i < cUnit->fpVmapTable.size(); i++) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -07001021 vmapTable.push_back(cUnit->fpVmapTable[i]);
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001022 }
Ian Rogersb5d09b22012-03-06 22:14:17 -08001023 CompiledMethod* result = new CompiledMethod(cUnit->instructionSet, cUnit->codeBuffer,
Ian Rogers0571d352011-11-03 19:51:38 -07001024 cUnit->frameSize, cUnit->coreSpillMask,
1025 cUnit->fpSpillMask, cUnit->mappingTable,
1026 vmapTable);
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001027
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -08001028 VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file)
buzbee5abfa3e2012-01-31 17:01:43 -08001029 << " (" << (cUnit->codeBuffer.size() * sizeof(cUnit->codeBuffer[0]))
1030 << " bytes)";
1031
1032#ifdef WITH_MEMSTATS
1033 if (cUnit->enableDebug & (1 << kDebugShowMemoryUsage)) {
1034 oatDumpMemStats(cUnit.get());
1035 }
1036#endif
buzbee67bf8852011-08-17 17:51:35 -07001037
buzbeeba938cb2012-02-03 14:47:55 -08001038 oatArenaReset(cUnit.get());
1039
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001040 return result;
buzbee67bf8852011-08-17 17:51:35 -07001041}
1042
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001043} // namespace art
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001044
Elliott Hughes3fa1b7e2012-03-13 17:06:22 -07001045extern "C" art::CompiledMethod* ArtCompileMethod(art::Compiler& compiler,
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001046 const art::DexFile::CodeItem* code_item,
1047 uint32_t access_flags, uint32_t method_idx,
1048 const art::ClassLoader* class_loader,
1049 const art::DexFile& dex_file)
1050{
1051 CHECK_EQ(compiler.GetInstructionSet(), art::oatInstructionSet());
Elliott Hughes3fa1b7e2012-03-13 17:06:22 -07001052 return art::oatCompileMethod(compiler, code_item, access_flags, method_idx, class_loader, dex_file);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001053}