blob: 5be51f46f23e23a81f71e69dcd2fed8b7bdb3dd4 [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
buzbeece302932011-10-04 14:32:18 -070025/* Default optimizer/debug setting for the compiler. */
26uint32_t compilerOptimizerDisableFlags = 0 | // Disable specific optimizations
buzbee67bc2362011-10-11 18:08:40 -070027 //(1 << kLoadStoreElimination) |
28 //(1 << kLoadHoisting) |
29 //(1 << kSuppressLoads) |
30 //(1 << kNullCheckElimination) |
buzbee769fde12012-01-05 17:35:23 -080031 //(1 << kPromoteRegs) |
32 //(1 << kTrackLiveTemps) |
buzbeece302932011-10-04 14:32:18 -070033 0;
34
35uint32_t compilerDebugFlags = 0 | // Enable debug/testing modes
buzbeee3de7492011-10-05 13:37:17 -070036 //(1 << kDebugDisplayMissingTargets) |
buzbeece302932011-10-04 14:32:18 -070037 //(1 << kDebugVerbose) |
38 //(1 << kDebugDumpCFG) |
39 //(1 << kDebugSlowFieldPath) |
40 //(1 << kDebugSlowInvokePath) |
41 //(1 << kDebugSlowStringPath) |
42 //(1 << kDebugSlowestFieldPath) |
43 //(1 << kDebugSlowestStringPath) |
buzbee34c77ad2012-01-11 13:01:32 -080044 //(1 << kDebugExerciseResolveMethod) |
buzbeece302932011-10-04 14:32:18 -070045 0;
46
47std::string compilerMethodMatch; // Method name match to apply above flags
48
49bool compilerFlipMatch = false; // Reverses sense of method name match
50
buzbeeed3e9302011-09-23 17:34:19 -070051STATIC inline bool contentIsInsn(const u2* codePtr) {
buzbee67bf8852011-08-17 17:51:35 -070052 u2 instr = *codePtr;
53 Opcode opcode = (Opcode)(instr & 0xff);
54
55 /*
56 * Since the low 8-bit in metadata may look like OP_NOP, we need to check
57 * both the low and whole sub-word to determine whether it is code or data.
58 */
59 return (opcode != OP_NOP || instr == 0);
60}
61
62/*
63 * Parse an instruction, return the length of the instruction
64 */
buzbeeed3e9302011-09-23 17:34:19 -070065STATIC inline int parseInsn(const u2* codePtr, DecodedInstruction* decInsn,
buzbee67bf8852011-08-17 17:51:35 -070066 bool printMe)
67{
68 // Don't parse instruction data
69 if (!contentIsInsn(codePtr)) {
70 return 0;
71 }
72
73 u2 instr = *codePtr;
74 Opcode opcode = dexOpcodeFromCodeUnit(instr);
75
76 dexDecodeInstruction(codePtr, decInsn);
77 if (printMe) {
Elliott Hughesc1f143d2011-12-01 17:31:10 -080078 char* decodedString = oatGetDalvikDisassembly(decInsn, NULL);
buzbee67bf8852011-08-17 17:51:35 -070079 LOG(INFO) << codePtr << ": 0x" << std::hex << (int)opcode <<
80 " " << decodedString;
81 }
82 return dexGetWidthFromOpcode(opcode);
83}
84
85#define UNKNOWN_TARGET 0xffffffff
86
buzbeeed3e9302011-09-23 17:34:19 -070087STATIC inline bool isGoto(MIR* insn)
buzbee67bf8852011-08-17 17:51:35 -070088{
89 switch (insn->dalvikInsn.opcode) {
90 case OP_GOTO:
91 case OP_GOTO_16:
92 case OP_GOTO_32:
93 return true;
94 default:
95 return false;
96 }
97}
98
99/*
100 * Identify unconditional branch instructions
101 */
buzbeeed3e9302011-09-23 17:34:19 -0700102STATIC inline bool isUnconditionalBranch(MIR* insn)
buzbee67bf8852011-08-17 17:51:35 -0700103{
104 switch (insn->dalvikInsn.opcode) {
105 case OP_RETURN_VOID:
106 case OP_RETURN:
107 case OP_RETURN_WIDE:
108 case OP_RETURN_OBJECT:
109 return true;
110 default:
111 return isGoto(insn);
112 }
113}
114
115/* Split an existing block from the specified code offset into two */
buzbeeed3e9302011-09-23 17:34:19 -0700116STATIC BasicBlock *splitBlock(CompilationUnit* cUnit,
buzbee67bf8852011-08-17 17:51:35 -0700117 unsigned int codeOffset,
buzbee9ab05de2012-01-18 15:43:48 -0800118 BasicBlock* origBlock,
119 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 }
129 BasicBlock *bottomBlock = oatNewBB(kDalvikByteCode,
130 cUnit->numBlocks++);
131 oatInsertGrowableList(&cUnit->blockList, (intptr_t) bottomBlock);
132
133 bottomBlock->startOffset = codeOffset;
134 bottomBlock->firstMIRInsn = insn;
135 bottomBlock->lastMIRInsn = origBlock->lastMIRInsn;
136
137 /* Handle the taken path */
138 bottomBlock->taken = origBlock->taken;
139 if (bottomBlock->taken) {
140 origBlock->taken = NULL;
141 oatClearBit(bottomBlock->taken->predecessors, origBlock->id);
142 oatSetBit(bottomBlock->taken->predecessors, bottomBlock->id);
143 }
144
145 /* Handle the fallthrough path */
146 bottomBlock->needFallThroughBranch = origBlock->needFallThroughBranch;
147 bottomBlock->fallThrough = origBlock->fallThrough;
148 origBlock->fallThrough = bottomBlock;
149 origBlock->needFallThroughBranch = true;
150 oatSetBit(bottomBlock->predecessors, origBlock->id);
151 if (bottomBlock->fallThrough) {
152 oatClearBit(bottomBlock->fallThrough->predecessors,
153 origBlock->id);
154 oatSetBit(bottomBlock->fallThrough->predecessors,
155 bottomBlock->id);
156 }
157
158 /* Handle the successor list */
159 if (origBlock->successorBlockList.blockListType != kNotUsed) {
160 bottomBlock->successorBlockList = origBlock->successorBlockList;
161 origBlock->successorBlockList.blockListType = kNotUsed;
162 GrowableListIterator iterator;
163
164 oatGrowableListIteratorInit(&bottomBlock->successorBlockList.blocks,
165 &iterator);
166 while (true) {
167 SuccessorBlockInfo *successorBlockInfo =
168 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
169 if (successorBlockInfo == NULL) break;
170 BasicBlock *bb = successorBlockInfo->block;
171 oatClearBit(bb->predecessors, origBlock->id);
172 oatSetBit(bb->predecessors, bottomBlock->id);
173 }
174 }
175
176 origBlock->lastMIRInsn = insn->prev;
177
178 insn->prev->next = NULL;
179 insn->prev = NULL;
buzbee9ab05de2012-01-18 15:43:48 -0800180 /*
181 * Update the immediate predecessor block pointer so that outgoing edges
182 * can be applied to the proper block.
183 */
184 if (immedPredBlockP) {
185 DCHECK_EQ(*immedPredBlockP, origBlock);
186 *immedPredBlockP = bottomBlock;
187 }
buzbee67bf8852011-08-17 17:51:35 -0700188 return bottomBlock;
189}
190
191/*
192 * Given a code offset, find out the block that starts with it. If the offset
buzbee9ab05de2012-01-18 15:43:48 -0800193 * is in the middle of an existing block, split it into two. If immedPredBlockP
194 * is not non-null and is the block being split, update *immedPredBlockP to
195 * point to the bottom block so that outgoing edges can be set up properly
196 * (by the caller)
buzbee67bf8852011-08-17 17:51:35 -0700197 */
buzbeeed3e9302011-09-23 17:34:19 -0700198STATIC BasicBlock *findBlock(CompilationUnit* cUnit,
buzbee67bf8852011-08-17 17:51:35 -0700199 unsigned int codeOffset,
buzbee9ab05de2012-01-18 15:43:48 -0800200 bool split, bool create,
201 BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700202{
203 GrowableList* blockList = &cUnit->blockList;
204 BasicBlock* bb;
205 unsigned int i;
206
207 for (i = 0; i < blockList->numUsed; i++) {
208 bb = (BasicBlock *) blockList->elemList[i];
209 if (bb->blockType != kDalvikByteCode) continue;
210 if (bb->startOffset == codeOffset) return bb;
211 /* Check if a branch jumps into the middle of an existing block */
212 if ((split == true) && (codeOffset > bb->startOffset) &&
213 (bb->lastMIRInsn != NULL) &&
214 (codeOffset <= bb->lastMIRInsn->offset)) {
buzbee9ab05de2012-01-18 15:43:48 -0800215 BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb,
216 bb == *immedPredBlockP ?
217 immedPredBlockP : NULL);
buzbee67bf8852011-08-17 17:51:35 -0700218 return newBB;
219 }
220 }
221 if (create) {
222 bb = oatNewBB(kDalvikByteCode, cUnit->numBlocks++);
223 oatInsertGrowableList(&cUnit->blockList, (intptr_t) bb);
224 bb->startOffset = codeOffset;
225 return bb;
226 }
227 return NULL;
228}
229
230/* Dump the CFG into a DOT graph */
231void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix)
232{
buzbee67bf8852011-08-17 17:51:35 -0700233 FILE* file;
Elliott Hughes95572412011-12-13 18:14:20 -0800234 std::string name(art::PrettyMethod(cUnit->method_idx, *cUnit->dex_file));
buzbee67bf8852011-08-17 17:51:35 -0700235 char startOffset[80];
236 sprintf(startOffset, "_%x", cUnit->entryBlock->fallThrough->startOffset);
Elliott Hughesc1f143d2011-12-01 17:31:10 -0800237 char* fileName = (char*) oatNew(
buzbeec143c552011-08-20 17:38:58 -0700238 strlen(dirPrefix) +
239 name.length() +
240 strlen(".dot") + 1, true);
241 sprintf(fileName, "%s%s%s.dot", dirPrefix, name.c_str(), startOffset);
buzbee67bf8852011-08-17 17:51:35 -0700242
243 /*
244 * Convert the special characters into a filesystem- and shell-friendly
245 * format.
246 */
247 int i;
248 for (i = strlen(dirPrefix); fileName[i]; i++) {
249 if (fileName[i] == '/') {
250 fileName[i] = '_';
251 } else if (fileName[i] == ';') {
252 fileName[i] = '#';
253 } else if (fileName[i] == '$') {
254 fileName[i] = '+';
255 } else if (fileName[i] == '(' || fileName[i] == ')') {
256 fileName[i] = '@';
257 } else if (fileName[i] == '<' || fileName[i] == '>') {
258 fileName[i] = '=';
259 }
260 }
261 file = fopen(fileName, "w");
262 if (file == NULL) {
263 return;
264 }
265 fprintf(file, "digraph G {\n");
266
267 fprintf(file, " rankdir=TB\n");
268
269 int numReachableBlocks = cUnit->numReachableBlocks;
270 int idx;
271 const GrowableList *blockList = &cUnit->blockList;
272
273 for (idx = 0; idx < numReachableBlocks; idx++) {
274 int blockIdx = cUnit->dfsOrder.elemList[idx];
275 BasicBlock *bb = (BasicBlock *) oatGrowableListGetElement(blockList,
276 blockIdx);
277 if (bb == NULL) break;
278 if (bb->blockType == kEntryBlock) {
279 fprintf(file, " entry [shape=Mdiamond];\n");
280 } else if (bb->blockType == kExitBlock) {
281 fprintf(file, " exit [shape=Mdiamond];\n");
282 } else if (bb->blockType == kDalvikByteCode) {
283 fprintf(file, " block%04x [shape=record,label = \"{ \\\n",
284 bb->startOffset);
285 const MIR *mir;
286 fprintf(file, " {block id %d\\l}%s\\\n", bb->id,
287 bb->firstMIRInsn ? " | " : " ");
288 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
289 fprintf(file, " {%04x %s\\l}%s\\\n", mir->offset,
290 mir->ssaRep ?
291 oatFullDisassembler(cUnit, mir) :
292 dexGetOpcodeName(mir->dalvikInsn.opcode),
293 mir->next ? " | " : " ");
294 }
295 fprintf(file, " }\"];\n\n");
296 } else if (bb->blockType == kExceptionHandling) {
297 char blockName[BLOCK_NAME_LEN];
298
299 oatGetBlockName(bb, blockName);
300 fprintf(file, " %s [shape=invhouse];\n", blockName);
301 }
302
303 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
304
305 if (bb->taken) {
306 oatGetBlockName(bb, blockName1);
307 oatGetBlockName(bb->taken, blockName2);
308 fprintf(file, " %s:s -> %s:n [style=dotted]\n",
309 blockName1, blockName2);
310 }
311 if (bb->fallThrough) {
312 oatGetBlockName(bb, blockName1);
313 oatGetBlockName(bb->fallThrough, blockName2);
314 fprintf(file, " %s:s -> %s:n\n", blockName1, blockName2);
315 }
316
317 if (bb->successorBlockList.blockListType != kNotUsed) {
318 fprintf(file, " succ%04x [shape=%s,label = \"{ \\\n",
319 bb->startOffset,
320 (bb->successorBlockList.blockListType == kCatch) ?
321 "Mrecord" : "record");
322 GrowableListIterator iterator;
323 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
324 &iterator);
325 SuccessorBlockInfo *successorBlockInfo =
326 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
327
328 int succId = 0;
329 while (true) {
330 if (successorBlockInfo == NULL) break;
331
332 BasicBlock *destBlock = successorBlockInfo->block;
333 SuccessorBlockInfo *nextSuccessorBlockInfo =
334 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
335
336 fprintf(file, " {<f%d> %04x: %04x\\l}%s\\\n",
337 succId++,
338 successorBlockInfo->key,
339 destBlock->startOffset,
340 (nextSuccessorBlockInfo != NULL) ? " | " : " ");
341
342 successorBlockInfo = nextSuccessorBlockInfo;
343 }
344 fprintf(file, " }\"];\n\n");
345
346 oatGetBlockName(bb, blockName1);
347 fprintf(file, " %s:s -> succ%04x:n [style=dashed]\n",
348 blockName1, bb->startOffset);
349
350 if (bb->successorBlockList.blockListType == kPackedSwitch ||
351 bb->successorBlockList.blockListType == kSparseSwitch) {
352
353 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
354 &iterator);
355
356 succId = 0;
357 while (true) {
358 SuccessorBlockInfo *successorBlockInfo =
359 (SuccessorBlockInfo *)
360 oatGrowableListIteratorNext(&iterator);
361 if (successorBlockInfo == NULL) break;
362
363 BasicBlock *destBlock = successorBlockInfo->block;
364
365 oatGetBlockName(destBlock, blockName2);
366 fprintf(file, " succ%04x:f%d:e -> %s:n\n",
367 bb->startOffset, succId++,
368 blockName2);
369 }
370 }
371 }
372 fprintf(file, "\n");
373
buzbeece302932011-10-04 14:32:18 -0700374 /* Display the dominator tree */
buzbee67bf8852011-08-17 17:51:35 -0700375 oatGetBlockName(bb, blockName1);
376 fprintf(file, " cfg%s [label=\"%s\", shape=none];\n",
377 blockName1, blockName1);
378 if (bb->iDom) {
379 oatGetBlockName(bb->iDom, blockName2);
380 fprintf(file, " cfg%s:s -> cfg%s:n\n\n",
381 blockName2, blockName1);
382 }
buzbee67bf8852011-08-17 17:51:35 -0700383 }
384 fprintf(file, "}\n");
385 fclose(file);
386}
387
388/* Verify if all the successor is connected with all the claimed predecessors */
buzbeeed3e9302011-09-23 17:34:19 -0700389STATIC bool verifyPredInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700390{
391 ArenaBitVectorIterator bvIterator;
392
393 oatBitVectorIteratorInit(bb->predecessors, &bvIterator);
394 while (true) {
395 int blockIdx = oatBitVectorIteratorNext(&bvIterator);
396 if (blockIdx == -1) break;
397 BasicBlock *predBB = (BasicBlock *)
398 oatGrowableListGetElement(&cUnit->blockList, blockIdx);
399 bool found = false;
400 if (predBB->taken == bb) {
401 found = true;
402 } else if (predBB->fallThrough == bb) {
403 found = true;
404 } else if (predBB->successorBlockList.blockListType != kNotUsed) {
405 GrowableListIterator iterator;
406 oatGrowableListIteratorInit(&predBB->successorBlockList.blocks,
407 &iterator);
408 while (true) {
409 SuccessorBlockInfo *successorBlockInfo =
410 (SuccessorBlockInfo *)
411 oatGrowableListIteratorNext(&iterator);
412 if (successorBlockInfo == NULL) break;
413 BasicBlock *succBB = successorBlockInfo->block;
414 if (succBB == bb) {
415 found = true;
416 break;
417 }
418 }
419 }
420 if (found == false) {
421 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
422 oatGetBlockName(bb, blockName1);
423 oatGetBlockName(predBB, blockName2);
424 oatDumpCFG(cUnit, "/sdcard/cfg/");
425 LOG(FATAL) << "Successor " << blockName1 << "not found from "
426 << blockName2;
427 }
428 }
429 return true;
430}
431
432/* Identify code range in try blocks and set up the empty catch blocks */
buzbeeed3e9302011-09-23 17:34:19 -0700433STATIC void processTryCatchBlocks(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700434{
Ian Rogersa3760aa2011-11-14 14:32:37 -0800435 const art::DexFile::CodeItem* code_item = cUnit->code_item;
buzbeee9a72f62011-09-04 17:59:07 -0700436 int triesSize = code_item->tries_size_;
buzbee67bf8852011-08-17 17:51:35 -0700437 int offset;
438
439 if (triesSize == 0) {
440 return;
441 }
442
buzbee67bf8852011-08-17 17:51:35 -0700443 ArenaBitVector* tryBlockAddr = cUnit->tryBlockAddr;
444
buzbeee9a72f62011-09-04 17:59:07 -0700445 for (int i = 0; i < triesSize; i++) {
446 const art::DexFile::TryItem* pTry =
Ian Rogers0571d352011-11-03 19:51:38 -0700447 art::DexFile::GetTryItems(*code_item, i);
buzbeee9a72f62011-09-04 17:59:07 -0700448 int startOffset = pTry->start_addr_;
449 int endOffset = startOffset + pTry->insn_count_;
buzbee67bf8852011-08-17 17:51:35 -0700450 for (offset = startOffset; offset < endOffset; offset++) {
451 oatSetBit(tryBlockAddr, offset);
452 }
453 }
454
buzbeee9a72f62011-09-04 17:59:07 -0700455 // Iterate over each of the handlers to enqueue the empty Catch blocks
456 const art::byte* handlers_ptr =
Ian Rogers0571d352011-11-03 19:51:38 -0700457 art::DexFile::GetCatchHandlerData(*code_item, 0);
buzbeee9a72f62011-09-04 17:59:07 -0700458 uint32_t handlers_size = art::DecodeUnsignedLeb128(&handlers_ptr);
459 for (uint32_t idx = 0; idx < handlers_size; idx++) {
Ian Rogers0571d352011-11-03 19:51:38 -0700460 art::CatchHandlerIterator iterator(handlers_ptr);
461 for (; iterator.HasNext(); iterator.Next()) {
462 uint32_t address = iterator.GetHandlerAddress();
buzbee9ab05de2012-01-18 15:43:48 -0800463 findBlock(cUnit, address, false /* split */, true /*create*/,
464 /* immedPredBlockP */ NULL);
buzbee67bf8852011-08-17 17:51:35 -0700465 }
Ian Rogers0571d352011-11-03 19:51:38 -0700466 handlers_ptr = iterator.EndDataPointer();
buzbee67bf8852011-08-17 17:51:35 -0700467 }
468}
469
470/* Process instructions with the kInstrCanBranch flag */
buzbeee941e2c2011-12-05 12:38:17 -0800471STATIC BasicBlock* processCanBranch(CompilationUnit* cUnit,
472 BasicBlock* curBlock, MIR* insn,
473 int curOffset, int width, int flags,
474 const u2* codePtr, const u2* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700475{
476 int target = curOffset;
477 switch (insn->dalvikInsn.opcode) {
478 case OP_GOTO:
479 case OP_GOTO_16:
480 case OP_GOTO_32:
481 target += (int) insn->dalvikInsn.vA;
482 break;
483 case OP_IF_EQ:
484 case OP_IF_NE:
485 case OP_IF_LT:
486 case OP_IF_GE:
487 case OP_IF_GT:
488 case OP_IF_LE:
489 target += (int) insn->dalvikInsn.vC;
490 break;
491 case OP_IF_EQZ:
492 case OP_IF_NEZ:
493 case OP_IF_LTZ:
494 case OP_IF_GEZ:
495 case OP_IF_GTZ:
496 case OP_IF_LEZ:
497 target += (int) insn->dalvikInsn.vB;
498 break;
499 default:
500 LOG(FATAL) << "Unexpected opcode(" << (int)insn->dalvikInsn.opcode
501 << ") with kInstrCanBranch set";
502 }
503 BasicBlock *takenBlock = findBlock(cUnit, target,
504 /* split */
505 true,
506 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800507 true,
508 /* immedPredBlockP */
509 &curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700510 curBlock->taken = takenBlock;
511 oatSetBit(takenBlock->predecessors, curBlock->id);
512
513 /* Always terminate the current block for conditional branches */
514 if (flags & kInstrCanContinue) {
515 BasicBlock *fallthroughBlock = findBlock(cUnit,
516 curOffset + width,
517 /*
518 * If the method is processed
519 * in sequential order from the
520 * beginning, we don't need to
521 * specify split for continue
522 * blocks. However, this
523 * routine can be called by
524 * compileLoop, which starts
525 * parsing the method from an
526 * arbitrary address in the
527 * method body.
528 */
529 true,
530 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800531 true,
532 /* immedPredBlockP */
533 &curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700534 curBlock->fallThrough = fallthroughBlock;
535 oatSetBit(fallthroughBlock->predecessors, curBlock->id);
536 } else if (codePtr < codeEnd) {
537 /* Create a fallthrough block for real instructions (incl. OP_NOP) */
538 if (contentIsInsn(codePtr)) {
539 findBlock(cUnit, curOffset + width,
540 /* split */
541 false,
542 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800543 true,
544 /* immedPredBlockP */
545 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700546 }
547 }
buzbeee941e2c2011-12-05 12:38:17 -0800548 return curBlock;
buzbee67bf8852011-08-17 17:51:35 -0700549}
550
551/* Process instructions with the kInstrCanSwitch flag */
buzbeeed3e9302011-09-23 17:34:19 -0700552STATIC void processCanSwitch(CompilationUnit* cUnit, BasicBlock* curBlock,
buzbee67bf8852011-08-17 17:51:35 -0700553 MIR* insn, int curOffset, int width, int flags)
554{
555 u2* switchData= (u2 *) (cUnit->insns + curOffset +
556 insn->dalvikInsn.vB);
557 int size;
558 int* keyTable;
559 int* targetTable;
560 int i;
561 int firstKey;
562
563 /*
564 * Packed switch data format:
565 * ushort ident = 0x0100 magic value
566 * ushort size number of entries in the table
567 * int first_key first (and lowest) switch case value
568 * int targets[size] branch targets, relative to switch opcode
569 *
570 * Total size is (4+size*2) 16-bit code units.
571 */
572 if (insn->dalvikInsn.opcode == OP_PACKED_SWITCH) {
buzbeeed3e9302011-09-23 17:34:19 -0700573 DCHECK_EQ(switchData[0], kPackedSwitchSignature);
buzbee67bf8852011-08-17 17:51:35 -0700574 size = switchData[1];
575 firstKey = switchData[2] | (switchData[3] << 16);
576 targetTable = (int *) &switchData[4];
577 keyTable = NULL; // Make the compiler happy
578 /*
579 * Sparse switch data format:
580 * ushort ident = 0x0200 magic value
581 * ushort size number of entries in the table; > 0
582 * int keys[size] keys, sorted low-to-high; 32-bit aligned
583 * int targets[size] branch targets, relative to switch opcode
584 *
585 * Total size is (2+size*4) 16-bit code units.
586 */
587 } else {
buzbeeed3e9302011-09-23 17:34:19 -0700588 DCHECK_EQ(switchData[0], kSparseSwitchSignature);
buzbee67bf8852011-08-17 17:51:35 -0700589 size = switchData[1];
590 keyTable = (int *) &switchData[2];
591 targetTable = (int *) &switchData[2 + size*2];
592 firstKey = 0; // To make the compiler happy
593 }
594
595 if (curBlock->successorBlockList.blockListType != kNotUsed) {
596 LOG(FATAL) << "Successor block list already in use: " <<
597 (int)curBlock->successorBlockList.blockListType;
598 }
599 curBlock->successorBlockList.blockListType =
600 (insn->dalvikInsn.opcode == OP_PACKED_SWITCH) ?
601 kPackedSwitch : kSparseSwitch;
602 oatInitGrowableList(&curBlock->successorBlockList.blocks, size);
603
604 for (i = 0; i < size; i++) {
605 BasicBlock *caseBlock = findBlock(cUnit, curOffset + targetTable[i],
606 /* split */
607 true,
608 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800609 true,
610 /* immedPredBlockP */
611 &curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700612 SuccessorBlockInfo *successorBlockInfo =
613 (SuccessorBlockInfo *) oatNew(sizeof(SuccessorBlockInfo),
614 false);
615 successorBlockInfo->block = caseBlock;
616 successorBlockInfo->key = (insn->dalvikInsn.opcode == OP_PACKED_SWITCH)?
617 firstKey + i : keyTable[i];
618 oatInsertGrowableList(&curBlock->successorBlockList.blocks,
619 (intptr_t) successorBlockInfo);
620 oatSetBit(caseBlock->predecessors, curBlock->id);
621 }
622
623 /* Fall-through case */
624 BasicBlock* fallthroughBlock = findBlock(cUnit,
625 curOffset + width,
626 /* split */
627 false,
628 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800629 true,
630 /* immedPredBlockP */
631 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700632 curBlock->fallThrough = fallthroughBlock;
633 oatSetBit(fallthroughBlock->predecessors, curBlock->id);
634}
635
636/* Process instructions with the kInstrCanThrow flag */
buzbeeed3e9302011-09-23 17:34:19 -0700637STATIC void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock,
buzbee67bf8852011-08-17 17:51:35 -0700638 MIR* insn, int curOffset, int width, int flags,
639 ArenaBitVector* tryBlockAddr, const u2* codePtr,
640 const u2* codeEnd)
641{
Ian Rogersa3760aa2011-11-14 14:32:37 -0800642 const art::DexFile::CodeItem* code_item = cUnit->code_item;
buzbee67bf8852011-08-17 17:51:35 -0700643
644 /* In try block */
645 if (oatIsBitSet(tryBlockAddr, curOffset)) {
Ian Rogers0571d352011-11-03 19:51:38 -0700646 art::CatchHandlerIterator iterator(*code_item, curOffset);
buzbee67bf8852011-08-17 17:51:35 -0700647
buzbee67bf8852011-08-17 17:51:35 -0700648 if (curBlock->successorBlockList.blockListType != kNotUsed) {
649 LOG(FATAL) << "Successor block list already in use: " <<
650 (int)curBlock->successorBlockList.blockListType;
651 }
buzbeee9a72f62011-09-04 17:59:07 -0700652
buzbee67bf8852011-08-17 17:51:35 -0700653 curBlock->successorBlockList.blockListType = kCatch;
654 oatInitGrowableList(&curBlock->successorBlockList.blocks, 2);
655
Ian Rogers0571d352011-11-03 19:51:38 -0700656 for (;iterator.HasNext(); iterator.Next()) {
657 BasicBlock *catchBlock = findBlock(cUnit, iterator.GetHandlerAddress(),
buzbeee9a72f62011-09-04 17:59:07 -0700658 false /* split*/,
buzbee9ab05de2012-01-18 15:43:48 -0800659 false /* creat */,
660 NULL /* immedPredBlockP */);
buzbee43a36422011-09-14 14:00:13 -0700661 catchBlock->catchEntry = true;
buzbee67bf8852011-08-17 17:51:35 -0700662 SuccessorBlockInfo *successorBlockInfo =
buzbeee9a72f62011-09-04 17:59:07 -0700663 (SuccessorBlockInfo *) oatNew(sizeof(SuccessorBlockInfo),
664 false);
buzbee67bf8852011-08-17 17:51:35 -0700665 successorBlockInfo->block = catchBlock;
Ian Rogers0571d352011-11-03 19:51:38 -0700666 successorBlockInfo->key = iterator.GetHandlerTypeIndex();
buzbee67bf8852011-08-17 17:51:35 -0700667 oatInsertGrowableList(&curBlock->successorBlockList.blocks,
668 (intptr_t) successorBlockInfo);
669 oatSetBit(catchBlock->predecessors, curBlock->id);
670 }
671 } else {
672 BasicBlock *ehBlock = oatNewBB(kExceptionHandling,
673 cUnit->numBlocks++);
674 curBlock->taken = ehBlock;
675 oatInsertGrowableList(&cUnit->blockList, (intptr_t) ehBlock);
676 ehBlock->startOffset = curOffset;
677 oatSetBit(ehBlock->predecessors, curBlock->id);
678 }
679
680 /*
681 * Force the current block to terminate.
682 *
683 * Data may be present before codeEnd, so we need to parse it to know
684 * whether it is code or data.
685 */
686 if (codePtr < codeEnd) {
687 /* Create a fallthrough block for real instructions (incl. OP_NOP) */
688 if (contentIsInsn(codePtr)) {
689 BasicBlock *fallthroughBlock = findBlock(cUnit,
690 curOffset + width,
691 /* split */
692 false,
693 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800694 true,
695 /* immedPredBlockP */
696 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700697 /*
buzbee510c6052011-10-27 10:47:20 -0700698 * OP_THROW is an unconditional branch. NOTE:
699 * OP_THROW_VERIFICATION_ERROR is also an unconditional
700 * branch, but we shouldn't treat it as such until we have
701 * a dead code elimination pass (which won't be important
702 * until inlining w/ constant propogation is implemented.
buzbee67bf8852011-08-17 17:51:35 -0700703 */
buzbee510c6052011-10-27 10:47:20 -0700704 if (insn->dalvikInsn.opcode != OP_THROW) {
buzbee67bf8852011-08-17 17:51:35 -0700705 curBlock->fallThrough = fallthroughBlock;
706 oatSetBit(fallthroughBlock->predecessors, curBlock->id);
707 }
708 }
709 }
710}
711
712/*
713 * Compile a method.
714 */
Ian Rogersa3760aa2011-11-14 14:32:37 -0800715CompiledMethod* oatCompileMethod(const Compiler& compiler, const art::DexFile::CodeItem* code_item,
716 uint32_t access_flags, uint32_t method_idx,
717 const art::ClassLoader* class_loader,
718 const art::DexFile& dex_file, art::InstructionSet insnSet)
buzbee67bf8852011-08-17 17:51:35 -0700719{
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800720 VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
buzbee2a475e72011-09-07 17:19:17 -0700721 oatArenaReset();
Brian Carlstrom94496d32011-08-22 09:22:47 -0700722
buzbeec143c552011-08-20 17:38:58 -0700723 const u2* codePtr = code_item->insns_;
Ian Rogersd81871c2011-10-03 13:57:23 -0700724 const u2* codeEnd = code_item->insns_ + code_item->insns_size_in_code_units_;
buzbee67bf8852011-08-17 17:51:35 -0700725 int numBlocks = 0;
726 unsigned int curOffset = 0;
727
Brian Carlstrom16192862011-09-12 17:50:06 -0700728 oatInit(compiler);
buzbee67bf8852011-08-17 17:51:35 -0700729
Ian Rogersa3760aa2011-11-14 14:32:37 -0800730 art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker();
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700731 UniquePtr<CompilationUnit> cUnit(new CompilationUnit);
732 memset(cUnit.get(), 0, sizeof(*cUnit));
733 cUnit->compiler = &compiler;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800734 cUnit->class_linker = class_linker;
735 cUnit->dex_file = &dex_file;
736 cUnit->dex_cache = class_linker->FindDexCache(dex_file);
737 cUnit->method_idx = method_idx;
738 cUnit->code_item = code_item;
739 cUnit->access_flags = access_flags;
740 cUnit->shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700741 cUnit->instructionSet = (OatInstructionSetType)insnSet;
742 cUnit->insns = code_item->insns_;
Ian Rogersd81871c2011-10-03 13:57:23 -0700743 cUnit->insnsSize = code_item->insns_size_in_code_units_;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800744 cUnit->numIns = code_item->ins_size_;
745 cUnit->numRegs = code_item->registers_size_ - cUnit->numIns;
746 cUnit->numOuts = code_item->outs_size_;
747 /* Adjust this value accordingly once inlining is performed */
748 cUnit->numDalvikRegisters = code_item->registers_size_;
buzbeece302932011-10-04 14:32:18 -0700749 bool useMatch = compilerMethodMatch.length() != 0;
750 bool match = useMatch && (compilerFlipMatch ^
Ian Rogersa3760aa2011-11-14 14:32:37 -0800751 (PrettyMethod(method_idx, dex_file).find(compilerMethodMatch) != std::string::npos));
buzbeece302932011-10-04 14:32:18 -0700752 if (!useMatch || match) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700753 cUnit->disableOpt = compilerOptimizerDisableFlags;
754 cUnit->enableDebug = compilerDebugFlags;
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800755 cUnit->printMe = VLOG_IS_ON(compiler) || (cUnit->enableDebug & (1 << kDebugVerbose));
buzbeece302932011-10-04 14:32:18 -0700756 }
buzbee67bf8852011-08-17 17:51:35 -0700757
buzbeecefd1872011-09-09 09:59:52 -0700758 /* Assume non-throwing leaf */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700759 cUnit->attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE);
buzbeecefd1872011-09-09 09:59:52 -0700760
buzbee67bf8852011-08-17 17:51:35 -0700761 /* Initialize the block list */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700762 oatInitGrowableList(&cUnit->blockList, 40);
buzbee67bf8852011-08-17 17:51:35 -0700763
764 /* Initialize the switchTables list */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700765 oatInitGrowableList(&cUnit->switchTables, 4);
buzbee67bf8852011-08-17 17:51:35 -0700766
767 /* Intialize the fillArrayData list */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700768 oatInitGrowableList(&cUnit->fillArrayData, 4);
buzbee67bf8852011-08-17 17:51:35 -0700769
buzbee5ade1d22011-09-09 14:44:52 -0700770 /* Intialize the throwLaunchpads list */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700771 oatInitGrowableList(&cUnit->throwLaunchpads, 4);
buzbee5ade1d22011-09-09 14:44:52 -0700772
buzbeec1f45042011-09-21 16:03:19 -0700773 /* Intialize the suspendLaunchpads list */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700774 oatInitGrowableList(&cUnit->suspendLaunchpads, 4);
buzbeec1f45042011-09-21 16:03:19 -0700775
buzbee67bf8852011-08-17 17:51:35 -0700776 /* Allocate the bit-vector to track the beginning of basic blocks */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700777 ArenaBitVector *tryBlockAddr = oatAllocBitVector(cUnit->insnsSize,
buzbee67bf8852011-08-17 17:51:35 -0700778 true /* expandable */);
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700779 cUnit->tryBlockAddr = tryBlockAddr;
buzbee67bf8852011-08-17 17:51:35 -0700780
781 /* Create the default entry and exit blocks and enter them to the list */
782 BasicBlock *entryBlock = oatNewBB(kEntryBlock, numBlocks++);
783 BasicBlock *exitBlock = oatNewBB(kExitBlock, numBlocks++);
784
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700785 cUnit->entryBlock = entryBlock;
786 cUnit->exitBlock = exitBlock;
buzbee67bf8852011-08-17 17:51:35 -0700787
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700788 oatInsertGrowableList(&cUnit->blockList, (intptr_t) entryBlock);
789 oatInsertGrowableList(&cUnit->blockList, (intptr_t) exitBlock);
buzbee67bf8852011-08-17 17:51:35 -0700790
791 /* Current block to record parsed instructions */
792 BasicBlock *curBlock = oatNewBB(kDalvikByteCode, numBlocks++);
793 curBlock->startOffset = 0;
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700794 oatInsertGrowableList(&cUnit->blockList, (intptr_t) curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700795 entryBlock->fallThrough = curBlock;
796 oatSetBit(curBlock->predecessors, entryBlock->id);
797
798 /*
799 * Store back the number of blocks since new blocks may be created of
800 * accessing cUnit.
801 */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700802 cUnit->numBlocks = numBlocks;
buzbee67bf8852011-08-17 17:51:35 -0700803
804 /* Identify code range in try blocks and set up the empty catch blocks */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700805 processTryCatchBlocks(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700806
807 /* Parse all instructions and put them into containing basic blocks */
808 while (codePtr < codeEnd) {
809 MIR *insn = (MIR *) oatNew(sizeof(MIR), true);
810 insn->offset = curOffset;
811 int width = parseInsn(codePtr, &insn->dalvikInsn, false);
812 insn->width = width;
813
814 /* Terminate when the data section is seen */
815 if (width == 0)
816 break;
817
818 oatAppendMIR(curBlock, insn);
819
820 codePtr += width;
821 int flags = dexGetFlagsFromOpcode(insn->dalvikInsn.opcode);
822
823 if (flags & kInstrCanBranch) {
buzbeee941e2c2011-12-05 12:38:17 -0800824 curBlock = processCanBranch(cUnit.get(), curBlock, insn, curOffset,
825 width, flags, codePtr, codeEnd);
buzbee67bf8852011-08-17 17:51:35 -0700826 } else if (flags & kInstrCanReturn) {
827 curBlock->fallThrough = exitBlock;
828 oatSetBit(exitBlock->predecessors, curBlock->id);
829 /*
830 * Terminate the current block if there are instructions
831 * afterwards.
832 */
833 if (codePtr < codeEnd) {
834 /*
835 * Create a fallthrough block for real instructions
836 * (incl. OP_NOP).
837 */
838 if (contentIsInsn(codePtr)) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700839 findBlock(cUnit.get(), curOffset + width,
buzbee67bf8852011-08-17 17:51:35 -0700840 /* split */
841 false,
842 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800843 true,
844 /* immedPredBlockP */
845 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700846 }
847 }
848 } else if (flags & kInstrCanThrow) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700849 processCanThrow(cUnit.get(), curBlock, insn, curOffset, width, flags,
buzbee67bf8852011-08-17 17:51:35 -0700850 tryBlockAddr, codePtr, codeEnd);
851 } else if (flags & kInstrCanSwitch) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700852 processCanSwitch(cUnit.get(), curBlock, insn, curOffset, width, flags);
buzbee67bf8852011-08-17 17:51:35 -0700853 }
854 curOffset += width;
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700855 BasicBlock *nextBlock = findBlock(cUnit.get(), curOffset,
buzbee67bf8852011-08-17 17:51:35 -0700856 /* split */
857 false,
858 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800859 false,
860 /* immedPredBlockP */
861 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700862 if (nextBlock) {
863 /*
864 * The next instruction could be the target of a previously parsed
865 * forward branch so a block is already created. If the current
866 * instruction is not an unconditional branch, connect them through
867 * the fall-through link.
868 */
buzbeeed3e9302011-09-23 17:34:19 -0700869 DCHECK(curBlock->fallThrough == NULL ||
buzbee67bf8852011-08-17 17:51:35 -0700870 curBlock->fallThrough == nextBlock ||
871 curBlock->fallThrough == exitBlock);
872
873 if ((curBlock->fallThrough == NULL) &&
874 (flags & kInstrCanContinue)) {
875 curBlock->fallThrough = nextBlock;
876 oatSetBit(nextBlock->predecessors, curBlock->id);
877 }
878 curBlock = nextBlock;
879 }
880 }
881
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700882 if (cUnit->printMe) {
883 oatDumpCompilationUnit(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700884 }
885
buzbee67bf8852011-08-17 17:51:35 -0700886 /* Verify if all blocks are connected as claimed */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700887 oatDataFlowAnalysisDispatcher(cUnit.get(), verifyPredInfo, kAllNodes, false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700888
889 /* Perform SSA transformation for the whole method */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700890 oatMethodSSATransformation(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700891
buzbee43a36422011-09-14 14:00:13 -0700892 /* Perform null check elimination */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700893 oatMethodNullCheckElimination(cUnit.get());
buzbee43a36422011-09-14 14:00:13 -0700894
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700895 oatInitializeRegAlloc(cUnit.get()); // Needs to happen after SSA naming
buzbee67bf8852011-08-17 17:51:35 -0700896
897 /* Allocate Registers using simple local allocation scheme */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700898 oatSimpleRegAlloc(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700899
900 /* Convert MIR to LIR, etc. */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700901 oatMethodMIR2LIR(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700902
903 // Debugging only
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700904 if (cUnit->enableDebug & (1 << kDebugDumpCFG)) {
905 oatDumpCFG(cUnit.get(), "/sdcard/cfg/");
buzbeeec5adf32011-09-11 15:25:43 -0700906 }
buzbee67bf8852011-08-17 17:51:35 -0700907
908 /* Method is not empty */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700909 if (cUnit->firstLIRInsn) {
buzbee67bf8852011-08-17 17:51:35 -0700910
911 // mark the targets of switch statement case labels
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700912 oatProcessSwitchTables(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700913
914 /* Convert LIR into machine code. */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700915 oatAssembleLIR(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700916
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700917 if (cUnit->printMe) {
918 oatCodegenDump(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700919 }
920 }
921
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700922 // Combine vmap tables - core regs, then fp regs - into vmapTable
923 std::vector<uint16_t> vmapTable;
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700924 for (size_t i = 0 ; i < cUnit->coreVmapTable.size(); i++) {
925 vmapTable.push_back(cUnit->coreVmapTable[i]);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700926 }
buzbeec41e5b52011-09-23 12:46:19 -0700927 // Add a marker to take place of lr
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700928 vmapTable.push_back(INVALID_VREG);
buzbeec41e5b52011-09-23 12:46:19 -0700929 // Combine vmap tables - core regs, then fp regs
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700930 for (uint32_t i = 0; i < cUnit->fpVmapTable.size(); i++) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700931 vmapTable.push_back(cUnit->fpVmapTable[i]);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700932 }
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700933 DCHECK_EQ(vmapTable.size(),
934 static_cast<uint32_t>(__builtin_popcount(cUnit->coreSpillMask)
935 + __builtin_popcount(cUnit->fpSpillMask)));
936 DCHECK_GE(vmapTable.size(), 1U); // should always at least one INVALID_VREG for lr
937
Ian Rogers0571d352011-11-03 19:51:38 -0700938 CompiledMethod* result = new CompiledMethod(art::kThumb2, cUnit->codeBuffer,
939 cUnit->frameSize, cUnit->coreSpillMask,
940 cUnit->fpSpillMask, cUnit->mappingTable,
941 vmapTable);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700942
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800943 VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file)
944 << " (" << (cUnit->codeBuffer.size() * sizeof(cUnit->codeBuffer[0])) << " bytes)";
buzbee67bf8852011-08-17 17:51:35 -0700945
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700946 return result;
buzbee67bf8852011-08-17 17:51:35 -0700947}
948
Brian Carlstrom16192862011-09-12 17:50:06 -0700949void oatInit(const Compiler& compiler)
buzbee67bf8852011-08-17 17:51:35 -0700950{
buzbee67bf8852011-08-17 17:51:35 -0700951 static bool initialized = false;
952 if (initialized)
953 return;
954 initialized = true;
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800955 VLOG(compiler) << "Initializing compiler";
buzbee67bf8852011-08-17 17:51:35 -0700956 if (!oatArchInit()) {
957 LOG(FATAL) << "Failed to initialize oat";
958 }
959 if (!oatHeapInit()) {
960 LOG(FATAL) << "Failed to initialize oat heap";
961 }
962}