blob: 8070e6f5b2393d3c82bd3368b5a298022487f424 [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) |
buzbeece302932011-10-04 14:32:18 -070047 0;
48
49std::string compilerMethodMatch; // Method name match to apply above flags
50
51bool compilerFlipMatch = false; // Reverses sense of method name match
52
buzbeeed3e9302011-09-23 17:34:19 -070053STATIC inline bool contentIsInsn(const u2* codePtr) {
buzbee67bf8852011-08-17 17:51:35 -070054 u2 instr = *codePtr;
55 Opcode opcode = (Opcode)(instr & 0xff);
56
57 /*
58 * Since the low 8-bit in metadata may look like OP_NOP, we need to check
59 * both the low and whole sub-word to determine whether it is code or data.
60 */
61 return (opcode != OP_NOP || instr == 0);
62}
63
64/*
65 * Parse an instruction, return the length of the instruction
66 */
buzbeeed3e9302011-09-23 17:34:19 -070067STATIC inline int parseInsn(const u2* codePtr, DecodedInstruction* decInsn,
buzbee67bf8852011-08-17 17:51:35 -070068 bool printMe)
69{
70 // Don't parse instruction data
71 if (!contentIsInsn(codePtr)) {
72 return 0;
73 }
74
75 u2 instr = *codePtr;
76 Opcode opcode = dexOpcodeFromCodeUnit(instr);
77
78 dexDecodeInstruction(codePtr, decInsn);
79 if (printMe) {
Elliott Hughesc1f143d2011-12-01 17:31:10 -080080 char* decodedString = oatGetDalvikDisassembly(decInsn, NULL);
buzbee67bf8852011-08-17 17:51:35 -070081 LOG(INFO) << codePtr << ": 0x" << std::hex << (int)opcode <<
82 " " << decodedString;
83 }
84 return dexGetWidthFromOpcode(opcode);
85}
86
87#define UNKNOWN_TARGET 0xffffffff
88
buzbeeed3e9302011-09-23 17:34:19 -070089STATIC inline bool isGoto(MIR* insn)
buzbee67bf8852011-08-17 17:51:35 -070090{
91 switch (insn->dalvikInsn.opcode) {
92 case OP_GOTO:
93 case OP_GOTO_16:
94 case OP_GOTO_32:
95 return true;
96 default:
97 return false;
98 }
99}
100
101/*
102 * Identify unconditional branch instructions
103 */
buzbeeed3e9302011-09-23 17:34:19 -0700104STATIC inline bool isUnconditionalBranch(MIR* insn)
buzbee67bf8852011-08-17 17:51:35 -0700105{
106 switch (insn->dalvikInsn.opcode) {
107 case OP_RETURN_VOID:
108 case OP_RETURN:
109 case OP_RETURN_WIDE:
110 case OP_RETURN_OBJECT:
111 return true;
112 default:
113 return isGoto(insn);
114 }
115}
116
117/* Split an existing block from the specified code offset into two */
buzbeeed3e9302011-09-23 17:34:19 -0700118STATIC BasicBlock *splitBlock(CompilationUnit* cUnit,
buzbee67bf8852011-08-17 17:51:35 -0700119 unsigned int codeOffset,
buzbee9ab05de2012-01-18 15:43:48 -0800120 BasicBlock* origBlock,
121 BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700122{
123 MIR* insn = origBlock->firstMIRInsn;
124 while (insn) {
125 if (insn->offset == codeOffset) break;
126 insn = insn->next;
127 }
128 if (insn == NULL) {
129 LOG(FATAL) << "Break split failed";
130 }
131 BasicBlock *bottomBlock = oatNewBB(kDalvikByteCode,
132 cUnit->numBlocks++);
133 oatInsertGrowableList(&cUnit->blockList, (intptr_t) bottomBlock);
134
135 bottomBlock->startOffset = codeOffset;
136 bottomBlock->firstMIRInsn = insn;
137 bottomBlock->lastMIRInsn = origBlock->lastMIRInsn;
138
139 /* Handle the taken path */
140 bottomBlock->taken = origBlock->taken;
141 if (bottomBlock->taken) {
142 origBlock->taken = NULL;
143 oatClearBit(bottomBlock->taken->predecessors, origBlock->id);
144 oatSetBit(bottomBlock->taken->predecessors, bottomBlock->id);
145 }
146
147 /* Handle the fallthrough path */
148 bottomBlock->needFallThroughBranch = origBlock->needFallThroughBranch;
149 bottomBlock->fallThrough = origBlock->fallThrough;
150 origBlock->fallThrough = bottomBlock;
151 origBlock->needFallThroughBranch = true;
152 oatSetBit(bottomBlock->predecessors, origBlock->id);
153 if (bottomBlock->fallThrough) {
154 oatClearBit(bottomBlock->fallThrough->predecessors,
155 origBlock->id);
156 oatSetBit(bottomBlock->fallThrough->predecessors,
157 bottomBlock->id);
158 }
159
160 /* Handle the successor list */
161 if (origBlock->successorBlockList.blockListType != kNotUsed) {
162 bottomBlock->successorBlockList = origBlock->successorBlockList;
163 origBlock->successorBlockList.blockListType = kNotUsed;
164 GrowableListIterator iterator;
165
166 oatGrowableListIteratorInit(&bottomBlock->successorBlockList.blocks,
167 &iterator);
168 while (true) {
169 SuccessorBlockInfo *successorBlockInfo =
170 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
171 if (successorBlockInfo == NULL) break;
172 BasicBlock *bb = successorBlockInfo->block;
173 oatClearBit(bb->predecessors, origBlock->id);
174 oatSetBit(bb->predecessors, bottomBlock->id);
175 }
176 }
177
178 origBlock->lastMIRInsn = insn->prev;
179
180 insn->prev->next = NULL;
181 insn->prev = NULL;
buzbee9ab05de2012-01-18 15:43:48 -0800182 /*
183 * Update the immediate predecessor block pointer so that outgoing edges
184 * can be applied to the proper block.
185 */
186 if (immedPredBlockP) {
187 DCHECK_EQ(*immedPredBlockP, origBlock);
188 *immedPredBlockP = bottomBlock;
189 }
buzbee67bf8852011-08-17 17:51:35 -0700190 return bottomBlock;
191}
192
193/*
194 * Given a code offset, find out the block that starts with it. If the offset
buzbee9ab05de2012-01-18 15:43:48 -0800195 * is in the middle of an existing block, split it into two. If immedPredBlockP
196 * is not non-null and is the block being split, update *immedPredBlockP to
197 * point to the bottom block so that outgoing edges can be set up properly
198 * (by the caller)
buzbee67bf8852011-08-17 17:51:35 -0700199 */
buzbeeed3e9302011-09-23 17:34:19 -0700200STATIC BasicBlock *findBlock(CompilationUnit* cUnit,
buzbee67bf8852011-08-17 17:51:35 -0700201 unsigned int codeOffset,
buzbee9ab05de2012-01-18 15:43:48 -0800202 bool split, bool create,
203 BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700204{
205 GrowableList* blockList = &cUnit->blockList;
206 BasicBlock* bb;
207 unsigned int i;
208
209 for (i = 0; i < blockList->numUsed; i++) {
210 bb = (BasicBlock *) blockList->elemList[i];
211 if (bb->blockType != kDalvikByteCode) continue;
212 if (bb->startOffset == codeOffset) return bb;
213 /* Check if a branch jumps into the middle of an existing block */
214 if ((split == true) && (codeOffset > bb->startOffset) &&
215 (bb->lastMIRInsn != NULL) &&
216 (codeOffset <= bb->lastMIRInsn->offset)) {
buzbee9ab05de2012-01-18 15:43:48 -0800217 BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb,
218 bb == *immedPredBlockP ?
219 immedPredBlockP : NULL);
buzbee67bf8852011-08-17 17:51:35 -0700220 return newBB;
221 }
222 }
223 if (create) {
224 bb = oatNewBB(kDalvikByteCode, cUnit->numBlocks++);
225 oatInsertGrowableList(&cUnit->blockList, (intptr_t) bb);
226 bb->startOffset = codeOffset;
227 return bb;
228 }
229 return NULL;
230}
231
232/* Dump the CFG into a DOT graph */
233void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix)
234{
buzbee67bf8852011-08-17 17:51:35 -0700235 FILE* file;
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800236 std::string name(PrettyMethod(cUnit->method_idx, *cUnit->dex_file));
buzbee67bf8852011-08-17 17:51:35 -0700237 char startOffset[80];
238 sprintf(startOffset, "_%x", cUnit->entryBlock->fallThrough->startOffset);
Elliott Hughesc1f143d2011-12-01 17:31:10 -0800239 char* fileName = (char*) oatNew(
buzbeec143c552011-08-20 17:38:58 -0700240 strlen(dirPrefix) +
241 name.length() +
242 strlen(".dot") + 1, true);
243 sprintf(fileName, "%s%s%s.dot", dirPrefix, name.c_str(), startOffset);
buzbee67bf8852011-08-17 17:51:35 -0700244
245 /*
246 * Convert the special characters into a filesystem- and shell-friendly
247 * format.
248 */
249 int i;
250 for (i = strlen(dirPrefix); fileName[i]; i++) {
251 if (fileName[i] == '/') {
252 fileName[i] = '_';
253 } else if (fileName[i] == ';') {
254 fileName[i] = '#';
255 } else if (fileName[i] == '$') {
256 fileName[i] = '+';
257 } else if (fileName[i] == '(' || fileName[i] == ')') {
258 fileName[i] = '@';
259 } else if (fileName[i] == '<' || fileName[i] == '>') {
260 fileName[i] = '=';
261 }
262 }
263 file = fopen(fileName, "w");
264 if (file == NULL) {
265 return;
266 }
267 fprintf(file, "digraph G {\n");
268
269 fprintf(file, " rankdir=TB\n");
270
271 int numReachableBlocks = cUnit->numReachableBlocks;
272 int idx;
273 const GrowableList *blockList = &cUnit->blockList;
274
275 for (idx = 0; idx < numReachableBlocks; idx++) {
276 int blockIdx = cUnit->dfsOrder.elemList[idx];
277 BasicBlock *bb = (BasicBlock *) oatGrowableListGetElement(blockList,
278 blockIdx);
279 if (bb == NULL) break;
280 if (bb->blockType == kEntryBlock) {
281 fprintf(file, " entry [shape=Mdiamond];\n");
282 } else if (bb->blockType == kExitBlock) {
283 fprintf(file, " exit [shape=Mdiamond];\n");
284 } else if (bb->blockType == kDalvikByteCode) {
285 fprintf(file, " block%04x [shape=record,label = \"{ \\\n",
286 bb->startOffset);
287 const MIR *mir;
288 fprintf(file, " {block id %d\\l}%s\\\n", bb->id,
289 bb->firstMIRInsn ? " | " : " ");
290 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
291 fprintf(file, " {%04x %s\\l}%s\\\n", mir->offset,
292 mir->ssaRep ?
293 oatFullDisassembler(cUnit, mir) :
294 dexGetOpcodeName(mir->dalvikInsn.opcode),
295 mir->next ? " | " : " ");
296 }
297 fprintf(file, " }\"];\n\n");
298 } else if (bb->blockType == kExceptionHandling) {
299 char blockName[BLOCK_NAME_LEN];
300
301 oatGetBlockName(bb, blockName);
302 fprintf(file, " %s [shape=invhouse];\n", blockName);
303 }
304
305 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
306
307 if (bb->taken) {
308 oatGetBlockName(bb, blockName1);
309 oatGetBlockName(bb->taken, blockName2);
310 fprintf(file, " %s:s -> %s:n [style=dotted]\n",
311 blockName1, blockName2);
312 }
313 if (bb->fallThrough) {
314 oatGetBlockName(bb, blockName1);
315 oatGetBlockName(bb->fallThrough, blockName2);
316 fprintf(file, " %s:s -> %s:n\n", blockName1, blockName2);
317 }
318
319 if (bb->successorBlockList.blockListType != kNotUsed) {
320 fprintf(file, " succ%04x [shape=%s,label = \"{ \\\n",
321 bb->startOffset,
322 (bb->successorBlockList.blockListType == kCatch) ?
323 "Mrecord" : "record");
324 GrowableListIterator iterator;
325 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
326 &iterator);
327 SuccessorBlockInfo *successorBlockInfo =
328 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
329
330 int succId = 0;
331 while (true) {
332 if (successorBlockInfo == NULL) break;
333
334 BasicBlock *destBlock = successorBlockInfo->block;
335 SuccessorBlockInfo *nextSuccessorBlockInfo =
336 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
337
338 fprintf(file, " {<f%d> %04x: %04x\\l}%s\\\n",
339 succId++,
340 successorBlockInfo->key,
341 destBlock->startOffset,
342 (nextSuccessorBlockInfo != NULL) ? " | " : " ");
343
344 successorBlockInfo = nextSuccessorBlockInfo;
345 }
346 fprintf(file, " }\"];\n\n");
347
348 oatGetBlockName(bb, blockName1);
349 fprintf(file, " %s:s -> succ%04x:n [style=dashed]\n",
350 blockName1, bb->startOffset);
351
352 if (bb->successorBlockList.blockListType == kPackedSwitch ||
353 bb->successorBlockList.blockListType == kSparseSwitch) {
354
355 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
356 &iterator);
357
358 succId = 0;
359 while (true) {
360 SuccessorBlockInfo *successorBlockInfo =
361 (SuccessorBlockInfo *)
362 oatGrowableListIteratorNext(&iterator);
363 if (successorBlockInfo == NULL) break;
364
365 BasicBlock *destBlock = successorBlockInfo->block;
366
367 oatGetBlockName(destBlock, blockName2);
368 fprintf(file, " succ%04x:f%d:e -> %s:n\n",
369 bb->startOffset, succId++,
370 blockName2);
371 }
372 }
373 }
374 fprintf(file, "\n");
375
buzbeece302932011-10-04 14:32:18 -0700376 /* Display the dominator tree */
buzbee67bf8852011-08-17 17:51:35 -0700377 oatGetBlockName(bb, blockName1);
378 fprintf(file, " cfg%s [label=\"%s\", shape=none];\n",
379 blockName1, blockName1);
380 if (bb->iDom) {
381 oatGetBlockName(bb->iDom, blockName2);
382 fprintf(file, " cfg%s:s -> cfg%s:n\n\n",
383 blockName2, blockName1);
384 }
buzbee67bf8852011-08-17 17:51:35 -0700385 }
386 fprintf(file, "}\n");
387 fclose(file);
388}
389
390/* Verify if all the successor is connected with all the claimed predecessors */
buzbeeed3e9302011-09-23 17:34:19 -0700391STATIC bool verifyPredInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700392{
393 ArenaBitVectorIterator bvIterator;
394
395 oatBitVectorIteratorInit(bb->predecessors, &bvIterator);
396 while (true) {
397 int blockIdx = oatBitVectorIteratorNext(&bvIterator);
398 if (blockIdx == -1) break;
399 BasicBlock *predBB = (BasicBlock *)
400 oatGrowableListGetElement(&cUnit->blockList, blockIdx);
401 bool found = false;
402 if (predBB->taken == bb) {
403 found = true;
404 } else if (predBB->fallThrough == bb) {
405 found = true;
406 } else if (predBB->successorBlockList.blockListType != kNotUsed) {
407 GrowableListIterator iterator;
408 oatGrowableListIteratorInit(&predBB->successorBlockList.blocks,
409 &iterator);
410 while (true) {
411 SuccessorBlockInfo *successorBlockInfo =
412 (SuccessorBlockInfo *)
413 oatGrowableListIteratorNext(&iterator);
414 if (successorBlockInfo == NULL) break;
415 BasicBlock *succBB = successorBlockInfo->block;
416 if (succBB == bb) {
417 found = true;
418 break;
419 }
420 }
421 }
422 if (found == false) {
423 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
424 oatGetBlockName(bb, blockName1);
425 oatGetBlockName(predBB, blockName2);
426 oatDumpCFG(cUnit, "/sdcard/cfg/");
427 LOG(FATAL) << "Successor " << blockName1 << "not found from "
428 << blockName2;
429 }
430 }
431 return true;
432}
433
434/* Identify code range in try blocks and set up the empty catch blocks */
buzbeeed3e9302011-09-23 17:34:19 -0700435STATIC void processTryCatchBlocks(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700436{
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800437 const DexFile::CodeItem* code_item = cUnit->code_item;
buzbeee9a72f62011-09-04 17:59:07 -0700438 int triesSize = code_item->tries_size_;
buzbee67bf8852011-08-17 17:51:35 -0700439 int offset;
440
441 if (triesSize == 0) {
442 return;
443 }
444
buzbee67bf8852011-08-17 17:51:35 -0700445 ArenaBitVector* tryBlockAddr = cUnit->tryBlockAddr;
446
buzbeee9a72f62011-09-04 17:59:07 -0700447 for (int i = 0; i < triesSize; i++) {
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800448 const DexFile::TryItem* pTry =
449 DexFile::GetTryItems(*code_item, i);
buzbeee9a72f62011-09-04 17:59:07 -0700450 int startOffset = pTry->start_addr_;
451 int endOffset = startOffset + pTry->insn_count_;
buzbee67bf8852011-08-17 17:51:35 -0700452 for (offset = startOffset; offset < endOffset; offset++) {
453 oatSetBit(tryBlockAddr, offset);
454 }
455 }
456
buzbeee9a72f62011-09-04 17:59:07 -0700457 // Iterate over each of the handlers to enqueue the empty Catch blocks
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800458 const byte* handlers_ptr =
459 DexFile::GetCatchHandlerData(*code_item, 0);
460 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
buzbeee9a72f62011-09-04 17:59:07 -0700461 for (uint32_t idx = 0; idx < handlers_size; idx++) {
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800462 CatchHandlerIterator iterator(handlers_ptr);
Ian Rogers0571d352011-11-03 19:51:38 -0700463 for (; iterator.HasNext(); iterator.Next()) {
464 uint32_t address = iterator.GetHandlerAddress();
buzbee9ab05de2012-01-18 15:43:48 -0800465 findBlock(cUnit, address, false /* split */, true /*create*/,
466 /* immedPredBlockP */ NULL);
buzbee67bf8852011-08-17 17:51:35 -0700467 }
Ian Rogers0571d352011-11-03 19:51:38 -0700468 handlers_ptr = iterator.EndDataPointer();
buzbee67bf8852011-08-17 17:51:35 -0700469 }
470}
471
472/* Process instructions with the kInstrCanBranch flag */
buzbeee941e2c2011-12-05 12:38:17 -0800473STATIC BasicBlock* processCanBranch(CompilationUnit* cUnit,
474 BasicBlock* curBlock, MIR* insn,
475 int curOffset, int width, int flags,
476 const u2* codePtr, const u2* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700477{
478 int target = curOffset;
479 switch (insn->dalvikInsn.opcode) {
480 case OP_GOTO:
481 case OP_GOTO_16:
482 case OP_GOTO_32:
483 target += (int) insn->dalvikInsn.vA;
484 break;
485 case OP_IF_EQ:
486 case OP_IF_NE:
487 case OP_IF_LT:
488 case OP_IF_GE:
489 case OP_IF_GT:
490 case OP_IF_LE:
491 target += (int) insn->dalvikInsn.vC;
492 break;
493 case OP_IF_EQZ:
494 case OP_IF_NEZ:
495 case OP_IF_LTZ:
496 case OP_IF_GEZ:
497 case OP_IF_GTZ:
498 case OP_IF_LEZ:
499 target += (int) insn->dalvikInsn.vB;
500 break;
501 default:
502 LOG(FATAL) << "Unexpected opcode(" << (int)insn->dalvikInsn.opcode
503 << ") with kInstrCanBranch set";
504 }
505 BasicBlock *takenBlock = findBlock(cUnit, target,
506 /* split */
507 true,
508 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800509 true,
510 /* immedPredBlockP */
511 &curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700512 curBlock->taken = takenBlock;
513 oatSetBit(takenBlock->predecessors, curBlock->id);
514
515 /* Always terminate the current block for conditional branches */
516 if (flags & kInstrCanContinue) {
517 BasicBlock *fallthroughBlock = findBlock(cUnit,
518 curOffset + width,
519 /*
520 * If the method is processed
521 * in sequential order from the
522 * beginning, we don't need to
523 * specify split for continue
524 * blocks. However, this
525 * routine can be called by
526 * compileLoop, which starts
527 * parsing the method from an
528 * arbitrary address in the
529 * method body.
530 */
531 true,
532 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800533 true,
534 /* immedPredBlockP */
535 &curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700536 curBlock->fallThrough = fallthroughBlock;
537 oatSetBit(fallthroughBlock->predecessors, curBlock->id);
538 } else if (codePtr < codeEnd) {
539 /* Create a fallthrough block for real instructions (incl. OP_NOP) */
540 if (contentIsInsn(codePtr)) {
541 findBlock(cUnit, curOffset + width,
542 /* split */
543 false,
544 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800545 true,
546 /* immedPredBlockP */
547 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700548 }
549 }
buzbeee941e2c2011-12-05 12:38:17 -0800550 return curBlock;
buzbee67bf8852011-08-17 17:51:35 -0700551}
552
553/* Process instructions with the kInstrCanSwitch flag */
buzbeeed3e9302011-09-23 17:34:19 -0700554STATIC void processCanSwitch(CompilationUnit* cUnit, BasicBlock* curBlock,
buzbee67bf8852011-08-17 17:51:35 -0700555 MIR* insn, int curOffset, int width, int flags)
556{
557 u2* switchData= (u2 *) (cUnit->insns + curOffset +
558 insn->dalvikInsn.vB);
559 int size;
560 int* keyTable;
561 int* targetTable;
562 int i;
563 int firstKey;
564
565 /*
566 * Packed switch data format:
567 * ushort ident = 0x0100 magic value
568 * ushort size number of entries in the table
569 * int first_key first (and lowest) switch case value
570 * int targets[size] branch targets, relative to switch opcode
571 *
572 * Total size is (4+size*2) 16-bit code units.
573 */
574 if (insn->dalvikInsn.opcode == OP_PACKED_SWITCH) {
buzbeeed3e9302011-09-23 17:34:19 -0700575 DCHECK_EQ(switchData[0], kPackedSwitchSignature);
buzbee67bf8852011-08-17 17:51:35 -0700576 size = switchData[1];
577 firstKey = switchData[2] | (switchData[3] << 16);
578 targetTable = (int *) &switchData[4];
579 keyTable = NULL; // Make the compiler happy
580 /*
581 * Sparse switch data format:
582 * ushort ident = 0x0200 magic value
583 * ushort size number of entries in the table; > 0
584 * int keys[size] keys, sorted low-to-high; 32-bit aligned
585 * int targets[size] branch targets, relative to switch opcode
586 *
587 * Total size is (2+size*4) 16-bit code units.
588 */
589 } else {
buzbeeed3e9302011-09-23 17:34:19 -0700590 DCHECK_EQ(switchData[0], kSparseSwitchSignature);
buzbee67bf8852011-08-17 17:51:35 -0700591 size = switchData[1];
592 keyTable = (int *) &switchData[2];
593 targetTable = (int *) &switchData[2 + size*2];
594 firstKey = 0; // To make the compiler happy
595 }
596
597 if (curBlock->successorBlockList.blockListType != kNotUsed) {
598 LOG(FATAL) << "Successor block list already in use: " <<
599 (int)curBlock->successorBlockList.blockListType;
600 }
601 curBlock->successorBlockList.blockListType =
602 (insn->dalvikInsn.opcode == OP_PACKED_SWITCH) ?
603 kPackedSwitch : kSparseSwitch;
604 oatInitGrowableList(&curBlock->successorBlockList.blocks, size);
605
606 for (i = 0; i < size; i++) {
607 BasicBlock *caseBlock = findBlock(cUnit, curOffset + targetTable[i],
608 /* split */
609 true,
610 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800611 true,
612 /* immedPredBlockP */
613 &curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700614 SuccessorBlockInfo *successorBlockInfo =
615 (SuccessorBlockInfo *) oatNew(sizeof(SuccessorBlockInfo),
616 false);
617 successorBlockInfo->block = caseBlock;
618 successorBlockInfo->key = (insn->dalvikInsn.opcode == OP_PACKED_SWITCH)?
619 firstKey + i : keyTable[i];
620 oatInsertGrowableList(&curBlock->successorBlockList.blocks,
621 (intptr_t) successorBlockInfo);
622 oatSetBit(caseBlock->predecessors, curBlock->id);
623 }
624
625 /* Fall-through case */
626 BasicBlock* fallthroughBlock = findBlock(cUnit,
627 curOffset + width,
628 /* split */
629 false,
630 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800631 true,
632 /* immedPredBlockP */
633 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700634 curBlock->fallThrough = fallthroughBlock;
635 oatSetBit(fallthroughBlock->predecessors, curBlock->id);
636}
637
638/* Process instructions with the kInstrCanThrow flag */
buzbeeed3e9302011-09-23 17:34:19 -0700639STATIC void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock,
buzbee67bf8852011-08-17 17:51:35 -0700640 MIR* insn, int curOffset, int width, int flags,
641 ArenaBitVector* tryBlockAddr, const u2* codePtr,
642 const u2* codeEnd)
643{
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800644 const DexFile::CodeItem* code_item = cUnit->code_item;
buzbee67bf8852011-08-17 17:51:35 -0700645
646 /* In try block */
647 if (oatIsBitSet(tryBlockAddr, curOffset)) {
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800648 CatchHandlerIterator iterator(*code_item, curOffset);
buzbee67bf8852011-08-17 17:51:35 -0700649
buzbee67bf8852011-08-17 17:51:35 -0700650 if (curBlock->successorBlockList.blockListType != kNotUsed) {
651 LOG(FATAL) << "Successor block list already in use: " <<
652 (int)curBlock->successorBlockList.blockListType;
653 }
buzbeee9a72f62011-09-04 17:59:07 -0700654
buzbee67bf8852011-08-17 17:51:35 -0700655 curBlock->successorBlockList.blockListType = kCatch;
656 oatInitGrowableList(&curBlock->successorBlockList.blocks, 2);
657
Ian Rogers0571d352011-11-03 19:51:38 -0700658 for (;iterator.HasNext(); iterator.Next()) {
659 BasicBlock *catchBlock = findBlock(cUnit, iterator.GetHandlerAddress(),
buzbeee9a72f62011-09-04 17:59:07 -0700660 false /* split*/,
buzbee9ab05de2012-01-18 15:43:48 -0800661 false /* creat */,
662 NULL /* immedPredBlockP */);
buzbee43a36422011-09-14 14:00:13 -0700663 catchBlock->catchEntry = true;
buzbee67bf8852011-08-17 17:51:35 -0700664 SuccessorBlockInfo *successorBlockInfo =
buzbeee9a72f62011-09-04 17:59:07 -0700665 (SuccessorBlockInfo *) oatNew(sizeof(SuccessorBlockInfo),
666 false);
buzbee67bf8852011-08-17 17:51:35 -0700667 successorBlockInfo->block = catchBlock;
Ian Rogers0571d352011-11-03 19:51:38 -0700668 successorBlockInfo->key = iterator.GetHandlerTypeIndex();
buzbee67bf8852011-08-17 17:51:35 -0700669 oatInsertGrowableList(&curBlock->successorBlockList.blocks,
670 (intptr_t) successorBlockInfo);
671 oatSetBit(catchBlock->predecessors, curBlock->id);
672 }
673 } else {
674 BasicBlock *ehBlock = oatNewBB(kExceptionHandling,
675 cUnit->numBlocks++);
676 curBlock->taken = ehBlock;
677 oatInsertGrowableList(&cUnit->blockList, (intptr_t) ehBlock);
678 ehBlock->startOffset = curOffset;
679 oatSetBit(ehBlock->predecessors, curBlock->id);
680 }
681
682 /*
683 * Force the current block to terminate.
684 *
685 * Data may be present before codeEnd, so we need to parse it to know
686 * whether it is code or data.
687 */
688 if (codePtr < codeEnd) {
689 /* Create a fallthrough block for real instructions (incl. OP_NOP) */
690 if (contentIsInsn(codePtr)) {
691 BasicBlock *fallthroughBlock = findBlock(cUnit,
692 curOffset + width,
693 /* split */
694 false,
695 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800696 true,
697 /* immedPredBlockP */
698 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700699 /*
buzbee510c6052011-10-27 10:47:20 -0700700 * OP_THROW is an unconditional branch. NOTE:
701 * OP_THROW_VERIFICATION_ERROR is also an unconditional
702 * branch, but we shouldn't treat it as such until we have
703 * a dead code elimination pass (which won't be important
704 * until inlining w/ constant propogation is implemented.
buzbee67bf8852011-08-17 17:51:35 -0700705 */
buzbee510c6052011-10-27 10:47:20 -0700706 if (insn->dalvikInsn.opcode != OP_THROW) {
buzbee67bf8852011-08-17 17:51:35 -0700707 curBlock->fallThrough = fallthroughBlock;
708 oatSetBit(fallthroughBlock->predecessors, curBlock->id);
709 }
710 }
711 }
712}
713
714/*
715 * Compile a method.
716 */
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800717CompiledMethod* oatCompileMethod(const Compiler& compiler, const DexFile::CodeItem* code_item,
Ian Rogersa3760aa2011-11-14 14:32:37 -0800718 uint32_t access_flags, uint32_t method_idx,
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800719 const ClassLoader* class_loader,
720 const DexFile& dex_file, InstructionSet insnSet)
buzbee67bf8852011-08-17 17:51:35 -0700721{
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800722 VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
buzbee2a475e72011-09-07 17:19:17 -0700723 oatArenaReset();
Brian Carlstrom94496d32011-08-22 09:22:47 -0700724
buzbeec143c552011-08-20 17:38:58 -0700725 const u2* codePtr = code_item->insns_;
Ian Rogersd81871c2011-10-03 13:57:23 -0700726 const u2* codeEnd = code_item->insns_ + code_item->insns_size_in_code_units_;
buzbee67bf8852011-08-17 17:51:35 -0700727 int numBlocks = 0;
728 unsigned int curOffset = 0;
729
Brian Carlstrom16192862011-09-12 17:50:06 -0700730 oatInit(compiler);
buzbee67bf8852011-08-17 17:51:35 -0700731
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800732 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700733 UniquePtr<CompilationUnit> cUnit(new CompilationUnit);
734 memset(cUnit.get(), 0, sizeof(*cUnit));
735 cUnit->compiler = &compiler;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800736 cUnit->class_linker = class_linker;
737 cUnit->dex_file = &dex_file;
738 cUnit->dex_cache = class_linker->FindDexCache(dex_file);
739 cUnit->method_idx = method_idx;
740 cUnit->code_item = code_item;
741 cUnit->access_flags = access_flags;
742 cUnit->shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700743 cUnit->instructionSet = (OatInstructionSetType)insnSet;
744 cUnit->insns = code_item->insns_;
Ian Rogersd81871c2011-10-03 13:57:23 -0700745 cUnit->insnsSize = code_item->insns_size_in_code_units_;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800746 cUnit->numIns = code_item->ins_size_;
747 cUnit->numRegs = code_item->registers_size_ - cUnit->numIns;
748 cUnit->numOuts = code_item->outs_size_;
749 /* Adjust this value accordingly once inlining is performed */
750 cUnit->numDalvikRegisters = code_item->registers_size_;
buzbeece302932011-10-04 14:32:18 -0700751 bool useMatch = compilerMethodMatch.length() != 0;
752 bool match = useMatch && (compilerFlipMatch ^
Ian Rogersa3760aa2011-11-14 14:32:37 -0800753 (PrettyMethod(method_idx, dex_file).find(compilerMethodMatch) != std::string::npos));
buzbeece302932011-10-04 14:32:18 -0700754 if (!useMatch || match) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700755 cUnit->disableOpt = compilerOptimizerDisableFlags;
756 cUnit->enableDebug = compilerDebugFlags;
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800757 cUnit->printMe = VLOG_IS_ON(compiler) || (cUnit->enableDebug & (1 << kDebugVerbose));
buzbeece302932011-10-04 14:32:18 -0700758 }
buzbee67bf8852011-08-17 17:51:35 -0700759
buzbeecefd1872011-09-09 09:59:52 -0700760 /* Assume non-throwing leaf */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700761 cUnit->attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE);
buzbeecefd1872011-09-09 09:59:52 -0700762
buzbee67bf8852011-08-17 17:51:35 -0700763 /* Initialize the block list */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700764 oatInitGrowableList(&cUnit->blockList, 40);
buzbee67bf8852011-08-17 17:51:35 -0700765
766 /* Initialize the switchTables list */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700767 oatInitGrowableList(&cUnit->switchTables, 4);
buzbee67bf8852011-08-17 17:51:35 -0700768
769 /* Intialize the fillArrayData list */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700770 oatInitGrowableList(&cUnit->fillArrayData, 4);
buzbee67bf8852011-08-17 17:51:35 -0700771
buzbee5ade1d22011-09-09 14:44:52 -0700772 /* Intialize the throwLaunchpads list */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700773 oatInitGrowableList(&cUnit->throwLaunchpads, 4);
buzbee5ade1d22011-09-09 14:44:52 -0700774
buzbeec1f45042011-09-21 16:03:19 -0700775 /* Intialize the suspendLaunchpads list */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700776 oatInitGrowableList(&cUnit->suspendLaunchpads, 4);
buzbeec1f45042011-09-21 16:03:19 -0700777
buzbee67bf8852011-08-17 17:51:35 -0700778 /* Allocate the bit-vector to track the beginning of basic blocks */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700779 ArenaBitVector *tryBlockAddr = oatAllocBitVector(cUnit->insnsSize,
buzbee67bf8852011-08-17 17:51:35 -0700780 true /* expandable */);
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700781 cUnit->tryBlockAddr = tryBlockAddr;
buzbee67bf8852011-08-17 17:51:35 -0700782
783 /* Create the default entry and exit blocks and enter them to the list */
784 BasicBlock *entryBlock = oatNewBB(kEntryBlock, numBlocks++);
785 BasicBlock *exitBlock = oatNewBB(kExitBlock, numBlocks++);
786
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700787 cUnit->entryBlock = entryBlock;
788 cUnit->exitBlock = exitBlock;
buzbee67bf8852011-08-17 17:51:35 -0700789
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700790 oatInsertGrowableList(&cUnit->blockList, (intptr_t) entryBlock);
791 oatInsertGrowableList(&cUnit->blockList, (intptr_t) exitBlock);
buzbee67bf8852011-08-17 17:51:35 -0700792
793 /* Current block to record parsed instructions */
794 BasicBlock *curBlock = oatNewBB(kDalvikByteCode, numBlocks++);
795 curBlock->startOffset = 0;
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700796 oatInsertGrowableList(&cUnit->blockList, (intptr_t) curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700797 entryBlock->fallThrough = curBlock;
798 oatSetBit(curBlock->predecessors, entryBlock->id);
799
800 /*
801 * Store back the number of blocks since new blocks may be created of
802 * accessing cUnit.
803 */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700804 cUnit->numBlocks = numBlocks;
buzbee67bf8852011-08-17 17:51:35 -0700805
806 /* Identify code range in try blocks and set up the empty catch blocks */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700807 processTryCatchBlocks(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700808
809 /* Parse all instructions and put them into containing basic blocks */
810 while (codePtr < codeEnd) {
811 MIR *insn = (MIR *) oatNew(sizeof(MIR), true);
812 insn->offset = curOffset;
813 int width = parseInsn(codePtr, &insn->dalvikInsn, false);
814 insn->width = width;
815
816 /* Terminate when the data section is seen */
817 if (width == 0)
818 break;
819
820 oatAppendMIR(curBlock, insn);
821
822 codePtr += width;
823 int flags = dexGetFlagsFromOpcode(insn->dalvikInsn.opcode);
824
825 if (flags & kInstrCanBranch) {
buzbeee941e2c2011-12-05 12:38:17 -0800826 curBlock = processCanBranch(cUnit.get(), curBlock, insn, curOffset,
827 width, flags, codePtr, codeEnd);
buzbee67bf8852011-08-17 17:51:35 -0700828 } else if (flags & kInstrCanReturn) {
829 curBlock->fallThrough = exitBlock;
830 oatSetBit(exitBlock->predecessors, curBlock->id);
831 /*
832 * Terminate the current block if there are instructions
833 * afterwards.
834 */
835 if (codePtr < codeEnd) {
836 /*
837 * Create a fallthrough block for real instructions
838 * (incl. OP_NOP).
839 */
840 if (contentIsInsn(codePtr)) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700841 findBlock(cUnit.get(), curOffset + width,
buzbee67bf8852011-08-17 17:51:35 -0700842 /* split */
843 false,
844 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800845 true,
846 /* immedPredBlockP */
847 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700848 }
849 }
850 } else if (flags & kInstrCanThrow) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700851 processCanThrow(cUnit.get(), curBlock, insn, curOffset, width, flags,
buzbee67bf8852011-08-17 17:51:35 -0700852 tryBlockAddr, codePtr, codeEnd);
853 } else if (flags & kInstrCanSwitch) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700854 processCanSwitch(cUnit.get(), curBlock, insn, curOffset, width, flags);
buzbee67bf8852011-08-17 17:51:35 -0700855 }
856 curOffset += width;
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700857 BasicBlock *nextBlock = findBlock(cUnit.get(), curOffset,
buzbee67bf8852011-08-17 17:51:35 -0700858 /* split */
859 false,
860 /* create */
buzbee9ab05de2012-01-18 15:43:48 -0800861 false,
862 /* immedPredBlockP */
863 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700864 if (nextBlock) {
865 /*
866 * The next instruction could be the target of a previously parsed
867 * forward branch so a block is already created. If the current
868 * instruction is not an unconditional branch, connect them through
869 * the fall-through link.
870 */
buzbeeed3e9302011-09-23 17:34:19 -0700871 DCHECK(curBlock->fallThrough == NULL ||
buzbee67bf8852011-08-17 17:51:35 -0700872 curBlock->fallThrough == nextBlock ||
873 curBlock->fallThrough == exitBlock);
874
875 if ((curBlock->fallThrough == NULL) &&
876 (flags & kInstrCanContinue)) {
877 curBlock->fallThrough = nextBlock;
878 oatSetBit(nextBlock->predecessors, curBlock->id);
879 }
880 curBlock = nextBlock;
881 }
882 }
883
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700884 if (cUnit->printMe) {
885 oatDumpCompilationUnit(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700886 }
887
buzbee67bf8852011-08-17 17:51:35 -0700888 /* Verify if all blocks are connected as claimed */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700889 oatDataFlowAnalysisDispatcher(cUnit.get(), verifyPredInfo, kAllNodes, false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700890
891 /* Perform SSA transformation for the whole method */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700892 oatMethodSSATransformation(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700893
buzbee43a36422011-09-14 14:00:13 -0700894 /* Perform null check elimination */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700895 oatMethodNullCheckElimination(cUnit.get());
buzbee43a36422011-09-14 14:00:13 -0700896
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700897 oatInitializeRegAlloc(cUnit.get()); // Needs to happen after SSA naming
buzbee67bf8852011-08-17 17:51:35 -0700898
899 /* Allocate Registers using simple local allocation scheme */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700900 oatSimpleRegAlloc(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700901
902 /* Convert MIR to LIR, etc. */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700903 oatMethodMIR2LIR(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700904
905 // Debugging only
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700906 if (cUnit->enableDebug & (1 << kDebugDumpCFG)) {
907 oatDumpCFG(cUnit.get(), "/sdcard/cfg/");
buzbeeec5adf32011-09-11 15:25:43 -0700908 }
buzbee67bf8852011-08-17 17:51:35 -0700909
910 /* Method is not empty */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700911 if (cUnit->firstLIRInsn) {
buzbee67bf8852011-08-17 17:51:35 -0700912
913 // mark the targets of switch statement case labels
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700914 oatProcessSwitchTables(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700915
916 /* Convert LIR into machine code. */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700917 oatAssembleLIR(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700918
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700919 if (cUnit->printMe) {
920 oatCodegenDump(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -0700921 }
922 }
923
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700924 // Combine vmap tables - core regs, then fp regs - into vmapTable
925 std::vector<uint16_t> vmapTable;
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700926 for (size_t i = 0 ; i < cUnit->coreVmapTable.size(); i++) {
927 vmapTable.push_back(cUnit->coreVmapTable[i]);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700928 }
buzbeec41e5b52011-09-23 12:46:19 -0700929 // Add a marker to take place of lr
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700930 vmapTable.push_back(INVALID_VREG);
buzbeec41e5b52011-09-23 12:46:19 -0700931 // Combine vmap tables - core regs, then fp regs
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700932 for (uint32_t i = 0; i < cUnit->fpVmapTable.size(); i++) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700933 vmapTable.push_back(cUnit->fpVmapTable[i]);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700934 }
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700935 DCHECK_EQ(vmapTable.size(),
936 static_cast<uint32_t>(__builtin_popcount(cUnit->coreSpillMask)
937 + __builtin_popcount(cUnit->fpSpillMask)));
938 DCHECK_GE(vmapTable.size(), 1U); // should always at least one INVALID_VREG for lr
939
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800940 CompiledMethod* result = new CompiledMethod(kThumb2, cUnit->codeBuffer,
Ian Rogers0571d352011-11-03 19:51:38 -0700941 cUnit->frameSize, cUnit->coreSpillMask,
942 cUnit->fpSpillMask, cUnit->mappingTable,
943 vmapTable);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700944
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800945 VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file)
946 << " (" << (cUnit->codeBuffer.size() * sizeof(cUnit->codeBuffer[0])) << " bytes)";
buzbee67bf8852011-08-17 17:51:35 -0700947
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700948 return result;
buzbee67bf8852011-08-17 17:51:35 -0700949}
950
Brian Carlstrom16192862011-09-12 17:50:06 -0700951void oatInit(const Compiler& compiler)
buzbee67bf8852011-08-17 17:51:35 -0700952{
buzbee67bf8852011-08-17 17:51:35 -0700953 static bool initialized = false;
954 if (initialized)
955 return;
956 initialized = true;
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800957 VLOG(compiler) << "Initializing compiler";
buzbee67bf8852011-08-17 17:51:35 -0700958 if (!oatArchInit()) {
959 LOG(FATAL) << "Failed to initialize oat";
960 }
961 if (!oatHeapInit()) {
962 LOG(FATAL) << "Failed to initialize oat heap";
963 }
964}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800965
966} // namespace art