blob: 134aaa7f32d517d2f8bf207e425b079e8161a61f [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
buzbeeeaf09bc2012-11-15 14:51:41 -080017#include "compiler.h"
buzbeeefc63692012-11-14 16:31:52 -080018#include "compiler_internals.h"
19#include "dataflow.h"
buzbeeeaf09bc2012-11-15 14:51:41 -080020#include "ssa_transformation.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"
buzbeeeaf09bc2012-11-15 14:51:41 -080024#include "codegen/codegen_util.h"
25#include "codegen/method_bitcode.h"
26#include "codegen/method_codegen_driver.h"
buzbee67bf8852011-08-17 17:51:35 -070027
buzbee4df2bbd2012-10-11 14:46:06 -070028#include <llvm/Support/Threading.h>
29
30namespace {
Shih-wei Liao215a9262012-10-12 10:29:46 -070031#if !defined(ART_USE_LLVM_COMPILER)
buzbee4df2bbd2012-10-11 14:46:06 -070032 pthread_once_t llvm_multi_init = PTHREAD_ONCE_INIT;
Shih-wei Liao215a9262012-10-12 10:29:46 -070033#endif
buzbee4df2bbd2012-10-11 14:46:06 -070034 void InitializeLLVMForQuick() {
35 llvm::llvm_start_multithreaded();
36 }
37}
buzbee4df2bbd2012-10-11 14:46:06 -070038
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080039namespace art {
40
buzbee4df2bbd2012-10-11 14:46:06 -070041LLVMInfo::LLVMInfo() {
42#if !defined(ART_USE_LLVM_COMPILER)
43 pthread_once(&llvm_multi_init, InitializeLLVMForQuick);
44#endif
buzbee692be802012-08-29 15:52:59 -070045 // Create context, module, intrinsic helper & ir builder
46 llvm_context_.reset(new llvm::LLVMContext());
TDYa12755e5e6c2012-09-11 15:14:42 -070047 llvm_module_ = new llvm::Module("art", *llvm_context_);
buzbee692be802012-08-29 15:52:59 -070048 llvm::StructType::create(*llvm_context_, "JavaObject");
buzbee692be802012-08-29 15:52:59 -070049 intrinsic_helper_.reset( new greenland::IntrinsicHelper(*llvm_context_, *llvm_module_));
50 ir_builder_.reset(new greenland::IRBuilder(*llvm_context_, *llvm_module_, *intrinsic_helper_));
51}
52
buzbee4df2bbd2012-10-11 14:46:06 -070053LLVMInfo::~LLVMInfo() {
buzbee692be802012-08-29 15:52:59 -070054}
55
56extern "C" void ArtInitQuickCompilerContext(art::Compiler& compiler) {
57 CHECK(compiler.GetCompilerContext() == NULL);
buzbee4df2bbd2012-10-11 14:46:06 -070058 LLVMInfo* llvmInfo = new LLVMInfo();
59 compiler.SetCompilerContext(llvmInfo);
buzbee692be802012-08-29 15:52:59 -070060}
61
62extern "C" void ArtUnInitQuickCompilerContext(art::Compiler& compiler) {
buzbee4df2bbd2012-10-11 14:46:06 -070063 delete reinterpret_cast<LLVMInfo*>(compiler.GetCompilerContext());
buzbee692be802012-08-29 15:52:59 -070064 compiler.SetCompilerContext(NULL);
65}
buzbee692be802012-08-29 15:52:59 -070066
buzbeece302932011-10-04 14:32:18 -070067/* Default optimizer/debug setting for the compiler. */
Elliott Hughese52e49b2012-04-02 16:05:44 -070068static uint32_t kCompilerOptimizerDisableFlags = 0 | // Disable specific optimizations
Bill Buzbeea114add2012-05-03 15:00:40 -070069 //(1 << kLoadStoreElimination) |
70 //(1 << kLoadHoisting) |
71 //(1 << kSuppressLoads) |
72 //(1 << kNullCheckElimination) |
73 //(1 << kPromoteRegs) |
74 //(1 << kTrackLiveTemps) |
75 //(1 << kSkipLargeMethodOptimization) |
76 //(1 << kSafeOptimizations) |
77 //(1 << kBBOpt) |
78 //(1 << kMatch) |
79 //(1 << kPromoteCompilerTemps) |
80 0;
buzbeece302932011-10-04 14:32:18 -070081
Elliott Hughese52e49b2012-04-02 16:05:44 -070082static uint32_t kCompilerDebugFlags = 0 | // Enable debug/testing modes
Bill Buzbeea114add2012-05-03 15:00:40 -070083 //(1 << kDebugDisplayMissingTargets) |
84 //(1 << kDebugVerbose) |
85 //(1 << kDebugDumpCFG) |
86 //(1 << kDebugSlowFieldPath) |
87 //(1 << kDebugSlowInvokePath) |
88 //(1 << kDebugSlowStringPath) |
89 //(1 << kDebugSlowestFieldPath) |
90 //(1 << kDebugSlowestStringPath) |
91 //(1 << kDebugExerciseResolveMethod) |
92 //(1 << kDebugVerifyDataflow) |
93 //(1 << kDebugShowMemoryUsage) |
94 //(1 << kDebugShowNops) |
95 //(1 << kDebugCountOpcodes) |
buzbeed1643e42012-09-05 14:06:51 -070096 //(1 << kDebugDumpCheckStats) |
buzbeead8f15e2012-06-18 14:49:45 -070097 //(1 << kDebugDumpBitcodeFile) |
Bill Buzbeec9f40dd2012-08-15 11:35:25 -070098 //(1 << kDebugVerifyBitcode) |
Bill Buzbeea114add2012-05-03 15:00:40 -070099 0;
buzbeece302932011-10-04 14:32:18 -0700100
buzbeeeaf09bc2012-11-15 14:51:41 -0800101inline bool contentIsInsn(const uint16_t* codePtr) {
102 uint16_t instr = *codePtr;
Bill Buzbeea114add2012-05-03 15:00:40 -0700103 Instruction::Code opcode = (Instruction::Code)(instr & 0xff);
buzbee67bf8852011-08-17 17:51:35 -0700104
Bill Buzbeea114add2012-05-03 15:00:40 -0700105 /*
106 * Since the low 8-bit in metadata may look like NOP, we need to check
107 * both the low and whole sub-word to determine whether it is code or data.
108 */
109 return (opcode != Instruction::NOP || instr == 0);
buzbee67bf8852011-08-17 17:51:35 -0700110}
111
112/*
113 * Parse an instruction, return the length of the instruction
114 */
buzbeeeaf09bc2012-11-15 14:51:41 -0800115inline int parseInsn(CompilationUnit* cUnit, const uint16_t* codePtr,
Bill Buzbeea114add2012-05-03 15:00:40 -0700116 DecodedInstruction* decoded_instruction, bool printMe)
buzbee67bf8852011-08-17 17:51:35 -0700117{
Elliott Hughesadb8c672012-03-06 16:49:32 -0800118 // Don't parse instruction data
119 if (!contentIsInsn(codePtr)) {
120 return 0;
121 }
buzbee67bf8852011-08-17 17:51:35 -0700122
Elliott Hughesadb8c672012-03-06 16:49:32 -0800123 const Instruction* instruction = Instruction::At(codePtr);
124 *decoded_instruction = DecodedInstruction(instruction);
buzbee67bf8852011-08-17 17:51:35 -0700125
Elliott Hughesadb8c672012-03-06 16:49:32 -0800126 if (printMe) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700127 char* decodedString = oatGetDalvikDisassembly(cUnit, *decoded_instruction,
128 NULL);
129 LOG(INFO) << codePtr << ": 0x"
130 << std::hex << static_cast<int>(decoded_instruction->opcode)
Elliott Hughesadb8c672012-03-06 16:49:32 -0800131 << " " << decodedString;
132 }
133 return instruction->SizeInCodeUnits();
buzbee67bf8852011-08-17 17:51:35 -0700134}
135
136#define UNKNOWN_TARGET 0xffffffff
137
Elliott Hughesadb8c672012-03-06 16:49:32 -0800138inline bool isGoto(MIR* insn) {
139 switch (insn->dalvikInsn.opcode) {
140 case Instruction::GOTO:
141 case Instruction::GOTO_16:
142 case Instruction::GOTO_32:
143 return true;
144 default:
145 return false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 }
buzbee67bf8852011-08-17 17:51:35 -0700147}
148
149/*
150 * Identify unconditional branch instructions
151 */
Elliott Hughesadb8c672012-03-06 16:49:32 -0800152inline bool isUnconditionalBranch(MIR* insn) {
153 switch (insn->dalvikInsn.opcode) {
154 case Instruction::RETURN_VOID:
155 case Instruction::RETURN:
156 case Instruction::RETURN_WIDE:
157 case Instruction::RETURN_OBJECT:
158 return true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700159 default:
160 return isGoto(insn);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800161 }
buzbee67bf8852011-08-17 17:51:35 -0700162}
163
164/* Split an existing block from the specified code offset into two */
buzbee31a4a6f2012-02-28 15:36:15 -0800165BasicBlock *splitBlock(CompilationUnit* cUnit, unsigned int codeOffset,
Bill Buzbeea114add2012-05-03 15:00:40 -0700166 BasicBlock* origBlock, BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700167{
Bill Buzbeea114add2012-05-03 15:00:40 -0700168 MIR* insn = origBlock->firstMIRInsn;
169 while (insn) {
170 if (insn->offset == codeOffset) break;
171 insn = insn->next;
172 }
173 if (insn == NULL) {
174 LOG(FATAL) << "Break split failed";
175 }
176 BasicBlock *bottomBlock = oatNewBB(cUnit, kDalvikByteCode,
177 cUnit->numBlocks++);
178 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700179
Bill Buzbeea114add2012-05-03 15:00:40 -0700180 bottomBlock->startOffset = codeOffset;
181 bottomBlock->firstMIRInsn = insn;
182 bottomBlock->lastMIRInsn = origBlock->lastMIRInsn;
buzbee67bf8852011-08-17 17:51:35 -0700183
Bill Buzbeea114add2012-05-03 15:00:40 -0700184 /* Add it to the quick lookup cache */
185 cUnit->blockMap.Put(bottomBlock->startOffset, bottomBlock);
buzbee5b537102012-01-17 17:33:47 -0800186
Bill Buzbeea114add2012-05-03 15:00:40 -0700187 /* Handle the taken path */
188 bottomBlock->taken = origBlock->taken;
189 if (bottomBlock->taken) {
190 origBlock->taken = NULL;
191 oatDeleteGrowableList(bottomBlock->taken->predecessors,
buzbeeba938cb2012-02-03 14:47:55 -0800192 (intptr_t)origBlock);
Bill Buzbeea114add2012-05-03 15:00:40 -0700193 oatInsertGrowableList(cUnit, bottomBlock->taken->predecessors,
194 (intptr_t)bottomBlock);
195 }
196
197 /* Handle the fallthrough path */
Bill Buzbeea114add2012-05-03 15:00:40 -0700198 bottomBlock->fallThrough = origBlock->fallThrough;
199 origBlock->fallThrough = bottomBlock;
Bill Buzbeea114add2012-05-03 15:00:40 -0700200 oatInsertGrowableList(cUnit, bottomBlock->predecessors,
201 (intptr_t)origBlock);
202 if (bottomBlock->fallThrough) {
203 oatDeleteGrowableList(bottomBlock->fallThrough->predecessors,
204 (intptr_t)origBlock);
205 oatInsertGrowableList(cUnit, bottomBlock->fallThrough->predecessors,
206 (intptr_t)bottomBlock);
207 }
208
209 /* Handle the successor list */
210 if (origBlock->successorBlockList.blockListType != kNotUsed) {
211 bottomBlock->successorBlockList = origBlock->successorBlockList;
212 origBlock->successorBlockList.blockListType = kNotUsed;
213 GrowableListIterator iterator;
214
215 oatGrowableListIteratorInit(&bottomBlock->successorBlockList.blocks,
216 &iterator);
217 while (true) {
218 SuccessorBlockInfo *successorBlockInfo =
219 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
220 if (successorBlockInfo == NULL) break;
221 BasicBlock *bb = successorBlockInfo->block;
222 oatDeleteGrowableList(bb->predecessors, (intptr_t)origBlock);
223 oatInsertGrowableList(cUnit, bb->predecessors, (intptr_t)bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700224 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700225 }
buzbee67bf8852011-08-17 17:51:35 -0700226
Bill Buzbeea114add2012-05-03 15:00:40 -0700227 origBlock->lastMIRInsn = insn->prev;
buzbee67bf8852011-08-17 17:51:35 -0700228
Bill Buzbeea114add2012-05-03 15:00:40 -0700229 insn->prev->next = NULL;
230 insn->prev = NULL;
231 /*
232 * Update the immediate predecessor block pointer so that outgoing edges
233 * can be applied to the proper block.
234 */
235 if (immedPredBlockP) {
236 DCHECK_EQ(*immedPredBlockP, origBlock);
237 *immedPredBlockP = bottomBlock;
238 }
239 return bottomBlock;
buzbee67bf8852011-08-17 17:51:35 -0700240}
241
242/*
243 * Given a code offset, find out the block that starts with it. If the offset
buzbee9ab05de2012-01-18 15:43:48 -0800244 * is in the middle of an existing block, split it into two. If immedPredBlockP
245 * is not non-null and is the block being split, update *immedPredBlockP to
246 * point to the bottom block so that outgoing edges can be set up properly
247 * (by the caller)
buzbee5b537102012-01-17 17:33:47 -0800248 * Utilizes a map for fast lookup of the typical cases.
buzbee67bf8852011-08-17 17:51:35 -0700249 */
buzbee31a4a6f2012-02-28 15:36:15 -0800250BasicBlock *findBlock(CompilationUnit* cUnit, unsigned int codeOffset,
251 bool split, bool create, BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700252{
Bill Buzbeea114add2012-05-03 15:00:40 -0700253 GrowableList* blockList = &cUnit->blockList;
254 BasicBlock* bb;
255 unsigned int i;
256 SafeMap<unsigned int, BasicBlock*>::iterator it;
buzbee67bf8852011-08-17 17:51:35 -0700257
Bill Buzbeea114add2012-05-03 15:00:40 -0700258 it = cUnit->blockMap.find(codeOffset);
259 if (it != cUnit->blockMap.end()) {
260 return it->second;
261 } else if (!create) {
262 return NULL;
263 }
264
265 if (split) {
266 for (i = 0; i < blockList->numUsed; i++) {
267 bb = (BasicBlock *) blockList->elemList[i];
268 if (bb->blockType != kDalvikByteCode) continue;
269 /* Check if a branch jumps into the middle of an existing block */
270 if ((codeOffset > bb->startOffset) && (bb->lastMIRInsn != NULL) &&
271 (codeOffset <= bb->lastMIRInsn->offset)) {
272 BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb,
273 bb == *immedPredBlockP ?
274 immedPredBlockP : NULL);
275 return newBB;
276 }
buzbee5b537102012-01-17 17:33:47 -0800277 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700278 }
buzbee5b537102012-01-17 17:33:47 -0800279
Bill Buzbeea114add2012-05-03 15:00:40 -0700280 /* Create a new one */
281 bb = oatNewBB(cUnit, kDalvikByteCode, cUnit->numBlocks++);
282 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) bb);
283 bb->startOffset = codeOffset;
284 cUnit->blockMap.Put(bb->startOffset, bb);
285 return bb;
buzbee67bf8852011-08-17 17:51:35 -0700286}
287
buzbeef58c12c2012-07-03 15:06:29 -0700288/* Find existing block */
289BasicBlock* oatFindBlock(CompilationUnit* cUnit, unsigned int codeOffset)
290{
291 return findBlock(cUnit, codeOffset, false, false, NULL);
292}
293
buzbeead8f15e2012-06-18 14:49:45 -0700294/* Turn method name into a legal Linux file name */
295void oatReplaceSpecialChars(std::string& str)
296{
297 static const struct { const char before; const char after; } match[] =
298 {{'/','-'}, {';','#'}, {' ','#'}, {'$','+'},
299 {'(','@'}, {')','@'}, {'<','='}, {'>','='}};
300 for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) {
301 std::replace(str.begin(), str.end(), match[i].before, match[i].after);
302 }
303}
304
buzbee67bf8852011-08-17 17:51:35 -0700305/* Dump the CFG into a DOT graph */
306void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix)
307{
Bill Buzbeea114add2012-05-03 15:00:40 -0700308 FILE* file;
buzbeead8f15e2012-06-18 14:49:45 -0700309 std::string fname(PrettyMethod(cUnit->method_idx, *cUnit->dex_file));
310 oatReplaceSpecialChars(fname);
311 fname = StringPrintf("%s%s%x.dot", dirPrefix, fname.c_str(),
312 cUnit->entryBlock->fallThrough->startOffset);
313 file = fopen(fname.c_str(), "w");
Bill Buzbeea114add2012-05-03 15:00:40 -0700314 if (file == NULL) {
315 return;
316 }
317 fprintf(file, "digraph G {\n");
318
319 fprintf(file, " rankdir=TB\n");
320
321 int numReachableBlocks = cUnit->numReachableBlocks;
322 int idx;
323 const GrowableList *blockList = &cUnit->blockList;
324
325 for (idx = 0; idx < numReachableBlocks; idx++) {
326 int blockIdx = cUnit->dfsOrder.elemList[idx];
327 BasicBlock *bb = (BasicBlock *) oatGrowableListGetElement(blockList,
328 blockIdx);
329 if (bb == NULL) break;
buzbeed1643e42012-09-05 14:06:51 -0700330 if (bb->blockType == kDead) continue;
Bill Buzbeea114add2012-05-03 15:00:40 -0700331 if (bb->blockType == kEntryBlock) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700332 fprintf(file, " entry_%d [shape=Mdiamond];\n", bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700333 } else if (bb->blockType == kExitBlock) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700334 fprintf(file, " exit_%d [shape=Mdiamond];\n", bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700335 } else if (bb->blockType == kDalvikByteCode) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700336 fprintf(file, " block%04x_%d [shape=record,label = \"{ \\\n",
337 bb->startOffset, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700338 const MIR *mir;
339 fprintf(file, " {block id %d\\l}%s\\\n", bb->id,
340 bb->firstMIRInsn ? " | " : " ");
341 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
342 fprintf(file, " {%04x %s\\l}%s\\\n", mir->offset,
343 mir->ssaRep ? oatFullDisassembler(cUnit, mir) :
344 Instruction::Name(mir->dalvikInsn.opcode),
345 mir->next ? " | " : " ");
346 }
347 fprintf(file, " }\"];\n\n");
348 } else if (bb->blockType == kExceptionHandling) {
349 char blockName[BLOCK_NAME_LEN];
350
351 oatGetBlockName(bb, blockName);
352 fprintf(file, " %s [shape=invhouse];\n", blockName);
buzbee67bf8852011-08-17 17:51:35 -0700353 }
buzbee67bf8852011-08-17 17:51:35 -0700354
Bill Buzbeea114add2012-05-03 15:00:40 -0700355 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
buzbee67bf8852011-08-17 17:51:35 -0700356
Bill Buzbeea114add2012-05-03 15:00:40 -0700357 if (bb->taken) {
358 oatGetBlockName(bb, blockName1);
359 oatGetBlockName(bb->taken, blockName2);
360 fprintf(file, " %s:s -> %s:n [style=dotted]\n",
361 blockName1, blockName2);
buzbee67bf8852011-08-17 17:51:35 -0700362 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700363 if (bb->fallThrough) {
364 oatGetBlockName(bb, blockName1);
365 oatGetBlockName(bb->fallThrough, blockName2);
366 fprintf(file, " %s:s -> %s:n\n", blockName1, blockName2);
367 }
368
369 if (bb->successorBlockList.blockListType != kNotUsed) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700370 fprintf(file, " succ%04x_%d [shape=%s,label = \"{ \\\n",
371 bb->startOffset, bb->id,
Bill Buzbeea114add2012-05-03 15:00:40 -0700372 (bb->successorBlockList.blockListType == kCatch) ?
373 "Mrecord" : "record");
374 GrowableListIterator iterator;
375 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
376 &iterator);
377 SuccessorBlockInfo *successorBlockInfo =
378 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
379
380 int succId = 0;
381 while (true) {
382 if (successorBlockInfo == NULL) break;
383
384 BasicBlock *destBlock = successorBlockInfo->block;
385 SuccessorBlockInfo *nextSuccessorBlockInfo =
386 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
387
388 fprintf(file, " {<f%d> %04x: %04x\\l}%s\\\n",
389 succId++,
390 successorBlockInfo->key,
391 destBlock->startOffset,
392 (nextSuccessorBlockInfo != NULL) ? " | " : " ");
393
394 successorBlockInfo = nextSuccessorBlockInfo;
395 }
396 fprintf(file, " }\"];\n\n");
397
398 oatGetBlockName(bb, blockName1);
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700399 fprintf(file, " %s:s -> succ%04x_%d:n [style=dashed]\n",
400 blockName1, bb->startOffset, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700401
402 if (bb->successorBlockList.blockListType == kPackedSwitch ||
403 bb->successorBlockList.blockListType == kSparseSwitch) {
404
405 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
406 &iterator);
407
408 succId = 0;
409 while (true) {
410 SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
411 oatGrowableListIteratorNext(&iterator);
412 if (successorBlockInfo == NULL) break;
413
414 BasicBlock *destBlock = successorBlockInfo->block;
415
416 oatGetBlockName(destBlock, blockName2);
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700417 fprintf(file, " succ%04x_%d:f%d:e -> %s:n\n", bb->startOffset,
418 bb->id, succId++, blockName2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700419 }
420 }
421 }
422 fprintf(file, "\n");
423
424 /* Display the dominator tree */
425 oatGetBlockName(bb, blockName1);
426 fprintf(file, " cfg%s [label=\"%s\", shape=none];\n",
427 blockName1, blockName1);
428 if (bb->iDom) {
429 oatGetBlockName(bb->iDom, blockName2);
430 fprintf(file, " cfg%s:s -> cfg%s:n\n\n", blockName2, blockName1);
431 }
432 }
433 fprintf(file, "}\n");
434 fclose(file);
buzbee67bf8852011-08-17 17:51:35 -0700435}
436
437/* Verify if all the successor is connected with all the claimed predecessors */
buzbee31a4a6f2012-02-28 15:36:15 -0800438bool verifyPredInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700439{
Bill Buzbeea114add2012-05-03 15:00:40 -0700440 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700441
Bill Buzbeea114add2012-05-03 15:00:40 -0700442 oatGrowableListIteratorInit(bb->predecessors, &iter);
443 while (true) {
444 BasicBlock *predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
445 if (!predBB) break;
446 bool found = false;
447 if (predBB->taken == bb) {
448 found = true;
449 } else if (predBB->fallThrough == bb) {
450 found = true;
451 } else if (predBB->successorBlockList.blockListType != kNotUsed) {
452 GrowableListIterator iterator;
453 oatGrowableListIteratorInit(&predBB->successorBlockList.blocks,
454 &iterator);
455 while (true) {
456 SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
457 oatGrowableListIteratorNext(&iterator);
458 if (successorBlockInfo == NULL) break;
459 BasicBlock *succBB = successorBlockInfo->block;
460 if (succBB == bb) {
buzbee67bf8852011-08-17 17:51:35 -0700461 found = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700462 break;
buzbee67bf8852011-08-17 17:51:35 -0700463 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700464 }
buzbee67bf8852011-08-17 17:51:35 -0700465 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700466 if (found == false) {
467 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
468 oatGetBlockName(bb, blockName1);
469 oatGetBlockName(predBB, blockName2);
470 oatDumpCFG(cUnit, "/sdcard/cfg/");
471 LOG(FATAL) << "Successor " << blockName1 << "not found from "
472 << blockName2;
473 }
474 }
475 return true;
buzbee67bf8852011-08-17 17:51:35 -0700476}
477
478/* Identify code range in try blocks and set up the empty catch blocks */
buzbee31a4a6f2012-02-28 15:36:15 -0800479void processTryCatchBlocks(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700480{
Bill Buzbeea114add2012-05-03 15:00:40 -0700481 const DexFile::CodeItem* code_item = cUnit->code_item;
482 int triesSize = code_item->tries_size_;
483 int offset;
buzbee67bf8852011-08-17 17:51:35 -0700484
Bill Buzbeea114add2012-05-03 15:00:40 -0700485 if (triesSize == 0) {
486 return;
487 }
488
489 ArenaBitVector* tryBlockAddr = cUnit->tryBlockAddr;
490
491 for (int i = 0; i < triesSize; i++) {
492 const DexFile::TryItem* pTry =
493 DexFile::GetTryItems(*code_item, i);
494 int startOffset = pTry->start_addr_;
495 int endOffset = startOffset + pTry->insn_count_;
496 for (offset = startOffset; offset < endOffset; offset++) {
497 oatSetBit(cUnit, tryBlockAddr, offset);
buzbee67bf8852011-08-17 17:51:35 -0700498 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700499 }
buzbee67bf8852011-08-17 17:51:35 -0700500
Bill Buzbeea114add2012-05-03 15:00:40 -0700501 // Iterate over each of the handlers to enqueue the empty Catch blocks
502 const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item, 0);
503 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
504 for (uint32_t idx = 0; idx < handlers_size; idx++) {
505 CatchHandlerIterator iterator(handlers_ptr);
506 for (; iterator.HasNext(); iterator.Next()) {
507 uint32_t address = iterator.GetHandlerAddress();
508 findBlock(cUnit, address, false /* split */, true /*create*/,
509 /* immedPredBlockP */ NULL);
buzbee67bf8852011-08-17 17:51:35 -0700510 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700511 handlers_ptr = iterator.EndDataPointer();
512 }
buzbee67bf8852011-08-17 17:51:35 -0700513}
514
Elliott Hughesadb8c672012-03-06 16:49:32 -0800515/* Process instructions with the kBranch flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800516BasicBlock* processCanBranch(CompilationUnit* cUnit, BasicBlock* curBlock,
Bill Buzbeea114add2012-05-03 15:00:40 -0700517 MIR* insn, int curOffset, int width, int flags,
buzbeeeaf09bc2012-11-15 14:51:41 -0800518 const uint16_t* codePtr, const uint16_t* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700519{
Bill Buzbeea114add2012-05-03 15:00:40 -0700520 int target = curOffset;
521 switch (insn->dalvikInsn.opcode) {
522 case Instruction::GOTO:
523 case Instruction::GOTO_16:
524 case Instruction::GOTO_32:
525 target += (int) insn->dalvikInsn.vA;
526 break;
527 case Instruction::IF_EQ:
528 case Instruction::IF_NE:
529 case Instruction::IF_LT:
530 case Instruction::IF_GE:
531 case Instruction::IF_GT:
532 case Instruction::IF_LE:
buzbee0967a252012-09-14 10:43:54 -0700533 curBlock->conditionalBranch = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700534 target += (int) insn->dalvikInsn.vC;
535 break;
536 case Instruction::IF_EQZ:
537 case Instruction::IF_NEZ:
538 case Instruction::IF_LTZ:
539 case Instruction::IF_GEZ:
540 case Instruction::IF_GTZ:
541 case Instruction::IF_LEZ:
buzbee0967a252012-09-14 10:43:54 -0700542 curBlock->conditionalBranch = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700543 target += (int) insn->dalvikInsn.vB;
544 break;
545 default:
546 LOG(FATAL) << "Unexpected opcode(" << (int)insn->dalvikInsn.opcode
547 << ") with kBranch set";
548 }
549 BasicBlock *takenBlock = findBlock(cUnit, target,
550 /* split */
551 true,
552 /* create */
553 true,
554 /* immedPredBlockP */
555 &curBlock);
556 curBlock->taken = takenBlock;
557 oatInsertGrowableList(cUnit, takenBlock->predecessors, (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700558
Bill Buzbeea114add2012-05-03 15:00:40 -0700559 /* Always terminate the current block for conditional branches */
560 if (flags & Instruction::kContinue) {
561 BasicBlock *fallthroughBlock = findBlock(cUnit,
562 curOffset + width,
563 /*
564 * If the method is processed
565 * in sequential order from the
566 * beginning, we don't need to
567 * specify split for continue
568 * blocks. However, this
569 * routine can be called by
570 * compileLoop, which starts
571 * parsing the method from an
572 * arbitrary address in the
573 * method body.
574 */
575 true,
576 /* create */
577 true,
578 /* immedPredBlockP */
579 &curBlock);
580 curBlock->fallThrough = fallthroughBlock;
581 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
582 (intptr_t)curBlock);
583 } else if (codePtr < codeEnd) {
584 /* Create a fallthrough block for real instructions (incl. NOP) */
585 if (contentIsInsn(codePtr)) {
586 findBlock(cUnit, curOffset + width,
587 /* split */
588 false,
589 /* create */
590 true,
591 /* immedPredBlockP */
592 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700593 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700594 }
595 return curBlock;
buzbee67bf8852011-08-17 17:51:35 -0700596}
597
Elliott Hughesadb8c672012-03-06 16:49:32 -0800598/* Process instructions with the kSwitch flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800599void processCanSwitch(CompilationUnit* cUnit, BasicBlock* curBlock,
600 MIR* insn, int curOffset, int width, int flags)
buzbee67bf8852011-08-17 17:51:35 -0700601{
buzbeeeaf09bc2012-11-15 14:51:41 -0800602 uint16_t* switchData= (uint16_t*) (cUnit->insns + curOffset + insn->dalvikInsn.vB);
Bill Buzbeea114add2012-05-03 15:00:40 -0700603 int size;
604 int* keyTable;
605 int* targetTable;
606 int i;
607 int firstKey;
buzbee67bf8852011-08-17 17:51:35 -0700608
Bill Buzbeea114add2012-05-03 15:00:40 -0700609 /*
610 * Packed switch data format:
611 * ushort ident = 0x0100 magic value
612 * ushort size number of entries in the table
613 * int first_key first (and lowest) switch case value
614 * int targets[size] branch targets, relative to switch opcode
615 *
616 * Total size is (4+size*2) 16-bit code units.
617 */
618 if (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) {
619 DCHECK_EQ(static_cast<int>(switchData[0]),
620 static_cast<int>(Instruction::kPackedSwitchSignature));
621 size = switchData[1];
622 firstKey = switchData[2] | (switchData[3] << 16);
623 targetTable = (int *) &switchData[4];
624 keyTable = NULL; // Make the compiler happy
625 /*
626 * Sparse switch data format:
627 * ushort ident = 0x0200 magic value
628 * ushort size number of entries in the table; > 0
629 * int keys[size] keys, sorted low-to-high; 32-bit aligned
630 * int targets[size] branch targets, relative to switch opcode
631 *
632 * Total size is (2+size*4) 16-bit code units.
633 */
634 } else {
635 DCHECK_EQ(static_cast<int>(switchData[0]),
636 static_cast<int>(Instruction::kSparseSwitchSignature));
637 size = switchData[1];
638 keyTable = (int *) &switchData[2];
639 targetTable = (int *) &switchData[2 + size*2];
640 firstKey = 0; // To make the compiler happy
641 }
buzbee67bf8852011-08-17 17:51:35 -0700642
Bill Buzbeea114add2012-05-03 15:00:40 -0700643 if (curBlock->successorBlockList.blockListType != kNotUsed) {
644 LOG(FATAL) << "Successor block list already in use: "
645 << (int)curBlock->successorBlockList.blockListType;
646 }
647 curBlock->successorBlockList.blockListType =
648 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
649 kPackedSwitch : kSparseSwitch;
650 oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, size,
651 kListSuccessorBlocks);
652
653 for (i = 0; i < size; i++) {
654 BasicBlock *caseBlock = findBlock(cUnit, curOffset + targetTable[i],
655 /* split */
656 true,
657 /* create */
658 true,
659 /* immedPredBlockP */
660 &curBlock);
661 SuccessorBlockInfo *successorBlockInfo =
662 (SuccessorBlockInfo *) oatNew(cUnit, sizeof(SuccessorBlockInfo),
663 false, kAllocSuccessor);
664 successorBlockInfo->block = caseBlock;
665 successorBlockInfo->key =
Elliott Hughesadb8c672012-03-06 16:49:32 -0800666 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
Bill Buzbeea114add2012-05-03 15:00:40 -0700667 firstKey + i : keyTable[i];
668 oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
669 (intptr_t) successorBlockInfo);
670 oatInsertGrowableList(cUnit, caseBlock->predecessors,
buzbeeba938cb2012-02-03 14:47:55 -0800671 (intptr_t)curBlock);
Bill Buzbeea114add2012-05-03 15:00:40 -0700672 }
673
674 /* Fall-through case */
675 BasicBlock* fallthroughBlock = findBlock(cUnit,
676 curOffset + width,
677 /* split */
678 false,
679 /* create */
680 true,
681 /* immedPredBlockP */
682 NULL);
683 curBlock->fallThrough = fallthroughBlock;
684 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
685 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700686}
687
Elliott Hughesadb8c672012-03-06 16:49:32 -0800688/* Process instructions with the kThrow flag */
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700689BasicBlock* processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock,
690 MIR* insn, int curOffset, int width, int flags,
buzbeeeaf09bc2012-11-15 14:51:41 -0800691 ArenaBitVector* tryBlockAddr, const uint16_t* codePtr,
692 const uint16_t* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700693{
Bill Buzbeea114add2012-05-03 15:00:40 -0700694 const DexFile::CodeItem* code_item = cUnit->code_item;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700695 bool inTryBlock = oatIsBitSet(tryBlockAddr, curOffset);
buzbee67bf8852011-08-17 17:51:35 -0700696
Bill Buzbeea114add2012-05-03 15:00:40 -0700697 /* In try block */
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700698 if (inTryBlock) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700699 CatchHandlerIterator iterator(*code_item, curOffset);
buzbee67bf8852011-08-17 17:51:35 -0700700
Bill Buzbeea114add2012-05-03 15:00:40 -0700701 if (curBlock->successorBlockList.blockListType != kNotUsed) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700702 LOG(INFO) << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
Bill Buzbeea114add2012-05-03 15:00:40 -0700703 LOG(FATAL) << "Successor block list already in use: "
704 << (int)curBlock->successorBlockList.blockListType;
buzbee67bf8852011-08-17 17:51:35 -0700705 }
706
Bill Buzbeea114add2012-05-03 15:00:40 -0700707 curBlock->successorBlockList.blockListType = kCatch;
708 oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, 2,
709 kListSuccessorBlocks);
710
711 for (;iterator.HasNext(); iterator.Next()) {
712 BasicBlock *catchBlock = findBlock(cUnit, iterator.GetHandlerAddress(),
713 false /* split*/,
714 false /* creat */,
715 NULL /* immedPredBlockP */);
716 catchBlock->catchEntry = true;
buzbee6459e7c2012-10-02 14:42:41 -0700717 cUnit->catches.insert(catchBlock->startOffset);
Bill Buzbeea114add2012-05-03 15:00:40 -0700718 SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
719 oatNew(cUnit, sizeof(SuccessorBlockInfo), false, kAllocSuccessor);
720 successorBlockInfo->block = catchBlock;
721 successorBlockInfo->key = iterator.GetHandlerTypeIndex();
722 oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
723 (intptr_t) successorBlockInfo);
724 oatInsertGrowableList(cUnit, catchBlock->predecessors,
725 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700726 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700727 } else {
728 BasicBlock *ehBlock = oatNewBB(cUnit, kExceptionHandling,
729 cUnit->numBlocks++);
730 curBlock->taken = ehBlock;
731 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) ehBlock);
732 ehBlock->startOffset = curOffset;
733 oatInsertGrowableList(cUnit, ehBlock->predecessors, (intptr_t)curBlock);
734 }
735
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700736 if (insn->dalvikInsn.opcode == Instruction::THROW){
buzbee0967a252012-09-14 10:43:54 -0700737 curBlock->explicitThrow = true;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700738 if ((codePtr < codeEnd) && contentIsInsn(codePtr)) {
739 // Force creation of new block following THROW via side-effect
740 findBlock(cUnit, curOffset + width, /* split */ false,
741 /* create */ true, /* immedPredBlockP */ NULL);
742 }
743 if (!inTryBlock) {
744 // Don't split a THROW that can't rethrow - we're done.
745 return curBlock;
Bill Buzbeea114add2012-05-03 15:00:40 -0700746 }
747 }
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700748
749 /*
750 * Split the potentially-throwing instruction into two parts.
751 * The first half will be a pseudo-op that captures the exception
752 * edges and terminates the basic block. It always falls through.
753 * Then, create a new basic block that begins with the throwing instruction
754 * (minus exceptions). Note: this new basic block must NOT be entered into
755 * the blockMap. If the potentially-throwing instruction is the target of a
756 * future branch, we need to find the check psuedo half. The new
757 * basic block containing the work portion of the instruction should
758 * only be entered via fallthrough from the block containing the
759 * pseudo exception edge MIR. Note also that this new block is
760 * not automatically terminated after the work portion, and may
761 * contain following instructions.
762 */
763 BasicBlock *newBlock = oatNewBB(cUnit, kDalvikByteCode, cUnit->numBlocks++);
764 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t)newBlock);
765 newBlock->startOffset = insn->offset;
766 curBlock->fallThrough = newBlock;
767 oatInsertGrowableList(cUnit, newBlock->predecessors, (intptr_t)curBlock);
768 MIR* newInsn = (MIR*)oatNew(cUnit, sizeof(MIR), true, kAllocMIR);
769 *newInsn = *insn;
770 insn->dalvikInsn.opcode =
771 static_cast<Instruction::Code>(kMirOpCheck);
772 // Associate the two halves
773 insn->meta.throwInsn = newInsn;
774 newInsn->meta.throwInsn = insn;
775 oatAppendMIR(newBlock, newInsn);
776 return newBlock;
buzbee67bf8852011-08-17 17:51:35 -0700777}
778
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800779void oatInit(CompilationUnit* cUnit, const Compiler& compiler) {
780 if (!oatArchInit()) {
781 LOG(FATAL) << "Failed to initialize oat";
782 }
783 if (!oatHeapInit(cUnit)) {
784 LOG(FATAL) << "Failed to initialize oat heap";
785 }
786}
787
buzbeeabc4c6b2012-08-23 08:17:15 -0700788CompiledMethod* compileMethod(Compiler& compiler,
buzbeec531cef2012-10-18 07:09:20 -0700789 const CompilerBackend compilerBackend,
buzbeeabc4c6b2012-08-23 08:17:15 -0700790 const DexFile::CodeItem* code_item,
791 uint32_t access_flags, InvokeType invoke_type,
792 uint32_t method_idx, jobject class_loader,
buzbeec531cef2012-10-18 07:09:20 -0700793 const DexFile& dex_file,
794 LLVMInfo* llvm_info
buzbeeabc4c6b2012-08-23 08:17:15 -0700795 )
buzbee67bf8852011-08-17 17:51:35 -0700796{
Bill Buzbeea114add2012-05-03 15:00:40 -0700797 VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
Brian Carlstrom94496d32011-08-22 09:22:47 -0700798
buzbeeeaf09bc2012-11-15 14:51:41 -0800799 const uint16_t* codePtr = code_item->insns_;
800 const uint16_t* codeEnd = code_item->insns_ + code_item->insns_size_in_code_units_;
Bill Buzbeea114add2012-05-03 15:00:40 -0700801 int numBlocks = 0;
802 unsigned int curOffset = 0;
buzbee67bf8852011-08-17 17:51:35 -0700803
Bill Buzbeea114add2012-05-03 15:00:40 -0700804 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
805 UniquePtr<CompilationUnit> cUnit(new CompilationUnit);
buzbeeba938cb2012-02-03 14:47:55 -0800806
Bill Buzbeea114add2012-05-03 15:00:40 -0700807 oatInit(cUnit.get(), compiler);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800808
Bill Buzbeea114add2012-05-03 15:00:40 -0700809 cUnit->compiler = &compiler;
810 cUnit->class_linker = class_linker;
811 cUnit->dex_file = &dex_file;
Bill Buzbeea114add2012-05-03 15:00:40 -0700812 cUnit->method_idx = method_idx;
813 cUnit->code_item = code_item;
814 cUnit->access_flags = access_flags;
Ian Rogers08f753d2012-08-24 14:35:25 -0700815 cUnit->invoke_type = invoke_type;
Bill Buzbeea114add2012-05-03 15:00:40 -0700816 cUnit->shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
817 cUnit->instructionSet = compiler.GetInstructionSet();
818 cUnit->insns = code_item->insns_;
819 cUnit->insnsSize = code_item->insns_size_in_code_units_;
820 cUnit->numIns = code_item->ins_size_;
821 cUnit->numRegs = code_item->registers_size_ - cUnit->numIns;
822 cUnit->numOuts = code_item->outs_size_;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700823 DCHECK((cUnit->instructionSet == kThumb2) ||
824 (cUnit->instructionSet == kX86) ||
825 (cUnit->instructionSet == kMips));
buzbeec531cef2012-10-18 07:09:20 -0700826 if ((compilerBackend == kQuickGBC) || (compilerBackend == kPortable)) {
buzbee85eee022012-07-16 22:12:38 -0700827 cUnit->genBitcode = true;
828 }
buzbeec531cef2012-10-18 07:09:20 -0700829 DCHECK_NE(compilerBackend, kIceland); // TODO: remove when Portable/Iceland merge complete
830 // TODO: remove this once x86 is tested
831 if (cUnit->genBitcode && (cUnit->instructionSet != kThumb2)) {
832 UNIMPLEMENTED(WARNING) << "GBC generation untested for non-Thumb targets";
833 }
834 cUnit->llvm_info = llvm_info;
Bill Buzbeea114add2012-05-03 15:00:40 -0700835 /* Adjust this value accordingly once inlining is performed */
836 cUnit->numDalvikRegisters = code_item->registers_size_;
837 // TODO: set this from command line
838 cUnit->compilerFlipMatch = false;
839 bool useMatch = !cUnit->compilerMethodMatch.empty();
840 bool match = useMatch && (cUnit->compilerFlipMatch ^
841 (PrettyMethod(method_idx, dex_file).find(cUnit->compilerMethodMatch) !=
842 std::string::npos));
843 if (!useMatch || match) {
844 cUnit->disableOpt = kCompilerOptimizerDisableFlags;
845 cUnit->enableDebug = kCompilerDebugFlags;
846 cUnit->printMe = VLOG_IS_ON(compiler) ||
847 (cUnit->enableDebug & (1 << kDebugVerbose));
848 }
buzbee6459e7c2012-10-02 14:42:41 -0700849#ifndef NDEBUG
buzbeec531cef2012-10-18 07:09:20 -0700850 if (cUnit->genBitcode) {
buzbee6459e7c2012-10-02 14:42:41 -0700851 cUnit->enableDebug |= (1 << kDebugVerifyBitcode);
buzbee6969d502012-06-15 16:40:31 -0700852 }
buzbee2cfc6392012-05-07 14:51:40 -0700853#endif
buzbee9281f002012-10-24 12:17:24 -0700854
855#if 1
856// *** Temporary ****
857// For use in debugging issue 7250540. Disable optimization in problem method
858// to see if monkey results change. Should be removed after monkey runs
859// complete.
860if (PrettyMethod(method_idx, dex_file).find("void com.android.inputmethod.keyboard.Key.<init>(android.content.res.Resources, com.android.inputmethod.keyboard.Keyboard$Params, com.android.inputmethod.keyboard.Keyboard$Builder$Row, org.xmlpull.v1.XmlPullParser)") != std::string::npos) {
861 cUnit->disableOpt |= (
862 (1 << kLoadStoreElimination) |
863 (1 << kLoadHoisting) |
864 (1 << kSuppressLoads) |
buzbee663c09f2012-10-31 05:21:00 -0700865 //(1 << kNullCheckElimination) |
866 //(1 << kPromoteRegs) |
buzbee9281f002012-10-24 12:17:24 -0700867 (1 << kTrackLiveTemps) |
buzbee663c09f2012-10-31 05:21:00 -0700868 //(1 << kSkipLargeMethodOptimization) |
869 //(1 << kSafeOptimizations) |
buzbee9281f002012-10-24 12:17:24 -0700870 (1 << kBBOpt) |
871 (1 << kMatch) |
buzbee663c09f2012-10-31 05:21:00 -0700872 //(1 << kPromoteCompilerTemps) |
873 0);
buzbee9281f002012-10-24 12:17:24 -0700874}
875#endif
876
jeffhao7fbee072012-08-24 17:56:54 -0700877 if (cUnit->instructionSet == kMips) {
878 // Disable some optimizations for mips for now
879 cUnit->disableOpt |= (
880 (1 << kLoadStoreElimination) |
881 (1 << kLoadHoisting) |
882 (1 << kSuppressLoads) |
883 (1 << kNullCheckElimination) |
884 (1 << kPromoteRegs) |
885 (1 << kTrackLiveTemps) |
886 (1 << kSkipLargeMethodOptimization) |
887 (1 << kSafeOptimizations) |
888 (1 << kBBOpt) |
889 (1 << kMatch) |
890 (1 << kPromoteCompilerTemps));
891 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700892
893 /* Gathering opcode stats? */
894 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
895 cUnit->opcodeCount = (int*)oatNew(cUnit.get(),
896 kNumPackedOpcodes * sizeof(int), true, kAllocMisc);
897 }
898
899 /* Assume non-throwing leaf */
900 cUnit->attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE);
901
902 /* Initialize the block list, estimate size based on insnsSize */
903 oatInitGrowableList(cUnit.get(), &cUnit->blockList, cUnit->insnsSize,
904 kListBlockList);
905
906 /* Initialize the switchTables list */
907 oatInitGrowableList(cUnit.get(), &cUnit->switchTables, 4,
908 kListSwitchTables);
909
910 /* Intialize the fillArrayData list */
911 oatInitGrowableList(cUnit.get(), &cUnit->fillArrayData, 4,
912 kListFillArrayData);
913
914 /* Intialize the throwLaunchpads list, estimate size based on insnsSize */
915 oatInitGrowableList(cUnit.get(), &cUnit->throwLaunchpads, cUnit->insnsSize,
916 kListThrowLaunchPads);
917
918 /* Intialize the instrinsicLaunchpads list */
919 oatInitGrowableList(cUnit.get(), &cUnit->intrinsicLaunchpads, 4,
920 kListMisc);
921
922
923 /* Intialize the suspendLaunchpads list */
924 oatInitGrowableList(cUnit.get(), &cUnit->suspendLaunchpads, 2048,
925 kListSuspendLaunchPads);
926
927 /* Allocate the bit-vector to track the beginning of basic blocks */
928 ArenaBitVector *tryBlockAddr = oatAllocBitVector(cUnit.get(),
929 cUnit->insnsSize,
930 true /* expandable */);
931 cUnit->tryBlockAddr = tryBlockAddr;
932
933 /* Create the default entry and exit blocks and enter them to the list */
934 BasicBlock *entryBlock = oatNewBB(cUnit.get(), kEntryBlock, numBlocks++);
935 BasicBlock *exitBlock = oatNewBB(cUnit.get(), kExitBlock, numBlocks++);
936
937 cUnit->entryBlock = entryBlock;
938 cUnit->exitBlock = exitBlock;
939
940 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) entryBlock);
941 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) exitBlock);
942
943 /* Current block to record parsed instructions */
944 BasicBlock *curBlock = oatNewBB(cUnit.get(), kDalvikByteCode, numBlocks++);
945 curBlock->startOffset = 0;
946 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) curBlock);
947 /* Add first block to the fast lookup cache */
948 cUnit->blockMap.Put(curBlock->startOffset, curBlock);
949 entryBlock->fallThrough = curBlock;
950 oatInsertGrowableList(cUnit.get(), curBlock->predecessors,
951 (intptr_t)entryBlock);
952
953 /*
954 * Store back the number of blocks since new blocks may be created of
955 * accessing cUnit.
956 */
957 cUnit->numBlocks = numBlocks;
958
959 /* Identify code range in try blocks and set up the empty catch blocks */
960 processTryCatchBlocks(cUnit.get());
961
962 /* Set up for simple method detection */
963 int numPatterns = sizeof(specialPatterns)/sizeof(specialPatterns[0]);
964 bool livePattern = (numPatterns > 0) && !(cUnit->disableOpt & (1 << kMatch));
Elliott Hughesabe64aa2012-05-30 17:34:45 -0700965 bool* deadPattern = (bool*)oatNew(cUnit.get(), sizeof(bool) * numPatterns, true,
Bill Buzbeea114add2012-05-03 15:00:40 -0700966 kAllocMisc);
967 SpecialCaseHandler specialCase = kNoHandler;
968 int patternPos = 0;
969
970 /* Parse all instructions and put them into containing basic blocks */
971 while (codePtr < codeEnd) {
972 MIR *insn = (MIR *) oatNew(cUnit.get(), sizeof(MIR), true, kAllocMIR);
973 insn->offset = curOffset;
974 int width = parseInsn(cUnit.get(), codePtr, &insn->dalvikInsn, false);
975 insn->width = width;
976 Instruction::Code opcode = insn->dalvikInsn.opcode;
977 if (cUnit->opcodeCount != NULL) {
978 cUnit->opcodeCount[static_cast<int>(opcode)]++;
buzbee44b412b2012-02-04 08:50:53 -0800979 }
980
Bill Buzbeea114add2012-05-03 15:00:40 -0700981 /* Terminate when the data section is seen */
982 if (width == 0)
983 break;
984
985 /* Possible simple method? */
986 if (livePattern) {
987 livePattern = false;
988 specialCase = kNoHandler;
989 for (int i = 0; i < numPatterns; i++) {
990 if (!deadPattern[i]) {
991 if (specialPatterns[i].opcodes[patternPos] == opcode) {
992 livePattern = true;
993 specialCase = specialPatterns[i].handlerCode;
994 } else {
995 deadPattern[i] = true;
996 }
997 }
998 }
999 patternPos++;
buzbeea7c12682012-03-19 13:13:53 -07001000 }
1001
Bill Buzbeea114add2012-05-03 15:00:40 -07001002 oatAppendMIR(curBlock, insn);
buzbeecefd1872011-09-09 09:59:52 -07001003
Bill Buzbeea114add2012-05-03 15:00:40 -07001004 codePtr += width;
Ian Rogersa75a0132012-09-28 11:41:42 -07001005 int flags = Instruction::FlagsOf(insn->dalvikInsn.opcode);
buzbee67bf8852011-08-17 17:51:35 -07001006
Bill Buzbeea114add2012-05-03 15:00:40 -07001007 int dfFlags = oatDataFlowAttributes[insn->dalvikInsn.opcode];
buzbee67bf8852011-08-17 17:51:35 -07001008
Bill Buzbeea114add2012-05-03 15:00:40 -07001009 if (dfFlags & DF_HAS_DEFS) {
buzbeebff24652012-05-06 16:22:05 -07001010 cUnit->defCount += (dfFlags & DF_A_WIDE) ? 2 : 1;
Bill Buzbeea114add2012-05-03 15:00:40 -07001011 }
buzbee67bf8852011-08-17 17:51:35 -07001012
Bill Buzbeea114add2012-05-03 15:00:40 -07001013 if (flags & Instruction::kBranch) {
1014 curBlock = processCanBranch(cUnit.get(), curBlock, insn, curOffset,
1015 width, flags, codePtr, codeEnd);
1016 } else if (flags & Instruction::kReturn) {
1017 curBlock->fallThrough = exitBlock;
1018 oatInsertGrowableList(cUnit.get(), exitBlock->predecessors,
1019 (intptr_t)curBlock);
1020 /*
1021 * Terminate the current block if there are instructions
1022 * afterwards.
1023 */
1024 if (codePtr < codeEnd) {
1025 /*
1026 * Create a fallthrough block for real instructions
1027 * (incl. NOP).
1028 */
1029 if (contentIsInsn(codePtr)) {
1030 findBlock(cUnit.get(), curOffset + width,
1031 /* split */
1032 false,
1033 /* create */
1034 true,
1035 /* immedPredBlockP */
1036 NULL);
1037 }
1038 }
1039 } else if (flags & Instruction::kThrow) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -07001040 curBlock = processCanThrow(cUnit.get(), curBlock, insn, curOffset,
1041 width, flags, tryBlockAddr, codePtr, codeEnd);
Bill Buzbeea114add2012-05-03 15:00:40 -07001042 } else if (flags & Instruction::kSwitch) {
1043 processCanSwitch(cUnit.get(), curBlock, insn, curOffset, width, flags);
1044 }
1045 curOffset += width;
1046 BasicBlock *nextBlock = findBlock(cUnit.get(), curOffset,
1047 /* split */
1048 false,
1049 /* create */
1050 false,
1051 /* immedPredBlockP */
1052 NULL);
1053 if (nextBlock) {
1054 /*
1055 * The next instruction could be the target of a previously parsed
1056 * forward branch so a block is already created. If the current
1057 * instruction is not an unconditional branch, connect them through
1058 * the fall-through link.
1059 */
1060 DCHECK(curBlock->fallThrough == NULL ||
1061 curBlock->fallThrough == nextBlock ||
1062 curBlock->fallThrough == exitBlock);
buzbee5ade1d22011-09-09 14:44:52 -07001063
Bill Buzbeea114add2012-05-03 15:00:40 -07001064 if ((curBlock->fallThrough == NULL) && (flags & Instruction::kContinue)) {
1065 curBlock->fallThrough = nextBlock;
1066 oatInsertGrowableList(cUnit.get(), nextBlock->predecessors,
1067 (intptr_t)curBlock);
1068 }
1069 curBlock = nextBlock;
1070 }
1071 }
buzbeefc9e6fa2012-03-23 15:14:29 -07001072
Bill Buzbeea114add2012-05-03 15:00:40 -07001073 if (!(cUnit->disableOpt & (1 << kSkipLargeMethodOptimization))) {
1074 if ((cUnit->numBlocks > MANY_BLOCKS) ||
1075 ((cUnit->numBlocks > MANY_BLOCKS_INITIALIZER) &&
1076 PrettyMethod(method_idx, dex_file, false).find("init>") !=
1077 std::string::npos)) {
1078 cUnit->qdMode = true;
1079 }
1080 }
buzbeefc9e6fa2012-03-23 15:14:29 -07001081
Bill Buzbeea114add2012-05-03 15:00:40 -07001082 if (cUnit->qdMode) {
buzbeed1643e42012-09-05 14:06:51 -07001083 // Bitcode generation requires full dataflow analysis
buzbeec531cef2012-10-18 07:09:20 -07001084 cUnit->disableDataflow = !cUnit->genBitcode;
Bill Buzbeea114add2012-05-03 15:00:40 -07001085 // Disable optimization which require dataflow/ssa
buzbeec531cef2012-10-18 07:09:20 -07001086 cUnit->disableOpt |= (1 << kBBOpt) | (1 << kPromoteRegs) | (1 << kNullCheckElimination);
Bill Buzbeea114add2012-05-03 15:00:40 -07001087 if (cUnit->printMe) {
1088 LOG(INFO) << "QD mode enabled: "
1089 << PrettyMethod(method_idx, dex_file)
buzbeec531cef2012-10-18 07:09:20 -07001090 << " num blocks: " << cUnit->numBlocks;
Bill Buzbeea114add2012-05-03 15:00:40 -07001091 }
1092 }
buzbeec1f45042011-09-21 16:03:19 -07001093
Bill Buzbeea114add2012-05-03 15:00:40 -07001094 if (cUnit->printMe) {
1095 oatDumpCompilationUnit(cUnit.get());
1096 }
buzbee67bf8852011-08-17 17:51:35 -07001097
buzbee0967a252012-09-14 10:43:54 -07001098 /* Do a code layout pass */
1099 oatMethodCodeLayout(cUnit.get());
1100
Bill Buzbeea114add2012-05-03 15:00:40 -07001101 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
1102 /* Verify if all blocks are connected as claimed */
1103 oatDataFlowAnalysisDispatcher(cUnit.get(), verifyPredInfo, kAllNodes,
1104 false /* isIterative */);
1105 }
buzbee67bf8852011-08-17 17:51:35 -07001106
Bill Buzbeea114add2012-05-03 15:00:40 -07001107 /* Perform SSA transformation for the whole method */
1108 oatMethodSSATransformation(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001109
buzbee2cfc6392012-05-07 14:51:40 -07001110 /* Do constant propagation */
1111 // TODO: Probably need to make these expandable to support new ssa names
1112 // introducted during MIR optimization passes
1113 cUnit->isConstantV = oatAllocBitVector(cUnit.get(), cUnit->numSSARegs,
1114 false /* not expandable */);
1115 cUnit->constantValues =
1116 (int*)oatNew(cUnit.get(), sizeof(int) * cUnit->numSSARegs, true,
1117 kAllocDFInfo);
1118 oatDataFlowAnalysisDispatcher(cUnit.get(), oatDoConstantPropagation,
1119 kAllNodes,
1120 false /* isIterative */);
1121
Bill Buzbeea114add2012-05-03 15:00:40 -07001122 /* Detect loops */
1123 oatMethodLoopDetection(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001124
Bill Buzbeea114add2012-05-03 15:00:40 -07001125 /* Count uses */
1126 oatMethodUseCount(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001127
Bill Buzbeea114add2012-05-03 15:00:40 -07001128 /* Perform null check elimination */
1129 oatMethodNullCheckElimination(cUnit.get());
1130
buzbeed1643e42012-09-05 14:06:51 -07001131 /* Combine basic blocks where possible */
1132 oatMethodBasicBlockCombine(cUnit.get());
1133
Bill Buzbeea114add2012-05-03 15:00:40 -07001134 /* Do some basic block optimizations */
1135 oatMethodBasicBlockOptimization(cUnit.get());
1136
buzbeed1643e42012-09-05 14:06:51 -07001137 if (cUnit->enableDebug & (1 << kDebugDumpCheckStats)) {
1138 oatDumpCheckStats(cUnit.get());
1139 }
1140
Bill Buzbeea114add2012-05-03 15:00:40 -07001141 oatInitializeRegAlloc(cUnit.get()); // Needs to happen after SSA naming
1142
1143 /* Allocate Registers using simple local allocation scheme */
1144 oatSimpleRegAlloc(cUnit.get());
1145
buzbee2cfc6392012-05-07 14:51:40 -07001146 /* Go the LLVM path? */
1147 if (cUnit->genBitcode) {
1148 // MIR->Bitcode
1149 oatMethodMIR2Bitcode(cUnit.get());
buzbeec531cef2012-10-18 07:09:20 -07001150 if (compilerBackend == kPortable) {
buzbeeabc4c6b2012-08-23 08:17:15 -07001151 // all done
1152 oatArenaReset(cUnit.get());
1153 return NULL;
1154 }
buzbee2cfc6392012-05-07 14:51:40 -07001155 // Bitcode->LIR
1156 oatMethodBitcode2LIR(cUnit.get());
1157 } else {
buzbee2cfc6392012-05-07 14:51:40 -07001158 if (specialCase != kNoHandler) {
1159 /*
1160 * Custom codegen for special cases. If for any reason the
1161 * special codegen doesn't succeed, cUnit->firstLIRInsn will
1162 * set to NULL;
1163 */
1164 oatSpecialMIR2LIR(cUnit.get(), specialCase);
1165 }
buzbee67bf8852011-08-17 17:51:35 -07001166
buzbee2cfc6392012-05-07 14:51:40 -07001167 /* Convert MIR to LIR, etc. */
1168 if (cUnit->firstLIRInsn == NULL) {
1169 oatMethodMIR2LIR(cUnit.get());
1170 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001171 }
buzbee67bf8852011-08-17 17:51:35 -07001172
Bill Buzbeea114add2012-05-03 15:00:40 -07001173 // Debugging only
1174 if (cUnit->enableDebug & (1 << kDebugDumpCFG)) {
1175 oatDumpCFG(cUnit.get(), "/sdcard/cfg/");
1176 }
buzbee16da88c2012-03-20 10:38:17 -07001177
Bill Buzbeea114add2012-05-03 15:00:40 -07001178 /* Method is not empty */
1179 if (cUnit->firstLIRInsn) {
buzbee67bf8852011-08-17 17:51:35 -07001180
Bill Buzbeea114add2012-05-03 15:00:40 -07001181 // mark the targets of switch statement case labels
1182 oatProcessSwitchTables(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001183
Bill Buzbeea114add2012-05-03 15:00:40 -07001184 /* Convert LIR into machine code. */
1185 oatAssembleLIR(cUnit.get());
buzbee99ba9642012-01-25 14:23:14 -08001186
Elliott Hughes3b6baaa2011-10-14 19:13:56 -07001187 if (cUnit->printMe) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001188 oatCodegenDump(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001189 }
1190
Bill Buzbeea114add2012-05-03 15:00:40 -07001191 if (cUnit->opcodeCount != NULL) {
1192 LOG(INFO) << "Opcode Count";
1193 for (int i = 0; i < kNumPackedOpcodes; i++) {
1194 if (cUnit->opcodeCount[i] != 0) {
1195 LOG(INFO) << "-C- "
1196 << Instruction::Name(static_cast<Instruction::Code>(i))
1197 << " " << cUnit->opcodeCount[i];
buzbee67bf8852011-08-17 17:51:35 -07001198 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001199 }
1200 }
1201 }
buzbeea7c12682012-03-19 13:13:53 -07001202
Bill Buzbeea114add2012-05-03 15:00:40 -07001203 // Combine vmap tables - core regs, then fp regs - into vmapTable
1204 std::vector<uint16_t> vmapTable;
buzbeeca7a5e42012-08-20 11:12:18 -07001205 // Core regs may have been inserted out of order - sort first
1206 std::sort(cUnit->coreVmapTable.begin(), cUnit->coreVmapTable.end());
Bill Buzbeea114add2012-05-03 15:00:40 -07001207 for (size_t i = 0 ; i < cUnit->coreVmapTable.size(); i++) {
buzbeeca7a5e42012-08-20 11:12:18 -07001208 // Copy, stripping out the phys register sort key
1209 vmapTable.push_back(~(-1 << VREG_NUM_WIDTH) & cUnit->coreVmapTable[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001210 }
1211 // If we have a frame, push a marker to take place of lr
1212 if (cUnit->frameSize > 0) {
1213 vmapTable.push_back(INVALID_VREG);
1214 } else {
1215 DCHECK_EQ(__builtin_popcount(cUnit->coreSpillMask), 0);
1216 DCHECK_EQ(__builtin_popcount(cUnit->fpSpillMask), 0);
1217 }
buzbeeca7a5e42012-08-20 11:12:18 -07001218 // Combine vmap tables - core regs, then fp regs. fp regs already sorted
Bill Buzbeea114add2012-05-03 15:00:40 -07001219 for (uint32_t i = 0; i < cUnit->fpVmapTable.size(); i++) {
1220 vmapTable.push_back(cUnit->fpVmapTable[i]);
1221 }
1222 CompiledMethod* result =
1223 new CompiledMethod(cUnit->instructionSet, cUnit->codeBuffer,
Bill Buzbeea5b30242012-09-28 07:19:44 -07001224 cUnit->frameSize, cUnit->coreSpillMask, cUnit->fpSpillMask,
1225 cUnit->combinedMappingTable, vmapTable, cUnit->nativeGcMap);
buzbee67bf8852011-08-17 17:51:35 -07001226
Bill Buzbeea114add2012-05-03 15:00:40 -07001227 VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file)
1228 << " (" << (cUnit->codeBuffer.size() * sizeof(cUnit->codeBuffer[0]))
1229 << " bytes)";
buzbee5abfa3e2012-01-31 17:01:43 -08001230
1231#ifdef WITH_MEMSTATS
Bill Buzbeea114add2012-05-03 15:00:40 -07001232 if (cUnit->enableDebug & (1 << kDebugShowMemoryUsage)) {
1233 oatDumpMemStats(cUnit.get());
1234 }
buzbee5abfa3e2012-01-31 17:01:43 -08001235#endif
buzbee67bf8852011-08-17 17:51:35 -07001236
Bill Buzbeea114add2012-05-03 15:00:40 -07001237 oatArenaReset(cUnit.get());
buzbeeba938cb2012-02-03 14:47:55 -08001238
Bill Buzbeea114add2012-05-03 15:00:40 -07001239 return result;
buzbee67bf8852011-08-17 17:51:35 -07001240}
1241
buzbeeabc4c6b2012-08-23 08:17:15 -07001242CompiledMethod* oatCompileMethod(Compiler& compiler,
buzbeec531cef2012-10-18 07:09:20 -07001243 const CompilerBackend backend,
buzbeeabc4c6b2012-08-23 08:17:15 -07001244 const DexFile::CodeItem* code_item,
1245 uint32_t access_flags, InvokeType invoke_type,
1246 uint32_t method_idx, jobject class_loader,
buzbeec531cef2012-10-18 07:09:20 -07001247 const DexFile& dex_file,
1248 LLVMInfo* llvmInfo)
buzbeeabc4c6b2012-08-23 08:17:15 -07001249{
buzbeec531cef2012-10-18 07:09:20 -07001250 return compileMethod(compiler, backend, code_item, access_flags, invoke_type, method_idx, class_loader,
1251 dex_file, llvmInfo);
buzbeeabc4c6b2012-08-23 08:17:15 -07001252}
1253
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001254} // namespace art
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001255
Bill Buzbeea114add2012-05-03 15:00:40 -07001256extern "C" art::CompiledMethod*
buzbeec531cef2012-10-18 07:09:20 -07001257 ArtQuickCompileMethod(art::Compiler& compiler,
1258 const art::DexFile::CodeItem* code_item,
1259 uint32_t access_flags, art::InvokeType invoke_type,
1260 uint32_t method_idx, jobject class_loader,
1261 const art::DexFile& dex_file)
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001262{
1263 CHECK_EQ(compiler.GetInstructionSet(), art::oatInstructionSet());
buzbeec531cef2012-10-18 07:09:20 -07001264 // TODO: check method fingerprint here to determine appropriate backend type. Until then, use build default
1265 art::CompilerBackend backend = compiler.GetCompilerBackend();
1266 return art::oatCompileMethod(compiler, backend, code_item, access_flags, invoke_type,
1267 method_idx, class_loader, dex_file, NULL /* use thread llvmInfo */);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001268}