blob: 1b1215a6bdfe0ccf9b427756baa08a785320fcf4 [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) |
buzbeece302932011-10-04 14:32:18 -070035 0;
36
37uint32_t compilerDebugFlags = 0 | // Enable debug/testing modes
buzbeee3de7492011-10-05 13:37:17 -070038 //(1 << kDebugDisplayMissingTargets) |
buzbeece302932011-10-04 14:32:18 -070039 //(1 << kDebugVerbose) |
40 //(1 << kDebugDumpCFG) |
41 //(1 << kDebugSlowFieldPath) |
42 //(1 << kDebugSlowInvokePath) |
43 //(1 << kDebugSlowStringPath) |
44 //(1 << kDebugSlowestFieldPath) |
45 //(1 << kDebugSlowestStringPath) |
buzbee34c77ad2012-01-11 13:01:32 -080046 //(1 << kDebugExerciseResolveMethod) |
buzbee5b537102012-01-17 17:33:47 -080047 //(1 << kDebugVerifyDataflow) |
buzbeece302932011-10-04 14:32:18 -070048 0;
49
50std::string compilerMethodMatch; // Method name match to apply above flags
51
52bool compilerFlipMatch = false; // Reverses sense of method name match
53
buzbeeed3e9302011-09-23 17:34:19 -070054STATIC inline bool contentIsInsn(const u2* codePtr) {
buzbee67bf8852011-08-17 17:51:35 -070055 u2 instr = *codePtr;
56 Opcode opcode = (Opcode)(instr & 0xff);
57
58 /*
59 * Since the low 8-bit in metadata may look like OP_NOP, we need to check
60 * both the low and whole sub-word to determine whether it is code or data.
61 */
62 return (opcode != OP_NOP || instr == 0);
63}
64
65/*
66 * Parse an instruction, return the length of the instruction
67 */
buzbeeed3e9302011-09-23 17:34:19 -070068STATIC inline int parseInsn(const u2* codePtr, DecodedInstruction* decInsn,
buzbee67bf8852011-08-17 17:51:35 -070069 bool printMe)
70{
71 // Don't parse instruction data
72 if (!contentIsInsn(codePtr)) {
73 return 0;
74 }
75
76 u2 instr = *codePtr;
77 Opcode opcode = dexOpcodeFromCodeUnit(instr);
78
79 dexDecodeInstruction(codePtr, decInsn);
80 if (printMe) {
Elliott Hughesc1f143d2011-12-01 17:31:10 -080081 char* decodedString = oatGetDalvikDisassembly(decInsn, NULL);
buzbee67bf8852011-08-17 17:51:35 -070082 LOG(INFO) << codePtr << ": 0x" << std::hex << (int)opcode <<
83 " " << decodedString;
84 }
85 return dexGetWidthFromOpcode(opcode);
86}
87
88#define UNKNOWN_TARGET 0xffffffff
89
buzbeeed3e9302011-09-23 17:34:19 -070090STATIC inline bool isGoto(MIR* insn)
buzbee67bf8852011-08-17 17:51:35 -070091{
92 switch (insn->dalvikInsn.opcode) {
93 case OP_GOTO:
94 case OP_GOTO_16:
95 case OP_GOTO_32:
96 return true;
97 default:
98 return false;
99 }
100}
101
102/*
103 * Identify unconditional branch instructions
104 */
buzbeeed3e9302011-09-23 17:34:19 -0700105STATIC inline bool isUnconditionalBranch(MIR* insn)
buzbee67bf8852011-08-17 17:51:35 -0700106{
107 switch (insn->dalvikInsn.opcode) {
108 case OP_RETURN_VOID:
109 case OP_RETURN:
110 case OP_RETURN_WIDE:
111 case OP_RETURN_OBJECT:
112 return true;
113 default:
114 return isGoto(insn);
115 }
116}
117
118/* Split an existing block from the specified code offset into two */
buzbeeed3e9302011-09-23 17:34:19 -0700119STATIC BasicBlock *splitBlock(CompilationUnit* cUnit,
buzbee67bf8852011-08-17 17:51:35 -0700120 unsigned int codeOffset,
buzbee9ab05de2012-01-18 15:43:48 -0800121 BasicBlock* origBlock,
122 BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700123{
124 MIR* insn = origBlock->firstMIRInsn;
125 while (insn) {
126 if (insn->offset == codeOffset) break;
127 insn = insn->next;
128 }
129 if (insn == NULL) {
130 LOG(FATAL) << "Break split failed";
131 }
132 BasicBlock *bottomBlock = oatNewBB(kDalvikByteCode,
133 cUnit->numBlocks++);
134 oatInsertGrowableList(&cUnit->blockList, (intptr_t) bottomBlock);
135
136 bottomBlock->startOffset = codeOffset;
137 bottomBlock->firstMIRInsn = insn;
138 bottomBlock->lastMIRInsn = origBlock->lastMIRInsn;
139
buzbee5b537102012-01-17 17:33:47 -0800140 /* Add it to the quick lookup cache */
141 cUnit->blockMap.insert(std::make_pair(bottomBlock->startOffset,
142 bottomBlock));
143
buzbee67bf8852011-08-17 17:51:35 -0700144 /* Handle the taken path */
145 bottomBlock->taken = origBlock->taken;
146 if (bottomBlock->taken) {
147 origBlock->taken = NULL;
148 oatClearBit(bottomBlock->taken->predecessors, origBlock->id);
149 oatSetBit(bottomBlock->taken->predecessors, bottomBlock->id);
150 }
151
152 /* Handle the fallthrough path */
153 bottomBlock->needFallThroughBranch = origBlock->needFallThroughBranch;
154 bottomBlock->fallThrough = origBlock->fallThrough;
155 origBlock->fallThrough = bottomBlock;
156 origBlock->needFallThroughBranch = true;
157 oatSetBit(bottomBlock->predecessors, origBlock->id);
158 if (bottomBlock->fallThrough) {
159 oatClearBit(bottomBlock->fallThrough->predecessors,
160 origBlock->id);
161 oatSetBit(bottomBlock->fallThrough->predecessors,
162 bottomBlock->id);
163 }
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;
178 oatClearBit(bb->predecessors, origBlock->id);
179 oatSetBit(bb->predecessors, bottomBlock->id);
180 }
181 }
182
183 origBlock->lastMIRInsn = insn->prev;
184
185 insn->prev->next = NULL;
186 insn->prev = NULL;
buzbee9ab05de2012-01-18 15:43:48 -0800187 /*
188 * Update the immediate predecessor block pointer so that outgoing edges
189 * can be applied to the proper block.
190 */
191 if (immedPredBlockP) {
192 DCHECK_EQ(*immedPredBlockP, origBlock);
193 *immedPredBlockP = bottomBlock;
194 }
buzbee67bf8852011-08-17 17:51:35 -0700195 return bottomBlock;
196}
197
198/*
199 * Given a code offset, find out the block that starts with it. If the offset
buzbee9ab05de2012-01-18 15:43:48 -0800200 * is in the middle of an existing block, split it into two. If immedPredBlockP
201 * is not non-null and is the block being split, update *immedPredBlockP to
202 * point to the bottom block so that outgoing edges can be set up properly
203 * (by the caller)
buzbee5b537102012-01-17 17:33:47 -0800204 * Utilizes a map for fast lookup of the typical cases.
buzbee67bf8852011-08-17 17:51:35 -0700205 */
buzbeeed3e9302011-09-23 17:34:19 -0700206STATIC BasicBlock *findBlock(CompilationUnit* cUnit,
buzbee67bf8852011-08-17 17:51:35 -0700207 unsigned int codeOffset,
buzbee9ab05de2012-01-18 15:43:48 -0800208 bool split, bool create,
209 BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700210{
211 GrowableList* blockList = &cUnit->blockList;
212 BasicBlock* bb;
213 unsigned int i;
buzbee5b537102012-01-17 17:33:47 -0800214 std::map<unsigned int, BasicBlock*>::iterator it;
buzbee67bf8852011-08-17 17:51:35 -0700215
buzbee5b537102012-01-17 17:33:47 -0800216 it = cUnit->blockMap.find(codeOffset);
217 if (it != cUnit->blockMap.end()) {
218 return it->second;
219 } else if (!create) {
220 return NULL;
221 }
222
223 if (split) {
224 for (i = 0; i < blockList->numUsed; i++) {
225 bb = (BasicBlock *) blockList->elemList[i];
226 if (bb->blockType != kDalvikByteCode) continue;
227 /* Check if a branch jumps into the middle of an existing block */
228 if ((codeOffset > bb->startOffset) && (bb->lastMIRInsn != NULL) &&
229 (codeOffset <= bb->lastMIRInsn->offset)) {
230 BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb,
231 bb == *immedPredBlockP ?
232 immedPredBlockP : NULL);
233 return newBB;
234 }
buzbee67bf8852011-08-17 17:51:35 -0700235 }
236 }
buzbee5b537102012-01-17 17:33:47 -0800237
238 /* Create a new one */
239 bb = oatNewBB(kDalvikByteCode, cUnit->numBlocks++);
240 oatInsertGrowableList(&cUnit->blockList, (intptr_t) bb);
241 bb->startOffset = codeOffset;
242 cUnit->blockMap.insert(std::make_pair(bb->startOffset, bb));
243 return bb;
buzbee67bf8852011-08-17 17:51:35 -0700244}
245
246/* Dump the CFG into a DOT graph */
247void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix)
248{
buzbee67bf8852011-08-17 17:51:35 -0700249 FILE* file;
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800250 std::string name(PrettyMethod(cUnit->method_idx, *cUnit->dex_file));
buzbee67bf8852011-08-17 17:51:35 -0700251 char startOffset[80];
252 sprintf(startOffset, "_%x", cUnit->entryBlock->fallThrough->startOffset);
Elliott Hughesc1f143d2011-12-01 17:31:10 -0800253 char* fileName = (char*) oatNew(
buzbeec143c552011-08-20 17:38:58 -0700254 strlen(dirPrefix) +
255 name.length() +
256 strlen(".dot") + 1, true);
257 sprintf(fileName, "%s%s%s.dot", dirPrefix, name.c_str(), startOffset);
buzbee67bf8852011-08-17 17:51:35 -0700258
259 /*
260 * Convert the special characters into a filesystem- and shell-friendly
261 * format.
262 */
263 int i;
264 for (i = strlen(dirPrefix); fileName[i]; i++) {
265 if (fileName[i] == '/') {
266 fileName[i] = '_';
267 } else if (fileName[i] == ';') {
268 fileName[i] = '#';
269 } else if (fileName[i] == '$') {
270 fileName[i] = '+';
271 } else if (fileName[i] == '(' || fileName[i] == ')') {
272 fileName[i] = '@';
273 } else if (fileName[i] == '<' || fileName[i] == '>') {
274 fileName[i] = '=';
275 }
276 }
277 file = fopen(fileName, "w");
278 if (file == NULL) {
279 return;
280 }
281 fprintf(file, "digraph G {\n");
282
283 fprintf(file, " rankdir=TB\n");
284
285 int numReachableBlocks = cUnit->numReachableBlocks;
286 int idx;
287 const GrowableList *blockList = &cUnit->blockList;
288
289 for (idx = 0; idx < numReachableBlocks; idx++) {
290 int blockIdx = cUnit->dfsOrder.elemList[idx];
291 BasicBlock *bb = (BasicBlock *) oatGrowableListGetElement(blockList,
292 blockIdx);
293 if (bb == NULL) break;
294 if (bb->blockType == kEntryBlock) {
295 fprintf(file, " entry [shape=Mdiamond];\n");
296 } else if (bb->blockType == kExitBlock) {
297 fprintf(file, " exit [shape=Mdiamond];\n");
298 } else if (bb->blockType == kDalvikByteCode) {
299 fprintf(file, " block%04x [shape=record,label = \"{ \\\n",
300 bb->startOffset);
301 const MIR *mir;
302 fprintf(file, " {block id %d\\l}%s\\\n", bb->id,
303 bb->firstMIRInsn ? " | " : " ");
304 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
305 fprintf(file, " {%04x %s\\l}%s\\\n", mir->offset,
306 mir->ssaRep ?
307 oatFullDisassembler(cUnit, mir) :
308 dexGetOpcodeName(mir->dalvikInsn.opcode),
309 mir->next ? " | " : " ");
310 }
311 fprintf(file, " }\"];\n\n");
312 } else if (bb->blockType == kExceptionHandling) {
313 char blockName[BLOCK_NAME_LEN];
314
315 oatGetBlockName(bb, blockName);
316 fprintf(file, " %s [shape=invhouse];\n", blockName);
317 }
318
319 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
320
321 if (bb->taken) {
322 oatGetBlockName(bb, blockName1);
323 oatGetBlockName(bb->taken, blockName2);
324 fprintf(file, " %s:s -> %s:n [style=dotted]\n",
325 blockName1, blockName2);
326 }
327 if (bb->fallThrough) {
328 oatGetBlockName(bb, blockName1);
329 oatGetBlockName(bb->fallThrough, blockName2);
330 fprintf(file, " %s:s -> %s:n\n", blockName1, blockName2);
331 }
332
333 if (bb->successorBlockList.blockListType != kNotUsed) {
334 fprintf(file, " succ%04x [shape=%s,label = \"{ \\\n",
335 bb->startOffset,
336 (bb->successorBlockList.blockListType == kCatch) ?
337 "Mrecord" : "record");
338 GrowableListIterator iterator;
339 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
340 &iterator);
341 SuccessorBlockInfo *successorBlockInfo =
342 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
343
344 int succId = 0;
345 while (true) {
346 if (successorBlockInfo == NULL) break;
347
348 BasicBlock *destBlock = successorBlockInfo->block;
349 SuccessorBlockInfo *nextSuccessorBlockInfo =
350 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
351
352 fprintf(file, " {<f%d> %04x: %04x\\l}%s\\\n",
353 succId++,
354 successorBlockInfo->key,
355 destBlock->startOffset,
356 (nextSuccessorBlockInfo != NULL) ? " | " : " ");
357
358 successorBlockInfo = nextSuccessorBlockInfo;
359 }
360 fprintf(file, " }\"];\n\n");
361
362 oatGetBlockName(bb, blockName1);
363 fprintf(file, " %s:s -> succ%04x:n [style=dashed]\n",
364 blockName1, bb->startOffset);
365
366 if (bb->successorBlockList.blockListType == kPackedSwitch ||
367 bb->successorBlockList.blockListType == kSparseSwitch) {
368
369 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
370 &iterator);
371
372 succId = 0;
373 while (true) {
374 SuccessorBlockInfo *successorBlockInfo =
375 (SuccessorBlockInfo *)
376 oatGrowableListIteratorNext(&iterator);
377 if (successorBlockInfo == NULL) break;
378
379 BasicBlock *destBlock = successorBlockInfo->block;
380
381 oatGetBlockName(destBlock, blockName2);
382 fprintf(file, " succ%04x:f%d:e -> %s:n\n",
383 bb->startOffset, succId++,
384 blockName2);
385 }
386 }
387 }
388 fprintf(file, "\n");
389
buzbeece302932011-10-04 14:32:18 -0700390 /* Display the dominator tree */
buzbee67bf8852011-08-17 17:51:35 -0700391 oatGetBlockName(bb, blockName1);
392 fprintf(file, " cfg%s [label=\"%s\", shape=none];\n",
393 blockName1, blockName1);
394 if (bb->iDom) {
395 oatGetBlockName(bb->iDom, blockName2);
396 fprintf(file, " cfg%s:s -> cfg%s:n\n\n",
397 blockName2, blockName1);
398 }
buzbee67bf8852011-08-17 17:51:35 -0700399 }
400 fprintf(file, "}\n");
401 fclose(file);
402}
403
404/* Verify if all the successor is connected with all the claimed predecessors */
buzbeeed3e9302011-09-23 17:34:19 -0700405STATIC bool verifyPredInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700406{
407 ArenaBitVectorIterator bvIterator;
408
409 oatBitVectorIteratorInit(bb->predecessors, &bvIterator);
410 while (true) {
411 int blockIdx = oatBitVectorIteratorNext(&bvIterator);
412 if (blockIdx == -1) break;
413 BasicBlock *predBB = (BasicBlock *)
414 oatGrowableListGetElement(&cUnit->blockList, blockIdx);
415 bool found = false;
416 if (predBB->taken == bb) {
417 found = true;
418 } else if (predBB->fallThrough == bb) {
419 found = true;
420 } else if (predBB->successorBlockList.blockListType != kNotUsed) {
421 GrowableListIterator iterator;
422 oatGrowableListIteratorInit(&predBB->successorBlockList.blocks,
423 &iterator);
424 while (true) {
425 SuccessorBlockInfo *successorBlockInfo =
426 (SuccessorBlockInfo *)
427 oatGrowableListIteratorNext(&iterator);
428 if (successorBlockInfo == NULL) break;
429 BasicBlock *succBB = successorBlockInfo->block;
430 if (succBB == bb) {
431 found = true;
432 break;
433 }
434 }
435 }
436 if (found == false) {
437 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
438 oatGetBlockName(bb, blockName1);
439 oatGetBlockName(predBB, blockName2);
440 oatDumpCFG(cUnit, "/sdcard/cfg/");
441 LOG(FATAL) << "Successor " << blockName1 << "not found from "
442 << blockName2;
443 }
444 }
445 return true;
446}
447
448/* Identify code range in try blocks and set up the empty catch blocks */
buzbeeed3e9302011-09-23 17:34:19 -0700449STATIC void processTryCatchBlocks(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700450{
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800451 const DexFile::CodeItem* code_item = cUnit->code_item;
buzbeee9a72f62011-09-04 17:59:07 -0700452 int triesSize = code_item->tries_size_;
buzbee67bf8852011-08-17 17:51:35 -0700453 int offset;
454
455 if (triesSize == 0) {
456 return;
457 }
458
buzbee67bf8852011-08-17 17:51:35 -0700459 ArenaBitVector* tryBlockAddr = cUnit->tryBlockAddr;
460
buzbeee9a72f62011-09-04 17:59:07 -0700461 for (int i = 0; i < triesSize; i++) {
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800462 const DexFile::TryItem* pTry =
463 DexFile::GetTryItems(*code_item, i);
buzbeee9a72f62011-09-04 17:59:07 -0700464 int startOffset = pTry->start_addr_;
465 int endOffset = startOffset + pTry->insn_count_;
buzbee67bf8852011-08-17 17:51:35 -0700466 for (offset = startOffset; offset < endOffset; offset++) {
467 oatSetBit(tryBlockAddr, offset);
468 }
469 }
470
buzbeee9a72f62011-09-04 17:59:07 -0700471 // Iterate over each of the handlers to enqueue the empty Catch blocks
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800472 const byte* handlers_ptr =
473 DexFile::GetCatchHandlerData(*code_item, 0);
474 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
buzbeee9a72f62011-09-04 17:59:07 -0700475 for (uint32_t idx = 0; idx < handlers_size; idx++) {
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800476 CatchHandlerIterator iterator(handlers_ptr);
Ian Rogers0571d352011-11-03 19:51:38 -0700477 for (; iterator.HasNext(); iterator.Next()) {
478 uint32_t address = iterator.GetHandlerAddress();
buzbee9ab05de2012-01-18 15:43:48 -0800479 findBlock(cUnit, address, false /* split */, true /*create*/,
480 /* immedPredBlockP */ NULL);
buzbee67bf8852011-08-17 17:51:35 -0700481 }
Ian Rogers0571d352011-11-03 19:51:38 -0700482 handlers_ptr = iterator.EndDataPointer();
buzbee67bf8852011-08-17 17:51:35 -0700483 }
484}
485
486/* Process instructions with the kInstrCanBranch flag */
buzbeee941e2c2011-12-05 12:38:17 -0800487STATIC BasicBlock* processCanBranch(CompilationUnit* cUnit,
488 BasicBlock* curBlock, MIR* insn,
489 int curOffset, int width, int flags,
490 const u2* codePtr, const u2* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700491{
492 int target = curOffset;
493 switch (insn->dalvikInsn.opcode) {
494 case OP_GOTO:
495 case OP_GOTO_16:
496 case OP_GOTO_32:
497 target += (int) insn->dalvikInsn.vA;
498 break;
499 case OP_IF_EQ:
500 case OP_IF_NE:
501 case OP_IF_LT:
502 case OP_IF_GE:
503 case OP_IF_GT:
504 case OP_IF_LE:
505 target += (int) insn->dalvikInsn.vC;
506 break;
507 case OP_IF_EQZ:
508 case OP_IF_NEZ:
509 case OP_IF_LTZ:
510 case OP_IF_GEZ:
511 case OP_IF_GTZ:
512 case OP_IF_LEZ:
513 target += (int) insn->dalvikInsn.vB;
514 break;
515 default:
516 LOG(FATAL) << "Unexpected opcode(" << (int)insn->dalvikInsn.opcode
517 << ") with kInstrCanBranch set";
518 }
519 BasicBlock *takenBlock = findBlock(cUnit, target,
520 /* split */
521 true,
522 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800523 true,
524 /* immedPredBlockP */
525 &curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700526 curBlock->taken = takenBlock;
527 oatSetBit(takenBlock->predecessors, curBlock->id);
528
529 /* Always terminate the current block for conditional branches */
530 if (flags & kInstrCanContinue) {
531 BasicBlock *fallthroughBlock = findBlock(cUnit,
532 curOffset + width,
533 /*
534 * If the method is processed
535 * in sequential order from the
536 * beginning, we don't need to
537 * specify split for continue
538 * blocks. However, this
539 * routine can be called by
540 * compileLoop, which starts
541 * parsing the method from an
542 * arbitrary address in the
543 * method body.
544 */
545 true,
546 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800547 true,
548 /* immedPredBlockP */
549 &curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700550 curBlock->fallThrough = fallthroughBlock;
551 oatSetBit(fallthroughBlock->predecessors, curBlock->id);
552 } else if (codePtr < codeEnd) {
553 /* Create a fallthrough block for real instructions (incl. OP_NOP) */
554 if (contentIsInsn(codePtr)) {
555 findBlock(cUnit, curOffset + width,
556 /* split */
557 false,
558 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800559 true,
560 /* immedPredBlockP */
561 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700562 }
563 }
buzbeee941e2c2011-12-05 12:38:17 -0800564 return curBlock;
buzbee67bf8852011-08-17 17:51:35 -0700565}
566
567/* Process instructions with the kInstrCanSwitch flag */
buzbeeed3e9302011-09-23 17:34:19 -0700568STATIC void processCanSwitch(CompilationUnit* cUnit, BasicBlock* curBlock,
buzbee67bf8852011-08-17 17:51:35 -0700569 MIR* insn, int curOffset, int width, int flags)
570{
571 u2* switchData= (u2 *) (cUnit->insns + curOffset +
572 insn->dalvikInsn.vB);
573 int size;
574 int* keyTable;
575 int* targetTable;
576 int i;
577 int firstKey;
578
579 /*
580 * Packed switch data format:
581 * ushort ident = 0x0100 magic value
582 * ushort size number of entries in the table
583 * int first_key first (and lowest) switch case value
584 * int targets[size] branch targets, relative to switch opcode
585 *
586 * Total size is (4+size*2) 16-bit code units.
587 */
588 if (insn->dalvikInsn.opcode == OP_PACKED_SWITCH) {
buzbeeed3e9302011-09-23 17:34:19 -0700589 DCHECK_EQ(switchData[0], kPackedSwitchSignature);
buzbee67bf8852011-08-17 17:51:35 -0700590 size = switchData[1];
591 firstKey = switchData[2] | (switchData[3] << 16);
592 targetTable = (int *) &switchData[4];
593 keyTable = NULL; // Make the compiler happy
594 /*
595 * Sparse switch data format:
596 * ushort ident = 0x0200 magic value
597 * ushort size number of entries in the table; > 0
598 * int keys[size] keys, sorted low-to-high; 32-bit aligned
599 * int targets[size] branch targets, relative to switch opcode
600 *
601 * Total size is (2+size*4) 16-bit code units.
602 */
603 } else {
buzbeeed3e9302011-09-23 17:34:19 -0700604 DCHECK_EQ(switchData[0], kSparseSwitchSignature);
buzbee67bf8852011-08-17 17:51:35 -0700605 size = switchData[1];
606 keyTable = (int *) &switchData[2];
607 targetTable = (int *) &switchData[2 + size*2];
608 firstKey = 0; // To make the compiler happy
609 }
610
611 if (curBlock->successorBlockList.blockListType != kNotUsed) {
612 LOG(FATAL) << "Successor block list already in use: " <<
613 (int)curBlock->successorBlockList.blockListType;
614 }
615 curBlock->successorBlockList.blockListType =
616 (insn->dalvikInsn.opcode == OP_PACKED_SWITCH) ?
617 kPackedSwitch : kSparseSwitch;
618 oatInitGrowableList(&curBlock->successorBlockList.blocks, size);
619
620 for (i = 0; i < size; i++) {
621 BasicBlock *caseBlock = findBlock(cUnit, curOffset + targetTable[i],
622 /* split */
623 true,
624 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800625 true,
626 /* immedPredBlockP */
627 &curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700628 SuccessorBlockInfo *successorBlockInfo =
629 (SuccessorBlockInfo *) oatNew(sizeof(SuccessorBlockInfo),
630 false);
631 successorBlockInfo->block = caseBlock;
632 successorBlockInfo->key = (insn->dalvikInsn.opcode == OP_PACKED_SWITCH)?
633 firstKey + i : keyTable[i];
634 oatInsertGrowableList(&curBlock->successorBlockList.blocks,
635 (intptr_t) successorBlockInfo);
636 oatSetBit(caseBlock->predecessors, curBlock->id);
637 }
638
639 /* Fall-through case */
640 BasicBlock* fallthroughBlock = findBlock(cUnit,
641 curOffset + width,
642 /* split */
643 false,
644 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800645 true,
646 /* immedPredBlockP */
647 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700648 curBlock->fallThrough = fallthroughBlock;
649 oatSetBit(fallthroughBlock->predecessors, curBlock->id);
650}
651
652/* Process instructions with the kInstrCanThrow flag */
buzbeeed3e9302011-09-23 17:34:19 -0700653STATIC void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock,
buzbee67bf8852011-08-17 17:51:35 -0700654 MIR* insn, int curOffset, int width, int flags,
655 ArenaBitVector* tryBlockAddr, const u2* codePtr,
656 const u2* codeEnd)
657{
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800658 const DexFile::CodeItem* code_item = cUnit->code_item;
buzbee67bf8852011-08-17 17:51:35 -0700659
660 /* In try block */
661 if (oatIsBitSet(tryBlockAddr, curOffset)) {
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800662 CatchHandlerIterator iterator(*code_item, curOffset);
buzbee67bf8852011-08-17 17:51:35 -0700663
buzbee67bf8852011-08-17 17:51:35 -0700664 if (curBlock->successorBlockList.blockListType != kNotUsed) {
665 LOG(FATAL) << "Successor block list already in use: " <<
666 (int)curBlock->successorBlockList.blockListType;
667 }
buzbeee9a72f62011-09-04 17:59:07 -0700668
buzbee67bf8852011-08-17 17:51:35 -0700669 curBlock->successorBlockList.blockListType = kCatch;
670 oatInitGrowableList(&curBlock->successorBlockList.blocks, 2);
671
Ian Rogers0571d352011-11-03 19:51:38 -0700672 for (;iterator.HasNext(); iterator.Next()) {
673 BasicBlock *catchBlock = findBlock(cUnit, iterator.GetHandlerAddress(),
buzbeee9a72f62011-09-04 17:59:07 -0700674 false /* split*/,
buzbee9ab05de2012-01-18 15:43:48 -0800675 false /* creat */,
676 NULL /* immedPredBlockP */);
buzbee43a36422011-09-14 14:00:13 -0700677 catchBlock->catchEntry = true;
buzbee67bf8852011-08-17 17:51:35 -0700678 SuccessorBlockInfo *successorBlockInfo =
buzbeee9a72f62011-09-04 17:59:07 -0700679 (SuccessorBlockInfo *) oatNew(sizeof(SuccessorBlockInfo),
680 false);
buzbee67bf8852011-08-17 17:51:35 -0700681 successorBlockInfo->block = catchBlock;
Ian Rogers0571d352011-11-03 19:51:38 -0700682 successorBlockInfo->key = iterator.GetHandlerTypeIndex();
buzbee67bf8852011-08-17 17:51:35 -0700683 oatInsertGrowableList(&curBlock->successorBlockList.blocks,
684 (intptr_t) successorBlockInfo);
685 oatSetBit(catchBlock->predecessors, curBlock->id);
686 }
687 } else {
688 BasicBlock *ehBlock = oatNewBB(kExceptionHandling,
689 cUnit->numBlocks++);
690 curBlock->taken = ehBlock;
691 oatInsertGrowableList(&cUnit->blockList, (intptr_t) ehBlock);
692 ehBlock->startOffset = curOffset;
693 oatSetBit(ehBlock->predecessors, curBlock->id);
694 }
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) {
703 /* Create a fallthrough block for real instructions (incl. OP_NOP) */
704 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 /*
buzbee510c6052011-10-27 10:47:20 -0700714 * OP_THROW is an unconditional branch. NOTE:
715 * OP_THROW_VERIFICATION_ERROR is also an unconditional
716 * 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 */
buzbee510c6052011-10-27 10:47:20 -0700720 if (insn->dalvikInsn.opcode != OP_THROW) {
buzbee67bf8852011-08-17 17:51:35 -0700721 curBlock->fallThrough = fallthroughBlock;
722 oatSetBit(fallthroughBlock->predecessors, curBlock->id);
723 }
724 }
725 }
726}
727
728/*
729 * Compile a method.
730 */
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800731CompiledMethod* oatCompileMethod(const Compiler& compiler, const DexFile::CodeItem* code_item,
Ian Rogersa3760aa2011-11-14 14:32:37 -0800732 uint32_t access_flags, uint32_t method_idx,
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800733 const ClassLoader* class_loader,
734 const DexFile& dex_file, InstructionSet insnSet)
buzbee67bf8852011-08-17 17:51:35 -0700735{
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800736 VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
buzbee2a475e72011-09-07 17:19:17 -0700737 oatArenaReset();
Brian Carlstrom94496d32011-08-22 09:22:47 -0700738
buzbeec143c552011-08-20 17:38:58 -0700739 const u2* codePtr = code_item->insns_;
Ian Rogersd81871c2011-10-03 13:57:23 -0700740 const u2* codeEnd = code_item->insns_ + code_item->insns_size_in_code_units_;
buzbee67bf8852011-08-17 17:51:35 -0700741 int numBlocks = 0;
742 unsigned int curOffset = 0;
743
Brian Carlstrom16192862011-09-12 17:50:06 -0700744 oatInit(compiler);
buzbee67bf8852011-08-17 17:51:35 -0700745
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800746 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700747 UniquePtr<CompilationUnit> cUnit(new CompilationUnit);
748 memset(cUnit.get(), 0, sizeof(*cUnit));
749 cUnit->compiler = &compiler;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800750 cUnit->class_linker = class_linker;
751 cUnit->dex_file = &dex_file;
752 cUnit->dex_cache = class_linker->FindDexCache(dex_file);
753 cUnit->method_idx = method_idx;
754 cUnit->code_item = code_item;
755 cUnit->access_flags = access_flags;
756 cUnit->shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700757 cUnit->instructionSet = (OatInstructionSetType)insnSet;
758 cUnit->insns = code_item->insns_;
Ian Rogersd81871c2011-10-03 13:57:23 -0700759 cUnit->insnsSize = code_item->insns_size_in_code_units_;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800760 cUnit->numIns = code_item->ins_size_;
761 cUnit->numRegs = code_item->registers_size_ - cUnit->numIns;
762 cUnit->numOuts = code_item->outs_size_;
763 /* Adjust this value accordingly once inlining is performed */
764 cUnit->numDalvikRegisters = code_item->registers_size_;
buzbee5b537102012-01-17 17:33:47 -0800765 cUnit->blockMap = std::map<unsigned int, BasicBlock*>();
766 cUnit->blockMap.clear();
buzbeece302932011-10-04 14:32:18 -0700767 bool useMatch = compilerMethodMatch.length() != 0;
768 bool match = useMatch && (compilerFlipMatch ^
Ian Rogersa3760aa2011-11-14 14:32:37 -0800769 (PrettyMethod(method_idx, dex_file).find(compilerMethodMatch) != std::string::npos));
buzbeece302932011-10-04 14:32:18 -0700770 if (!useMatch || match) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700771 cUnit->disableOpt = compilerOptimizerDisableFlags;
772 cUnit->enableDebug = compilerDebugFlags;
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800773 cUnit->printMe = VLOG_IS_ON(compiler) || (cUnit->enableDebug & (1 << kDebugVerbose));
buzbeece302932011-10-04 14:32:18 -0700774 }
buzbee67bf8852011-08-17 17:51:35 -0700775
buzbeecefd1872011-09-09 09:59:52 -0700776 /* Assume non-throwing leaf */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700777 cUnit->attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE);
buzbeecefd1872011-09-09 09:59:52 -0700778
buzbee67bf8852011-08-17 17:51:35 -0700779 /* Initialize the block list */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700780 oatInitGrowableList(&cUnit->blockList, 40);
buzbee67bf8852011-08-17 17:51:35 -0700781
782 /* Initialize the switchTables list */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700783 oatInitGrowableList(&cUnit->switchTables, 4);
buzbee67bf8852011-08-17 17:51:35 -0700784
785 /* Intialize the fillArrayData list */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700786 oatInitGrowableList(&cUnit->fillArrayData, 4);
buzbee67bf8852011-08-17 17:51:35 -0700787
buzbee5ade1d22011-09-09 14:44:52 -0700788 /* Intialize the throwLaunchpads list */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700789 oatInitGrowableList(&cUnit->throwLaunchpads, 4);
buzbee5ade1d22011-09-09 14:44:52 -0700790
buzbeec1f45042011-09-21 16:03:19 -0700791 /* Intialize the suspendLaunchpads list */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700792 oatInitGrowableList(&cUnit->suspendLaunchpads, 4);
buzbeec1f45042011-09-21 16:03:19 -0700793
buzbee67bf8852011-08-17 17:51:35 -0700794 /* Allocate the bit-vector to track the beginning of basic blocks */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700795 ArenaBitVector *tryBlockAddr = oatAllocBitVector(cUnit->insnsSize,
buzbee67bf8852011-08-17 17:51:35 -0700796 true /* expandable */);
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700797 cUnit->tryBlockAddr = tryBlockAddr;
buzbee67bf8852011-08-17 17:51:35 -0700798
799 /* Create the default entry and exit blocks and enter them to the list */
800 BasicBlock *entryBlock = oatNewBB(kEntryBlock, numBlocks++);
801 BasicBlock *exitBlock = oatNewBB(kExitBlock, numBlocks++);
802
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700803 cUnit->entryBlock = entryBlock;
804 cUnit->exitBlock = exitBlock;
buzbee67bf8852011-08-17 17:51:35 -0700805
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700806 oatInsertGrowableList(&cUnit->blockList, (intptr_t) entryBlock);
807 oatInsertGrowableList(&cUnit->blockList, (intptr_t) exitBlock);
buzbee67bf8852011-08-17 17:51:35 -0700808
809 /* Current block to record parsed instructions */
810 BasicBlock *curBlock = oatNewBB(kDalvikByteCode, numBlocks++);
811 curBlock->startOffset = 0;
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700812 oatInsertGrowableList(&cUnit->blockList, (intptr_t) curBlock);
buzbee5b537102012-01-17 17:33:47 -0800813 /* Add first block to the fast lookup cache */
814 cUnit->blockMap.insert(std::make_pair(curBlock->startOffset, curBlock));
buzbee67bf8852011-08-17 17:51:35 -0700815 entryBlock->fallThrough = curBlock;
816 oatSetBit(curBlock->predecessors, entryBlock->id);
817
818 /*
819 * Store back the number of blocks since new blocks may be created of
820 * accessing cUnit.
821 */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700822 cUnit->numBlocks = numBlocks;
buzbee67bf8852011-08-17 17:51:35 -0700823
824 /* Identify code range in try blocks and set up the empty catch blocks */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700825 processTryCatchBlocks(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700826
827 /* Parse all instructions and put them into containing basic blocks */
828 while (codePtr < codeEnd) {
829 MIR *insn = (MIR *) oatNew(sizeof(MIR), true);
830 insn->offset = curOffset;
831 int width = parseInsn(codePtr, &insn->dalvikInsn, false);
832 insn->width = width;
833
834 /* Terminate when the data section is seen */
835 if (width == 0)
836 break;
837
838 oatAppendMIR(curBlock, insn);
839
840 codePtr += width;
841 int flags = dexGetFlagsFromOpcode(insn->dalvikInsn.opcode);
842
843 if (flags & kInstrCanBranch) {
buzbeee941e2c2011-12-05 12:38:17 -0800844 curBlock = processCanBranch(cUnit.get(), curBlock, insn, curOffset,
845 width, flags, codePtr, codeEnd);
buzbee67bf8852011-08-17 17:51:35 -0700846 } else if (flags & kInstrCanReturn) {
847 curBlock->fallThrough = exitBlock;
848 oatSetBit(exitBlock->predecessors, curBlock->id);
849 /*
850 * Terminate the current block if there are instructions
851 * afterwards.
852 */
853 if (codePtr < codeEnd) {
854 /*
855 * Create a fallthrough block for real instructions
856 * (incl. OP_NOP).
857 */
858 if (contentIsInsn(codePtr)) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700859 findBlock(cUnit.get(), curOffset + width,
buzbee67bf8852011-08-17 17:51:35 -0700860 /* split */
861 false,
862 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800863 true,
864 /* immedPredBlockP */
865 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700866 }
867 }
868 } else if (flags & kInstrCanThrow) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700869 processCanThrow(cUnit.get(), curBlock, insn, curOffset, width, flags,
buzbee67bf8852011-08-17 17:51:35 -0700870 tryBlockAddr, codePtr, codeEnd);
871 } else if (flags & kInstrCanSwitch) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700872 processCanSwitch(cUnit.get(), curBlock, insn, curOffset, width, flags);
buzbee67bf8852011-08-17 17:51:35 -0700873 }
874 curOffset += width;
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700875 BasicBlock *nextBlock = findBlock(cUnit.get(), curOffset,
buzbee67bf8852011-08-17 17:51:35 -0700876 /* split */
877 false,
878 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800879 false,
880 /* immedPredBlockP */
881 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700882 if (nextBlock) {
883 /*
884 * The next instruction could be the target of a previously parsed
885 * forward branch so a block is already created. If the current
886 * instruction is not an unconditional branch, connect them through
887 * the fall-through link.
888 */
buzbeeed3e9302011-09-23 17:34:19 -0700889 DCHECK(curBlock->fallThrough == NULL ||
buzbee67bf8852011-08-17 17:51:35 -0700890 curBlock->fallThrough == nextBlock ||
891 curBlock->fallThrough == exitBlock);
892
893 if ((curBlock->fallThrough == NULL) &&
894 (flags & kInstrCanContinue)) {
895 curBlock->fallThrough = nextBlock;
896 oatSetBit(nextBlock->predecessors, curBlock->id);
897 }
898 curBlock = nextBlock;
899 }
900 }
901
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700902 if (cUnit->printMe) {
903 oatDumpCompilationUnit(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700904 }
905
buzbee5b537102012-01-17 17:33:47 -0800906 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
907 /* Verify if all blocks are connected as claimed */
908 oatDataFlowAnalysisDispatcher(cUnit.get(), verifyPredInfo, kAllNodes, false /* isIterative */);
909 }
buzbee67bf8852011-08-17 17:51:35 -0700910
911 /* Perform SSA transformation for the whole method */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700912 oatMethodSSATransformation(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700913
buzbee43a36422011-09-14 14:00:13 -0700914 /* Perform null check elimination */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700915 oatMethodNullCheckElimination(cUnit.get());
buzbee43a36422011-09-14 14:00:13 -0700916
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700917 oatInitializeRegAlloc(cUnit.get()); // Needs to happen after SSA naming
buzbee67bf8852011-08-17 17:51:35 -0700918
919 /* Allocate Registers using simple local allocation scheme */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700920 oatSimpleRegAlloc(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700921
922 /* Convert MIR to LIR, etc. */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700923 oatMethodMIR2LIR(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700924
925 // Debugging only
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700926 if (cUnit->enableDebug & (1 << kDebugDumpCFG)) {
927 oatDumpCFG(cUnit.get(), "/sdcard/cfg/");
buzbeeec5adf32011-09-11 15:25:43 -0700928 }
buzbee67bf8852011-08-17 17:51:35 -0700929
930 /* Method is not empty */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700931 if (cUnit->firstLIRInsn) {
buzbee67bf8852011-08-17 17:51:35 -0700932
933 // mark the targets of switch statement case labels
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700934 oatProcessSwitchTables(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700935
936 /* Convert LIR into machine code. */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700937 oatAssembleLIR(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700938
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700939 if (cUnit->printMe) {
940 oatCodegenDump(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700941 }
942 }
943
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700944 // Combine vmap tables - core regs, then fp regs - into vmapTable
945 std::vector<uint16_t> vmapTable;
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700946 for (size_t i = 0 ; i < cUnit->coreVmapTable.size(); i++) {
947 vmapTable.push_back(cUnit->coreVmapTable[i]);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700948 }
buzbeec41e5b52011-09-23 12:46:19 -0700949 // Add a marker to take place of lr
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700950 vmapTable.push_back(INVALID_VREG);
buzbeec41e5b52011-09-23 12:46:19 -0700951 // Combine vmap tables - core regs, then fp regs
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700952 for (uint32_t i = 0; i < cUnit->fpVmapTable.size(); i++) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700953 vmapTable.push_back(cUnit->fpVmapTable[i]);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700954 }
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700955 DCHECK_EQ(vmapTable.size(),
956 static_cast<uint32_t>(__builtin_popcount(cUnit->coreSpillMask)
957 + __builtin_popcount(cUnit->fpSpillMask)));
958 DCHECK_GE(vmapTable.size(), 1U); // should always at least one INVALID_VREG for lr
959
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800960 CompiledMethod* result = new CompiledMethod(kThumb2, cUnit->codeBuffer,
Ian Rogers0571d352011-11-03 19:51:38 -0700961 cUnit->frameSize, cUnit->coreSpillMask,
962 cUnit->fpSpillMask, cUnit->mappingTable,
963 vmapTable);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700964
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800965 VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file)
966 << " (" << (cUnit->codeBuffer.size() * sizeof(cUnit->codeBuffer[0])) << " bytes)";
buzbee67bf8852011-08-17 17:51:35 -0700967
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700968 return result;
buzbee67bf8852011-08-17 17:51:35 -0700969}
970
Brian Carlstrom16192862011-09-12 17:50:06 -0700971void oatInit(const Compiler& compiler)
buzbee67bf8852011-08-17 17:51:35 -0700972{
buzbee67bf8852011-08-17 17:51:35 -0700973 static bool initialized = false;
974 if (initialized)
975 return;
976 initialized = true;
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800977 VLOG(compiler) << "Initializing compiler";
buzbee67bf8852011-08-17 17:51:35 -0700978 if (!oatArchInit()) {
979 LOG(FATAL) << "Failed to initialize oat";
980 }
981 if (!oatHeapInit()) {
982 LOG(FATAL) << "Failed to initialize oat heap";
983 }
984}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800985
986} // namespace art