blob: c329e9d2ef621ee3cdf4b2fbae6b4428b6208705 [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;
buzbeecbd6d442012-11-17 14:11:25 -0800103 Instruction::Code opcode = static_cast<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);
buzbeecbd6d442012-11-17 14:11:25 -0800129 LOG(INFO) << codePtr << ": 0x" << std::hex << static_cast<int>(decoded_instruction->opcode)
Elliott Hughesadb8c672012-03-06 16:49:32 -0800130 << " " << decodedString;
131 }
132 return instruction->SizeInCodeUnits();
buzbee67bf8852011-08-17 17:51:35 -0700133}
134
135#define UNKNOWN_TARGET 0xffffffff
136
Elliott Hughesadb8c672012-03-06 16:49:32 -0800137inline bool isGoto(MIR* insn) {
138 switch (insn->dalvikInsn.opcode) {
139 case Instruction::GOTO:
140 case Instruction::GOTO_16:
141 case Instruction::GOTO_32:
142 return true;
143 default:
144 return false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700145 }
buzbee67bf8852011-08-17 17:51:35 -0700146}
147
148/*
149 * Identify unconditional branch instructions
150 */
Elliott Hughesadb8c672012-03-06 16:49:32 -0800151inline bool isUnconditionalBranch(MIR* insn) {
152 switch (insn->dalvikInsn.opcode) {
153 case Instruction::RETURN_VOID:
154 case Instruction::RETURN:
155 case Instruction::RETURN_WIDE:
156 case Instruction::RETURN_OBJECT:
157 return true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700158 default:
159 return isGoto(insn);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800160 }
buzbee67bf8852011-08-17 17:51:35 -0700161}
162
163/* Split an existing block from the specified code offset into two */
buzbee31a4a6f2012-02-28 15:36:15 -0800164BasicBlock *splitBlock(CompilationUnit* cUnit, unsigned int codeOffset,
Bill Buzbeea114add2012-05-03 15:00:40 -0700165 BasicBlock* origBlock, BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700166{
Bill Buzbeea114add2012-05-03 15:00:40 -0700167 MIR* insn = origBlock->firstMIRInsn;
168 while (insn) {
169 if (insn->offset == codeOffset) break;
170 insn = insn->next;
171 }
172 if (insn == NULL) {
173 LOG(FATAL) << "Break split failed";
174 }
175 BasicBlock *bottomBlock = oatNewBB(cUnit, kDalvikByteCode,
176 cUnit->numBlocks++);
buzbeecbd6d442012-11-17 14:11:25 -0800177 oatInsertGrowableList(cUnit, &cUnit->blockList, reinterpret_cast<uintptr_t>(bottomBlock));
buzbee67bf8852011-08-17 17:51:35 -0700178
Bill Buzbeea114add2012-05-03 15:00:40 -0700179 bottomBlock->startOffset = codeOffset;
180 bottomBlock->firstMIRInsn = insn;
181 bottomBlock->lastMIRInsn = origBlock->lastMIRInsn;
buzbee67bf8852011-08-17 17:51:35 -0700182
Bill Buzbeea114add2012-05-03 15:00:40 -0700183 /* Add it to the quick lookup cache */
184 cUnit->blockMap.Put(bottomBlock->startOffset, bottomBlock);
buzbee5b537102012-01-17 17:33:47 -0800185
Bill Buzbeea114add2012-05-03 15:00:40 -0700186 /* Handle the taken path */
187 bottomBlock->taken = origBlock->taken;
188 if (bottomBlock->taken) {
189 origBlock->taken = NULL;
buzbeecbd6d442012-11-17 14:11:25 -0800190 oatDeleteGrowableList(bottomBlock->taken->predecessors, reinterpret_cast<uintptr_t>(origBlock));
Bill Buzbeea114add2012-05-03 15:00:40 -0700191 oatInsertGrowableList(cUnit, bottomBlock->taken->predecessors,
buzbeecbd6d442012-11-17 14:11:25 -0800192 reinterpret_cast<uintptr_t>(bottomBlock));
Bill Buzbeea114add2012-05-03 15:00:40 -0700193 }
194
195 /* Handle the fallthrough path */
Bill Buzbeea114add2012-05-03 15:00:40 -0700196 bottomBlock->fallThrough = origBlock->fallThrough;
197 origBlock->fallThrough = bottomBlock;
Bill Buzbeea114add2012-05-03 15:00:40 -0700198 oatInsertGrowableList(cUnit, bottomBlock->predecessors,
buzbeecbd6d442012-11-17 14:11:25 -0800199 reinterpret_cast<uintptr_t>(origBlock));
Bill Buzbeea114add2012-05-03 15:00:40 -0700200 if (bottomBlock->fallThrough) {
201 oatDeleteGrowableList(bottomBlock->fallThrough->predecessors,
buzbeecbd6d442012-11-17 14:11:25 -0800202 reinterpret_cast<uintptr_t>(origBlock));
Bill Buzbeea114add2012-05-03 15:00:40 -0700203 oatInsertGrowableList(cUnit, bottomBlock->fallThrough->predecessors,
buzbeecbd6d442012-11-17 14:11:25 -0800204 reinterpret_cast<uintptr_t>(bottomBlock));
Bill Buzbeea114add2012-05-03 15:00:40 -0700205 }
206
207 /* Handle the successor list */
208 if (origBlock->successorBlockList.blockListType != kNotUsed) {
209 bottomBlock->successorBlockList = origBlock->successorBlockList;
210 origBlock->successorBlockList.blockListType = kNotUsed;
211 GrowableListIterator iterator;
212
213 oatGrowableListIteratorInit(&bottomBlock->successorBlockList.blocks,
214 &iterator);
215 while (true) {
216 SuccessorBlockInfo *successorBlockInfo =
buzbeecbd6d442012-11-17 14:11:25 -0800217 reinterpret_cast<SuccessorBlockInfo*>(oatGrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700218 if (successorBlockInfo == NULL) break;
219 BasicBlock *bb = successorBlockInfo->block;
buzbeecbd6d442012-11-17 14:11:25 -0800220 oatDeleteGrowableList(bb->predecessors, reinterpret_cast<uintptr_t>(origBlock));
221 oatInsertGrowableList(cUnit, bb->predecessors, reinterpret_cast<uintptr_t>(bottomBlock));
buzbee67bf8852011-08-17 17:51:35 -0700222 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700223 }
buzbee67bf8852011-08-17 17:51:35 -0700224
Bill Buzbeea114add2012-05-03 15:00:40 -0700225 origBlock->lastMIRInsn = insn->prev;
buzbee67bf8852011-08-17 17:51:35 -0700226
Bill Buzbeea114add2012-05-03 15:00:40 -0700227 insn->prev->next = NULL;
228 insn->prev = NULL;
229 /*
230 * Update the immediate predecessor block pointer so that outgoing edges
231 * can be applied to the proper block.
232 */
233 if (immedPredBlockP) {
234 DCHECK_EQ(*immedPredBlockP, origBlock);
235 *immedPredBlockP = bottomBlock;
236 }
237 return bottomBlock;
buzbee67bf8852011-08-17 17:51:35 -0700238}
239
240/*
241 * Given a code offset, find out the block that starts with it. If the offset
buzbee9ab05de2012-01-18 15:43:48 -0800242 * is in the middle of an existing block, split it into two. If immedPredBlockP
243 * is not non-null and is the block being split, update *immedPredBlockP to
244 * point to the bottom block so that outgoing edges can be set up properly
245 * (by the caller)
buzbee5b537102012-01-17 17:33:47 -0800246 * Utilizes a map for fast lookup of the typical cases.
buzbee67bf8852011-08-17 17:51:35 -0700247 */
buzbee31a4a6f2012-02-28 15:36:15 -0800248BasicBlock *findBlock(CompilationUnit* cUnit, unsigned int codeOffset,
249 bool split, bool create, BasicBlock** immedPredBlockP)
buzbee67bf8852011-08-17 17:51:35 -0700250{
Bill Buzbeea114add2012-05-03 15:00:40 -0700251 GrowableList* blockList = &cUnit->blockList;
252 BasicBlock* bb;
253 unsigned int i;
254 SafeMap<unsigned int, BasicBlock*>::iterator it;
buzbee67bf8852011-08-17 17:51:35 -0700255
Bill Buzbeea114add2012-05-03 15:00:40 -0700256 it = cUnit->blockMap.find(codeOffset);
257 if (it != cUnit->blockMap.end()) {
258 return it->second;
259 } else if (!create) {
260 return NULL;
261 }
262
263 if (split) {
264 for (i = 0; i < blockList->numUsed; i++) {
buzbeecbd6d442012-11-17 14:11:25 -0800265 bb = reinterpret_cast<BasicBlock*>(blockList->elemList[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700266 if (bb->blockType != kDalvikByteCode) continue;
267 /* Check if a branch jumps into the middle of an existing block */
268 if ((codeOffset > bb->startOffset) && (bb->lastMIRInsn != NULL) &&
269 (codeOffset <= bb->lastMIRInsn->offset)) {
270 BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb,
271 bb == *immedPredBlockP ?
272 immedPredBlockP : NULL);
273 return newBB;
274 }
buzbee5b537102012-01-17 17:33:47 -0800275 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700276 }
buzbee5b537102012-01-17 17:33:47 -0800277
Bill Buzbeea114add2012-05-03 15:00:40 -0700278 /* Create a new one */
279 bb = oatNewBB(cUnit, kDalvikByteCode, cUnit->numBlocks++);
buzbeecbd6d442012-11-17 14:11:25 -0800280 oatInsertGrowableList(cUnit, &cUnit->blockList, reinterpret_cast<uintptr_t>(bb));
Bill Buzbeea114add2012-05-03 15:00:40 -0700281 bb->startOffset = codeOffset;
282 cUnit->blockMap.Put(bb->startOffset, bb);
283 return bb;
buzbee67bf8852011-08-17 17:51:35 -0700284}
285
buzbeef58c12c2012-07-03 15:06:29 -0700286/* Find existing block */
287BasicBlock* oatFindBlock(CompilationUnit* cUnit, unsigned int codeOffset)
288{
289 return findBlock(cUnit, codeOffset, false, false, NULL);
290}
291
buzbeead8f15e2012-06-18 14:49:45 -0700292/* Turn method name into a legal Linux file name */
293void oatReplaceSpecialChars(std::string& str)
294{
295 static const struct { const char before; const char after; } match[] =
296 {{'/','-'}, {';','#'}, {' ','#'}, {'$','+'},
297 {'(','@'}, {')','@'}, {'<','='}, {'>','='}};
298 for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) {
299 std::replace(str.begin(), str.end(), match[i].before, match[i].after);
300 }
301}
302
buzbee67bf8852011-08-17 17:51:35 -0700303/* Dump the CFG into a DOT graph */
304void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix)
305{
Bill Buzbeea114add2012-05-03 15:00:40 -0700306 FILE* file;
buzbeead8f15e2012-06-18 14:49:45 -0700307 std::string fname(PrettyMethod(cUnit->method_idx, *cUnit->dex_file));
308 oatReplaceSpecialChars(fname);
309 fname = StringPrintf("%s%s%x.dot", dirPrefix, fname.c_str(),
310 cUnit->entryBlock->fallThrough->startOffset);
311 file = fopen(fname.c_str(), "w");
Bill Buzbeea114add2012-05-03 15:00:40 -0700312 if (file == NULL) {
313 return;
314 }
315 fprintf(file, "digraph G {\n");
316
317 fprintf(file, " rankdir=TB\n");
318
319 int numReachableBlocks = cUnit->numReachableBlocks;
320 int idx;
321 const GrowableList *blockList = &cUnit->blockList;
322
323 for (idx = 0; idx < numReachableBlocks; idx++) {
324 int blockIdx = cUnit->dfsOrder.elemList[idx];
buzbeecbd6d442012-11-17 14:11:25 -0800325 BasicBlock *bb = reinterpret_cast<BasicBlock*>(oatGrowableListGetElement(blockList, blockIdx));
Bill Buzbeea114add2012-05-03 15:00:40 -0700326 if (bb == NULL) break;
buzbeed1643e42012-09-05 14:06:51 -0700327 if (bb->blockType == kDead) continue;
Bill Buzbeea114add2012-05-03 15:00:40 -0700328 if (bb->blockType == kEntryBlock) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700329 fprintf(file, " entry_%d [shape=Mdiamond];\n", bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700330 } else if (bb->blockType == kExitBlock) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700331 fprintf(file, " exit_%d [shape=Mdiamond];\n", bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700332 } else if (bb->blockType == kDalvikByteCode) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700333 fprintf(file, " block%04x_%d [shape=record,label = \"{ \\\n",
334 bb->startOffset, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700335 const MIR *mir;
336 fprintf(file, " {block id %d\\l}%s\\\n", bb->id,
337 bb->firstMIRInsn ? " | " : " ");
338 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
339 fprintf(file, " {%04x %s\\l}%s\\\n", mir->offset,
340 mir->ssaRep ? oatFullDisassembler(cUnit, mir) :
341 Instruction::Name(mir->dalvikInsn.opcode),
342 mir->next ? " | " : " ");
343 }
344 fprintf(file, " }\"];\n\n");
345 } else if (bb->blockType == kExceptionHandling) {
346 char blockName[BLOCK_NAME_LEN];
347
348 oatGetBlockName(bb, blockName);
349 fprintf(file, " %s [shape=invhouse];\n", blockName);
buzbee67bf8852011-08-17 17:51:35 -0700350 }
buzbee67bf8852011-08-17 17:51:35 -0700351
Bill Buzbeea114add2012-05-03 15:00:40 -0700352 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
buzbee67bf8852011-08-17 17:51:35 -0700353
Bill Buzbeea114add2012-05-03 15:00:40 -0700354 if (bb->taken) {
355 oatGetBlockName(bb, blockName1);
356 oatGetBlockName(bb->taken, blockName2);
357 fprintf(file, " %s:s -> %s:n [style=dotted]\n",
358 blockName1, blockName2);
buzbee67bf8852011-08-17 17:51:35 -0700359 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700360 if (bb->fallThrough) {
361 oatGetBlockName(bb, blockName1);
362 oatGetBlockName(bb->fallThrough, blockName2);
363 fprintf(file, " %s:s -> %s:n\n", blockName1, blockName2);
364 }
365
366 if (bb->successorBlockList.blockListType != kNotUsed) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700367 fprintf(file, " succ%04x_%d [shape=%s,label = \"{ \\\n",
368 bb->startOffset, bb->id,
Bill Buzbeea114add2012-05-03 15:00:40 -0700369 (bb->successorBlockList.blockListType == kCatch) ?
370 "Mrecord" : "record");
371 GrowableListIterator iterator;
372 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
373 &iterator);
374 SuccessorBlockInfo *successorBlockInfo =
buzbeecbd6d442012-11-17 14:11:25 -0800375 reinterpret_cast<SuccessorBlockInfo*>(oatGrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700376
377 int succId = 0;
378 while (true) {
379 if (successorBlockInfo == NULL) break;
380
381 BasicBlock *destBlock = successorBlockInfo->block;
382 SuccessorBlockInfo *nextSuccessorBlockInfo =
buzbeecbd6d442012-11-17 14:11:25 -0800383 reinterpret_cast<SuccessorBlockInfo*>(oatGrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700384
385 fprintf(file, " {<f%d> %04x: %04x\\l}%s\\\n",
386 succId++,
387 successorBlockInfo->key,
388 destBlock->startOffset,
389 (nextSuccessorBlockInfo != NULL) ? " | " : " ");
390
391 successorBlockInfo = nextSuccessorBlockInfo;
392 }
393 fprintf(file, " }\"];\n\n");
394
395 oatGetBlockName(bb, blockName1);
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700396 fprintf(file, " %s:s -> succ%04x_%d:n [style=dashed]\n",
397 blockName1, bb->startOffset, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700398
399 if (bb->successorBlockList.blockListType == kPackedSwitch ||
400 bb->successorBlockList.blockListType == kSparseSwitch) {
401
402 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
403 &iterator);
404
405 succId = 0;
406 while (true) {
buzbeecbd6d442012-11-17 14:11:25 -0800407 SuccessorBlockInfo *successorBlockInfo =
408 reinterpret_cast<SuccessorBlockInfo*>( oatGrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700409 if (successorBlockInfo == NULL) break;
410
411 BasicBlock *destBlock = successorBlockInfo->block;
412
413 oatGetBlockName(destBlock, blockName2);
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700414 fprintf(file, " succ%04x_%d:f%d:e -> %s:n\n", bb->startOffset,
415 bb->id, succId++, blockName2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700416 }
417 }
418 }
419 fprintf(file, "\n");
420
421 /* Display the dominator tree */
422 oatGetBlockName(bb, blockName1);
423 fprintf(file, " cfg%s [label=\"%s\", shape=none];\n",
424 blockName1, blockName1);
425 if (bb->iDom) {
426 oatGetBlockName(bb->iDom, blockName2);
427 fprintf(file, " cfg%s:s -> cfg%s:n\n\n", blockName2, blockName1);
428 }
429 }
430 fprintf(file, "}\n");
431 fclose(file);
buzbee67bf8852011-08-17 17:51:35 -0700432}
433
434/* Verify if all the successor is connected with all the claimed predecessors */
buzbee31a4a6f2012-02-28 15:36:15 -0800435bool verifyPredInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700436{
Bill Buzbeea114add2012-05-03 15:00:40 -0700437 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700438
Bill Buzbeea114add2012-05-03 15:00:40 -0700439 oatGrowableListIteratorInit(bb->predecessors, &iter);
440 while (true) {
buzbeecbd6d442012-11-17 14:11:25 -0800441 BasicBlock *predBB = reinterpret_cast<BasicBlock*>(oatGrowableListIteratorNext(&iter));
Bill Buzbeea114add2012-05-03 15:00:40 -0700442 if (!predBB) break;
443 bool found = false;
444 if (predBB->taken == bb) {
445 found = true;
446 } else if (predBB->fallThrough == bb) {
447 found = true;
448 } else if (predBB->successorBlockList.blockListType != kNotUsed) {
449 GrowableListIterator iterator;
450 oatGrowableListIteratorInit(&predBB->successorBlockList.blocks,
451 &iterator);
452 while (true) {
buzbeecbd6d442012-11-17 14:11:25 -0800453 SuccessorBlockInfo *successorBlockInfo =
454 reinterpret_cast<SuccessorBlockInfo*>(oatGrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700455 if (successorBlockInfo == NULL) break;
456 BasicBlock *succBB = successorBlockInfo->block;
457 if (succBB == bb) {
buzbee67bf8852011-08-17 17:51:35 -0700458 found = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700459 break;
buzbee67bf8852011-08-17 17:51:35 -0700460 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700461 }
buzbee67bf8852011-08-17 17:51:35 -0700462 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700463 if (found == false) {
464 char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
465 oatGetBlockName(bb, blockName1);
466 oatGetBlockName(predBB, blockName2);
467 oatDumpCFG(cUnit, "/sdcard/cfg/");
468 LOG(FATAL) << "Successor " << blockName1 << "not found from "
469 << blockName2;
470 }
471 }
472 return true;
buzbee67bf8852011-08-17 17:51:35 -0700473}
474
475/* Identify code range in try blocks and set up the empty catch blocks */
buzbee31a4a6f2012-02-28 15:36:15 -0800476void processTryCatchBlocks(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700477{
Bill Buzbeea114add2012-05-03 15:00:40 -0700478 const DexFile::CodeItem* code_item = cUnit->code_item;
479 int triesSize = code_item->tries_size_;
480 int offset;
buzbee67bf8852011-08-17 17:51:35 -0700481
Bill Buzbeea114add2012-05-03 15:00:40 -0700482 if (triesSize == 0) {
483 return;
484 }
485
486 ArenaBitVector* tryBlockAddr = cUnit->tryBlockAddr;
487
488 for (int i = 0; i < triesSize; i++) {
489 const DexFile::TryItem* pTry =
490 DexFile::GetTryItems(*code_item, i);
491 int startOffset = pTry->start_addr_;
492 int endOffset = startOffset + pTry->insn_count_;
493 for (offset = startOffset; offset < endOffset; offset++) {
494 oatSetBit(cUnit, tryBlockAddr, offset);
buzbee67bf8852011-08-17 17:51:35 -0700495 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700496 }
buzbee67bf8852011-08-17 17:51:35 -0700497
Bill Buzbeea114add2012-05-03 15:00:40 -0700498 // Iterate over each of the handlers to enqueue the empty Catch blocks
499 const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item, 0);
500 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
501 for (uint32_t idx = 0; idx < handlers_size; idx++) {
502 CatchHandlerIterator iterator(handlers_ptr);
503 for (; iterator.HasNext(); iterator.Next()) {
504 uint32_t address = iterator.GetHandlerAddress();
505 findBlock(cUnit, address, false /* split */, true /*create*/,
506 /* immedPredBlockP */ NULL);
buzbee67bf8852011-08-17 17:51:35 -0700507 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700508 handlers_ptr = iterator.EndDataPointer();
509 }
buzbee67bf8852011-08-17 17:51:35 -0700510}
511
Elliott Hughesadb8c672012-03-06 16:49:32 -0800512/* Process instructions with the kBranch flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800513BasicBlock* processCanBranch(CompilationUnit* cUnit, BasicBlock* curBlock,
Bill Buzbeea114add2012-05-03 15:00:40 -0700514 MIR* insn, int curOffset, int width, int flags,
buzbeeeaf09bc2012-11-15 14:51:41 -0800515 const uint16_t* codePtr, const uint16_t* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700516{
Bill Buzbeea114add2012-05-03 15:00:40 -0700517 int target = curOffset;
518 switch (insn->dalvikInsn.opcode) {
519 case Instruction::GOTO:
520 case Instruction::GOTO_16:
521 case Instruction::GOTO_32:
buzbeecbd6d442012-11-17 14:11:25 -0800522 target += insn->dalvikInsn.vA;
Bill Buzbeea114add2012-05-03 15:00:40 -0700523 break;
524 case Instruction::IF_EQ:
525 case Instruction::IF_NE:
526 case Instruction::IF_LT:
527 case Instruction::IF_GE:
528 case Instruction::IF_GT:
529 case Instruction::IF_LE:
buzbee0967a252012-09-14 10:43:54 -0700530 curBlock->conditionalBranch = true;
buzbeecbd6d442012-11-17 14:11:25 -0800531 target += insn->dalvikInsn.vC;
Bill Buzbeea114add2012-05-03 15:00:40 -0700532 break;
533 case Instruction::IF_EQZ:
534 case Instruction::IF_NEZ:
535 case Instruction::IF_LTZ:
536 case Instruction::IF_GEZ:
537 case Instruction::IF_GTZ:
538 case Instruction::IF_LEZ:
buzbee0967a252012-09-14 10:43:54 -0700539 curBlock->conditionalBranch = true;
buzbeecbd6d442012-11-17 14:11:25 -0800540 target += insn->dalvikInsn.vB;
Bill Buzbeea114add2012-05-03 15:00:40 -0700541 break;
542 default:
buzbeecbd6d442012-11-17 14:11:25 -0800543 LOG(FATAL) << "Unexpected opcode(" << insn->dalvikInsn.opcode << ") with kBranch set";
Bill Buzbeea114add2012-05-03 15:00:40 -0700544 }
545 BasicBlock *takenBlock = findBlock(cUnit, target,
546 /* split */
547 true,
548 /* create */
549 true,
550 /* immedPredBlockP */
551 &curBlock);
552 curBlock->taken = takenBlock;
buzbeecbd6d442012-11-17 14:11:25 -0800553 oatInsertGrowableList(cUnit, takenBlock->predecessors, reinterpret_cast<uintptr_t>(curBlock));
buzbee67bf8852011-08-17 17:51:35 -0700554
Bill Buzbeea114add2012-05-03 15:00:40 -0700555 /* Always terminate the current block for conditional branches */
556 if (flags & Instruction::kContinue) {
557 BasicBlock *fallthroughBlock = findBlock(cUnit,
558 curOffset + width,
559 /*
560 * If the method is processed
561 * in sequential order from the
562 * beginning, we don't need to
563 * specify split for continue
564 * blocks. However, this
565 * routine can be called by
566 * compileLoop, which starts
567 * parsing the method from an
568 * arbitrary address in the
569 * method body.
570 */
571 true,
572 /* create */
573 true,
574 /* immedPredBlockP */
575 &curBlock);
576 curBlock->fallThrough = fallthroughBlock;
577 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
buzbeecbd6d442012-11-17 14:11:25 -0800578 reinterpret_cast<uintptr_t>(curBlock));
Bill Buzbeea114add2012-05-03 15:00:40 -0700579 } else if (codePtr < codeEnd) {
580 /* Create a fallthrough block for real instructions (incl. NOP) */
581 if (contentIsInsn(codePtr)) {
582 findBlock(cUnit, curOffset + width,
583 /* split */
584 false,
585 /* create */
586 true,
587 /* immedPredBlockP */
588 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700589 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700590 }
591 return curBlock;
buzbee67bf8852011-08-17 17:51:35 -0700592}
593
Elliott Hughesadb8c672012-03-06 16:49:32 -0800594/* Process instructions with the kSwitch flag */
buzbee31a4a6f2012-02-28 15:36:15 -0800595void processCanSwitch(CompilationUnit* cUnit, BasicBlock* curBlock,
596 MIR* insn, int curOffset, int width, int flags)
buzbee67bf8852011-08-17 17:51:35 -0700597{
buzbeecbd6d442012-11-17 14:11:25 -0800598 const uint16_t* switchData =
599 reinterpret_cast<const uint16_t*>(cUnit->insns + curOffset + insn->dalvikInsn.vB);
Bill Buzbeea114add2012-05-03 15:00:40 -0700600 int size;
buzbeecbd6d442012-11-17 14:11:25 -0800601 const int* keyTable;
602 const int* targetTable;
Bill Buzbeea114add2012-05-03 15:00:40 -0700603 int i;
604 int firstKey;
buzbee67bf8852011-08-17 17:51:35 -0700605
Bill Buzbeea114add2012-05-03 15:00:40 -0700606 /*
607 * Packed switch data format:
608 * ushort ident = 0x0100 magic value
609 * ushort size number of entries in the table
610 * int first_key first (and lowest) switch case value
611 * int targets[size] branch targets, relative to switch opcode
612 *
613 * Total size is (4+size*2) 16-bit code units.
614 */
615 if (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) {
616 DCHECK_EQ(static_cast<int>(switchData[0]),
617 static_cast<int>(Instruction::kPackedSwitchSignature));
618 size = switchData[1];
619 firstKey = switchData[2] | (switchData[3] << 16);
buzbeecbd6d442012-11-17 14:11:25 -0800620 targetTable = reinterpret_cast<const int*>(&switchData[4]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700621 keyTable = NULL; // Make the compiler happy
622 /*
623 * Sparse switch data format:
624 * ushort ident = 0x0200 magic value
625 * ushort size number of entries in the table; > 0
626 * int keys[size] keys, sorted low-to-high; 32-bit aligned
627 * int targets[size] branch targets, relative to switch opcode
628 *
629 * Total size is (2+size*4) 16-bit code units.
630 */
631 } else {
632 DCHECK_EQ(static_cast<int>(switchData[0]),
633 static_cast<int>(Instruction::kSparseSwitchSignature));
634 size = switchData[1];
buzbeecbd6d442012-11-17 14:11:25 -0800635 keyTable = reinterpret_cast<const int*>(&switchData[2]);
636 targetTable = reinterpret_cast<const int*>(&switchData[2 + size*2]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700637 firstKey = 0; // To make the compiler happy
638 }
buzbee67bf8852011-08-17 17:51:35 -0700639
Bill Buzbeea114add2012-05-03 15:00:40 -0700640 if (curBlock->successorBlockList.blockListType != kNotUsed) {
641 LOG(FATAL) << "Successor block list already in use: "
buzbeecbd6d442012-11-17 14:11:25 -0800642 << static_cast<int>(curBlock->successorBlockList.blockListType);
Bill Buzbeea114add2012-05-03 15:00:40 -0700643 }
644 curBlock->successorBlockList.blockListType =
645 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
646 kPackedSwitch : kSparseSwitch;
647 oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, size,
648 kListSuccessorBlocks);
649
650 for (i = 0; i < size; i++) {
651 BasicBlock *caseBlock = findBlock(cUnit, curOffset + targetTable[i],
652 /* split */
653 true,
654 /* create */
655 true,
656 /* immedPredBlockP */
657 &curBlock);
658 SuccessorBlockInfo *successorBlockInfo =
buzbeecbd6d442012-11-17 14:11:25 -0800659 static_cast<SuccessorBlockInfo*>(oatNew(cUnit, sizeof(SuccessorBlockInfo),
660 false, kAllocSuccessor));
Bill Buzbeea114add2012-05-03 15:00:40 -0700661 successorBlockInfo->block = caseBlock;
662 successorBlockInfo->key =
Elliott Hughesadb8c672012-03-06 16:49:32 -0800663 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
Bill Buzbeea114add2012-05-03 15:00:40 -0700664 firstKey + i : keyTable[i];
665 oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
buzbeecbd6d442012-11-17 14:11:25 -0800666 reinterpret_cast<uintptr_t>(successorBlockInfo));
Bill Buzbeea114add2012-05-03 15:00:40 -0700667 oatInsertGrowableList(cUnit, caseBlock->predecessors,
buzbeecbd6d442012-11-17 14:11:25 -0800668 reinterpret_cast<uintptr_t>(curBlock));
Bill Buzbeea114add2012-05-03 15:00:40 -0700669 }
670
671 /* Fall-through case */
672 BasicBlock* fallthroughBlock = findBlock(cUnit,
673 curOffset + width,
674 /* split */
675 false,
676 /* create */
677 true,
678 /* immedPredBlockP */
679 NULL);
680 curBlock->fallThrough = fallthroughBlock;
681 oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
buzbeecbd6d442012-11-17 14:11:25 -0800682 reinterpret_cast<uintptr_t>(curBlock));
buzbee67bf8852011-08-17 17:51:35 -0700683}
684
Elliott Hughesadb8c672012-03-06 16:49:32 -0800685/* Process instructions with the kThrow flag */
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700686BasicBlock* processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock,
687 MIR* insn, int curOffset, int width, int flags,
buzbeeeaf09bc2012-11-15 14:51:41 -0800688 ArenaBitVector* tryBlockAddr, const uint16_t* codePtr,
689 const uint16_t* codeEnd)
buzbee67bf8852011-08-17 17:51:35 -0700690{
Bill Buzbeea114add2012-05-03 15:00:40 -0700691 const DexFile::CodeItem* code_item = cUnit->code_item;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700692 bool inTryBlock = oatIsBitSet(tryBlockAddr, curOffset);
buzbee67bf8852011-08-17 17:51:35 -0700693
Bill Buzbeea114add2012-05-03 15:00:40 -0700694 /* In try block */
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700695 if (inTryBlock) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700696 CatchHandlerIterator iterator(*code_item, curOffset);
buzbee67bf8852011-08-17 17:51:35 -0700697
Bill Buzbeea114add2012-05-03 15:00:40 -0700698 if (curBlock->successorBlockList.blockListType != kNotUsed) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700699 LOG(INFO) << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
Bill Buzbeea114add2012-05-03 15:00:40 -0700700 LOG(FATAL) << "Successor block list already in use: "
buzbeecbd6d442012-11-17 14:11:25 -0800701 << static_cast<int>(curBlock->successorBlockList.blockListType);
buzbee67bf8852011-08-17 17:51:35 -0700702 }
703
Bill Buzbeea114add2012-05-03 15:00:40 -0700704 curBlock->successorBlockList.blockListType = kCatch;
705 oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, 2,
706 kListSuccessorBlocks);
707
708 for (;iterator.HasNext(); iterator.Next()) {
709 BasicBlock *catchBlock = findBlock(cUnit, iterator.GetHandlerAddress(),
710 false /* split*/,
711 false /* creat */,
712 NULL /* immedPredBlockP */);
713 catchBlock->catchEntry = true;
buzbee6459e7c2012-10-02 14:42:41 -0700714 cUnit->catches.insert(catchBlock->startOffset);
buzbeecbd6d442012-11-17 14:11:25 -0800715 SuccessorBlockInfo *successorBlockInfo = reinterpret_cast<SuccessorBlockInfo*>
716 (oatNew(cUnit, sizeof(SuccessorBlockInfo), false, kAllocSuccessor));
Bill Buzbeea114add2012-05-03 15:00:40 -0700717 successorBlockInfo->block = catchBlock;
718 successorBlockInfo->key = iterator.GetHandlerTypeIndex();
719 oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
buzbeecbd6d442012-11-17 14:11:25 -0800720 reinterpret_cast<uintptr_t>(successorBlockInfo));
Bill Buzbeea114add2012-05-03 15:00:40 -0700721 oatInsertGrowableList(cUnit, catchBlock->predecessors,
buzbeecbd6d442012-11-17 14:11:25 -0800722 reinterpret_cast<uintptr_t>(curBlock));
buzbee67bf8852011-08-17 17:51:35 -0700723 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700724 } else {
725 BasicBlock *ehBlock = oatNewBB(cUnit, kExceptionHandling,
726 cUnit->numBlocks++);
727 curBlock->taken = ehBlock;
buzbeecbd6d442012-11-17 14:11:25 -0800728 oatInsertGrowableList(cUnit, &cUnit->blockList, reinterpret_cast<uintptr_t>(ehBlock));
Bill Buzbeea114add2012-05-03 15:00:40 -0700729 ehBlock->startOffset = curOffset;
buzbeecbd6d442012-11-17 14:11:25 -0800730 oatInsertGrowableList(cUnit, ehBlock->predecessors, reinterpret_cast<uintptr_t>(curBlock));
Bill Buzbeea114add2012-05-03 15:00:40 -0700731 }
732
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700733 if (insn->dalvikInsn.opcode == Instruction::THROW){
buzbee0967a252012-09-14 10:43:54 -0700734 curBlock->explicitThrow = true;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700735 if ((codePtr < codeEnd) && contentIsInsn(codePtr)) {
736 // Force creation of new block following THROW via side-effect
737 findBlock(cUnit, curOffset + width, /* split */ false,
738 /* create */ true, /* immedPredBlockP */ NULL);
739 }
740 if (!inTryBlock) {
741 // Don't split a THROW that can't rethrow - we're done.
742 return curBlock;
Bill Buzbeea114add2012-05-03 15:00:40 -0700743 }
744 }
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700745
746 /*
747 * Split the potentially-throwing instruction into two parts.
748 * The first half will be a pseudo-op that captures the exception
749 * edges and terminates the basic block. It always falls through.
750 * Then, create a new basic block that begins with the throwing instruction
751 * (minus exceptions). Note: this new basic block must NOT be entered into
752 * the blockMap. If the potentially-throwing instruction is the target of a
753 * future branch, we need to find the check psuedo half. The new
754 * basic block containing the work portion of the instruction should
755 * only be entered via fallthrough from the block containing the
756 * pseudo exception edge MIR. Note also that this new block is
757 * not automatically terminated after the work portion, and may
758 * contain following instructions.
759 */
760 BasicBlock *newBlock = oatNewBB(cUnit, kDalvikByteCode, cUnit->numBlocks++);
buzbeecbd6d442012-11-17 14:11:25 -0800761 oatInsertGrowableList(cUnit, &cUnit->blockList, reinterpret_cast<uintptr_t>(newBlock));
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700762 newBlock->startOffset = insn->offset;
763 curBlock->fallThrough = newBlock;
buzbeecbd6d442012-11-17 14:11:25 -0800764 oatInsertGrowableList(cUnit, newBlock->predecessors, reinterpret_cast<uintptr_t>(curBlock));
765 MIR* newInsn = static_cast<MIR*>(oatNew(cUnit, sizeof(MIR), true, kAllocMIR));
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700766 *newInsn = *insn;
767 insn->dalvikInsn.opcode =
768 static_cast<Instruction::Code>(kMirOpCheck);
769 // Associate the two halves
770 insn->meta.throwInsn = newInsn;
771 newInsn->meta.throwInsn = insn;
772 oatAppendMIR(newBlock, newInsn);
773 return newBlock;
buzbee67bf8852011-08-17 17:51:35 -0700774}
775
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800776void oatInit(CompilationUnit* cUnit, const Compiler& compiler) {
777 if (!oatArchInit()) {
778 LOG(FATAL) << "Failed to initialize oat";
779 }
780 if (!oatHeapInit(cUnit)) {
781 LOG(FATAL) << "Failed to initialize oat heap";
782 }
783}
784
buzbeeabc4c6b2012-08-23 08:17:15 -0700785CompiledMethod* compileMethod(Compiler& compiler,
buzbeec531cef2012-10-18 07:09:20 -0700786 const CompilerBackend compilerBackend,
buzbeeabc4c6b2012-08-23 08:17:15 -0700787 const DexFile::CodeItem* code_item,
788 uint32_t access_flags, InvokeType invoke_type,
789 uint32_t method_idx, jobject class_loader,
buzbeec531cef2012-10-18 07:09:20 -0700790 const DexFile& dex_file,
791 LLVMInfo* llvm_info
buzbeeabc4c6b2012-08-23 08:17:15 -0700792 )
buzbee67bf8852011-08-17 17:51:35 -0700793{
Bill Buzbeea114add2012-05-03 15:00:40 -0700794 VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
Brian Carlstrom94496d32011-08-22 09:22:47 -0700795
buzbeeeaf09bc2012-11-15 14:51:41 -0800796 const uint16_t* codePtr = code_item->insns_;
797 const uint16_t* codeEnd = code_item->insns_ + code_item->insns_size_in_code_units_;
Bill Buzbeea114add2012-05-03 15:00:40 -0700798 int numBlocks = 0;
799 unsigned int curOffset = 0;
buzbee67bf8852011-08-17 17:51:35 -0700800
Bill Buzbeea114add2012-05-03 15:00:40 -0700801 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
802 UniquePtr<CompilationUnit> cUnit(new CompilationUnit);
buzbeeba938cb2012-02-03 14:47:55 -0800803
Bill Buzbeea114add2012-05-03 15:00:40 -0700804 oatInit(cUnit.get(), compiler);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800805
Bill Buzbeea114add2012-05-03 15:00:40 -0700806 cUnit->compiler = &compiler;
807 cUnit->class_linker = class_linker;
808 cUnit->dex_file = &dex_file;
Bill Buzbeea114add2012-05-03 15:00:40 -0700809 cUnit->method_idx = method_idx;
810 cUnit->code_item = code_item;
811 cUnit->access_flags = access_flags;
Ian Rogers08f753d2012-08-24 14:35:25 -0700812 cUnit->invoke_type = invoke_type;
Bill Buzbeea114add2012-05-03 15:00:40 -0700813 cUnit->shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
814 cUnit->instructionSet = compiler.GetInstructionSet();
815 cUnit->insns = code_item->insns_;
816 cUnit->insnsSize = code_item->insns_size_in_code_units_;
817 cUnit->numIns = code_item->ins_size_;
818 cUnit->numRegs = code_item->registers_size_ - cUnit->numIns;
819 cUnit->numOuts = code_item->outs_size_;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700820 DCHECK((cUnit->instructionSet == kThumb2) ||
821 (cUnit->instructionSet == kX86) ||
822 (cUnit->instructionSet == kMips));
buzbeec531cef2012-10-18 07:09:20 -0700823 if ((compilerBackend == kQuickGBC) || (compilerBackend == kPortable)) {
buzbee85eee022012-07-16 22:12:38 -0700824 cUnit->genBitcode = true;
825 }
buzbeec531cef2012-10-18 07:09:20 -0700826 DCHECK_NE(compilerBackend, kIceland); // TODO: remove when Portable/Iceland merge complete
827 // TODO: remove this once x86 is tested
828 if (cUnit->genBitcode && (cUnit->instructionSet != kThumb2)) {
829 UNIMPLEMENTED(WARNING) << "GBC generation untested for non-Thumb targets";
830 }
831 cUnit->llvm_info = llvm_info;
Bill Buzbeea114add2012-05-03 15:00:40 -0700832 /* Adjust this value accordingly once inlining is performed */
833 cUnit->numDalvikRegisters = code_item->registers_size_;
834 // TODO: set this from command line
835 cUnit->compilerFlipMatch = false;
836 bool useMatch = !cUnit->compilerMethodMatch.empty();
837 bool match = useMatch && (cUnit->compilerFlipMatch ^
838 (PrettyMethod(method_idx, dex_file).find(cUnit->compilerMethodMatch) !=
839 std::string::npos));
840 if (!useMatch || match) {
841 cUnit->disableOpt = kCompilerOptimizerDisableFlags;
842 cUnit->enableDebug = kCompilerDebugFlags;
843 cUnit->printMe = VLOG_IS_ON(compiler) ||
844 (cUnit->enableDebug & (1 << kDebugVerbose));
845 }
buzbee6459e7c2012-10-02 14:42:41 -0700846#ifndef NDEBUG
buzbeec531cef2012-10-18 07:09:20 -0700847 if (cUnit->genBitcode) {
buzbee6459e7c2012-10-02 14:42:41 -0700848 cUnit->enableDebug |= (1 << kDebugVerifyBitcode);
buzbee6969d502012-06-15 16:40:31 -0700849 }
buzbee2cfc6392012-05-07 14:51:40 -0700850#endif
buzbee9281f002012-10-24 12:17:24 -0700851
852#if 1
853// *** Temporary ****
854// For use in debugging issue 7250540. Disable optimization in problem method
855// to see if monkey results change. Should be removed after monkey runs
856// complete.
857if (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) {
858 cUnit->disableOpt |= (
859 (1 << kLoadStoreElimination) |
860 (1 << kLoadHoisting) |
861 (1 << kSuppressLoads) |
buzbee663c09f2012-10-31 05:21:00 -0700862 //(1 << kNullCheckElimination) |
863 //(1 << kPromoteRegs) |
buzbee9281f002012-10-24 12:17:24 -0700864 (1 << kTrackLiveTemps) |
buzbee663c09f2012-10-31 05:21:00 -0700865 //(1 << kSkipLargeMethodOptimization) |
866 //(1 << kSafeOptimizations) |
buzbee9281f002012-10-24 12:17:24 -0700867 (1 << kBBOpt) |
868 (1 << kMatch) |
buzbee663c09f2012-10-31 05:21:00 -0700869 //(1 << kPromoteCompilerTemps) |
870 0);
buzbee9281f002012-10-24 12:17:24 -0700871}
872#endif
873
jeffhao7fbee072012-08-24 17:56:54 -0700874 if (cUnit->instructionSet == kMips) {
875 // Disable some optimizations for mips for now
876 cUnit->disableOpt |= (
877 (1 << kLoadStoreElimination) |
878 (1 << kLoadHoisting) |
879 (1 << kSuppressLoads) |
880 (1 << kNullCheckElimination) |
881 (1 << kPromoteRegs) |
882 (1 << kTrackLiveTemps) |
883 (1 << kSkipLargeMethodOptimization) |
884 (1 << kSafeOptimizations) |
885 (1 << kBBOpt) |
886 (1 << kMatch) |
887 (1 << kPromoteCompilerTemps));
888 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700889
890 /* Gathering opcode stats? */
891 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
buzbeecbd6d442012-11-17 14:11:25 -0800892 cUnit->opcodeCount =
893 static_cast<int*>(oatNew(cUnit.get(), kNumPackedOpcodes * sizeof(int), true, kAllocMisc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700894 }
895
896 /* Assume non-throwing leaf */
897 cUnit->attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE);
898
899 /* Initialize the block list, estimate size based on insnsSize */
900 oatInitGrowableList(cUnit.get(), &cUnit->blockList, cUnit->insnsSize,
901 kListBlockList);
902
903 /* Initialize the switchTables list */
904 oatInitGrowableList(cUnit.get(), &cUnit->switchTables, 4,
905 kListSwitchTables);
906
907 /* Intialize the fillArrayData list */
908 oatInitGrowableList(cUnit.get(), &cUnit->fillArrayData, 4,
909 kListFillArrayData);
910
911 /* Intialize the throwLaunchpads list, estimate size based on insnsSize */
912 oatInitGrowableList(cUnit.get(), &cUnit->throwLaunchpads, cUnit->insnsSize,
913 kListThrowLaunchPads);
914
915 /* Intialize the instrinsicLaunchpads list */
916 oatInitGrowableList(cUnit.get(), &cUnit->intrinsicLaunchpads, 4,
917 kListMisc);
918
919
920 /* Intialize the suspendLaunchpads list */
921 oatInitGrowableList(cUnit.get(), &cUnit->suspendLaunchpads, 2048,
922 kListSuspendLaunchPads);
923
924 /* Allocate the bit-vector to track the beginning of basic blocks */
925 ArenaBitVector *tryBlockAddr = oatAllocBitVector(cUnit.get(),
926 cUnit->insnsSize,
927 true /* expandable */);
928 cUnit->tryBlockAddr = tryBlockAddr;
929
930 /* Create the default entry and exit blocks and enter them to the list */
931 BasicBlock *entryBlock = oatNewBB(cUnit.get(), kEntryBlock, numBlocks++);
932 BasicBlock *exitBlock = oatNewBB(cUnit.get(), kExitBlock, numBlocks++);
933
934 cUnit->entryBlock = entryBlock;
935 cUnit->exitBlock = exitBlock;
936
buzbeecbd6d442012-11-17 14:11:25 -0800937 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, reinterpret_cast<uintptr_t>(entryBlock));
938 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, reinterpret_cast<uintptr_t>(exitBlock));
Bill Buzbeea114add2012-05-03 15:00:40 -0700939
940 /* Current block to record parsed instructions */
941 BasicBlock *curBlock = oatNewBB(cUnit.get(), kDalvikByteCode, numBlocks++);
942 curBlock->startOffset = 0;
buzbeecbd6d442012-11-17 14:11:25 -0800943 oatInsertGrowableList(cUnit.get(), &cUnit->blockList, reinterpret_cast<uintptr_t>(curBlock));
Bill Buzbeea114add2012-05-03 15:00:40 -0700944 /* Add first block to the fast lookup cache */
945 cUnit->blockMap.Put(curBlock->startOffset, curBlock);
946 entryBlock->fallThrough = curBlock;
947 oatInsertGrowableList(cUnit.get(), curBlock->predecessors,
buzbeecbd6d442012-11-17 14:11:25 -0800948 reinterpret_cast<uintptr_t>(entryBlock));
Bill Buzbeea114add2012-05-03 15:00:40 -0700949
950 /*
951 * Store back the number of blocks since new blocks may be created of
952 * accessing cUnit.
953 */
954 cUnit->numBlocks = numBlocks;
955
956 /* Identify code range in try blocks and set up the empty catch blocks */
957 processTryCatchBlocks(cUnit.get());
958
959 /* Set up for simple method detection */
960 int numPatterns = sizeof(specialPatterns)/sizeof(specialPatterns[0]);
961 bool livePattern = (numPatterns > 0) && !(cUnit->disableOpt & (1 << kMatch));
buzbeecbd6d442012-11-17 14:11:25 -0800962 bool* deadPattern =
963 static_cast<bool*>(oatNew(cUnit.get(), sizeof(bool) * numPatterns, true, kAllocMisc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700964 SpecialCaseHandler specialCase = kNoHandler;
965 int patternPos = 0;
966
967 /* Parse all instructions and put them into containing basic blocks */
968 while (codePtr < codeEnd) {
buzbeecbd6d442012-11-17 14:11:25 -0800969 MIR *insn = static_cast<MIR *>(oatNew(cUnit.get(), sizeof(MIR), true, kAllocMIR));
Bill Buzbeea114add2012-05-03 15:00:40 -0700970 insn->offset = curOffset;
971 int width = parseInsn(cUnit.get(), codePtr, &insn->dalvikInsn, false);
972 insn->width = width;
973 Instruction::Code opcode = insn->dalvikInsn.opcode;
974 if (cUnit->opcodeCount != NULL) {
975 cUnit->opcodeCount[static_cast<int>(opcode)]++;
buzbee44b412b2012-02-04 08:50:53 -0800976 }
977
Bill Buzbeea114add2012-05-03 15:00:40 -0700978 /* Terminate when the data section is seen */
979 if (width == 0)
980 break;
981
982 /* Possible simple method? */
983 if (livePattern) {
984 livePattern = false;
985 specialCase = kNoHandler;
986 for (int i = 0; i < numPatterns; i++) {
987 if (!deadPattern[i]) {
988 if (specialPatterns[i].opcodes[patternPos] == opcode) {
989 livePattern = true;
990 specialCase = specialPatterns[i].handlerCode;
991 } else {
992 deadPattern[i] = true;
993 }
994 }
995 }
996 patternPos++;
buzbeea7c12682012-03-19 13:13:53 -0700997 }
998
Bill Buzbeea114add2012-05-03 15:00:40 -0700999 oatAppendMIR(curBlock, insn);
buzbeecefd1872011-09-09 09:59:52 -07001000
Bill Buzbeea114add2012-05-03 15:00:40 -07001001 codePtr += width;
Ian Rogersa75a0132012-09-28 11:41:42 -07001002 int flags = Instruction::FlagsOf(insn->dalvikInsn.opcode);
buzbee67bf8852011-08-17 17:51:35 -07001003
Bill Buzbeea114add2012-05-03 15:00:40 -07001004 int dfFlags = oatDataFlowAttributes[insn->dalvikInsn.opcode];
buzbee67bf8852011-08-17 17:51:35 -07001005
Bill Buzbeea114add2012-05-03 15:00:40 -07001006 if (dfFlags & DF_HAS_DEFS) {
buzbeebff24652012-05-06 16:22:05 -07001007 cUnit->defCount += (dfFlags & DF_A_WIDE) ? 2 : 1;
Bill Buzbeea114add2012-05-03 15:00:40 -07001008 }
buzbee67bf8852011-08-17 17:51:35 -07001009
Bill Buzbeea114add2012-05-03 15:00:40 -07001010 if (flags & Instruction::kBranch) {
1011 curBlock = processCanBranch(cUnit.get(), curBlock, insn, curOffset,
1012 width, flags, codePtr, codeEnd);
1013 } else if (flags & Instruction::kReturn) {
1014 curBlock->fallThrough = exitBlock;
1015 oatInsertGrowableList(cUnit.get(), exitBlock->predecessors,
buzbeecbd6d442012-11-17 14:11:25 -08001016 reinterpret_cast<uintptr_t>(curBlock));
Bill Buzbeea114add2012-05-03 15:00:40 -07001017 /*
1018 * Terminate the current block if there are instructions
1019 * afterwards.
1020 */
1021 if (codePtr < codeEnd) {
1022 /*
1023 * Create a fallthrough block for real instructions
1024 * (incl. NOP).
1025 */
1026 if (contentIsInsn(codePtr)) {
1027 findBlock(cUnit.get(), curOffset + width,
1028 /* split */
1029 false,
1030 /* create */
1031 true,
1032 /* immedPredBlockP */
1033 NULL);
1034 }
1035 }
1036 } else if (flags & Instruction::kThrow) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -07001037 curBlock = processCanThrow(cUnit.get(), curBlock, insn, curOffset,
1038 width, flags, tryBlockAddr, codePtr, codeEnd);
Bill Buzbeea114add2012-05-03 15:00:40 -07001039 } else if (flags & Instruction::kSwitch) {
1040 processCanSwitch(cUnit.get(), curBlock, insn, curOffset, width, flags);
1041 }
1042 curOffset += width;
1043 BasicBlock *nextBlock = findBlock(cUnit.get(), curOffset,
1044 /* split */
1045 false,
1046 /* create */
1047 false,
1048 /* immedPredBlockP */
1049 NULL);
1050 if (nextBlock) {
1051 /*
1052 * The next instruction could be the target of a previously parsed
1053 * forward branch so a block is already created. If the current
1054 * instruction is not an unconditional branch, connect them through
1055 * the fall-through link.
1056 */
1057 DCHECK(curBlock->fallThrough == NULL ||
1058 curBlock->fallThrough == nextBlock ||
1059 curBlock->fallThrough == exitBlock);
buzbee5ade1d22011-09-09 14:44:52 -07001060
Bill Buzbeea114add2012-05-03 15:00:40 -07001061 if ((curBlock->fallThrough == NULL) && (flags & Instruction::kContinue)) {
1062 curBlock->fallThrough = nextBlock;
1063 oatInsertGrowableList(cUnit.get(), nextBlock->predecessors,
buzbeecbd6d442012-11-17 14:11:25 -08001064 reinterpret_cast<uintptr_t>(curBlock));
Bill Buzbeea114add2012-05-03 15:00:40 -07001065 }
1066 curBlock = nextBlock;
1067 }
1068 }
buzbeefc9e6fa2012-03-23 15:14:29 -07001069
Bill Buzbeea114add2012-05-03 15:00:40 -07001070 if (!(cUnit->disableOpt & (1 << kSkipLargeMethodOptimization))) {
1071 if ((cUnit->numBlocks > MANY_BLOCKS) ||
1072 ((cUnit->numBlocks > MANY_BLOCKS_INITIALIZER) &&
1073 PrettyMethod(method_idx, dex_file, false).find("init>") !=
1074 std::string::npos)) {
1075 cUnit->qdMode = true;
1076 }
1077 }
buzbeefc9e6fa2012-03-23 15:14:29 -07001078
Bill Buzbeea114add2012-05-03 15:00:40 -07001079 if (cUnit->qdMode) {
buzbeed1643e42012-09-05 14:06:51 -07001080 // Bitcode generation requires full dataflow analysis
buzbeec531cef2012-10-18 07:09:20 -07001081 cUnit->disableDataflow = !cUnit->genBitcode;
Bill Buzbeea114add2012-05-03 15:00:40 -07001082 // Disable optimization which require dataflow/ssa
buzbeec531cef2012-10-18 07:09:20 -07001083 cUnit->disableOpt |= (1 << kBBOpt) | (1 << kPromoteRegs) | (1 << kNullCheckElimination);
Bill Buzbeea114add2012-05-03 15:00:40 -07001084 if (cUnit->printMe) {
1085 LOG(INFO) << "QD mode enabled: "
1086 << PrettyMethod(method_idx, dex_file)
buzbeec531cef2012-10-18 07:09:20 -07001087 << " num blocks: " << cUnit->numBlocks;
Bill Buzbeea114add2012-05-03 15:00:40 -07001088 }
1089 }
buzbeec1f45042011-09-21 16:03:19 -07001090
Bill Buzbeea114add2012-05-03 15:00:40 -07001091 if (cUnit->printMe) {
1092 oatDumpCompilationUnit(cUnit.get());
1093 }
buzbee67bf8852011-08-17 17:51:35 -07001094
buzbee0967a252012-09-14 10:43:54 -07001095 /* Do a code layout pass */
1096 oatMethodCodeLayout(cUnit.get());
1097
Bill Buzbeea114add2012-05-03 15:00:40 -07001098 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
1099 /* Verify if all blocks are connected as claimed */
1100 oatDataFlowAnalysisDispatcher(cUnit.get(), verifyPredInfo, kAllNodes,
1101 false /* isIterative */);
1102 }
buzbee67bf8852011-08-17 17:51:35 -07001103
Bill Buzbeea114add2012-05-03 15:00:40 -07001104 /* Perform SSA transformation for the whole method */
1105 oatMethodSSATransformation(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001106
buzbee2cfc6392012-05-07 14:51:40 -07001107 /* Do constant propagation */
1108 // TODO: Probably need to make these expandable to support new ssa names
1109 // introducted during MIR optimization passes
1110 cUnit->isConstantV = oatAllocBitVector(cUnit.get(), cUnit->numSSARegs,
1111 false /* not expandable */);
1112 cUnit->constantValues =
buzbeecbd6d442012-11-17 14:11:25 -08001113 static_cast<int*>(oatNew(cUnit.get(), sizeof(int) * cUnit->numSSARegs, true, kAllocDFInfo));
buzbee2cfc6392012-05-07 14:51:40 -07001114 oatDataFlowAnalysisDispatcher(cUnit.get(), oatDoConstantPropagation,
1115 kAllNodes,
1116 false /* isIterative */);
1117
Bill Buzbeea114add2012-05-03 15:00:40 -07001118 /* Detect loops */
1119 oatMethodLoopDetection(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001120
Bill Buzbeea114add2012-05-03 15:00:40 -07001121 /* Count uses */
1122 oatMethodUseCount(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001123
Bill Buzbeea114add2012-05-03 15:00:40 -07001124 /* Perform null check elimination */
1125 oatMethodNullCheckElimination(cUnit.get());
1126
buzbeed1643e42012-09-05 14:06:51 -07001127 /* Combine basic blocks where possible */
1128 oatMethodBasicBlockCombine(cUnit.get());
1129
Bill Buzbeea114add2012-05-03 15:00:40 -07001130 /* Do some basic block optimizations */
1131 oatMethodBasicBlockOptimization(cUnit.get());
1132
buzbeed1643e42012-09-05 14:06:51 -07001133 if (cUnit->enableDebug & (1 << kDebugDumpCheckStats)) {
1134 oatDumpCheckStats(cUnit.get());
1135 }
1136
Bill Buzbeea114add2012-05-03 15:00:40 -07001137 oatInitializeRegAlloc(cUnit.get()); // Needs to happen after SSA naming
1138
1139 /* Allocate Registers using simple local allocation scheme */
1140 oatSimpleRegAlloc(cUnit.get());
1141
buzbee2cfc6392012-05-07 14:51:40 -07001142 /* Go the LLVM path? */
1143 if (cUnit->genBitcode) {
1144 // MIR->Bitcode
1145 oatMethodMIR2Bitcode(cUnit.get());
buzbeec531cef2012-10-18 07:09:20 -07001146 if (compilerBackend == kPortable) {
buzbeeabc4c6b2012-08-23 08:17:15 -07001147 // all done
1148 oatArenaReset(cUnit.get());
1149 return NULL;
1150 }
buzbee2cfc6392012-05-07 14:51:40 -07001151 // Bitcode->LIR
1152 oatMethodBitcode2LIR(cUnit.get());
1153 } else {
buzbee2cfc6392012-05-07 14:51:40 -07001154 if (specialCase != kNoHandler) {
1155 /*
1156 * Custom codegen for special cases. If for any reason the
1157 * special codegen doesn't succeed, cUnit->firstLIRInsn will
1158 * set to NULL;
1159 */
1160 oatSpecialMIR2LIR(cUnit.get(), specialCase);
1161 }
buzbee67bf8852011-08-17 17:51:35 -07001162
buzbee2cfc6392012-05-07 14:51:40 -07001163 /* Convert MIR to LIR, etc. */
1164 if (cUnit->firstLIRInsn == NULL) {
1165 oatMethodMIR2LIR(cUnit.get());
1166 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001167 }
buzbee67bf8852011-08-17 17:51:35 -07001168
Bill Buzbeea114add2012-05-03 15:00:40 -07001169 // Debugging only
1170 if (cUnit->enableDebug & (1 << kDebugDumpCFG)) {
1171 oatDumpCFG(cUnit.get(), "/sdcard/cfg/");
1172 }
buzbee16da88c2012-03-20 10:38:17 -07001173
Bill Buzbeea114add2012-05-03 15:00:40 -07001174 /* Method is not empty */
1175 if (cUnit->firstLIRInsn) {
buzbee67bf8852011-08-17 17:51:35 -07001176
Bill Buzbeea114add2012-05-03 15:00:40 -07001177 // mark the targets of switch statement case labels
1178 oatProcessSwitchTables(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001179
Bill Buzbeea114add2012-05-03 15:00:40 -07001180 /* Convert LIR into machine code. */
1181 oatAssembleLIR(cUnit.get());
buzbee99ba9642012-01-25 14:23:14 -08001182
Elliott Hughes3b6baaa2011-10-14 19:13:56 -07001183 if (cUnit->printMe) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001184 oatCodegenDump(cUnit.get());
buzbee67bf8852011-08-17 17:51:35 -07001185 }
1186
Bill Buzbeea114add2012-05-03 15:00:40 -07001187 if (cUnit->opcodeCount != NULL) {
1188 LOG(INFO) << "Opcode Count";
1189 for (int i = 0; i < kNumPackedOpcodes; i++) {
1190 if (cUnit->opcodeCount[i] != 0) {
1191 LOG(INFO) << "-C- "
1192 << Instruction::Name(static_cast<Instruction::Code>(i))
1193 << " " << cUnit->opcodeCount[i];
buzbee67bf8852011-08-17 17:51:35 -07001194 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001195 }
1196 }
1197 }
buzbeea7c12682012-03-19 13:13:53 -07001198
Bill Buzbeea114add2012-05-03 15:00:40 -07001199 // Combine vmap tables - core regs, then fp regs - into vmapTable
1200 std::vector<uint16_t> vmapTable;
buzbeeca7a5e42012-08-20 11:12:18 -07001201 // Core regs may have been inserted out of order - sort first
1202 std::sort(cUnit->coreVmapTable.begin(), cUnit->coreVmapTable.end());
Bill Buzbeea114add2012-05-03 15:00:40 -07001203 for (size_t i = 0 ; i < cUnit->coreVmapTable.size(); i++) {
buzbeeca7a5e42012-08-20 11:12:18 -07001204 // Copy, stripping out the phys register sort key
1205 vmapTable.push_back(~(-1 << VREG_NUM_WIDTH) & cUnit->coreVmapTable[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001206 }
1207 // If we have a frame, push a marker to take place of lr
1208 if (cUnit->frameSize > 0) {
1209 vmapTable.push_back(INVALID_VREG);
1210 } else {
1211 DCHECK_EQ(__builtin_popcount(cUnit->coreSpillMask), 0);
1212 DCHECK_EQ(__builtin_popcount(cUnit->fpSpillMask), 0);
1213 }
buzbeeca7a5e42012-08-20 11:12:18 -07001214 // Combine vmap tables - core regs, then fp regs. fp regs already sorted
Bill Buzbeea114add2012-05-03 15:00:40 -07001215 for (uint32_t i = 0; i < cUnit->fpVmapTable.size(); i++) {
1216 vmapTable.push_back(cUnit->fpVmapTable[i]);
1217 }
1218 CompiledMethod* result =
1219 new CompiledMethod(cUnit->instructionSet, cUnit->codeBuffer,
Bill Buzbeea5b30242012-09-28 07:19:44 -07001220 cUnit->frameSize, cUnit->coreSpillMask, cUnit->fpSpillMask,
1221 cUnit->combinedMappingTable, vmapTable, cUnit->nativeGcMap);
buzbee67bf8852011-08-17 17:51:35 -07001222
Bill Buzbeea114add2012-05-03 15:00:40 -07001223 VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file)
1224 << " (" << (cUnit->codeBuffer.size() * sizeof(cUnit->codeBuffer[0]))
1225 << " bytes)";
buzbee5abfa3e2012-01-31 17:01:43 -08001226
1227#ifdef WITH_MEMSTATS
Bill Buzbeea114add2012-05-03 15:00:40 -07001228 if (cUnit->enableDebug & (1 << kDebugShowMemoryUsage)) {
1229 oatDumpMemStats(cUnit.get());
1230 }
buzbee5abfa3e2012-01-31 17:01:43 -08001231#endif
buzbee67bf8852011-08-17 17:51:35 -07001232
Bill Buzbeea114add2012-05-03 15:00:40 -07001233 oatArenaReset(cUnit.get());
buzbeeba938cb2012-02-03 14:47:55 -08001234
Bill Buzbeea114add2012-05-03 15:00:40 -07001235 return result;
buzbee67bf8852011-08-17 17:51:35 -07001236}
1237
buzbeeabc4c6b2012-08-23 08:17:15 -07001238CompiledMethod* oatCompileMethod(Compiler& compiler,
buzbeec531cef2012-10-18 07:09:20 -07001239 const CompilerBackend backend,
buzbeeabc4c6b2012-08-23 08:17:15 -07001240 const DexFile::CodeItem* code_item,
1241 uint32_t access_flags, InvokeType invoke_type,
1242 uint32_t method_idx, jobject class_loader,
buzbeec531cef2012-10-18 07:09:20 -07001243 const DexFile& dex_file,
1244 LLVMInfo* llvmInfo)
buzbeeabc4c6b2012-08-23 08:17:15 -07001245{
buzbeec531cef2012-10-18 07:09:20 -07001246 return compileMethod(compiler, backend, code_item, access_flags, invoke_type, method_idx, class_loader,
1247 dex_file, llvmInfo);
buzbeeabc4c6b2012-08-23 08:17:15 -07001248}
1249
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001250} // namespace art
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001251
Bill Buzbeea114add2012-05-03 15:00:40 -07001252extern "C" art::CompiledMethod*
buzbeec531cef2012-10-18 07:09:20 -07001253 ArtQuickCompileMethod(art::Compiler& compiler,
1254 const art::DexFile::CodeItem* code_item,
1255 uint32_t access_flags, art::InvokeType invoke_type,
1256 uint32_t method_idx, jobject class_loader,
1257 const art::DexFile& dex_file)
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001258{
1259 CHECK_EQ(compiler.GetInstructionSet(), art::oatInstructionSet());
buzbeec531cef2012-10-18 07:09:20 -07001260 // TODO: check method fingerprint here to determine appropriate backend type. Until then, use build default
1261 art::CompilerBackend backend = compiler.GetCompilerBackend();
1262 return art::oatCompileMethod(compiler, backend, code_item, access_flags, invoke_type,
1263 method_idx, class_loader, dex_file, NULL /* use thread llvmInfo */);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001264}