blob: 9db23acd20f16d2d7f14620fc65e589327e6ba27 [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"
Ian Rogers0571d352011-11-03 19:51:38 -070020#include "leb128.h"
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070021#include "object.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070022#include "runtime.h"
buzbee67bf8852011-08-17 17:51:35 -070023
buzbee4df2bbd2012-10-11 14:46:06 -070024#if defined(ART_USE_QUICK_COMPILER)
25#include <llvm/Support/Threading.h>
26
27namespace {
Shih-wei Liao215a9262012-10-12 10:29:46 -070028#if !defined(ART_USE_LLVM_COMPILER)
buzbee4df2bbd2012-10-11 14:46:06 -070029 pthread_once_t llvm_multi_init = PTHREAD_ONCE_INIT;
Shih-wei Liao215a9262012-10-12 10:29:46 -070030#endif
buzbee4df2bbd2012-10-11 14:46:06 -070031 void InitializeLLVMForQuick() {
32 llvm::llvm_start_multithreaded();
33 }
34}
35#endif
36
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080037namespace art {
38
buzbee692be802012-08-29 15:52:59 -070039#if defined(ART_USE_QUICK_COMPILER)
buzbee4df2bbd2012-10-11 14:46:06 -070040LLVMInfo::LLVMInfo() {
41#if !defined(ART_USE_LLVM_COMPILER)
42 pthread_once(&llvm_multi_init, InitializeLLVMForQuick);
43#endif
buzbee692be802012-08-29 15:52:59 -070044 // Create context, module, intrinsic helper & ir builder
45 llvm_context_.reset(new llvm::LLVMContext());
TDYa12755e5e6c2012-09-11 15:14:42 -070046 llvm_module_ = new llvm::Module("art", *llvm_context_);
buzbee692be802012-08-29 15:52:59 -070047 llvm::StructType::create(*llvm_context_, "JavaObject");
buzbee692be802012-08-29 15:52:59 -070048 intrinsic_helper_.reset( new greenland::IntrinsicHelper(*llvm_context_, *llvm_module_));
49 ir_builder_.reset(new greenland::IRBuilder(*llvm_context_, *llvm_module_, *intrinsic_helper_));
50}
51
buzbee4df2bbd2012-10-11 14:46:06 -070052LLVMInfo::~LLVMInfo() {
buzbee692be802012-08-29 15:52:59 -070053}
54
55extern "C" void ArtInitQuickCompilerContext(art::Compiler& compiler) {
56 CHECK(compiler.GetCompilerContext() == NULL);
buzbee4df2bbd2012-10-11 14:46:06 -070057 LLVMInfo* llvmInfo = new LLVMInfo();
58 compiler.SetCompilerContext(llvmInfo);
buzbee692be802012-08-29 15:52:59 -070059}
60
61extern "C" void ArtUnInitQuickCompilerContext(art::Compiler& compiler) {
buzbee4df2bbd2012-10-11 14:46:06 -070062 delete reinterpret_cast<LLVMInfo*>(compiler.GetCompilerContext());
buzbee692be802012-08-29 15:52:59 -070063 compiler.SetCompilerContext(NULL);
64}
65#endif
66
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#if defined(ART_USE_QUICK_COMPILER)
98 //(1 << kDebugDumpBitcodeFile) |
Bill Buzbeec9f40dd2012-08-15 11:35:25 -070099 //(1 << kDebugVerifyBitcode) |
buzbeead8f15e2012-06-18 14:49:45 -0700100#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700101 0;
buzbeece302932011-10-04 14:32:18 -0700102
buzbee31a4a6f2012-02-28 15:36:15 -0800103inline bool contentIsInsn(const u2* codePtr) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700104 u2 instr = *codePtr;
105 Instruction::Code opcode = (Instruction::Code)(instr & 0xff);
buzbee67bf8852011-08-17 17:51:35 -0700106
Bill Buzbeea114add2012-05-03 15:00:40 -0700107 /*
108 * Since the low 8-bit in metadata may look like NOP, we need to check
109 * both the low and whole sub-word to determine whether it is code or data.
110 */
111 return (opcode != Instruction::NOP || instr == 0);
buzbee67bf8852011-08-17 17:51:35 -0700112}
113
114/*
115 * Parse an instruction, return the length of the instruction
116 */
buzbee31a4a6f2012-02-28 15:36:15 -0800117inline int parseInsn(CompilationUnit* cUnit, const u2* codePtr,
Bill Buzbeea114add2012-05-03 15:00:40 -0700118 DecodedInstruction* decoded_instruction, bool printMe)
buzbee67bf8852011-08-17 17:51:35 -0700119{
Elliott Hughesadb8c672012-03-06 16:49:32 -0800120 // Don't parse instruction data
121 if (!contentIsInsn(codePtr)) {
122 return 0;
123 }
buzbee67bf8852011-08-17 17:51:35 -0700124
Elliott Hughesadb8c672012-03-06 16:49:32 -0800125 const Instruction* instruction = Instruction::At(codePtr);
126 *decoded_instruction = DecodedInstruction(instruction);
buzbee67bf8852011-08-17 17:51:35 -0700127
Elliott Hughesadb8c672012-03-06 16:49:32 -0800128 if (printMe) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700129 char* decodedString = oatGetDalvikDisassembly(cUnit, *decoded_instruction,
130 NULL);
131 LOG(INFO) << codePtr << ": 0x"
132 << std::hex << static_cast<int>(decoded_instruction->opcode)
Elliott Hughesadb8c672012-03-06 16:49:32 -0800133 << " " << decodedString;
134 }
135 return instruction->SizeInCodeUnits();
buzbee67bf8852011-08-17 17:51:35 -0700136}
137
138#define UNKNOWN_TARGET 0xffffffff
139
Elliott Hughesadb8c672012-03-06 16:49:32 -0800140inline bool isGoto(MIR* insn) {
141 switch (insn->dalvikInsn.opcode) {
142 case Instruction::GOTO:
143 case Instruction::GOTO_16:
144 case Instruction::GOTO_32:
145 return true;
146 default:
147 return false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700148 }
buzbee67bf8852011-08-17 17:51:35 -0700149}
150
151/*
152 * Identify unconditional branch instructions
153 */
Elliott Hughesadb8c672012-03-06 16:49:32 -0800154inline bool isUnconditionalBranch(MIR* insn) {
155 switch (insn->dalvikInsn.opcode) {
156 case Instruction::RETURN_VOID:
157 case Instruction::RETURN:
158 case Instruction::RETURN_WIDE:
159 case Instruction::RETURN_OBJECT:
160 return true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700161 default:
162 return isGoto(insn);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800163 }
buzbee67bf8852011-08-17 17:51:35 -0700164}
165
166/* Split an existing block from the specified code offset into two */
buzbee31a4a6f2012-02-28 15:36:15 -0800167BasicBlock *splitBlock(CompilationUnit* cUnit, unsigned int codeOffset,
Bill Buzbeea114add2012-05-03 15:00:40 -0700168 BasicBlock* origBlock, BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700169{
Bill Buzbeea114add2012-05-03 15:00:40 -0700170 MIR* insn = origBlock->firstMIRInsn;
171 while (insn) {
172 if (insn->offset == codeOffset) break;
173 insn = insn->next;
174 }
175 if (insn == NULL) {
176 LOG(FATAL) << "Break split failed";
177 }
178 BasicBlock *bottomBlock = oatNewBB(cUnit, kDalvikByteCode,
179 cUnit->numBlocks++);
180 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700181
Bill Buzbeea114add2012-05-03 15:00:40 -0700182 bottomBlock->startOffset = codeOffset;
183 bottomBlock->firstMIRInsn = insn;
184 bottomBlock->lastMIRInsn = origBlock->lastMIRInsn;
buzbee67bf8852011-08-17 17:51:35 -0700185
Bill Buzbeea114add2012-05-03 15:00:40 -0700186 /* Add it to the quick lookup cache */
187 cUnit->blockMap.Put(bottomBlock->startOffset, bottomBlock);
buzbee5b537102012-01-17 17:33:47 -0800188
Bill Buzbeea114add2012-05-03 15:00:40 -0700189 /* Handle the taken path */
190 bottomBlock->taken = origBlock->taken;
191 if (bottomBlock->taken) {
192 origBlock->taken = NULL;
193 oatDeleteGrowableList(bottomBlock->taken->predecessors,
buzbeeba938cb2012-02-03 14:47:55 -0800194 (intptr_t)origBlock);
Bill Buzbeea114add2012-05-03 15:00:40 -0700195 oatInsertGrowableList(cUnit, bottomBlock->taken->predecessors,
196 (intptr_t)bottomBlock);
197 }
198
199 /* Handle the fallthrough path */
Bill Buzbeea114add2012-05-03 15:00:40 -0700200 bottomBlock->fallThrough = origBlock->fallThrough;
201 origBlock->fallThrough = bottomBlock;
Bill Buzbeea114add2012-05-03 15:00:40 -0700202 oatInsertGrowableList(cUnit, bottomBlock->predecessors,
203 (intptr_t)origBlock);
204 if (bottomBlock->fallThrough) {
205 oatDeleteGrowableList(bottomBlock->fallThrough->predecessors,
206 (intptr_t)origBlock);
207 oatInsertGrowableList(cUnit, bottomBlock->fallThrough->predecessors,
208 (intptr_t)bottomBlock);
209 }
210
211 /* Handle the successor list */
212 if (origBlock->successorBlockList.blockListType != kNotUsed) {
213 bottomBlock->successorBlockList = origBlock->successorBlockList;
214 origBlock->successorBlockList.blockListType = kNotUsed;
215 GrowableListIterator iterator;
216
217 oatGrowableListIteratorInit(&bottomBlock->successorBlockList.blocks,
218 &iterator);
219 while (true) {
220 SuccessorBlockInfo *successorBlockInfo =
221 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
222 if (successorBlockInfo == NULL) break;
223 BasicBlock *bb = successorBlockInfo->block;
224 oatDeleteGrowableList(bb->predecessors, (intptr_t)origBlock);
225 oatInsertGrowableList(cUnit, bb->predecessors, (intptr_t)bottomBlock);
buzbee67bf8852011-08-17 17:51:35 -0700226 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700227 }
buzbee67bf8852011-08-17 17:51:35 -0700228
Bill Buzbeea114add2012-05-03 15:00:40 -0700229 origBlock->lastMIRInsn = insn->prev;
buzbee67bf8852011-08-17 17:51:35 -0700230
Bill Buzbeea114add2012-05-03 15:00:40 -0700231 insn->prev->next = NULL;
232 insn->prev = NULL;
233 /*
234 * Update the immediate predecessor block pointer so that outgoing edges
235 * can be applied to the proper block.
236 */
237 if (immedPredBlockP) {
238 DCHECK_EQ(*immedPredBlockP, origBlock);
239 *immedPredBlockP = bottomBlock;
240 }
241 return bottomBlock;
buzbee67bf8852011-08-17 17:51:35 -0700242}
243
244/*
245 * Given a code offset, find out the block that starts with it. If the offset
buzbee9ab05de2012-01-18 15:43:48 -0800246 * is in the middle of an existing block, split it into two. If immedPredBlockP
247 * is not non-null and is the block being split, update *immedPredBlockP to
248 * point to the bottom block so that outgoing edges can be set up properly
249 * (by the caller)
buzbee5b537102012-01-17 17:33:47 -0800250 * Utilizes a map for fast lookup of the typical cases.
buzbee67bf8852011-08-17 17:51:35 -0700251 */
buzbee31a4a6f2012-02-28 15:36:15 -0800252BasicBlock *findBlock(CompilationUnit* cUnit, unsigned int codeOffset,
253 bool split, bool create, BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700254{
Bill Buzbeea114add2012-05-03 15:00:40 -0700255 GrowableList* blockList = &cUnit->blockList;
256 BasicBlock* bb;
257 unsigned int i;
258 SafeMap<unsigned int, BasicBlock*>::iterator it;
buzbee67bf8852011-08-17 17:51:35 -0700259
Bill Buzbeea114add2012-05-03 15:00:40 -0700260 it = cUnit->blockMap.find(codeOffset);
261 if (it != cUnit->blockMap.end()) {
262 return it->second;
263 } else if (!create) {
264 return NULL;
265 }
266
267 if (split) {
268 for (i = 0; i < blockList->numUsed; i++) {
269 bb = (BasicBlock *) blockList->elemList[i];
270 if (bb->blockType != kDalvikByteCode) continue;
271 /* Check if a branch jumps into the middle of an existing block */
272 if ((codeOffset > bb->startOffset) && (bb->lastMIRInsn != NULL) &&
273 (codeOffset <= bb->lastMIRInsn->offset)) {
274 BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb,
275 bb == *immedPredBlockP ?
276 immedPredBlockP : NULL);
277 return newBB;
278 }
buzbee5b537102012-01-17 17:33:47 -0800279 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700280 }
buzbee5b537102012-01-17 17:33:47 -0800281
Bill Buzbeea114add2012-05-03 15:00:40 -0700282 /* Create a new one */
283 bb = oatNewBB(cUnit, kDalvikByteCode, cUnit->numBlocks++);
284 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) bb);
285 bb->startOffset = codeOffset;
286 cUnit->blockMap.Put(bb->startOffset, bb);
287 return bb;
buzbee67bf8852011-08-17 17:51:35 -0700288}
289
buzbeef58c12c2012-07-03 15:06:29 -0700290/* Find existing block */
291BasicBlock* oatFindBlock(CompilationUnit* cUnit, unsigned int codeOffset)
292{
293 return findBlock(cUnit, codeOffset, false, false, NULL);
294}
295
buzbeead8f15e2012-06-18 14:49:45 -0700296/* Turn method name into a legal Linux file name */
297void oatReplaceSpecialChars(std::string& str)
298{
299 static const struct { const char before; const char after; } match[] =
300 {{'/','-'}, {';','#'}, {' ','#'}, {'$','+'},
301 {'(','@'}, {')','@'}, {'<','='}, {'>','='}};
302 for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) {
303 std::replace(str.begin(), str.end(), match[i].before, match[i].after);
304 }
305}
306
buzbee67bf8852011-08-17 17:51:35 -0700307/* Dump the CFG into a DOT graph */
308void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix)
309{
Bill Buzbeea114add2012-05-03 15:00:40 -0700310 FILE* file;
buzbeead8f15e2012-06-18 14:49:45 -0700311 std::string fname(PrettyMethod(cUnit->method_idx, *cUnit->dex_file));
312 oatReplaceSpecialChars(fname);
313 fname = StringPrintf("%s%s%x.dot", dirPrefix, fname.c_str(),
314 cUnit->entryBlock->fallThrough->startOffset);
315 file = fopen(fname.c_str(), "w");
Bill Buzbeea114add2012-05-03 15:00:40 -0700316 if (file == NULL) {
317 return;
318 }
319 fprintf(file, "digraph G {\n");
320
321 fprintf(file, " rankdir=TB\n");
322
323 int numReachableBlocks = cUnit->numReachableBlocks;
324 int idx;
325 const GrowableList *blockList = &cUnit->blockList;
326
327 for (idx = 0; idx < numReachableBlocks; idx++) {
328 int blockIdx = cUnit->dfsOrder.elemList[idx];
329 BasicBlock *bb = (BasicBlock *) oatGrowableListGetElement(blockList,
330 blockIdx);
331 if (bb == NULL) break;
buzbeed1643e42012-09-05 14:06:51 -0700332 if (bb->blockType == kDead) continue;
Bill Buzbeea114add2012-05-03 15:00:40 -0700333 if (bb->blockType == kEntryBlock) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700334 fprintf(file, " entry_%d [shape=Mdiamond];\n", bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700335 } else if (bb->blockType == kExitBlock) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700336 fprintf(file, " exit_%d [shape=Mdiamond];\n", bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700337 } else if (bb->blockType == kDalvikByteCode) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700338 fprintf(file, " block%04x_%d [shape=record,label = \"{ \\\n",
339 bb->startOffset, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700340 const MIR *mir;
341 fprintf(file, " {block id %d\\l}%s\\\n", bb->id,
342 bb->firstMIRInsn ? " | " : " ");
343 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
344 fprintf(file, " {%04x %s\\l}%s\\\n", mir->offset,
345 mir->ssaRep ? oatFullDisassembler(cUnit, mir) :
346 Instruction::Name(mir->dalvikInsn.opcode),
347 mir->next ? " | " : " ");
348 }
349 fprintf(file, " }\"];\n\n");
350 } else if (bb->blockType == kExceptionHandling) {
351 char blockName[BLOCK_NAME_LEN];
352
353 oatGetBlockName(bb, blockName);
354 fprintf(file, " %s [shape=invhouse];\n", blockName);
buzbee67bf8852011-08-17 17:51:35 -0700355 }
buzbee67bf8852011-08-17 17:51:35 -0700356
Bill Buzbeea114add2012-05-03 15:00:40 -0700357 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
buzbee67bf8852011-08-17 17:51:35 -0700358
Bill Buzbeea114add2012-05-03 15:00:40 -0700359 if (bb->taken) {
360 oatGetBlockName(bb, blockName1);
361 oatGetBlockName(bb->taken, blockName2);
362 fprintf(file, " %s:s -> %s:n [style=dotted]\n",
363 blockName1, blockName2);
buzbee67bf8852011-08-17 17:51:35 -0700364 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700365 if (bb->fallThrough) {
366 oatGetBlockName(bb, blockName1);
367 oatGetBlockName(bb->fallThrough, blockName2);
368 fprintf(file, " %s:s -> %s:n\n", blockName1, blockName2);
369 }
370
371 if (bb->successorBlockList.blockListType != kNotUsed) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700372 fprintf(file, " succ%04x_%d [shape=%s,label = \"{ \\\n",
373 bb->startOffset, bb->id,
Bill Buzbeea114add2012-05-03 15:00:40 -0700374 (bb->successorBlockList.blockListType == kCatch) ?
375 "Mrecord" : "record");
376 GrowableListIterator iterator;
377 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
378 &iterator);
379 SuccessorBlockInfo *successorBlockInfo =
380 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
381
382 int succId = 0;
383 while (true) {
384 if (successorBlockInfo == NULL) break;
385
386 BasicBlock *destBlock = successorBlockInfo->block;
387 SuccessorBlockInfo *nextSuccessorBlockInfo =
388 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
389
390 fprintf(file, " {<f%d> %04x: %04x\\l}%s\\\n",
391 succId++,
392 successorBlockInfo->key,
393 destBlock->startOffset,
394 (nextSuccessorBlockInfo != NULL) ? " | " : " ");
395
396 successorBlockInfo = nextSuccessorBlockInfo;
397 }
398 fprintf(file, " }\"];\n\n");
399
400 oatGetBlockName(bb, blockName1);
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700401 fprintf(file, " %s:s -> succ%04x_%d:n [style=dashed]\n",
402 blockName1, bb->startOffset, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700403
404 if (bb->successorBlockList.blockListType == kPackedSwitch ||
405 bb->successorBlockList.blockListType == kSparseSwitch) {
406
407 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
408 &iterator);
409
410 succId = 0;
411 while (true) {
412 SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
413 oatGrowableListIteratorNext(&iterator);
414 if (successorBlockInfo == NULL) break;
415
416 BasicBlock *destBlock = successorBlockInfo->block;
417
418 oatGetBlockName(destBlock, blockName2);
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700419 fprintf(file, " succ%04x_%d:f%d:e -> %s:n\n", bb->startOffset,
420 bb->id, succId++, blockName2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700421 }
422 }
423 }
424 fprintf(file, "\n");
425
426 /* Display the dominator tree */
427 oatGetBlockName(bb, blockName1);
428 fprintf(file, " cfg%s [label=\"%s\", shape=none];\n",
429 blockName1, blockName1);
430 if (bb->iDom) {
431 oatGetBlockName(bb->iDom, blockName2);
432 fprintf(file, " cfg%s:s -> cfg%s:n\n\n", blockName2, blockName1);
433 }
434 }
435 fprintf(file, "}\n");
436 fclose(file);
buzbee67bf8852011-08-17 17:51:35 -0700437}
438
439/* Verify if all the successor is connected with all the claimed predecessors */
buzbee31a4a6f2012-02-28 15:36:15 -0800440bool verifyPredInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700441{
Bill Buzbeea114add2012-05-03 15:00:40 -0700442 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700443
Bill Buzbeea114add2012-05-03 15:00:40 -0700444 oatGrowableListIteratorInit(bb->predecessors, &iter);
445 while (true) {
446 BasicBlock *predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
447 if (!predBB) break;
448 bool found = false;
449 if (predBB->taken == bb) {
450 found = true;
451 } else if (predBB->fallThrough == bb) {
452 found = true;
453 } else if (predBB->successorBlockList.blockListType != kNotUsed) {
454 GrowableListIterator iterator;
455 oatGrowableListIteratorInit(&predBB->successorBlockList.blocks,
456 &iterator);
457 while (true) {
458 SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
459 oatGrowableListIteratorNext(&iterator);
460 if (successorBlockInfo == NULL) break;
461 BasicBlock *succBB = successorBlockInfo->block;
462 if (succBB == bb) {
buzbee67bf8852011-08-17 17:51:35 -0700463 found = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700464 break;
buzbee67bf8852011-08-17 17:51:35 -0700465 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700466 }
buzbee67bf8852011-08-17 17:51:35 -0700467 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700468 if (found == false) {
469 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
470 oatGetBlockName(bb, blockName1);
471 oatGetBlockName(predBB, blockName2);
472 oatDumpCFG(cUnit, "/sdcard/cfg/");
473 LOG(FATAL) << "Successor " << blockName1 << "not found from "
474 << blockName2;
475 }
476 }
477 return true;
buzbee67bf8852011-08-17 17:51:35 -0700478}
479
480/* Identify code range in try blocks and set up the empty catch blocks */
buzbee31a4a6f2012-02-28 15:36:15 -0800481void processTryCatchBlocks(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700482{
Bill Buzbeea114add2012-05-03 15:00:40 -0700483 const DexFile::CodeItem* code_item = cUnit->code_item;
484 int triesSize = code_item->tries_size_;
485 int offset;
buzbee67bf8852011-08-17 17:51:35 -0700486
Bill Buzbeea114add2012-05-03 15:00:40 -0700487 if (triesSize == 0) {
488 return;
489 }
490
491 ArenaBitVector* tryBlockAddr = cUnit->tryBlockAddr;
492
493 for (int i = 0; i < triesSize; i++) {
494 const DexFile::TryItem* pTry =
495 DexFile::GetTryItems(*code_item, i);
496 int startOffset = pTry->start_addr_;
497 int endOffset = startOffset + pTry->insn_count_;
498 for (offset = startOffset; offset < endOffset; offset++) {
499 oatSetBit(cUnit, tryBlockAddr, offset);
buzbee67bf8852011-08-17 17:51:35 -0700500 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700501 }
buzbee67bf8852011-08-17 17:51:35 -0700502
Bill Buzbeea114add2012-05-03 15:00:40 -0700503 // Iterate over each of the handlers to enqueue the empty Catch blocks
504 const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item, 0);
505 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
506 for (uint32_t idx = 0; idx < handlers_size; idx++) {
507 CatchHandlerIterator iterator(handlers_ptr);
508 for (; iterator.HasNext(); iterator.Next()) {
509 uint32_t address = iterator.GetHandlerAddress();
510 findBlock(cUnit, address, false /* split */, true /*create*/,
511 /* immedPredBlockP */ NULL);
buzbee67bf8852011-08-17 17:51:35 -0700512 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700513 handlers_ptr = iterator.EndDataPointer();
514 }
buzbee67bf8852011-08-17 17:51:35 -0700515}
516
Elliott Hughesadb8c672012-03-06 16:49:32 -0800517/* Process instructions with the kBranch flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800518BasicBlock* processCanBranch(CompilationUnit* cUnit, BasicBlock* curBlock,
Bill Buzbeea114add2012-05-03 15:00:40 -0700519 MIR* insn, int curOffset, int width, int flags,
520 const u2* codePtr, const u2* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700521{
Bill Buzbeea114add2012-05-03 15:00:40 -0700522 int target = curOffset;
523 switch (insn->dalvikInsn.opcode) {
524 case Instruction::GOTO:
525 case Instruction::GOTO_16:
526 case Instruction::GOTO_32:
527 target += (int) insn->dalvikInsn.vA;
528 break;
529 case Instruction::IF_EQ:
530 case Instruction::IF_NE:
531 case Instruction::IF_LT:
532 case Instruction::IF_GE:
533 case Instruction::IF_GT:
534 case Instruction::IF_LE:
buzbee0967a252012-09-14 10:43:54 -0700535 curBlock->conditionalBranch = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700536 target += (int) insn->dalvikInsn.vC;
537 break;
538 case Instruction::IF_EQZ:
539 case Instruction::IF_NEZ:
540 case Instruction::IF_LTZ:
541 case Instruction::IF_GEZ:
542 case Instruction::IF_GTZ:
543 case Instruction::IF_LEZ:
buzbee0967a252012-09-14 10:43:54 -0700544 curBlock->conditionalBranch = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700545 target += (int) insn->dalvikInsn.vB;
546 break;
547 default:
548 LOG(FATAL) << "Unexpected opcode(" << (int)insn->dalvikInsn.opcode
549 << ") with kBranch set";
550 }
551 BasicBlock *takenBlock = findBlock(cUnit, target,
552 /* split */
553 true,
554 /* create */
555 true,
556 /* immedPredBlockP */
557 &curBlock);
558 curBlock->taken = takenBlock;
559 oatInsertGrowableList(cUnit, takenBlock->predecessors, (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700560
Bill Buzbeea114add2012-05-03 15:00:40 -0700561 /* Always terminate the current block for conditional branches */
562 if (flags & Instruction::kContinue) {
563 BasicBlock *fallthroughBlock = findBlock(cUnit,
564 curOffset + width,
565 /*
566 * If the method is processed
567 * in sequential order from the
568 * beginning, we don't need to
569 * specify split for continue
570 * blocks. However, this
571 * routine can be called by
572 * compileLoop, which starts
573 * parsing the method from an
574 * arbitrary address in the
575 * method body.
576 */
577 true,
578 /* create */
579 true,
580 /* immedPredBlockP */
581 &curBlock);
582 curBlock->fallThrough = fallthroughBlock;
583 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
584 (intptr_t)curBlock);
585 } else if (codePtr < codeEnd) {
586 /* Create a fallthrough block for real instructions (incl. NOP) */
587 if (contentIsInsn(codePtr)) {
588 findBlock(cUnit, curOffset + width,
589 /* split */
590 false,
591 /* create */
592 true,
593 /* immedPredBlockP */
594 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700595 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700596 }
597 return curBlock;
buzbee67bf8852011-08-17 17:51:35 -0700598}
599
Elliott Hughesadb8c672012-03-06 16:49:32 -0800600/* Process instructions with the kSwitch flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800601void processCanSwitch(CompilationUnit* cUnit, BasicBlock* curBlock,
602 MIR* insn, int curOffset, int width, int flags)
buzbee67bf8852011-08-17 17:51:35 -0700603{
Bill Buzbeea114add2012-05-03 15:00:40 -0700604 u2* switchData= (u2 *) (cUnit->insns + curOffset + insn->dalvikInsn.vB);
605 int size;
606 int* keyTable;
607 int* targetTable;
608 int i;
609 int firstKey;
buzbee67bf8852011-08-17 17:51:35 -0700610
Bill Buzbeea114add2012-05-03 15:00:40 -0700611 /*
612 * Packed switch data format:
613 * ushort ident = 0x0100 magic value
614 * ushort size number of entries in the table
615 * int first_key first (and lowest) switch case value
616 * int targets[size] branch targets, relative to switch opcode
617 *
618 * Total size is (4+size*2) 16-bit code units.
619 */
620 if (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) {
621 DCHECK_EQ(static_cast<int>(switchData[0]),
622 static_cast<int>(Instruction::kPackedSwitchSignature));
623 size = switchData[1];
624 firstKey = switchData[2] | (switchData[3] << 16);
625 targetTable = (int *) &switchData[4];
626 keyTable = NULL; // Make the compiler happy
627 /*
628 * Sparse switch data format:
629 * ushort ident = 0x0200 magic value
630 * ushort size number of entries in the table; > 0
631 * int keys[size] keys, sorted low-to-high; 32-bit aligned
632 * int targets[size] branch targets, relative to switch opcode
633 *
634 * Total size is (2+size*4) 16-bit code units.
635 */
636 } else {
637 DCHECK_EQ(static_cast<int>(switchData[0]),
638 static_cast<int>(Instruction::kSparseSwitchSignature));
639 size = switchData[1];
640 keyTable = (int *) &switchData[2];
641 targetTable = (int *) &switchData[2 + size*2];
642 firstKey = 0; // To make the compiler happy
643 }
buzbee67bf8852011-08-17 17:51:35 -0700644
Bill Buzbeea114add2012-05-03 15:00:40 -0700645 if (curBlock->successorBlockList.blockListType != kNotUsed) {
646 LOG(FATAL) << "Successor block list already in use: "
647 << (int)curBlock->successorBlockList.blockListType;
648 }
649 curBlock->successorBlockList.blockListType =
650 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
651 kPackedSwitch : kSparseSwitch;
652 oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, size,
653 kListSuccessorBlocks);
654
655 for (i = 0; i < size; i++) {
656 BasicBlock *caseBlock = findBlock(cUnit, curOffset + targetTable[i],
657 /* split */
658 true,
659 /* create */
660 true,
661 /* immedPredBlockP */
662 &curBlock);
663 SuccessorBlockInfo *successorBlockInfo =
664 (SuccessorBlockInfo *) oatNew(cUnit, sizeof(SuccessorBlockInfo),
665 false, kAllocSuccessor);
666 successorBlockInfo->block = caseBlock;
667 successorBlockInfo->key =
Elliott Hughesadb8c672012-03-06 16:49:32 -0800668 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
Bill Buzbeea114add2012-05-03 15:00:40 -0700669 firstKey + i : keyTable[i];
670 oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
671 (intptr_t) successorBlockInfo);
672 oatInsertGrowableList(cUnit, caseBlock->predecessors,
buzbeeba938cb2012-02-03 14:47:55 -0800673 (intptr_t)curBlock);
Bill Buzbeea114add2012-05-03 15:00:40 -0700674 }
675
676 /* Fall-through case */
677 BasicBlock* fallthroughBlock = findBlock(cUnit,
678 curOffset + width,
679 /* split */
680 false,
681 /* create */
682 true,
683 /* immedPredBlockP */
684 NULL);
685 curBlock->fallThrough = fallthroughBlock;
686 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
687 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700688}
689
Elliott Hughesadb8c672012-03-06 16:49:32 -0800690/* Process instructions with the kThrow flag */
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700691BasicBlock* processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock,
692 MIR* insn, int curOffset, int width, int flags,
693 ArenaBitVector* tryBlockAddr, const u2* codePtr,
694 const u2* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700695{
Bill Buzbeea114add2012-05-03 15:00:40 -0700696 const DexFile::CodeItem* code_item = cUnit->code_item;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700697 bool inTryBlock = oatIsBitSet(tryBlockAddr, curOffset);
buzbee67bf8852011-08-17 17:51:35 -0700698
Bill Buzbeea114add2012-05-03 15:00:40 -0700699 /* In try block */
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700700 if (inTryBlock) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700701 CatchHandlerIterator iterator(*code_item, curOffset);
buzbee67bf8852011-08-17 17:51:35 -0700702
Bill Buzbeea114add2012-05-03 15:00:40 -0700703 if (curBlock->successorBlockList.blockListType != kNotUsed) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700704 LOG(INFO) << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
Bill Buzbeea114add2012-05-03 15:00:40 -0700705 LOG(FATAL) << "Successor block list already in use: "
706 << (int)curBlock->successorBlockList.blockListType;
buzbee67bf8852011-08-17 17:51:35 -0700707 }
708
Bill Buzbeea114add2012-05-03 15:00:40 -0700709 curBlock->successorBlockList.blockListType = kCatch;
710 oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, 2,
711 kListSuccessorBlocks);
712
713 for (;iterator.HasNext(); iterator.Next()) {
714 BasicBlock *catchBlock = findBlock(cUnit, iterator.GetHandlerAddress(),
715 false /* split*/,
716 false /* creat */,
717 NULL /* immedPredBlockP */);
718 catchBlock->catchEntry = true;
buzbee6459e7c2012-10-02 14:42:41 -0700719 cUnit->catches.insert(catchBlock->startOffset);
Bill Buzbeea114add2012-05-03 15:00:40 -0700720 SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
721 oatNew(cUnit, sizeof(SuccessorBlockInfo), false, kAllocSuccessor);
722 successorBlockInfo->block = catchBlock;
723 successorBlockInfo->key = iterator.GetHandlerTypeIndex();
724 oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
725 (intptr_t) successorBlockInfo);
726 oatInsertGrowableList(cUnit, catchBlock->predecessors,
727 (intptr_t)curBlock);
buzbee67bf8852011-08-17 17:51:35 -0700728 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700729 } else {
730 BasicBlock *ehBlock = oatNewBB(cUnit, kExceptionHandling,
731 cUnit->numBlocks++);
732 curBlock->taken = ehBlock;
733 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) ehBlock);
734 ehBlock->startOffset = curOffset;
735 oatInsertGrowableList(cUnit, ehBlock->predecessors, (intptr_t)curBlock);
736 }
737
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700738 if (insn->dalvikInsn.opcode == Instruction::THROW){
buzbee0967a252012-09-14 10:43:54 -0700739 curBlock->explicitThrow = true;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700740 if ((codePtr < codeEnd) && contentIsInsn(codePtr)) {
741 // Force creation of new block following THROW via side-effect
742 findBlock(cUnit, curOffset + width, /* split */ false,
743 /* create */ true, /* immedPredBlockP */ NULL);
744 }
745 if (!inTryBlock) {
746 // Don't split a THROW that can't rethrow - we're done.
747 return curBlock;
Bill Buzbeea114add2012-05-03 15:00:40 -0700748 }
749 }
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700750
751 /*
752 * Split the potentially-throwing instruction into two parts.
753 * The first half will be a pseudo-op that captures the exception
754 * edges and terminates the basic block. It always falls through.
755 * Then, create a new basic block that begins with the throwing instruction
756 * (minus exceptions). Note: this new basic block must NOT be entered into
757 * the blockMap. If the potentially-throwing instruction is the target of a
758 * future branch, we need to find the check psuedo half. The new
759 * basic block containing the work portion of the instruction should
760 * only be entered via fallthrough from the block containing the
761 * pseudo exception edge MIR. Note also that this new block is
762 * not automatically terminated after the work portion, and may
763 * contain following instructions.
764 */
765 BasicBlock *newBlock = oatNewBB(cUnit, kDalvikByteCode, cUnit->numBlocks++);
766 oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t)newBlock);
767 newBlock->startOffset = insn->offset;
768 curBlock->fallThrough = newBlock;
769 oatInsertGrowableList(cUnit, newBlock->predecessors, (intptr_t)curBlock);
770 MIR* newInsn = (MIR*)oatNew(cUnit, sizeof(MIR), true, kAllocMIR);
771 *newInsn = *insn;
772 insn->dalvikInsn.opcode =
773 static_cast<Instruction::Code>(kMirOpCheck);
774 // Associate the two halves
775 insn->meta.throwInsn = newInsn;
776 newInsn->meta.throwInsn = insn;
777 oatAppendMIR(newBlock, newInsn);
778 return newBlock;
buzbee67bf8852011-08-17 17:51:35 -0700779}
780
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800781void oatInit(CompilationUnit* cUnit, const Compiler& compiler) {
782 if (!oatArchInit()) {
783 LOG(FATAL) << "Failed to initialize oat";
784 }
785 if (!oatHeapInit(cUnit)) {
786 LOG(FATAL) << "Failed to initialize oat heap";
787 }
788}
789
buzbeeabc4c6b2012-08-23 08:17:15 -0700790CompiledMethod* compileMethod(Compiler& compiler,
791 const DexFile::CodeItem* code_item,
792 uint32_t access_flags, InvokeType invoke_type,
793 uint32_t method_idx, jobject class_loader,
794 const DexFile& dex_file
795#if defined(ART_USE_QUICK_COMPILER)
buzbee4df2bbd2012-10-11 14:46:06 -0700796 , LLVMInfo* llvm_info,
buzbeeabc4c6b2012-08-23 08:17:15 -0700797 bool gbcOnly
798#endif
799 )
buzbee67bf8852011-08-17 17:51:35 -0700800{
Bill Buzbeea114add2012-05-03 15:00:40 -0700801 VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
Brian Carlstrom94496d32011-08-22 09:22:47 -0700802
Bill Buzbeea114add2012-05-03 15:00:40 -0700803 const u2* codePtr = code_item->insns_;
804 const u2* codeEnd = code_item->insns_ + code_item->insns_size_in_code_units_;
805 int numBlocks = 0;
806 unsigned int curOffset = 0;
buzbee67bf8852011-08-17 17:51:35 -0700807
Bill Buzbeea114add2012-05-03 15:00:40 -0700808 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
809 UniquePtr<CompilationUnit> cUnit(new CompilationUnit);
buzbeeba938cb2012-02-03 14:47:55 -0800810
Bill Buzbeea114add2012-05-03 15:00:40 -0700811 oatInit(cUnit.get(), compiler);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800812
Bill Buzbeea114add2012-05-03 15:00:40 -0700813 cUnit->compiler = &compiler;
814 cUnit->class_linker = class_linker;
815 cUnit->dex_file = &dex_file;
Bill Buzbeea114add2012-05-03 15:00:40 -0700816 cUnit->method_idx = method_idx;
817 cUnit->code_item = code_item;
818 cUnit->access_flags = access_flags;
Ian Rogers08f753d2012-08-24 14:35:25 -0700819 cUnit->invoke_type = invoke_type;
Bill Buzbeea114add2012-05-03 15:00:40 -0700820 cUnit->shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
821 cUnit->instructionSet = compiler.GetInstructionSet();
822 cUnit->insns = code_item->insns_;
823 cUnit->insnsSize = code_item->insns_size_in_code_units_;
824 cUnit->numIns = code_item->ins_size_;
825 cUnit->numRegs = code_item->registers_size_ - cUnit->numIns;
826 cUnit->numOuts = code_item->outs_size_;
buzbee2cfc6392012-05-07 14:51:40 -0700827#if defined(ART_USE_QUICK_COMPILER)
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700828 DCHECK((cUnit->instructionSet == kThumb2) ||
829 (cUnit->instructionSet == kX86) ||
830 (cUnit->instructionSet == kMips));
buzbee4df2bbd2012-10-11 14:46:06 -0700831 cUnit->llvm_info = llvm_info;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700832 if (cUnit->instructionSet == kThumb2) {
833 // TODO: remove this once x86 is tested
buzbee85eee022012-07-16 22:12:38 -0700834 cUnit->genBitcode = true;
835 }
buzbee2a83e8f2012-07-13 16:42:30 -0700836#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700837 /* Adjust this value accordingly once inlining is performed */
838 cUnit->numDalvikRegisters = code_item->registers_size_;
839 // TODO: set this from command line
840 cUnit->compilerFlipMatch = false;
841 bool useMatch = !cUnit->compilerMethodMatch.empty();
842 bool match = useMatch && (cUnit->compilerFlipMatch ^
843 (PrettyMethod(method_idx, dex_file).find(cUnit->compilerMethodMatch) !=
844 std::string::npos));
845 if (!useMatch || match) {
846 cUnit->disableOpt = kCompilerOptimizerDisableFlags;
847 cUnit->enableDebug = kCompilerDebugFlags;
848 cUnit->printMe = VLOG_IS_ON(compiler) ||
849 (cUnit->enableDebug & (1 << kDebugVerbose));
850 }
buzbee2cfc6392012-05-07 14:51:40 -0700851#if defined(ART_USE_QUICK_COMPILER)
buzbee6969d502012-06-15 16:40:31 -0700852 if (cUnit->genBitcode) {
buzbee6459e7c2012-10-02 14:42:41 -0700853#ifndef NDEBUG
854 cUnit->enableDebug |= (1 << kDebugVerifyBitcode);
855#endif
buzbee2a83e8f2012-07-13 16:42:30 -0700856 //cUnit->printMe = true;
857 //cUnit->enableDebug |= (1 << kDebugDumpBitcodeFile);
buzbee6969d502012-06-15 16:40:31 -0700858 }
buzbee2cfc6392012-05-07 14:51:40 -0700859#endif
jeffhao7fbee072012-08-24 17:56:54 -0700860 if (cUnit->instructionSet == kMips) {
861 // Disable some optimizations for mips for now
862 cUnit->disableOpt |= (
863 (1 << kLoadStoreElimination) |
864 (1 << kLoadHoisting) |
865 (1 << kSuppressLoads) |
866 (1 << kNullCheckElimination) |
867 (1 << kPromoteRegs) |
868 (1 << kTrackLiveTemps) |
869 (1 << kSkipLargeMethodOptimization) |
870 (1 << kSafeOptimizations) |
871 (1 << kBBOpt) |
872 (1 << kMatch) |
873 (1 << kPromoteCompilerTemps));
874 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700875 /* Are we generating code for the debugger? */
876 if (compiler.IsDebuggingSupported()) {
877 cUnit->genDebugger = true;
878 // Yes, disable most optimizations
879 cUnit->disableOpt |= (
880 (1 << kLoadStoreElimination) |
881 (1 << kLoadHoisting) |
882 (1 << kSuppressLoads) |
883 (1 << kPromoteRegs) |
884 (1 << kBBOpt) |
885 (1 << kMatch) |
886 (1 << kTrackLiveTemps));
887 }
888
889 /* Gathering opcode stats? */
890 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
891 cUnit->opcodeCount = (int*)oatNew(cUnit.get(),
892 kNumPackedOpcodes * sizeof(int), true, kAllocMisc);
893 }
894
895 /* Assume non-throwing leaf */
896 cUnit->attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE);
897
898 /* Initialize the block list, estimate size based on insnsSize */
899 oatInitGrowableList(cUnit.get(), &cUnit->blockList, cUnit->insnsSize,
900 kListBlockList);
901
902 /* Initialize the switchTables list */
903 oatInitGrowableList(cUnit.get(), &cUnit->switchTables, 4,
904 kListSwitchTables);
905
906 /* Intialize the fillArrayData list */
907 oatInitGrowableList(cUnit.get(), &cUnit->fillArrayData, 4,
908 kListFillArrayData);
909
910 /* Intialize the throwLaunchpads list, estimate size based on insnsSize */
911 oatInitGrowableList(cUnit.get(), &cUnit->throwLaunchpads, cUnit->insnsSize,
912 kListThrowLaunchPads);
913
914 /* Intialize the instrinsicLaunchpads list */
915 oatInitGrowableList(cUnit.get(), &cUnit->intrinsicLaunchpads, 4,
916 kListMisc);
917
918
919 /* Intialize the suspendLaunchpads list */
920 oatInitGrowableList(cUnit.get(), &cUnit->suspendLaunchpads, 2048,
921 kListSuspendLaunchPads);
922
923 /* Allocate the bit-vector to track the beginning of basic blocks */
924 ArenaBitVector *tryBlockAddr = oatAllocBitVector(cUnit.get(),
925 cUnit->insnsSize,
926 true /* expandable */);
927 cUnit->tryBlockAddr = tryBlockAddr;
928
929 /* Create the default entry and exit blocks and enter them to the list */
930 BasicBlock *entryBlock = oatNewBB(cUnit.get(), kEntryBlock, numBlocks++);
931 BasicBlock *exitBlock = oatNewBB(cUnit.get(), kExitBlock, numBlocks++);
932
933 cUnit->entryBlock = entryBlock;
934 cUnit->exitBlock = exitBlock;
935
936 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) entryBlock);
937 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) exitBlock);
938
939 /* Current block to record parsed instructions */
940 BasicBlock *curBlock = oatNewBB(cUnit.get(), kDalvikByteCode, numBlocks++);
941 curBlock->startOffset = 0;
942 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) curBlock);
943 /* Add first block to the fast lookup cache */
944 cUnit->blockMap.Put(curBlock->startOffset, curBlock);
945 entryBlock->fallThrough = curBlock;
946 oatInsertGrowableList(cUnit.get(), curBlock->predecessors,
947 (intptr_t)entryBlock);
948
949 /*
950 * Store back the number of blocks since new blocks may be created of
951 * accessing cUnit.
952 */
953 cUnit->numBlocks = numBlocks;
954
955 /* Identify code range in try blocks and set up the empty catch blocks */
956 processTryCatchBlocks(cUnit.get());
957
958 /* Set up for simple method detection */
959 int numPatterns = sizeof(specialPatterns)/sizeof(specialPatterns[0]);
960 bool livePattern = (numPatterns > 0) && !(cUnit->disableOpt & (1 << kMatch));
Elliott Hughesabe64aa2012-05-30 17:34:45 -0700961 bool* deadPattern = (bool*)oatNew(cUnit.get(), sizeof(bool) * numPatterns, true,
Bill Buzbeea114add2012-05-03 15:00:40 -0700962 kAllocMisc);
963 SpecialCaseHandler specialCase = kNoHandler;
964 int patternPos = 0;
965
966 /* Parse all instructions and put them into containing basic blocks */
967 while (codePtr < codeEnd) {
968 MIR *insn = (MIR *) oatNew(cUnit.get(), sizeof(MIR), true, kAllocMIR);
969 insn->offset = curOffset;
970 int width = parseInsn(cUnit.get(), codePtr, &insn->dalvikInsn, false);
971 insn->width = width;
972 Instruction::Code opcode = insn->dalvikInsn.opcode;
973 if (cUnit->opcodeCount != NULL) {
974 cUnit->opcodeCount[static_cast<int>(opcode)]++;
buzbee44b412b2012-02-04 08:50:53 -0800975 }
976
Bill Buzbeea114add2012-05-03 15:00:40 -0700977 /* Terminate when the data section is seen */
978 if (width == 0)
979 break;
980
981 /* Possible simple method? */
982 if (livePattern) {
983 livePattern = false;
984 specialCase = kNoHandler;
985 for (int i = 0; i < numPatterns; i++) {
986 if (!deadPattern[i]) {
987 if (specialPatterns[i].opcodes[patternPos] == opcode) {
988 livePattern = true;
989 specialCase = specialPatterns[i].handlerCode;
990 } else {
991 deadPattern[i] = true;
992 }
993 }
994 }
995 patternPos++;
buzbeea7c12682012-03-19 13:13:53 -0700996 }
997
Bill Buzbeea114add2012-05-03 15:00:40 -0700998 oatAppendMIR(curBlock, insn);
buzbeecefd1872011-09-09 09:59:52 -0700999
Bill Buzbeea114add2012-05-03 15:00:40 -07001000 codePtr += width;
Ian Rogersa75a0132012-09-28 11:41:42 -07001001 int flags = Instruction::FlagsOf(insn->dalvikInsn.opcode);
buzbee67bf8852011-08-17 17:51:35 -07001002
Bill Buzbeea114add2012-05-03 15:00:40 -07001003 int dfFlags = oatDataFlowAttributes[insn->dalvikInsn.opcode];
buzbee67bf8852011-08-17 17:51:35 -07001004
Bill Buzbeea114add2012-05-03 15:00:40 -07001005 if (dfFlags & DF_HAS_DEFS) {
buzbeebff24652012-05-06 16:22:05 -07001006 cUnit->defCount += (dfFlags & DF_A_WIDE) ? 2 : 1;
Bill Buzbeea114add2012-05-03 15:00:40 -07001007 }
buzbee67bf8852011-08-17 17:51:35 -07001008
Bill Buzbeea114add2012-05-03 15:00:40 -07001009 if (flags & Instruction::kBranch) {
1010 curBlock = processCanBranch(cUnit.get(), curBlock, insn, curOffset,
1011 width, flags, codePtr, codeEnd);
1012 } else if (flags & Instruction::kReturn) {
1013 curBlock->fallThrough = exitBlock;
1014 oatInsertGrowableList(cUnit.get(), exitBlock->predecessors,
1015 (intptr_t)curBlock);
1016 /*
1017 * Terminate the current block if there are instructions
1018 * afterwards.
1019 */
1020 if (codePtr < codeEnd) {
1021 /*
1022 * Create a fallthrough block for real instructions
1023 * (incl. NOP).
1024 */
1025 if (contentIsInsn(codePtr)) {
1026 findBlock(cUnit.get(), curOffset + width,
1027 /* split */
1028 false,
1029 /* create */
1030 true,
1031 /* immedPredBlockP */
1032 NULL);
1033 }
1034 }
1035 } else if (flags & Instruction::kThrow) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -07001036 curBlock = processCanThrow(cUnit.get(), curBlock, insn, curOffset,
1037 width, flags, tryBlockAddr, codePtr, codeEnd);
Bill Buzbeea114add2012-05-03 15:00:40 -07001038 } else if (flags & Instruction::kSwitch) {
1039 processCanSwitch(cUnit.get(), curBlock, insn, curOffset, width, flags);
1040 }
1041 curOffset += width;
1042 BasicBlock *nextBlock = findBlock(cUnit.get(), curOffset,
1043 /* split */
1044 false,
1045 /* create */
1046 false,
1047 /* immedPredBlockP */
1048 NULL);
1049 if (nextBlock) {
1050 /*
1051 * The next instruction could be the target of a previously parsed
1052 * forward branch so a block is already created. If the current
1053 * instruction is not an unconditional branch, connect them through
1054 * the fall-through link.
1055 */
1056 DCHECK(curBlock->fallThrough == NULL ||
1057 curBlock->fallThrough == nextBlock ||
1058 curBlock->fallThrough == exitBlock);
buzbee5ade1d22011-09-09 14:44:52 -07001059
Bill Buzbeea114add2012-05-03 15:00:40 -07001060 if ((curBlock->fallThrough == NULL) && (flags & Instruction::kContinue)) {
1061 curBlock->fallThrough = nextBlock;
1062 oatInsertGrowableList(cUnit.get(), nextBlock->predecessors,
1063 (intptr_t)curBlock);
1064 }
1065 curBlock = nextBlock;
1066 }
1067 }
buzbeefc9e6fa2012-03-23 15:14:29 -07001068
Bill Buzbeea114add2012-05-03 15:00:40 -07001069 if (!(cUnit->disableOpt & (1 << kSkipLargeMethodOptimization))) {
1070 if ((cUnit->numBlocks > MANY_BLOCKS) ||
1071 ((cUnit->numBlocks > MANY_BLOCKS_INITIALIZER) &&
1072 PrettyMethod(method_idx, dex_file, false).find("init>") !=
1073 std::string::npos)) {
1074 cUnit->qdMode = true;
1075 }
1076 }
buzbeefc9e6fa2012-03-23 15:14:29 -07001077
Bill Buzbeea114add2012-05-03 15:00:40 -07001078 if (cUnit->qdMode) {
buzbeed1643e42012-09-05 14:06:51 -07001079#if !defined(ART_USE_QUICK_COMPILER)
1080 // Bitcode generation requires full dataflow analysis
Bill Buzbeea114add2012-05-03 15:00:40 -07001081 cUnit->disableDataflow = true;
buzbeed1643e42012-09-05 14:06:51 -07001082#endif
Bill Buzbeea114add2012-05-03 15:00:40 -07001083 // Disable optimization which require dataflow/ssa
1084 cUnit->disableOpt |=
buzbeed1643e42012-09-05 14:06:51 -07001085#if !defined(ART_USE_QUICK_COMPILER)
Bill Buzbeea114add2012-05-03 15:00:40 -07001086 (1 << kNullCheckElimination) |
buzbeed1643e42012-09-05 14:06:51 -07001087#endif
Bill Buzbeea114add2012-05-03 15:00:40 -07001088 (1 << kBBOpt) |
1089 (1 << kPromoteRegs);
1090 if (cUnit->printMe) {
1091 LOG(INFO) << "QD mode enabled: "
1092 << PrettyMethod(method_idx, dex_file)
1093 << " too big: " << cUnit->numBlocks;
1094 }
1095 }
buzbeec1f45042011-09-21 16:03:19 -07001096
Bill Buzbeea114add2012-05-03 15:00:40 -07001097 if (cUnit->printMe) {
1098 oatDumpCompilationUnit(cUnit.get());
1099 }
buzbee67bf8852011-08-17 17:51:35 -07001100
buzbee0967a252012-09-14 10:43:54 -07001101 /* Do a code layout pass */
1102 oatMethodCodeLayout(cUnit.get());
1103
Bill Buzbeea114add2012-05-03 15:00:40 -07001104 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
1105 /* Verify if all blocks are connected as claimed */
1106 oatDataFlowAnalysisDispatcher(cUnit.get(), verifyPredInfo, kAllNodes,
1107 false /* isIterative */);
1108 }
buzbee67bf8852011-08-17 17:51:35 -07001109
Bill Buzbeea114add2012-05-03 15:00:40 -07001110 /* Perform SSA transformation for the whole method */
1111 oatMethodSSATransformation(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001112
buzbee2cfc6392012-05-07 14:51:40 -07001113 /* Do constant propagation */
1114 // TODO: Probably need to make these expandable to support new ssa names
1115 // introducted during MIR optimization passes
1116 cUnit->isConstantV = oatAllocBitVector(cUnit.get(), cUnit->numSSARegs,
1117 false /* not expandable */);
1118 cUnit->constantValues =
1119 (int*)oatNew(cUnit.get(), sizeof(int) * cUnit->numSSARegs, true,
1120 kAllocDFInfo);
1121 oatDataFlowAnalysisDispatcher(cUnit.get(), oatDoConstantPropagation,
1122 kAllNodes,
1123 false /* isIterative */);
1124
Bill Buzbeea114add2012-05-03 15:00:40 -07001125 /* Detect loops */
1126 oatMethodLoopDetection(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001127
Bill Buzbeea114add2012-05-03 15:00:40 -07001128 /* Count uses */
1129 oatMethodUseCount(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001130
Bill Buzbeea114add2012-05-03 15:00:40 -07001131 /* Perform null check elimination */
1132 oatMethodNullCheckElimination(cUnit.get());
1133
buzbeed1643e42012-09-05 14:06:51 -07001134 /* Combine basic blocks where possible */
1135 oatMethodBasicBlockCombine(cUnit.get());
1136
Bill Buzbeea114add2012-05-03 15:00:40 -07001137 /* Do some basic block optimizations */
1138 oatMethodBasicBlockOptimization(cUnit.get());
1139
buzbeed1643e42012-09-05 14:06:51 -07001140 if (cUnit->enableDebug & (1 << kDebugDumpCheckStats)) {
1141 oatDumpCheckStats(cUnit.get());
1142 }
1143
Bill Buzbeea114add2012-05-03 15:00:40 -07001144 oatInitializeRegAlloc(cUnit.get()); // Needs to happen after SSA naming
1145
1146 /* Allocate Registers using simple local allocation scheme */
1147 oatSimpleRegAlloc(cUnit.get());
1148
buzbee2cfc6392012-05-07 14:51:40 -07001149#if defined(ART_USE_QUICK_COMPILER)
1150 /* Go the LLVM path? */
1151 if (cUnit->genBitcode) {
1152 // MIR->Bitcode
1153 oatMethodMIR2Bitcode(cUnit.get());
TDYa12755e5e6c2012-09-11 15:14:42 -07001154 if (gbcOnly) {
buzbeeabc4c6b2012-08-23 08:17:15 -07001155 // all done
1156 oatArenaReset(cUnit.get());
1157 return NULL;
1158 }
buzbee2cfc6392012-05-07 14:51:40 -07001159 // Bitcode->LIR
1160 oatMethodBitcode2LIR(cUnit.get());
1161 } else {
1162#endif
1163 if (specialCase != kNoHandler) {
1164 /*
1165 * Custom codegen for special cases. If for any reason the
1166 * special codegen doesn't succeed, cUnit->firstLIRInsn will
1167 * set to NULL;
1168 */
1169 oatSpecialMIR2LIR(cUnit.get(), specialCase);
1170 }
buzbee67bf8852011-08-17 17:51:35 -07001171
buzbee2cfc6392012-05-07 14:51:40 -07001172 /* Convert MIR to LIR, etc. */
1173 if (cUnit->firstLIRInsn == NULL) {
1174 oatMethodMIR2LIR(cUnit.get());
1175 }
1176#if defined(ART_USE_QUICK_COMPILER)
Bill Buzbeea114add2012-05-03 15:00:40 -07001177 }
buzbee2cfc6392012-05-07 14:51:40 -07001178#endif
buzbee67bf8852011-08-17 17:51:35 -07001179
Bill Buzbeea114add2012-05-03 15:00:40 -07001180 // Debugging only
1181 if (cUnit->enableDebug & (1 << kDebugDumpCFG)) {
1182 oatDumpCFG(cUnit.get(), "/sdcard/cfg/");
1183 }
buzbee16da88c2012-03-20 10:38:17 -07001184
Bill Buzbeea114add2012-05-03 15:00:40 -07001185 /* Method is not empty */
1186 if (cUnit->firstLIRInsn) {
buzbee67bf8852011-08-17 17:51:35 -07001187
Bill Buzbeea114add2012-05-03 15:00:40 -07001188 // mark the targets of switch statement case labels
1189 oatProcessSwitchTables(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001190
Bill Buzbeea114add2012-05-03 15:00:40 -07001191 /* Convert LIR into machine code. */
1192 oatAssembleLIR(cUnit.get());
buzbee99ba9642012-01-25 14:23:14 -08001193
Elliott Hughes3b6baaa2011-10-14 19:13:56 -07001194 if (cUnit->printMe) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001195 oatCodegenDump(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001196 }
1197
Bill Buzbeea114add2012-05-03 15:00:40 -07001198 if (cUnit->opcodeCount != NULL) {
1199 LOG(INFO) << "Opcode Count";
1200 for (int i = 0; i < kNumPackedOpcodes; i++) {
1201 if (cUnit->opcodeCount[i] != 0) {
1202 LOG(INFO) << "-C- "
1203 << Instruction::Name(static_cast<Instruction::Code>(i))
1204 << " " << cUnit->opcodeCount[i];
buzbee67bf8852011-08-17 17:51:35 -07001205 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001206 }
1207 }
1208 }
buzbeea7c12682012-03-19 13:13:53 -07001209
Bill Buzbeea114add2012-05-03 15:00:40 -07001210 // Combine vmap tables - core regs, then fp regs - into vmapTable
1211 std::vector<uint16_t> vmapTable;
buzbeeca7a5e42012-08-20 11:12:18 -07001212 // Core regs may have been inserted out of order - sort first
1213 std::sort(cUnit->coreVmapTable.begin(), cUnit->coreVmapTable.end());
Bill Buzbeea114add2012-05-03 15:00:40 -07001214 for (size_t i = 0 ; i < cUnit->coreVmapTable.size(); i++) {
buzbeeca7a5e42012-08-20 11:12:18 -07001215 // Copy, stripping out the phys register sort key
1216 vmapTable.push_back(~(-1 << VREG_NUM_WIDTH) & cUnit->coreVmapTable[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001217 }
1218 // If we have a frame, push a marker to take place of lr
1219 if (cUnit->frameSize > 0) {
1220 vmapTable.push_back(INVALID_VREG);
1221 } else {
1222 DCHECK_EQ(__builtin_popcount(cUnit->coreSpillMask), 0);
1223 DCHECK_EQ(__builtin_popcount(cUnit->fpSpillMask), 0);
1224 }
buzbeeca7a5e42012-08-20 11:12:18 -07001225 // Combine vmap tables - core regs, then fp regs. fp regs already sorted
Bill Buzbeea114add2012-05-03 15:00:40 -07001226 for (uint32_t i = 0; i < cUnit->fpVmapTable.size(); i++) {
1227 vmapTable.push_back(cUnit->fpVmapTable[i]);
1228 }
1229 CompiledMethod* result =
1230 new CompiledMethod(cUnit->instructionSet, cUnit->codeBuffer,
Bill Buzbeea5b30242012-09-28 07:19:44 -07001231 cUnit->frameSize, cUnit->coreSpillMask, cUnit->fpSpillMask,
1232 cUnit->combinedMappingTable, vmapTable, cUnit->nativeGcMap);
buzbee67bf8852011-08-17 17:51:35 -07001233
Bill Buzbeea114add2012-05-03 15:00:40 -07001234 VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file)
1235 << " (" << (cUnit->codeBuffer.size() * sizeof(cUnit->codeBuffer[0]))
1236 << " bytes)";
buzbee5abfa3e2012-01-31 17:01:43 -08001237
1238#ifdef WITH_MEMSTATS
Bill Buzbeea114add2012-05-03 15:00:40 -07001239 if (cUnit->enableDebug & (1 << kDebugShowMemoryUsage)) {
1240 oatDumpMemStats(cUnit.get());
1241 }
buzbee5abfa3e2012-01-31 17:01:43 -08001242#endif
buzbee67bf8852011-08-17 17:51:35 -07001243
Bill Buzbeea114add2012-05-03 15:00:40 -07001244 oatArenaReset(cUnit.get());
buzbeeba938cb2012-02-03 14:47:55 -08001245
Bill Buzbeea114add2012-05-03 15:00:40 -07001246 return result;
buzbee67bf8852011-08-17 17:51:35 -07001247}
1248
buzbeeabc4c6b2012-08-23 08:17:15 -07001249#if defined(ART_USE_QUICK_COMPILER)
1250CompiledMethod* oatCompileMethod(Compiler& compiler,
1251 const DexFile::CodeItem* code_item,
1252 uint32_t access_flags, InvokeType invoke_type,
1253 uint32_t method_idx, jobject class_loader,
1254 const DexFile& dex_file)
1255{
1256 return compileMethod(compiler, code_item, access_flags, invoke_type, method_idx, class_loader,
TDYa12755e5e6c2012-09-11 15:14:42 -07001257 dex_file, NULL, false);
buzbeeabc4c6b2012-08-23 08:17:15 -07001258}
1259
1260/*
1261 * Given existing llvm module, context, intrinsic_helper and IRBuilder,
1262 * add the bitcode for the method described by code_item to the module.
1263 */
1264void oatCompileMethodToGBC(Compiler& compiler,
1265 const DexFile::CodeItem* code_item,
1266 uint32_t access_flags, InvokeType invoke_type,
1267 uint32_t method_idx, jobject class_loader,
1268 const DexFile& dex_file,
buzbee4df2bbd2012-10-11 14:46:06 -07001269 LLVMInfo* llvm_info)
buzbeeabc4c6b2012-08-23 08:17:15 -07001270{
1271 compileMethod(compiler, code_item, access_flags, invoke_type, method_idx, class_loader,
buzbee4df2bbd2012-10-11 14:46:06 -07001272 dex_file, llvm_info, true);
buzbeeabc4c6b2012-08-23 08:17:15 -07001273}
1274#else
1275CompiledMethod* oatCompileMethod(Compiler& compiler,
1276 const DexFile::CodeItem* code_item,
1277 uint32_t access_flags, InvokeType invoke_type,
1278 uint32_t method_idx, jobject class_loader,
1279 const DexFile& dex_file)
1280{
1281 return compileMethod(compiler, code_item, access_flags, invoke_type, method_idx, class_loader,
1282 dex_file);
1283}
1284#endif
1285
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001286} // namespace art
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001287
Shih-wei Liao46bde5c2012-08-31 11:28:16 -07001288#if !defined(ART_USE_LLVM_COMPILER)
Bill Buzbeea114add2012-05-03 15:00:40 -07001289extern "C" art::CompiledMethod*
1290 ArtCompileMethod(art::Compiler& compiler,
1291 const art::DexFile::CodeItem* code_item,
Ian Rogers08f753d2012-08-24 14:35:25 -07001292 uint32_t access_flags, art::InvokeType invoke_type,
1293 uint32_t method_idx, jobject class_loader,
Bill Buzbeea114add2012-05-03 15:00:40 -07001294 const art::DexFile& dex_file)
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001295{
1296 CHECK_EQ(compiler.GetInstructionSet(), art::oatInstructionSet());
Ian Rogers08f753d2012-08-24 14:35:25 -07001297 return art::oatCompileMethod(compiler, code_item, access_flags, invoke_type,
1298 method_idx, class_loader, dex_file);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001299}
Shih-wei Liao46bde5c2012-08-31 11:28:16 -07001300#endif