blob: d7bf51f3681dfe83a166cc7e60e745f78e02442b [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) |
buzbeece302932011-10-04 14:32:18 -070036 0;
37
38uint32_t compilerDebugFlags = 0 | // Enable debug/testing modes
buzbeee3de7492011-10-05 13:37:17 -070039 //(1 << kDebugDisplayMissingTargets) |
buzbeece302932011-10-04 14:32:18 -070040 //(1 << kDebugVerbose) |
41 //(1 << kDebugDumpCFG) |
42 //(1 << kDebugSlowFieldPath) |
43 //(1 << kDebugSlowInvokePath) |
44 //(1 << kDebugSlowStringPath) |
45 //(1 << kDebugSlowestFieldPath) |
46 //(1 << kDebugSlowestStringPath) |
buzbee34c77ad2012-01-11 13:01:32 -080047 //(1 << kDebugExerciseResolveMethod) |
buzbee5b537102012-01-17 17:33:47 -080048 //(1 << kDebugVerifyDataflow) |
buzbee5abfa3e2012-01-31 17:01:43 -080049 //(1 << kDebugShowMemoryUsage) |
buzbeece302932011-10-04 14:32:18 -070050 0;
51
buzbee31a4a6f2012-02-28 15:36:15 -080052inline bool contentIsInsn(const u2* codePtr) {
buzbee67bf8852011-08-17 17:51:35 -070053 u2 instr = *codePtr;
Elliott Hughesadb8c672012-03-06 16:49:32 -080054 Instruction::Code opcode = (Instruction::Code)(instr & 0xff);
buzbee67bf8852011-08-17 17:51:35 -070055
56 /*
Elliott Hughesadb8c672012-03-06 16:49:32 -080057 * Since the low 8-bit in metadata may look like NOP, we need to check
buzbee67bf8852011-08-17 17:51:35 -070058 * both the low and whole sub-word to determine whether it is code or data.
59 */
Elliott Hughesadb8c672012-03-06 16:49:32 -080060 return (opcode != Instruction::NOP || instr == 0);
buzbee67bf8852011-08-17 17:51:35 -070061}
62
63/*
64 * Parse an instruction, return the length of the instruction
65 */
buzbee31a4a6f2012-02-28 15:36:15 -080066inline int parseInsn(CompilationUnit* cUnit, const u2* codePtr,
Elliott Hughesadb8c672012-03-06 16:49:32 -080067 DecodedInstruction* decoded_instruction, bool printMe)
buzbee67bf8852011-08-17 17:51:35 -070068{
Elliott Hughesadb8c672012-03-06 16:49:32 -080069 // Don't parse instruction data
70 if (!contentIsInsn(codePtr)) {
71 return 0;
72 }
buzbee67bf8852011-08-17 17:51:35 -070073
Elliott Hughesadb8c672012-03-06 16:49:32 -080074 const Instruction* instruction = Instruction::At(codePtr);
75 *decoded_instruction = DecodedInstruction(instruction);
buzbee67bf8852011-08-17 17:51:35 -070076
Elliott Hughesadb8c672012-03-06 16:49:32 -080077 if (printMe) {
78 char* decodedString = oatGetDalvikDisassembly(cUnit, *decoded_instruction, NULL);
79 LOG(INFO) << codePtr << ": 0x" << std::hex << static_cast<int>(decoded_instruction->opcode)
80 << " " << decodedString;
81 }
82 return instruction->SizeInCodeUnits();
buzbee67bf8852011-08-17 17:51:35 -070083}
84
85#define UNKNOWN_TARGET 0xffffffff
86
Elliott Hughesadb8c672012-03-06 16:49:32 -080087inline bool isGoto(MIR* insn) {
88 switch (insn->dalvikInsn.opcode) {
89 case Instruction::GOTO:
90 case Instruction::GOTO_16:
91 case Instruction::GOTO_32:
92 return true;
93 default:
94 return false;
buzbee67bf8852011-08-17 17:51:35 -070095 }
96}
97
98/*
99 * Identify unconditional branch instructions
100 */
Elliott Hughesadb8c672012-03-06 16:49:32 -0800101inline bool isUnconditionalBranch(MIR* insn) {
102 switch (insn->dalvikInsn.opcode) {
103 case Instruction::RETURN_VOID:
104 case Instruction::RETURN:
105 case Instruction::RETURN_WIDE:
106 case Instruction::RETURN_OBJECT:
107 return true;
108 default:
109 return isGoto(insn);
110 }
buzbee67bf8852011-08-17 17:51:35 -0700111}
112
113/* Split an existing block from the specified code offset into two */
buzbee31a4a6f2012-02-28 15:36:15 -0800114BasicBlock *splitBlock(CompilationUnit* cUnit, unsigned int codeOffset,
115 BasicBlock* origBlock, BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700116{
117 MIR* insn = origBlock->firstMIRInsn;
118 while (insn) {
119 if (insn->offset == codeOffset) break;
120 insn = insn->next;
121 }
122 if (insn == NULL) {
123 LOG(FATAL) << "Break split failed";
124 }
buzbee5abfa3e2012-01-31 17:01:43 -0800125 BasicBlock *bottomBlock = oatNewBB(cUnit, kDalvikByteCode,
126 cUnit->numBlocks++);
buzbeeba938cb2012-02-03 14:47:55 -0800127 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700128
129 bottomBlock->startOffset = codeOffset;
130 bottomBlock->firstMIRInsn = insn;
131 bottomBlock->lastMIRInsn = origBlock->lastMIRInsn;
132
buzbee5b537102012-01-17 17:33:47 -0800133 /* Add it to the quick lookup cache */
134 cUnit->blockMap.insert(std::make_pair(bottomBlock->startOffset,
135 bottomBlock));
136
buzbee67bf8852011-08-17 17:51:35 -0700137 /* Handle the taken path */
138 bottomBlock->taken = origBlock->taken;
139 if (bottomBlock->taken) {
140 origBlock->taken = NULL;
buzbee5abfa3e2012-01-31 17:01:43 -0800141 oatDeleteGrowableList(bottomBlock->taken->predecessors,
142 (intptr_t)origBlock);
buzbeeba938cb2012-02-03 14:47:55 -0800143 oatInsertGrowableList(cUnit, bottomBlock->taken->predecessors,
buzbee5abfa3e2012-01-31 17:01:43 -0800144 (intptr_t)bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700145 }
146
147 /* Handle the fallthrough path */
148 bottomBlock->needFallThroughBranch = origBlock->needFallThroughBranch;
149 bottomBlock->fallThrough = origBlock->fallThrough;
150 origBlock->fallThrough = bottomBlock;
151 origBlock->needFallThroughBranch = true;
buzbeeba938cb2012-02-03 14:47:55 -0800152 oatInsertGrowableList(cUnit, bottomBlock->predecessors,
153 (intptr_t)origBlock);
buzbee67bf8852011-08-17 17:51:35 -0700154 if (bottomBlock->fallThrough) {
buzbee5abfa3e2012-01-31 17:01:43 -0800155 oatDeleteGrowableList(bottomBlock->fallThrough->predecessors,
156 (intptr_t)origBlock);
buzbeeba938cb2012-02-03 14:47:55 -0800157 oatInsertGrowableList(cUnit, bottomBlock->fallThrough->predecessors,
buzbee5abfa3e2012-01-31 17:01:43 -0800158 (intptr_t)bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700159 }
160
161 /* Handle the successor list */
162 if (origBlock->successorBlockList.blockListType != kNotUsed) {
163 bottomBlock->successorBlockList = origBlock->successorBlockList;
164 origBlock->successorBlockList.blockListType = kNotUsed;
165 GrowableListIterator iterator;
166
167 oatGrowableListIteratorInit(&bottomBlock->successorBlockList.blocks,
168 &iterator);
169 while (true) {
170 SuccessorBlockInfo *successorBlockInfo =
171 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
172 if (successorBlockInfo == NULL) break;
173 BasicBlock *bb = successorBlockInfo->block;
buzbee5abfa3e2012-01-31 17:01:43 -0800174 oatDeleteGrowableList(bb->predecessors, (intptr_t)origBlock);
buzbeeba938cb2012-02-03 14:47:55 -0800175 oatInsertGrowableList(cUnit, bb->predecessors,
176 (intptr_t)bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700177 }
178 }
179
180 origBlock->lastMIRInsn = insn->prev;
181
182 insn->prev->next = NULL;
183 insn->prev = NULL;
buzbee9ab05de2012-01-18 15:43:48 -0800184 /*
185 * Update the immediate predecessor block pointer so that outgoing edges
186 * can be applied to the proper block.
187 */
188 if (immedPredBlockP) {
189 DCHECK_EQ(*immedPredBlockP, origBlock);
190 *immedPredBlockP = bottomBlock;
191 }
buzbee67bf8852011-08-17 17:51:35 -0700192 return bottomBlock;
193}
194
195/*
196 * Given a code offset, find out the block that starts with it. If the offset
buzbee9ab05de2012-01-18 15:43:48 -0800197 * is in the middle of an existing block, split it into two. If immedPredBlockP
198 * is not non-null and is the block being split, update *immedPredBlockP to
199 * point to the bottom block so that outgoing edges can be set up properly
200 * (by the caller)
buzbee5b537102012-01-17 17:33:47 -0800201 * Utilizes a map for fast lookup of the typical cases.
buzbee67bf8852011-08-17 17:51:35 -0700202 */
buzbee31a4a6f2012-02-28 15:36:15 -0800203BasicBlock *findBlock(CompilationUnit* cUnit, unsigned int codeOffset,
204 bool split, bool create, BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700205{
206 GrowableList* blockList = &cUnit->blockList;
207 BasicBlock* bb;
208 unsigned int i;
buzbee5b537102012-01-17 17:33:47 -0800209 std::map<unsigned int, BasicBlock*>::iterator it;
buzbee67bf8852011-08-17 17:51:35 -0700210
buzbee5b537102012-01-17 17:33:47 -0800211 it = cUnit->blockMap.find(codeOffset);
212 if (it != cUnit->blockMap.end()) {
213 return it->second;
214 } else if (!create) {
215 return NULL;
216 }
217
218 if (split) {
219 for (i = 0; i < blockList->numUsed; i++) {
220 bb = (BasicBlock *) blockList->elemList[i];
221 if (bb->blockType != kDalvikByteCode) continue;
222 /* Check if a branch jumps into the middle of an existing block */
223 if ((codeOffset > bb->startOffset) && (bb->lastMIRInsn != NULL) &&
224 (codeOffset <= bb->lastMIRInsn->offset)) {
225 BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb,
226 bb == *immedPredBlockP ?
227 immedPredBlockP : NULL);
228 return newBB;
229 }
buzbee67bf8852011-08-17 17:51:35 -0700230 }
231 }
buzbee5b537102012-01-17 17:33:47 -0800232
233 /* Create a new one */
buzbee5abfa3e2012-01-31 17:01:43 -0800234 bb = oatNewBB(cUnit, kDalvikByteCode, cUnit->numBlocks++);
buzbeeba938cb2012-02-03 14:47:55 -0800235 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) bb);
buzbee5b537102012-01-17 17:33:47 -0800236 bb->startOffset = codeOffset;
237 cUnit->blockMap.insert(std::make_pair(bb->startOffset, bb));
238 return bb;
buzbee67bf8852011-08-17 17:51:35 -0700239}
240
241/* Dump the CFG into a DOT graph */
242void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix)
243{
buzbee67bf8852011-08-17 17:51:35 -0700244 FILE* file;
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800245 std::string name(PrettyMethod(cUnit->method_idx, *cUnit->dex_file));
buzbee67bf8852011-08-17 17:51:35 -0700246 char startOffset[80];
247 sprintf(startOffset, "_%x", cUnit->entryBlock->fallThrough->startOffset);
buzbeeba938cb2012-02-03 14:47:55 -0800248 char* fileName = (char*) oatNew(cUnit,
buzbeec143c552011-08-20 17:38:58 -0700249 strlen(dirPrefix) +
250 name.length() +
buzbee5abfa3e2012-01-31 17:01:43 -0800251 strlen(".dot") + 1, true, kAllocDebugInfo);
buzbeec143c552011-08-20 17:38:58 -0700252 sprintf(fileName, "%s%s%s.dot", dirPrefix, name.c_str(), startOffset);
buzbee67bf8852011-08-17 17:51:35 -0700253
254 /*
255 * Convert the special characters into a filesystem- and shell-friendly
256 * format.
257 */
258 int i;
259 for (i = strlen(dirPrefix); fileName[i]; i++) {
260 if (fileName[i] == '/') {
261 fileName[i] = '_';
262 } else if (fileName[i] == ';') {
263 fileName[i] = '#';
264 } else if (fileName[i] == '$') {
265 fileName[i] = '+';
266 } else if (fileName[i] == '(' || fileName[i] == ')') {
267 fileName[i] = '@';
268 } else if (fileName[i] == '<' || fileName[i] == '>') {
269 fileName[i] = '=';
270 }
271 }
272 file = fopen(fileName, "w");
273 if (file == NULL) {
274 return;
275 }
276 fprintf(file, "digraph G {\n");
277
278 fprintf(file, " rankdir=TB\n");
279
280 int numReachableBlocks = cUnit->numReachableBlocks;
281 int idx;
282 const GrowableList *blockList = &cUnit->blockList;
283
284 for (idx = 0; idx < numReachableBlocks; idx++) {
285 int blockIdx = cUnit->dfsOrder.elemList[idx];
286 BasicBlock *bb = (BasicBlock *) oatGrowableListGetElement(blockList,
287 blockIdx);
288 if (bb == NULL) break;
289 if (bb->blockType == kEntryBlock) {
290 fprintf(file, " entry [shape=Mdiamond];\n");
291 } else if (bb->blockType == kExitBlock) {
292 fprintf(file, " exit [shape=Mdiamond];\n");
293 } else if (bb->blockType == kDalvikByteCode) {
294 fprintf(file, " block%04x [shape=record,label = \"{ \\\n",
295 bb->startOffset);
296 const MIR *mir;
297 fprintf(file, " {block id %d\\l}%s\\\n", bb->id,
298 bb->firstMIRInsn ? " | " : " ");
299 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
300 fprintf(file, " {%04x %s\\l}%s\\\n", mir->offset,
Elliott Hughesadb8c672012-03-06 16:49:32 -0800301 mir->ssaRep ? oatFullDisassembler(cUnit, mir) : Instruction::Name(mir->dalvikInsn.opcode),
buzbee67bf8852011-08-17 17:51:35 -0700302 mir->next ? " | " : " ");
303 }
304 fprintf(file, " }\"];\n\n");
305 } else if (bb->blockType == kExceptionHandling) {
306 char blockName[BLOCK_NAME_LEN];
307
308 oatGetBlockName(bb, blockName);
309 fprintf(file, " %s [shape=invhouse];\n", blockName);
310 }
311
312 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
313
314 if (bb->taken) {
315 oatGetBlockName(bb, blockName1);
316 oatGetBlockName(bb->taken, blockName2);
317 fprintf(file, " %s:s -> %s:n [style=dotted]\n",
318 blockName1, blockName2);
319 }
320 if (bb->fallThrough) {
321 oatGetBlockName(bb, blockName1);
322 oatGetBlockName(bb->fallThrough, blockName2);
323 fprintf(file, " %s:s -> %s:n\n", blockName1, blockName2);
324 }
325
326 if (bb->successorBlockList.blockListType != kNotUsed) {
327 fprintf(file, " succ%04x [shape=%s,label = \"{ \\\n",
328 bb->startOffset,
329 (bb->successorBlockList.blockListType == kCatch) ?
330 "Mrecord" : "record");
331 GrowableListIterator iterator;
332 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
333 &iterator);
334 SuccessorBlockInfo *successorBlockInfo =
335 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
336
337 int succId = 0;
338 while (true) {
339 if (successorBlockInfo == NULL) break;
340
341 BasicBlock *destBlock = successorBlockInfo->block;
342 SuccessorBlockInfo *nextSuccessorBlockInfo =
343 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
344
345 fprintf(file, " {<f%d> %04x: %04x\\l}%s\\\n",
346 succId++,
347 successorBlockInfo->key,
348 destBlock->startOffset,
349 (nextSuccessorBlockInfo != NULL) ? " | " : " ");
350
351 successorBlockInfo = nextSuccessorBlockInfo;
352 }
353 fprintf(file, " }\"];\n\n");
354
355 oatGetBlockName(bb, blockName1);
356 fprintf(file, " %s:s -> succ%04x:n [style=dashed]\n",
357 blockName1, bb->startOffset);
358
359 if (bb->successorBlockList.blockListType == kPackedSwitch ||
360 bb->successorBlockList.blockListType == kSparseSwitch) {
361
362 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
363 &iterator);
364
365 succId = 0;
366 while (true) {
367 SuccessorBlockInfo *successorBlockInfo =
368 (SuccessorBlockInfo *)
369 oatGrowableListIteratorNext(&iterator);
370 if (successorBlockInfo == NULL) break;
371
372 BasicBlock *destBlock = successorBlockInfo->block;
373
374 oatGetBlockName(destBlock, blockName2);
375 fprintf(file, " succ%04x:f%d:e -> %s:n\n",
376 bb->startOffset, succId++,
377 blockName2);
378 }
379 }
380 }
381 fprintf(file, "\n");
382
buzbeece302932011-10-04 14:32:18 -0700383 /* Display the dominator tree */
buzbee67bf8852011-08-17 17:51:35 -0700384 oatGetBlockName(bb, blockName1);
385 fprintf(file, " cfg%s [label=\"%s\", shape=none];\n",
386 blockName1, blockName1);
387 if (bb->iDom) {
388 oatGetBlockName(bb->iDom, blockName2);
389 fprintf(file, " cfg%s:s -> cfg%s:n\n\n",
390 blockName2, blockName1);
391 }
buzbee67bf8852011-08-17 17:51:35 -0700392 }
393 fprintf(file, "}\n");
394 fclose(file);
395}
396
397/* Verify if all the successor is connected with all the claimed predecessors */
buzbee31a4a6f2012-02-28 15:36:15 -0800398bool verifyPredInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700399{
buzbee5abfa3e2012-01-31 17:01:43 -0800400 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700401
buzbee5abfa3e2012-01-31 17:01:43 -0800402 oatGrowableListIteratorInit(bb->predecessors, &iter);
buzbee67bf8852011-08-17 17:51:35 -0700403 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800404 BasicBlock *predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
405 if (!predBB) break;
buzbee67bf8852011-08-17 17:51:35 -0700406 bool found = false;
407 if (predBB->taken == bb) {
408 found = true;
409 } else if (predBB->fallThrough == bb) {
410 found = true;
411 } else if (predBB->successorBlockList.blockListType != kNotUsed) {
412 GrowableListIterator iterator;
413 oatGrowableListIteratorInit(&predBB->successorBlockList.blocks,
414 &iterator);
415 while (true) {
416 SuccessorBlockInfo *successorBlockInfo =
417 (SuccessorBlockInfo *)
418 oatGrowableListIteratorNext(&iterator);
419 if (successorBlockInfo == NULL) break;
420 BasicBlock *succBB = successorBlockInfo->block;
421 if (succBB == bb) {
422 found = true;
423 break;
424 }
425 }
426 }
427 if (found == false) {
428 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
429 oatGetBlockName(bb, blockName1);
430 oatGetBlockName(predBB, blockName2);
431 oatDumpCFG(cUnit, "/sdcard/cfg/");
432 LOG(FATAL) << "Successor " << blockName1 << "not found from "
433 << blockName2;
434 }
435 }
436 return true;
437}
438
439/* Identify code range in try blocks and set up the empty catch blocks */
buzbee31a4a6f2012-02-28 15:36:15 -0800440void processTryCatchBlocks(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700441{
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800442 const DexFile::CodeItem* code_item = cUnit->code_item;
buzbeee9a72f62011-09-04 17:59:07 -0700443 int triesSize = code_item->tries_size_;
buzbee67bf8852011-08-17 17:51:35 -0700444 int offset;
445
446 if (triesSize == 0) {
447 return;
448 }
449
buzbee67bf8852011-08-17 17:51:35 -0700450 ArenaBitVector* tryBlockAddr = cUnit->tryBlockAddr;
451
buzbeee9a72f62011-09-04 17:59:07 -0700452 for (int i = 0; i < triesSize; i++) {
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800453 const DexFile::TryItem* pTry =
454 DexFile::GetTryItems(*code_item, i);
buzbeee9a72f62011-09-04 17:59:07 -0700455 int startOffset = pTry->start_addr_;
456 int endOffset = startOffset + pTry->insn_count_;
buzbee67bf8852011-08-17 17:51:35 -0700457 for (offset = startOffset; offset < endOffset; offset++) {
buzbeeba938cb2012-02-03 14:47:55 -0800458 oatSetBit(cUnit, tryBlockAddr, offset);
buzbee67bf8852011-08-17 17:51:35 -0700459 }
460 }
461
buzbeee9a72f62011-09-04 17:59:07 -0700462 // Iterate over each of the handlers to enqueue the empty Catch blocks
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800463 const byte* handlers_ptr =
464 DexFile::GetCatchHandlerData(*code_item, 0);
465 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
buzbeee9a72f62011-09-04 17:59:07 -0700466 for (uint32_t idx = 0; idx < handlers_size; idx++) {
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800467 CatchHandlerIterator iterator(handlers_ptr);
Ian Rogers0571d352011-11-03 19:51:38 -0700468 for (; iterator.HasNext(); iterator.Next()) {
469 uint32_t address = iterator.GetHandlerAddress();
buzbee9ab05de2012-01-18 15:43:48 -0800470 findBlock(cUnit, address, false /* split */, true /*create*/,
471 /* immedPredBlockP */ NULL);
buzbee67bf8852011-08-17 17:51:35 -0700472 }
Ian Rogers0571d352011-11-03 19:51:38 -0700473 handlers_ptr = iterator.EndDataPointer();
buzbee67bf8852011-08-17 17:51:35 -0700474 }
475}
476
Elliott Hughesadb8c672012-03-06 16:49:32 -0800477/* Process instructions with the kBranch flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800478BasicBlock* processCanBranch(CompilationUnit* cUnit, BasicBlock* curBlock,
479 MIR* insn, int curOffset, int width, int flags,
480 const u2* codePtr, const u2* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700481{
482 int target = curOffset;
483 switch (insn->dalvikInsn.opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800484 case Instruction::GOTO:
485 case Instruction::GOTO_16:
486 case Instruction::GOTO_32:
buzbee67bf8852011-08-17 17:51:35 -0700487 target += (int) insn->dalvikInsn.vA;
488 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800489 case Instruction::IF_EQ:
490 case Instruction::IF_NE:
491 case Instruction::IF_LT:
492 case Instruction::IF_GE:
493 case Instruction::IF_GT:
494 case Instruction::IF_LE:
buzbee67bf8852011-08-17 17:51:35 -0700495 target += (int) insn->dalvikInsn.vC;
496 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800497 case Instruction::IF_EQZ:
498 case Instruction::IF_NEZ:
499 case Instruction::IF_LTZ:
500 case Instruction::IF_GEZ:
501 case Instruction::IF_GTZ:
502 case Instruction::IF_LEZ:
buzbee67bf8852011-08-17 17:51:35 -0700503 target += (int) insn->dalvikInsn.vB;
504 break;
505 default:
506 LOG(FATAL) << "Unexpected opcode(" << (int)insn->dalvikInsn.opcode
Elliott Hughesadb8c672012-03-06 16:49:32 -0800507 << ") with kBranch set";
buzbee67bf8852011-08-17 17:51:35 -0700508 }
509 BasicBlock *takenBlock = findBlock(cUnit, target,
510 /* split */
511 true,
512 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800513 true,
514 /* immedPredBlockP */
515 &curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700516 curBlock->taken = takenBlock;
buzbeeba938cb2012-02-03 14:47:55 -0800517 oatInsertGrowableList(cUnit, takenBlock->predecessors, (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700518
519 /* Always terminate the current block for conditional branches */
Elliott Hughesadb8c672012-03-06 16:49:32 -0800520 if (flags & Instruction::kContinue) {
buzbee67bf8852011-08-17 17:51:35 -0700521 BasicBlock *fallthroughBlock = findBlock(cUnit,
522 curOffset + width,
523 /*
524 * If the method is processed
525 * in sequential order from the
526 * beginning, we don't need to
527 * specify split for continue
528 * blocks. However, this
529 * routine can be called by
530 * compileLoop, which starts
531 * parsing the method from an
532 * arbitrary address in the
533 * method body.
534 */
535 true,
536 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800537 true,
538 /* immedPredBlockP */
539 &curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700540 curBlock->fallThrough = fallthroughBlock;
buzbeeba938cb2012-02-03 14:47:55 -0800541 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
buzbee5abfa3e2012-01-31 17:01:43 -0800542 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700543 } else if (codePtr < codeEnd) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800544 /* Create a fallthrough block for real instructions (incl. NOP) */
buzbee67bf8852011-08-17 17:51:35 -0700545 if (contentIsInsn(codePtr)) {
546 findBlock(cUnit, curOffset + width,
547 /* split */
548 false,
549 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800550 true,
551 /* immedPredBlockP */
552 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700553 }
554 }
buzbeee941e2c2011-12-05 12:38:17 -0800555 return curBlock;
buzbee67bf8852011-08-17 17:51:35 -0700556}
557
Elliott Hughesadb8c672012-03-06 16:49:32 -0800558/* Process instructions with the kSwitch flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800559void processCanSwitch(CompilationUnit* cUnit, BasicBlock* curBlock,
560 MIR* insn, int curOffset, int width, int flags)
buzbee67bf8852011-08-17 17:51:35 -0700561{
562 u2* switchData= (u2 *) (cUnit->insns + curOffset +
563 insn->dalvikInsn.vB);
564 int size;
565 int* keyTable;
566 int* targetTable;
567 int i;
568 int firstKey;
569
570 /*
571 * Packed switch data format:
572 * ushort ident = 0x0100 magic value
573 * ushort size number of entries in the table
574 * int first_key first (and lowest) switch case value
575 * int targets[size] branch targets, relative to switch opcode
576 *
577 * Total size is (4+size*2) 16-bit code units.
578 */
Elliott Hughesadb8c672012-03-06 16:49:32 -0800579 if (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) {
580 DCHECK_EQ(static_cast<int>(switchData[0]), static_cast<int>(Instruction::kPackedSwitchSignature));
buzbee67bf8852011-08-17 17:51:35 -0700581 size = switchData[1];
582 firstKey = switchData[2] | (switchData[3] << 16);
583 targetTable = (int *) &switchData[4];
584 keyTable = NULL; // Make the compiler happy
585 /*
586 * Sparse switch data format:
587 * ushort ident = 0x0200 magic value
588 * ushort size number of entries in the table; > 0
589 * int keys[size] keys, sorted low-to-high; 32-bit aligned
590 * int targets[size] branch targets, relative to switch opcode
591 *
592 * Total size is (2+size*4) 16-bit code units.
593 */
594 } else {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800595 DCHECK_EQ(static_cast<int>(switchData[0]), static_cast<int>(Instruction::kSparseSwitchSignature));
buzbee67bf8852011-08-17 17:51:35 -0700596 size = switchData[1];
597 keyTable = (int *) &switchData[2];
598 targetTable = (int *) &switchData[2 + size*2];
599 firstKey = 0; // To make the compiler happy
600 }
601
602 if (curBlock->successorBlockList.blockListType != kNotUsed) {
603 LOG(FATAL) << "Successor block list already in use: " <<
604 (int)curBlock->successorBlockList.blockListType;
605 }
606 curBlock->successorBlockList.blockListType =
Elliott Hughesadb8c672012-03-06 16:49:32 -0800607 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
buzbee67bf8852011-08-17 17:51:35 -0700608 kPackedSwitch : kSparseSwitch;
buzbeeba938cb2012-02-03 14:47:55 -0800609 oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, size,
buzbee5abfa3e2012-01-31 17:01:43 -0800610 kListSuccessorBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700611
612 for (i = 0; i < size; i++) {
613 BasicBlock *caseBlock = findBlock(cUnit, curOffset + targetTable[i],
614 /* split */
615 true,
616 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800617 true,
618 /* immedPredBlockP */
619 &curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700620 SuccessorBlockInfo *successorBlockInfo =
buzbeeba938cb2012-02-03 14:47:55 -0800621 (SuccessorBlockInfo *) oatNew(cUnit, sizeof(SuccessorBlockInfo),
622 false, kAllocSuccessor);
buzbee67bf8852011-08-17 17:51:35 -0700623 successorBlockInfo->block = caseBlock;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800624 successorBlockInfo->key = (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH)?
buzbee67bf8852011-08-17 17:51:35 -0700625 firstKey + i : keyTable[i];
buzbeeba938cb2012-02-03 14:47:55 -0800626 oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
buzbee67bf8852011-08-17 17:51:35 -0700627 (intptr_t) successorBlockInfo);
buzbeeba938cb2012-02-03 14:47:55 -0800628 oatInsertGrowableList(cUnit, caseBlock->predecessors,
629 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700630 }
631
632 /* Fall-through case */
633 BasicBlock* fallthroughBlock = findBlock(cUnit,
634 curOffset + width,
635 /* split */
636 false,
637 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800638 true,
639 /* immedPredBlockP */
640 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700641 curBlock->fallThrough = fallthroughBlock;
buzbeeba938cb2012-02-03 14:47:55 -0800642 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
643 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700644}
645
Elliott Hughesadb8c672012-03-06 16:49:32 -0800646/* Process instructions with the kThrow flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800647void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock, MIR* insn,
648 int curOffset, int width, int flags,
649 ArenaBitVector* tryBlockAddr, const u2* codePtr,
650 const u2* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700651{
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800652 const DexFile::CodeItem* code_item = cUnit->code_item;
buzbee67bf8852011-08-17 17:51:35 -0700653
654 /* In try block */
655 if (oatIsBitSet(tryBlockAddr, curOffset)) {
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800656 CatchHandlerIterator iterator(*code_item, curOffset);
buzbee67bf8852011-08-17 17:51:35 -0700657
buzbee67bf8852011-08-17 17:51:35 -0700658 if (curBlock->successorBlockList.blockListType != kNotUsed) {
659 LOG(FATAL) << "Successor block list already in use: " <<
660 (int)curBlock->successorBlockList.blockListType;
661 }
buzbeee9a72f62011-09-04 17:59:07 -0700662
buzbee67bf8852011-08-17 17:51:35 -0700663 curBlock->successorBlockList.blockListType = kCatch;
buzbeeba938cb2012-02-03 14:47:55 -0800664 oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, 2,
buzbee5abfa3e2012-01-31 17:01:43 -0800665 kListSuccessorBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700666
Ian Rogers0571d352011-11-03 19:51:38 -0700667 for (;iterator.HasNext(); iterator.Next()) {
668 BasicBlock *catchBlock = findBlock(cUnit, iterator.GetHandlerAddress(),
buzbeee9a72f62011-09-04 17:59:07 -0700669 false /* split*/,
buzbee9ab05de2012-01-18 15:43:48 -0800670 false /* creat */,
671 NULL /* immedPredBlockP */);
buzbee43a36422011-09-14 14:00:13 -0700672 catchBlock->catchEntry = true;
buzbeeba938cb2012-02-03 14:47:55 -0800673 SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
674 oatNew(cUnit, sizeof(SuccessorBlockInfo), false,
675 kAllocSuccessor);
buzbee67bf8852011-08-17 17:51:35 -0700676 successorBlockInfo->block = catchBlock;
Ian Rogers0571d352011-11-03 19:51:38 -0700677 successorBlockInfo->key = iterator.GetHandlerTypeIndex();
buzbeeba938cb2012-02-03 14:47:55 -0800678 oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
buzbee67bf8852011-08-17 17:51:35 -0700679 (intptr_t) successorBlockInfo);
buzbeeba938cb2012-02-03 14:47:55 -0800680 oatInsertGrowableList(cUnit, catchBlock->predecessors,
681 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700682 }
683 } else {
buzbee5abfa3e2012-01-31 17:01:43 -0800684 BasicBlock *ehBlock = oatNewBB(cUnit, kExceptionHandling,
685 cUnit->numBlocks++);
buzbee67bf8852011-08-17 17:51:35 -0700686 curBlock->taken = ehBlock;
buzbeeba938cb2012-02-03 14:47:55 -0800687 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) ehBlock);
buzbee67bf8852011-08-17 17:51:35 -0700688 ehBlock->startOffset = curOffset;
buzbeeba938cb2012-02-03 14:47:55 -0800689 oatInsertGrowableList(cUnit, ehBlock->predecessors, (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700690 }
691
692 /*
693 * Force the current block to terminate.
694 *
695 * Data may be present before codeEnd, so we need to parse it to know
696 * whether it is code or data.
697 */
698 if (codePtr < codeEnd) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800699 /* Create a fallthrough block for real instructions (incl. NOP) */
buzbee67bf8852011-08-17 17:51:35 -0700700 if (contentIsInsn(codePtr)) {
701 BasicBlock *fallthroughBlock = findBlock(cUnit,
702 curOffset + width,
703 /* split */
704 false,
705 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800706 true,
707 /* immedPredBlockP */
708 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700709 /*
Elliott Hughesadb8c672012-03-06 16:49:32 -0800710 * THROW is an unconditional branch. NOTE:
711 * THROW_VERIFICATION_ERROR is also an unconditional
buzbee510c6052011-10-27 10:47:20 -0700712 * branch, but we shouldn't treat it as such until we have
713 * a dead code elimination pass (which won't be important
714 * until inlining w/ constant propogation is implemented.
buzbee67bf8852011-08-17 17:51:35 -0700715 */
Elliott Hughesadb8c672012-03-06 16:49:32 -0800716 if (insn->dalvikInsn.opcode != Instruction::THROW) {
buzbee67bf8852011-08-17 17:51:35 -0700717 curBlock->fallThrough = fallthroughBlock;
buzbeeba938cb2012-02-03 14:47:55 -0800718 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
buzbee5abfa3e2012-01-31 17:01:43 -0800719 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700720 }
721 }
722 }
723}
724
725/*
726 * Compile a method.
727 */
buzbee31a4a6f2012-02-28 15:36:15 -0800728CompiledMethod* oatCompileMethod(Compiler& compiler,
729 const DexFile::CodeItem* code_item,
Ian Rogersa3760aa2011-11-14 14:32:37 -0800730 uint32_t access_flags, uint32_t method_idx,
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800731 const ClassLoader* class_loader,
buzbee31a4a6f2012-02-28 15:36:15 -0800732 const DexFile& dex_file,
733 InstructionSet insnSet)
buzbee67bf8852011-08-17 17:51:35 -0700734{
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800735 VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
Brian Carlstrom94496d32011-08-22 09:22:47 -0700736
buzbeec143c552011-08-20 17:38:58 -0700737 const u2* codePtr = code_item->insns_;
Ian Rogersd81871c2011-10-03 13:57:23 -0700738 const u2* codeEnd = code_item->insns_ + code_item->insns_size_in_code_units_;
buzbee67bf8852011-08-17 17:51:35 -0700739 int numBlocks = 0;
740 unsigned int curOffset = 0;
741
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800742 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700743 UniquePtr<CompilationUnit> cUnit(new CompilationUnit);
744 memset(cUnit.get(), 0, sizeof(*cUnit));
buzbeeba938cb2012-02-03 14:47:55 -0800745
746 oatInit(cUnit.get(), compiler);
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700747 cUnit->compiler = &compiler;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800748 cUnit->class_linker = class_linker;
749 cUnit->dex_file = &dex_file;
750 cUnit->dex_cache = class_linker->FindDexCache(dex_file);
751 cUnit->method_idx = method_idx;
752 cUnit->code_item = code_item;
753 cUnit->access_flags = access_flags;
754 cUnit->shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700755 cUnit->instructionSet = (OatInstructionSetType)insnSet;
756 cUnit->insns = code_item->insns_;
Ian Rogersd81871c2011-10-03 13:57:23 -0700757 cUnit->insnsSize = code_item->insns_size_in_code_units_;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800758 cUnit->numIns = code_item->ins_size_;
759 cUnit->numRegs = code_item->registers_size_ - cUnit->numIns;
760 cUnit->numOuts = code_item->outs_size_;
761 /* Adjust this value accordingly once inlining is performed */
762 cUnit->numDalvikRegisters = code_item->registers_size_;
buzbee5b537102012-01-17 17:33:47 -0800763 cUnit->blockMap = std::map<unsigned int, BasicBlock*>();
764 cUnit->blockMap.clear();
buzbee85d8c1e2012-01-27 15:52:35 -0800765 cUnit->boundaryMap = std::map<unsigned int, LIR*>();
766 cUnit->boundaryMap.clear();
buzbeeba938cb2012-02-03 14:47:55 -0800767 // TODO: set these from command line
768 cUnit->compilerMethodMatch = new std::string("");
769 cUnit->compilerFlipMatch = false;
770 bool useMatch = cUnit->compilerMethodMatch->length() != 0;
771 bool match = useMatch && (cUnit->compilerFlipMatch ^
772 (PrettyMethod(method_idx, dex_file).find(*cUnit->compilerMethodMatch)
773 != std::string::npos));
buzbeece302932011-10-04 14:32:18 -0700774 if (!useMatch || match) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700775 cUnit->disableOpt = compilerOptimizerDisableFlags;
776 cUnit->enableDebug = compilerDebugFlags;
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800777 cUnit->printMe = VLOG_IS_ON(compiler) || (cUnit->enableDebug & (1 << kDebugVerbose));
buzbeece302932011-10-04 14:32:18 -0700778 }
buzbee67bf8852011-08-17 17:51:35 -0700779
buzbee44b412b2012-02-04 08:50:53 -0800780 /* Are we generating code for the debugger? */
Elliott Hughesde6e4cf2012-02-27 14:46:06 -0800781 if (compiler.IsDebuggingSupported()) {
buzbee44b412b2012-02-04 08:50:53 -0800782 cUnit->genDebugger = true;
783 // Yes, disable most optimizations
784 cUnit->disableOpt |= (
785 (1 << kLoadStoreElimination) |
786 (1 << kLoadHoisting) |
787 (1 << kSuppressLoads) |
788 (1 << kPromoteRegs) |
789 (1 << kTrackLiveTemps));
790 }
791
buzbeecefd1872011-09-09 09:59:52 -0700792 /* Assume non-throwing leaf */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700793 cUnit->attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE);
buzbeecefd1872011-09-09 09:59:52 -0700794
buzbee5abfa3e2012-01-31 17:01:43 -0800795 /* Initialize the block list, estimate size based on insnsSize */
buzbeeba938cb2012-02-03 14:47:55 -0800796 oatInitGrowableList(cUnit.get(), &cUnit->blockList, cUnit->insnsSize,
797 kListBlockList);
buzbee67bf8852011-08-17 17:51:35 -0700798
799 /* Initialize the switchTables list */
buzbeeba938cb2012-02-03 14:47:55 -0800800 oatInitGrowableList(cUnit.get(), &cUnit->switchTables, 4,
801 kListSwitchTables);
buzbee67bf8852011-08-17 17:51:35 -0700802
803 /* Intialize the fillArrayData list */
buzbeeba938cb2012-02-03 14:47:55 -0800804 oatInitGrowableList(cUnit.get(), &cUnit->fillArrayData, 4,
805 kListFillArrayData);
buzbee67bf8852011-08-17 17:51:35 -0700806
buzbee5abfa3e2012-01-31 17:01:43 -0800807 /* Intialize the throwLaunchpads list, estimate size based on insnsSize */
buzbeeba938cb2012-02-03 14:47:55 -0800808 oatInitGrowableList(cUnit.get(), &cUnit->throwLaunchpads, cUnit->insnsSize,
buzbee5abfa3e2012-01-31 17:01:43 -0800809 kListThrowLaunchPads);
buzbee5ade1d22011-09-09 14:44:52 -0700810
buzbeec1f45042011-09-21 16:03:19 -0700811 /* Intialize the suspendLaunchpads list */
buzbeeba938cb2012-02-03 14:47:55 -0800812 oatInitGrowableList(cUnit.get(), &cUnit->suspendLaunchpads, 2048,
buzbee5abfa3e2012-01-31 17:01:43 -0800813 kListSuspendLaunchPads);
buzbeec1f45042011-09-21 16:03:19 -0700814
buzbee67bf8852011-08-17 17:51:35 -0700815 /* Allocate the bit-vector to track the beginning of basic blocks */
buzbeeba938cb2012-02-03 14:47:55 -0800816 ArenaBitVector *tryBlockAddr = oatAllocBitVector(cUnit.get(),
817 cUnit->insnsSize,
buzbee67bf8852011-08-17 17:51:35 -0700818 true /* expandable */);
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700819 cUnit->tryBlockAddr = tryBlockAddr;
buzbee67bf8852011-08-17 17:51:35 -0700820
821 /* Create the default entry and exit blocks and enter them to the list */
buzbee5abfa3e2012-01-31 17:01:43 -0800822 BasicBlock *entryBlock = oatNewBB(cUnit.get(), kEntryBlock, numBlocks++);
823 BasicBlock *exitBlock = oatNewBB(cUnit.get(), kExitBlock, numBlocks++);
buzbee67bf8852011-08-17 17:51:35 -0700824
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700825 cUnit->entryBlock = entryBlock;
826 cUnit->exitBlock = exitBlock;
buzbee67bf8852011-08-17 17:51:35 -0700827
buzbeeba938cb2012-02-03 14:47:55 -0800828 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) entryBlock);
829 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) exitBlock);
buzbee67bf8852011-08-17 17:51:35 -0700830
831 /* Current block to record parsed instructions */
buzbee5abfa3e2012-01-31 17:01:43 -0800832 BasicBlock *curBlock = oatNewBB(cUnit.get(), kDalvikByteCode, numBlocks++);
buzbee67bf8852011-08-17 17:51:35 -0700833 curBlock->startOffset = 0;
buzbeeba938cb2012-02-03 14:47:55 -0800834 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) curBlock);
buzbee5b537102012-01-17 17:33:47 -0800835 /* Add first block to the fast lookup cache */
836 cUnit->blockMap.insert(std::make_pair(curBlock->startOffset, curBlock));
buzbee67bf8852011-08-17 17:51:35 -0700837 entryBlock->fallThrough = curBlock;
buzbeeba938cb2012-02-03 14:47:55 -0800838 oatInsertGrowableList(cUnit.get(), curBlock->predecessors,
839 (intptr_t)entryBlock);
buzbee67bf8852011-08-17 17:51:35 -0700840
841 /*
842 * Store back the number of blocks since new blocks may be created of
843 * accessing cUnit.
844 */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700845 cUnit->numBlocks = numBlocks;
buzbee67bf8852011-08-17 17:51:35 -0700846
847 /* Identify code range in try blocks and set up the empty catch blocks */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700848 processTryCatchBlocks(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700849
850 /* Parse all instructions and put them into containing basic blocks */
851 while (codePtr < codeEnd) {
buzbeeba938cb2012-02-03 14:47:55 -0800852 MIR *insn = (MIR *) oatNew(cUnit.get(), sizeof(MIR), true, kAllocMIR);
buzbee67bf8852011-08-17 17:51:35 -0700853 insn->offset = curOffset;
buzbeeba938cb2012-02-03 14:47:55 -0800854 int width = parseInsn(cUnit.get(), codePtr, &insn->dalvikInsn, false);
buzbee67bf8852011-08-17 17:51:35 -0700855 insn->width = width;
856
857 /* Terminate when the data section is seen */
858 if (width == 0)
859 break;
860
861 oatAppendMIR(curBlock, insn);
862
863 codePtr += width;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800864 int flags = Instruction::Flags(insn->dalvikInsn.opcode);
buzbee67bf8852011-08-17 17:51:35 -0700865
buzbee5abfa3e2012-01-31 17:01:43 -0800866 int dfFlags = oatDataFlowAttributes[insn->dalvikInsn.opcode];
867
868 if (dfFlags & DF_HAS_DEFS) {
869 cUnit->defCount += (dfFlags & DF_DA_WIDE) ? 2 : 1;
870 }
buzbee99ba9642012-01-25 14:23:14 -0800871
Elliott Hughesadb8c672012-03-06 16:49:32 -0800872 if (flags & Instruction::kBranch) {
buzbeee941e2c2011-12-05 12:38:17 -0800873 curBlock = processCanBranch(cUnit.get(), curBlock, insn, curOffset,
874 width, flags, codePtr, codeEnd);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800875 } else if (flags & Instruction::kReturn) {
buzbee67bf8852011-08-17 17:51:35 -0700876 curBlock->fallThrough = exitBlock;
buzbeeba938cb2012-02-03 14:47:55 -0800877 oatInsertGrowableList(cUnit.get(), exitBlock->predecessors,
878 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700879 /*
880 * Terminate the current block if there are instructions
881 * afterwards.
882 */
883 if (codePtr < codeEnd) {
884 /*
885 * Create a fallthrough block for real instructions
Elliott Hughesadb8c672012-03-06 16:49:32 -0800886 * (incl. NOP).
buzbee67bf8852011-08-17 17:51:35 -0700887 */
888 if (contentIsInsn(codePtr)) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700889 findBlock(cUnit.get(), curOffset + width,
buzbee67bf8852011-08-17 17:51:35 -0700890 /* split */
891 false,
892 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800893 true,
894 /* immedPredBlockP */
895 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700896 }
897 }
Elliott Hughesadb8c672012-03-06 16:49:32 -0800898 } else if (flags & Instruction::kThrow) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700899 processCanThrow(cUnit.get(), curBlock, insn, curOffset, width, flags,
buzbee67bf8852011-08-17 17:51:35 -0700900 tryBlockAddr, codePtr, codeEnd);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800901 } else if (flags & Instruction::kSwitch) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700902 processCanSwitch(cUnit.get(), curBlock, insn, curOffset, width, flags);
buzbee67bf8852011-08-17 17:51:35 -0700903 }
904 curOffset += width;
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700905 BasicBlock *nextBlock = findBlock(cUnit.get(), curOffset,
buzbee67bf8852011-08-17 17:51:35 -0700906 /* split */
907 false,
908 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800909 false,
910 /* immedPredBlockP */
911 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700912 if (nextBlock) {
913 /*
914 * The next instruction could be the target of a previously parsed
915 * forward branch so a block is already created. If the current
916 * instruction is not an unconditional branch, connect them through
917 * the fall-through link.
918 */
buzbeeed3e9302011-09-23 17:34:19 -0700919 DCHECK(curBlock->fallThrough == NULL ||
buzbee67bf8852011-08-17 17:51:35 -0700920 curBlock->fallThrough == nextBlock ||
921 curBlock->fallThrough == exitBlock);
922
Elliott Hughesadb8c672012-03-06 16:49:32 -0800923 if ((curBlock->fallThrough == NULL) && (flags & Instruction::kContinue)) {
buzbee67bf8852011-08-17 17:51:35 -0700924 curBlock->fallThrough = nextBlock;
buzbeeba938cb2012-02-03 14:47:55 -0800925 oatInsertGrowableList(cUnit.get(), nextBlock->predecessors,
buzbee5abfa3e2012-01-31 17:01:43 -0800926 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700927 }
928 curBlock = nextBlock;
929 }
930 }
931
buzbee5abfa3e2012-01-31 17:01:43 -0800932 if (!(cUnit->disableOpt & (1 << kSkipLargeMethodOptimization))) {
buzbee99ba9642012-01-25 14:23:14 -0800933 if ((cUnit->numBlocks > MANY_BLOCKS) ||
934 ((cUnit->numBlocks > MANY_BLOCKS_INITIALIZER) &&
935 PrettyMethod(method_idx, dex_file).find("init>") !=
936 std::string::npos)) {
937 cUnit->disableDataflow = true;
938 // Disable optimization which require dataflow/ssa
939 cUnit->disableOpt |=
940 (1 << kNullCheckElimination) |
941 (1 << kPromoteRegs);
942 if (cUnit->printMe) {
943 LOG(INFO) << "Compiler: " << PrettyMethod(method_idx, dex_file)
944 << " too big: " << cUnit->numBlocks;
945 }
946 }
947 }
948
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700949 if (cUnit->printMe) {
950 oatDumpCompilationUnit(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700951 }
952
buzbee5b537102012-01-17 17:33:47 -0800953 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
954 /* Verify if all blocks are connected as claimed */
buzbee5abfa3e2012-01-31 17:01:43 -0800955 oatDataFlowAnalysisDispatcher(cUnit.get(), verifyPredInfo, kAllNodes,
956 false /* isIterative */);
buzbee5b537102012-01-17 17:33:47 -0800957 }
buzbee67bf8852011-08-17 17:51:35 -0700958
959 /* Perform SSA transformation for the whole method */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700960 oatMethodSSATransformation(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700961
buzbee43a36422011-09-14 14:00:13 -0700962 /* Perform null check elimination */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700963 oatMethodNullCheckElimination(cUnit.get());
buzbee43a36422011-09-14 14:00:13 -0700964
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700965 oatInitializeRegAlloc(cUnit.get()); // Needs to happen after SSA naming
buzbee67bf8852011-08-17 17:51:35 -0700966
967 /* Allocate Registers using simple local allocation scheme */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700968 oatSimpleRegAlloc(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700969
970 /* Convert MIR to LIR, etc. */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700971 oatMethodMIR2LIR(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700972
973 // Debugging only
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700974 if (cUnit->enableDebug & (1 << kDebugDumpCFG)) {
975 oatDumpCFG(cUnit.get(), "/sdcard/cfg/");
buzbeeec5adf32011-09-11 15:25:43 -0700976 }
buzbee67bf8852011-08-17 17:51:35 -0700977
978 /* Method is not empty */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700979 if (cUnit->firstLIRInsn) {
buzbee67bf8852011-08-17 17:51:35 -0700980
981 // mark the targets of switch statement case labels
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700982 oatProcessSwitchTables(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700983
984 /* Convert LIR into machine code. */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700985 oatAssembleLIR(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700986
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700987 if (cUnit->printMe) {
988 oatCodegenDump(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700989 }
990 }
991
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700992 // Combine vmap tables - core regs, then fp regs - into vmapTable
993 std::vector<uint16_t> vmapTable;
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700994 for (size_t i = 0 ; i < cUnit->coreVmapTable.size(); i++) {
995 vmapTable.push_back(cUnit->coreVmapTable[i]);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700996 }
buzbeec41e5b52011-09-23 12:46:19 -0700997 // Add a marker to take place of lr
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700998 vmapTable.push_back(INVALID_VREG);
buzbeec41e5b52011-09-23 12:46:19 -0700999 // Combine vmap tables - core regs, then fp regs
Elliott Hughes3b6baaa2011-10-14 19:13:56 -07001000 for (uint32_t i = 0; i < cUnit->fpVmapTable.size(); i++) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -07001001 vmapTable.push_back(cUnit->fpVmapTable[i]);
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001002 }
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -07001003 DCHECK_EQ(vmapTable.size(),
1004 static_cast<uint32_t>(__builtin_popcount(cUnit->coreSpillMask)
1005 + __builtin_popcount(cUnit->fpSpillMask)));
1006 DCHECK_GE(vmapTable.size(), 1U); // should always at least one INVALID_VREG for lr
1007
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001008 CompiledMethod* result = new CompiledMethod(kThumb2, cUnit->codeBuffer,
Ian Rogers0571d352011-11-03 19:51:38 -07001009 cUnit->frameSize, cUnit->coreSpillMask,
1010 cUnit->fpSpillMask, cUnit->mappingTable,
1011 vmapTable);
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001012
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -08001013 VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file)
buzbee5abfa3e2012-01-31 17:01:43 -08001014 << " (" << (cUnit->codeBuffer.size() * sizeof(cUnit->codeBuffer[0]))
1015 << " bytes)";
1016
1017#ifdef WITH_MEMSTATS
1018 if (cUnit->enableDebug & (1 << kDebugShowMemoryUsage)) {
1019 oatDumpMemStats(cUnit.get());
1020 }
1021#endif
buzbee67bf8852011-08-17 17:51:35 -07001022
buzbeeba938cb2012-02-03 14:47:55 -08001023 oatArenaReset(cUnit.get());
1024
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001025 return result;
buzbee67bf8852011-08-17 17:51:35 -07001026}
1027
buzbeeba938cb2012-02-03 14:47:55 -08001028void oatInit(CompilationUnit* cUnit, const Compiler& compiler)
buzbee67bf8852011-08-17 17:51:35 -07001029{
buzbee67bf8852011-08-17 17:51:35 -07001030 if (!oatArchInit()) {
1031 LOG(FATAL) << "Failed to initialize oat";
1032 }
buzbeeba938cb2012-02-03 14:47:55 -08001033 if (!oatHeapInit(cUnit)) {
buzbee67bf8852011-08-17 17:51:35 -07001034 LOG(FATAL) << "Failed to initialize oat heap";
1035 }
1036}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001037
1038} // namespace art