blob: 4619052f4b6e1c500c5da40cd4ce8bb106d440d6 [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"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080022#include "mirror/object.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070023#include "runtime.h"
buzbee395116c2013-02-27 14:30:25 -080024#include "quick/codegen_util.h"
25#include "portable/mir_to_gbc.h"
26#include "quick/mir_to_lir.h"
buzbee67bf8852011-08-17 17:51:35 -070027
buzbee4df2bbd2012-10-11 14:46:06 -070028#include <llvm/Support/Threading.h>
29
30namespace {
Ian Rogersc928de92013-02-27 14:30:44 -080031#if !defined(ART_USE_PORTABLE_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 {
Ian Rogers76ae4fe2013-02-27 16:03:41 -080040namespace compiler_llvm {
41llvm::Module* makeLLVMModuleContents(llvm::Module* module);
42}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080043
buzbee4df2bbd2012-10-11 14:46:06 -070044LLVMInfo::LLVMInfo() {
Ian Rogersc928de92013-02-27 14:30:44 -080045#if !defined(ART_USE_PORTABLE_COMPILER)
buzbee4df2bbd2012-10-11 14:46:06 -070046 pthread_once(&llvm_multi_init, InitializeLLVMForQuick);
47#endif
buzbee692be802012-08-29 15:52:59 -070048 // Create context, module, intrinsic helper & ir builder
49 llvm_context_.reset(new llvm::LLVMContext());
TDYa12755e5e6c2012-09-11 15:14:42 -070050 llvm_module_ = new llvm::Module("art", *llvm_context_);
buzbee692be802012-08-29 15:52:59 -070051 llvm::StructType::create(*llvm_context_, "JavaObject");
Ian Rogers76ae4fe2013-02-27 16:03:41 -080052 compiler_llvm::makeLLVMModuleContents(llvm_module_);
53 intrinsic_helper_.reset( new compiler_llvm::IntrinsicHelper(*llvm_context_, *llvm_module_));
54 ir_builder_.reset(new compiler_llvm::IRBuilder(*llvm_context_, *llvm_module_, *intrinsic_helper_));
buzbee692be802012-08-29 15:52:59 -070055}
56
buzbee4df2bbd2012-10-11 14:46:06 -070057LLVMInfo::~LLVMInfo() {
buzbee692be802012-08-29 15:52:59 -070058}
59
60extern "C" void ArtInitQuickCompilerContext(art::Compiler& compiler) {
61 CHECK(compiler.GetCompilerContext() == NULL);
buzbeefa57c472012-11-21 12:06:18 -080062 LLVMInfo* llvm_info = new LLVMInfo();
63 compiler.SetCompilerContext(llvm_info);
buzbee692be802012-08-29 15:52:59 -070064}
65
66extern "C" void ArtUnInitQuickCompilerContext(art::Compiler& compiler) {
buzbee4df2bbd2012-10-11 14:46:06 -070067 delete reinterpret_cast<LLVMInfo*>(compiler.GetCompilerContext());
buzbee692be802012-08-29 15:52:59 -070068 compiler.SetCompilerContext(NULL);
69}
buzbee692be802012-08-29 15:52:59 -070070
buzbeece302932011-10-04 14:32:18 -070071/* Default optimizer/debug setting for the compiler. */
Elliott Hughese52e49b2012-04-02 16:05:44 -070072static uint32_t kCompilerOptimizerDisableFlags = 0 | // Disable specific optimizations
buzbee4ef3e452012-12-14 13:35:28 -080073 (1 << kLoadStoreElimination) |
Bill Buzbeea114add2012-05-03 15:00:40 -070074 //(1 << kLoadHoisting) |
75 //(1 << kSuppressLoads) |
76 //(1 << kNullCheckElimination) |
77 //(1 << kPromoteRegs) |
78 //(1 << kTrackLiveTemps) |
buzbee4ef3e452012-12-14 13:35:28 -080079 (1 << kSkipLargeMethodOptimization) |
Bill Buzbeea114add2012-05-03 15:00:40 -070080 //(1 << kSafeOptimizations) |
81 //(1 << kBBOpt) |
82 //(1 << kMatch) |
83 //(1 << kPromoteCompilerTemps) |
84 0;
buzbeece302932011-10-04 14:32:18 -070085
Elliott Hughese52e49b2012-04-02 16:05:44 -070086static uint32_t kCompilerDebugFlags = 0 | // Enable debug/testing modes
Bill Buzbeea114add2012-05-03 15:00:40 -070087 //(1 << kDebugDisplayMissingTargets) |
88 //(1 << kDebugVerbose) |
89 //(1 << kDebugDumpCFG) |
90 //(1 << kDebugSlowFieldPath) |
91 //(1 << kDebugSlowInvokePath) |
92 //(1 << kDebugSlowStringPath) |
93 //(1 << kDebugSlowestFieldPath) |
94 //(1 << kDebugSlowestStringPath) |
95 //(1 << kDebugExerciseResolveMethod) |
96 //(1 << kDebugVerifyDataflow) |
97 //(1 << kDebugShowMemoryUsage) |
98 //(1 << kDebugShowNops) |
99 //(1 << kDebugCountOpcodes) |
buzbeed1643e42012-09-05 14:06:51 -0700100 //(1 << kDebugDumpCheckStats) |
buzbeead8f15e2012-06-18 14:49:45 -0700101 //(1 << kDebugDumpBitcodeFile) |
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700102 //(1 << kDebugVerifyBitcode) |
Bill Buzbeea114add2012-05-03 15:00:40 -0700103 0;
buzbeece302932011-10-04 14:32:18 -0700104
buzbeefa57c472012-11-21 12:06:18 -0800105static bool ContentIsInsn(const uint16_t* code_ptr) {
106 uint16_t instr = *code_ptr;
buzbeecbd6d442012-11-17 14:11:25 -0800107 Instruction::Code opcode = static_cast<Instruction::Code>(instr & 0xff);
buzbee67bf8852011-08-17 17:51:35 -0700108
Bill Buzbeea114add2012-05-03 15:00:40 -0700109 /*
110 * Since the low 8-bit in metadata may look like NOP, we need to check
111 * both the low and whole sub-word to determine whether it is code or data.
112 */
113 return (opcode != Instruction::NOP || instr == 0);
buzbee67bf8852011-08-17 17:51:35 -0700114}
115
116/*
117 * Parse an instruction, return the length of the instruction
118 */
buzbeefa57c472012-11-21 12:06:18 -0800119static int ParseInsn(CompilationUnit* cu, const uint16_t* code_ptr,
buzbeea169e1d2012-12-05 14:26:44 -0800120 DecodedInstruction* decoded_instruction)
buzbee67bf8852011-08-17 17:51:35 -0700121{
Elliott Hughesadb8c672012-03-06 16:49:32 -0800122 // Don't parse instruction data
buzbeefa57c472012-11-21 12:06:18 -0800123 if (!ContentIsInsn(code_ptr)) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800124 return 0;
125 }
buzbee67bf8852011-08-17 17:51:35 -0700126
buzbeefa57c472012-11-21 12:06:18 -0800127 const Instruction* instruction = Instruction::At(code_ptr);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800128 *decoded_instruction = DecodedInstruction(instruction);
buzbee67bf8852011-08-17 17:51:35 -0700129
Elliott Hughesadb8c672012-03-06 16:49:32 -0800130 return instruction->SizeInCodeUnits();
buzbee67bf8852011-08-17 17:51:35 -0700131}
132
133#define UNKNOWN_TARGET 0xffffffff
134
buzbee67bf8852011-08-17 17:51:35 -0700135/* Split an existing block from the specified code offset into two */
buzbeefa57c472012-11-21 12:06:18 -0800136static BasicBlock *SplitBlock(CompilationUnit* cu, unsigned int code_offset,
137 BasicBlock* orig_block, BasicBlock** immed_pred_block_p)
buzbee67bf8852011-08-17 17:51:35 -0700138{
buzbeefa57c472012-11-21 12:06:18 -0800139 MIR* insn = orig_block->first_mir_insn;
Bill Buzbeea114add2012-05-03 15:00:40 -0700140 while (insn) {
buzbeefa57c472012-11-21 12:06:18 -0800141 if (insn->offset == code_offset) break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700142 insn = insn->next;
143 }
144 if (insn == NULL) {
145 LOG(FATAL) << "Break split failed";
146 }
buzbeefa57c472012-11-21 12:06:18 -0800147 BasicBlock *bottom_block = NewMemBB(cu, kDalvikByteCode,
148 cu->num_blocks++);
149 InsertGrowableList(cu, &cu->block_list, reinterpret_cast<uintptr_t>(bottom_block));
buzbee67bf8852011-08-17 17:51:35 -0700150
buzbeefa57c472012-11-21 12:06:18 -0800151 bottom_block->start_offset = code_offset;
152 bottom_block->first_mir_insn = insn;
153 bottom_block->last_mir_insn = orig_block->last_mir_insn;
buzbee67bf8852011-08-17 17:51:35 -0700154
buzbeebbdd0532013-02-07 09:33:02 -0800155 /* If this block was terminated by a return, the flag needs to go with the bottom block */
156 bottom_block->terminated_by_return = orig_block->terminated_by_return;
157 orig_block->terminated_by_return = false;
158
Bill Buzbeea114add2012-05-03 15:00:40 -0700159 /* Add it to the quick lookup cache */
buzbeefa57c472012-11-21 12:06:18 -0800160 cu->block_map.Put(bottom_block->start_offset, bottom_block);
buzbee5b537102012-01-17 17:33:47 -0800161
Bill Buzbeea114add2012-05-03 15:00:40 -0700162 /* Handle the taken path */
buzbeefa57c472012-11-21 12:06:18 -0800163 bottom_block->taken = orig_block->taken;
164 if (bottom_block->taken) {
165 orig_block->taken = NULL;
166 DeleteGrowableList(bottom_block->taken->predecessors, reinterpret_cast<uintptr_t>(orig_block));
167 InsertGrowableList(cu, bottom_block->taken->predecessors,
168 reinterpret_cast<uintptr_t>(bottom_block));
Bill Buzbeea114add2012-05-03 15:00:40 -0700169 }
170
171 /* Handle the fallthrough path */
buzbeefa57c472012-11-21 12:06:18 -0800172 bottom_block->fall_through = orig_block->fall_through;
173 orig_block->fall_through = bottom_block;
174 InsertGrowableList(cu, bottom_block->predecessors,
175 reinterpret_cast<uintptr_t>(orig_block));
176 if (bottom_block->fall_through) {
177 DeleteGrowableList(bottom_block->fall_through->predecessors,
178 reinterpret_cast<uintptr_t>(orig_block));
179 InsertGrowableList(cu, bottom_block->fall_through->predecessors,
180 reinterpret_cast<uintptr_t>(bottom_block));
Bill Buzbeea114add2012-05-03 15:00:40 -0700181 }
182
183 /* Handle the successor list */
buzbeefa57c472012-11-21 12:06:18 -0800184 if (orig_block->successor_block_list.block_list_type != kNotUsed) {
185 bottom_block->successor_block_list = orig_block->successor_block_list;
186 orig_block->successor_block_list.block_list_type = kNotUsed;
Bill Buzbeea114add2012-05-03 15:00:40 -0700187 GrowableListIterator iterator;
188
buzbeefa57c472012-11-21 12:06:18 -0800189 GrowableListIteratorInit(&bottom_block->successor_block_list.blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700190 &iterator);
191 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800192 SuccessorBlockInfo *successor_block_info =
buzbee52a77fc2012-11-20 19:50:46 -0800193 reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));
buzbeefa57c472012-11-21 12:06:18 -0800194 if (successor_block_info == NULL) break;
195 BasicBlock *bb = successor_block_info->block;
196 DeleteGrowableList(bb->predecessors, reinterpret_cast<uintptr_t>(orig_block));
197 InsertGrowableList(cu, bb->predecessors, reinterpret_cast<uintptr_t>(bottom_block));
buzbee67bf8852011-08-17 17:51:35 -0700198 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700199 }
buzbee67bf8852011-08-17 17:51:35 -0700200
buzbeefa57c472012-11-21 12:06:18 -0800201 orig_block->last_mir_insn = insn->prev;
buzbee67bf8852011-08-17 17:51:35 -0700202
Bill Buzbeea114add2012-05-03 15:00:40 -0700203 insn->prev->next = NULL;
204 insn->prev = NULL;
205 /*
206 * Update the immediate predecessor block pointer so that outgoing edges
207 * can be applied to the proper block.
208 */
buzbeefa57c472012-11-21 12:06:18 -0800209 if (immed_pred_block_p) {
210 DCHECK_EQ(*immed_pred_block_p, orig_block);
211 *immed_pred_block_p = bottom_block;
Bill Buzbeea114add2012-05-03 15:00:40 -0700212 }
buzbeefa57c472012-11-21 12:06:18 -0800213 return bottom_block;
buzbee67bf8852011-08-17 17:51:35 -0700214}
215
216/*
217 * Given a code offset, find out the block that starts with it. If the offset
buzbeefa57c472012-11-21 12:06:18 -0800218 * is in the middle of an existing block, split it into two. If immed_pred_block_p
219 * is not non-null and is the block being split, update *immed_pred_block_p to
buzbee9ab05de2012-01-18 15:43:48 -0800220 * point to the bottom block so that outgoing edges can be set up properly
221 * (by the caller)
buzbee5b537102012-01-17 17:33:47 -0800222 * Utilizes a map for fast lookup of the typical cases.
buzbee67bf8852011-08-17 17:51:35 -0700223 */
buzbeefa57c472012-11-21 12:06:18 -0800224BasicBlock *FindBlock(CompilationUnit* cu, unsigned int code_offset,
225 bool split, bool create, BasicBlock** immed_pred_block_p)
buzbee67bf8852011-08-17 17:51:35 -0700226{
buzbeefa57c472012-11-21 12:06:18 -0800227 GrowableList* block_list = &cu->block_list;
Bill Buzbeea114add2012-05-03 15:00:40 -0700228 BasicBlock* bb;
229 unsigned int i;
230 SafeMap<unsigned int, BasicBlock*>::iterator it;
buzbee67bf8852011-08-17 17:51:35 -0700231
buzbeefa57c472012-11-21 12:06:18 -0800232 it = cu->block_map.find(code_offset);
233 if (it != cu->block_map.end()) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700234 return it->second;
235 } else if (!create) {
236 return NULL;
237 }
238
239 if (split) {
buzbeefa57c472012-11-21 12:06:18 -0800240 for (i = 0; i < block_list->num_used; i++) {
241 bb = reinterpret_cast<BasicBlock*>(block_list->elem_list[i]);
242 if (bb->block_type != kDalvikByteCode) continue;
Bill Buzbeea114add2012-05-03 15:00:40 -0700243 /* Check if a branch jumps into the middle of an existing block */
buzbeefa57c472012-11-21 12:06:18 -0800244 if ((code_offset > bb->start_offset) && (bb->last_mir_insn != NULL) &&
245 (code_offset <= bb->last_mir_insn->offset)) {
246 BasicBlock *new_bb = SplitBlock(cu, code_offset, bb,
247 bb == *immed_pred_block_p ?
248 immed_pred_block_p : NULL);
249 return new_bb;
Bill Buzbeea114add2012-05-03 15:00:40 -0700250 }
buzbee5b537102012-01-17 17:33:47 -0800251 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700252 }
buzbee5b537102012-01-17 17:33:47 -0800253
Bill Buzbeea114add2012-05-03 15:00:40 -0700254 /* Create a new one */
buzbeefa57c472012-11-21 12:06:18 -0800255 bb = NewMemBB(cu, kDalvikByteCode, cu->num_blocks++);
256 InsertGrowableList(cu, &cu->block_list, reinterpret_cast<uintptr_t>(bb));
257 bb->start_offset = code_offset;
258 cu->block_map.Put(bb->start_offset, bb);
Bill Buzbeea114add2012-05-03 15:00:40 -0700259 return bb;
buzbee67bf8852011-08-17 17:51:35 -0700260}
261
buzbeef58c12c2012-07-03 15:06:29 -0700262/* Find existing block */
buzbeefa57c472012-11-21 12:06:18 -0800263BasicBlock* FindBlock(CompilationUnit* cu, unsigned int code_offset)
buzbeef58c12c2012-07-03 15:06:29 -0700264{
buzbeefa57c472012-11-21 12:06:18 -0800265 return FindBlock(cu, code_offset, false, false, NULL);
buzbeef58c12c2012-07-03 15:06:29 -0700266}
267
buzbeead8f15e2012-06-18 14:49:45 -0700268/* Turn method name into a legal Linux file name */
buzbee52a77fc2012-11-20 19:50:46 -0800269void ReplaceSpecialChars(std::string& str)
buzbeead8f15e2012-06-18 14:49:45 -0700270{
271 static const struct { const char before; const char after; } match[] =
272 {{'/','-'}, {';','#'}, {' ','#'}, {'$','+'},
273 {'(','@'}, {')','@'}, {'<','='}, {'>','='}};
274 for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) {
275 std::replace(str.begin(), str.end(), match[i].before, match[i].after);
276 }
277}
278
buzbee67bf8852011-08-17 17:51:35 -0700279/* Dump the CFG into a DOT graph */
buzbeed8506212012-12-20 14:15:05 -0800280void DumpCFG(CompilationUnit* cu, const char* dir_prefix, bool all_blocks)
buzbee67bf8852011-08-17 17:51:35 -0700281{
Bill Buzbeea114add2012-05-03 15:00:40 -0700282 FILE* file;
buzbeefa57c472012-11-21 12:06:18 -0800283 std::string fname(PrettyMethod(cu->method_idx, *cu->dex_file));
buzbee52a77fc2012-11-20 19:50:46 -0800284 ReplaceSpecialChars(fname);
buzbeefa57c472012-11-21 12:06:18 -0800285 fname = StringPrintf("%s%s%x.dot", dir_prefix, fname.c_str(),
286 cu->entry_block->fall_through->start_offset);
buzbeead8f15e2012-06-18 14:49:45 -0700287 file = fopen(fname.c_str(), "w");
Bill Buzbeea114add2012-05-03 15:00:40 -0700288 if (file == NULL) {
289 return;
290 }
291 fprintf(file, "digraph G {\n");
292
293 fprintf(file, " rankdir=TB\n");
294
buzbeed8506212012-12-20 14:15:05 -0800295 int num_blocks = all_blocks ? cu->num_blocks : cu->num_reachable_blocks;
Bill Buzbeea114add2012-05-03 15:00:40 -0700296 int idx;
buzbeefa57c472012-11-21 12:06:18 -0800297 const GrowableList *block_list = &cu->block_list;
Bill Buzbeea114add2012-05-03 15:00:40 -0700298
buzbeed8506212012-12-20 14:15:05 -0800299 for (idx = 0; idx < num_blocks; idx++) {
300 int block_idx = all_blocks ? idx : cu->dfs_order.elem_list[idx];
buzbeefa57c472012-11-21 12:06:18 -0800301 BasicBlock *bb = reinterpret_cast<BasicBlock*>(GrowableListGetElement(block_list, block_idx));
Bill Buzbeea114add2012-05-03 15:00:40 -0700302 if (bb == NULL) break;
buzbeefa57c472012-11-21 12:06:18 -0800303 if (bb->block_type == kDead) continue;
304 if (bb->block_type == kEntryBlock) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700305 fprintf(file, " entry_%d [shape=Mdiamond];\n", bb->id);
buzbeefa57c472012-11-21 12:06:18 -0800306 } else if (bb->block_type == kExitBlock) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700307 fprintf(file, " exit_%d [shape=Mdiamond];\n", bb->id);
buzbeefa57c472012-11-21 12:06:18 -0800308 } else if (bb->block_type == kDalvikByteCode) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700309 fprintf(file, " block%04x_%d [shape=record,label = \"{ \\\n",
buzbeefa57c472012-11-21 12:06:18 -0800310 bb->start_offset, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700311 const MIR *mir;
312 fprintf(file, " {block id %d\\l}%s\\\n", bb->id,
buzbeefa57c472012-11-21 12:06:18 -0800313 bb->first_mir_insn ? " | " : " ");
314 for (mir = bb->first_mir_insn; mir; mir = mir->next) {
buzbeed8506212012-12-20 14:15:05 -0800315 int opcode = mir->dalvikInsn.opcode;
316 fprintf(file, " {%04x %s %s %s\\l}%s\\\n", mir->offset,
buzbeea169e1d2012-12-05 14:26:44 -0800317 mir->ssa_rep ? GetDalvikDisassembly(cu, mir) :
buzbeed8506212012-12-20 14:15:05 -0800318 (opcode < kMirOpFirst) ? Instruction::Name(mir->dalvikInsn.opcode) :
319 extended_mir_op_names[opcode - kMirOpFirst],
320 (mir->optimization_flags & MIR_IGNORE_RANGE_CHECK) != 0 ? " no_rangecheck" : " ",
321 (mir->optimization_flags & MIR_IGNORE_NULL_CHECK) != 0 ? " no_nullcheck" : " ",
Bill Buzbeea114add2012-05-03 15:00:40 -0700322 mir->next ? " | " : " ");
323 }
324 fprintf(file, " }\"];\n\n");
buzbeefa57c472012-11-21 12:06:18 -0800325 } else if (bb->block_type == kExceptionHandling) {
326 char block_name[BLOCK_NAME_LEN];
Bill Buzbeea114add2012-05-03 15:00:40 -0700327
buzbeefa57c472012-11-21 12:06:18 -0800328 GetBlockName(bb, block_name);
329 fprintf(file, " %s [shape=invhouse];\n", block_name);
buzbee67bf8852011-08-17 17:51:35 -0700330 }
buzbee67bf8852011-08-17 17:51:35 -0700331
buzbeefa57c472012-11-21 12:06:18 -0800332 char block_name1[BLOCK_NAME_LEN], block_name2[BLOCK_NAME_LEN];
buzbee67bf8852011-08-17 17:51:35 -0700333
Bill Buzbeea114add2012-05-03 15:00:40 -0700334 if (bb->taken) {
buzbeefa57c472012-11-21 12:06:18 -0800335 GetBlockName(bb, block_name1);
336 GetBlockName(bb->taken, block_name2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700337 fprintf(file, " %s:s -> %s:n [style=dotted]\n",
buzbeefa57c472012-11-21 12:06:18 -0800338 block_name1, block_name2);
buzbee67bf8852011-08-17 17:51:35 -0700339 }
buzbeefa57c472012-11-21 12:06:18 -0800340 if (bb->fall_through) {
341 GetBlockName(bb, block_name1);
342 GetBlockName(bb->fall_through, block_name2);
343 fprintf(file, " %s:s -> %s:n\n", block_name1, block_name2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700344 }
345
buzbeefa57c472012-11-21 12:06:18 -0800346 if (bb->successor_block_list.block_list_type != kNotUsed) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700347 fprintf(file, " succ%04x_%d [shape=%s,label = \"{ \\\n",
buzbeefa57c472012-11-21 12:06:18 -0800348 bb->start_offset, bb->id,
349 (bb->successor_block_list.block_list_type == kCatch) ?
Bill Buzbeea114add2012-05-03 15:00:40 -0700350 "Mrecord" : "record");
351 GrowableListIterator iterator;
buzbeefa57c472012-11-21 12:06:18 -0800352 GrowableListIteratorInit(&bb->successor_block_list.blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700353 &iterator);
buzbeefa57c472012-11-21 12:06:18 -0800354 SuccessorBlockInfo *successor_block_info =
buzbee52a77fc2012-11-20 19:50:46 -0800355 reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700356
buzbeefa57c472012-11-21 12:06:18 -0800357 int succ_id = 0;
Bill Buzbeea114add2012-05-03 15:00:40 -0700358 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800359 if (successor_block_info == NULL) break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700360
buzbeefa57c472012-11-21 12:06:18 -0800361 BasicBlock *dest_block = successor_block_info->block;
362 SuccessorBlockInfo *next_successor_block_info =
buzbee52a77fc2012-11-20 19:50:46 -0800363 reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700364
365 fprintf(file, " {<f%d> %04x: %04x\\l}%s\\\n",
buzbeefa57c472012-11-21 12:06:18 -0800366 succ_id++,
367 successor_block_info->key,
368 dest_block->start_offset,
369 (next_successor_block_info != NULL) ? " | " : " ");
Bill Buzbeea114add2012-05-03 15:00:40 -0700370
buzbeefa57c472012-11-21 12:06:18 -0800371 successor_block_info = next_successor_block_info;
Bill Buzbeea114add2012-05-03 15:00:40 -0700372 }
373 fprintf(file, " }\"];\n\n");
374
buzbeefa57c472012-11-21 12:06:18 -0800375 GetBlockName(bb, block_name1);
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700376 fprintf(file, " %s:s -> succ%04x_%d:n [style=dashed]\n",
buzbeefa57c472012-11-21 12:06:18 -0800377 block_name1, bb->start_offset, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700378
buzbeefa57c472012-11-21 12:06:18 -0800379 if (bb->successor_block_list.block_list_type == kPackedSwitch ||
380 bb->successor_block_list.block_list_type == kSparseSwitch) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700381
buzbeefa57c472012-11-21 12:06:18 -0800382 GrowableListIteratorInit(&bb->successor_block_list.blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700383 &iterator);
384
buzbeefa57c472012-11-21 12:06:18 -0800385 succ_id = 0;
Bill Buzbeea114add2012-05-03 15:00:40 -0700386 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800387 SuccessorBlockInfo *successor_block_info =
buzbee52a77fc2012-11-20 19:50:46 -0800388 reinterpret_cast<SuccessorBlockInfo*>( GrowableListIteratorNext(&iterator));
buzbeefa57c472012-11-21 12:06:18 -0800389 if (successor_block_info == NULL) break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700390
buzbeefa57c472012-11-21 12:06:18 -0800391 BasicBlock *dest_block = successor_block_info->block;
Bill Buzbeea114add2012-05-03 15:00:40 -0700392
buzbeefa57c472012-11-21 12:06:18 -0800393 GetBlockName(dest_block, block_name2);
394 fprintf(file, " succ%04x_%d:f%d:e -> %s:n\n", bb->start_offset,
395 bb->id, succ_id++, block_name2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700396 }
397 }
398 }
399 fprintf(file, "\n");
400
buzbeed8506212012-12-20 14:15:05 -0800401 if (cu->verbose) {
402 /* Display the dominator tree */
403 GetBlockName(bb, block_name1);
404 fprintf(file, " cfg%s [label=\"%s\", shape=none];\n",
405 block_name1, block_name1);
406 if (bb->i_dom) {
407 GetBlockName(bb->i_dom, block_name2);
408 fprintf(file, " cfg%s:s -> cfg%s:n\n\n", block_name2, block_name1);
409 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700410 }
411 }
412 fprintf(file, "}\n");
413 fclose(file);
buzbee67bf8852011-08-17 17:51:35 -0700414}
415
416/* Verify if all the successor is connected with all the claimed predecessors */
buzbeefa57c472012-11-21 12:06:18 -0800417static bool VerifyPredInfo(CompilationUnit* cu, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700418{
Bill Buzbeea114add2012-05-03 15:00:40 -0700419 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700420
buzbee52a77fc2012-11-20 19:50:46 -0800421 GrowableListIteratorInit(bb->predecessors, &iter);
Bill Buzbeea114add2012-05-03 15:00:40 -0700422 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800423 BasicBlock *pred_bb = reinterpret_cast<BasicBlock*>(GrowableListIteratorNext(&iter));
424 if (!pred_bb) break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700425 bool found = false;
buzbeefa57c472012-11-21 12:06:18 -0800426 if (pred_bb->taken == bb) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700427 found = true;
buzbeefa57c472012-11-21 12:06:18 -0800428 } else if (pred_bb->fall_through == bb) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700429 found = true;
buzbeefa57c472012-11-21 12:06:18 -0800430 } else if (pred_bb->successor_block_list.block_list_type != kNotUsed) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700431 GrowableListIterator iterator;
buzbeefa57c472012-11-21 12:06:18 -0800432 GrowableListIteratorInit(&pred_bb->successor_block_list.blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700433 &iterator);
434 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800435 SuccessorBlockInfo *successor_block_info =
buzbee52a77fc2012-11-20 19:50:46 -0800436 reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));
buzbeefa57c472012-11-21 12:06:18 -0800437 if (successor_block_info == NULL) break;
438 BasicBlock *succ_bb = successor_block_info->block;
439 if (succ_bb == bb) {
buzbee67bf8852011-08-17 17:51:35 -0700440 found = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700441 break;
buzbee67bf8852011-08-17 17:51:35 -0700442 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700443 }
buzbee67bf8852011-08-17 17:51:35 -0700444 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700445 if (found == false) {
buzbeefa57c472012-11-21 12:06:18 -0800446 char block_name1[BLOCK_NAME_LEN], block_name2[BLOCK_NAME_LEN];
447 GetBlockName(bb, block_name1);
448 GetBlockName(pred_bb, block_name2);
buzbeed8506212012-12-20 14:15:05 -0800449 DumpCFG(cu, "/sdcard/cfg/", false);
buzbeefa57c472012-11-21 12:06:18 -0800450 LOG(FATAL) << "Successor " << block_name1 << "not found from "
451 << block_name2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700452 }
453 }
454 return true;
buzbee67bf8852011-08-17 17:51:35 -0700455}
456
457/* Identify code range in try blocks and set up the empty catch blocks */
buzbeefa57c472012-11-21 12:06:18 -0800458static void ProcessTryCatchBlocks(CompilationUnit* cu)
buzbee67bf8852011-08-17 17:51:35 -0700459{
buzbeefa57c472012-11-21 12:06:18 -0800460 const DexFile::CodeItem* code_item = cu->code_item;
461 int tries_size = code_item->tries_size_;
Bill Buzbeea114add2012-05-03 15:00:40 -0700462 int offset;
buzbee67bf8852011-08-17 17:51:35 -0700463
buzbeefa57c472012-11-21 12:06:18 -0800464 if (tries_size == 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700465 return;
466 }
467
buzbeefa57c472012-11-21 12:06:18 -0800468 ArenaBitVector* try_block_addr = cu->try_block_addr;
Bill Buzbeea114add2012-05-03 15:00:40 -0700469
buzbeefa57c472012-11-21 12:06:18 -0800470 for (int i = 0; i < tries_size; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700471 const DexFile::TryItem* pTry =
472 DexFile::GetTryItems(*code_item, i);
buzbeefa57c472012-11-21 12:06:18 -0800473 int start_offset = pTry->start_addr_;
474 int end_offset = start_offset + pTry->insn_count_;
475 for (offset = start_offset; offset < end_offset; offset++) {
476 SetBit(cu, try_block_addr, offset);
buzbee67bf8852011-08-17 17:51:35 -0700477 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700478 }
buzbee67bf8852011-08-17 17:51:35 -0700479
Bill Buzbeea114add2012-05-03 15:00:40 -0700480 // Iterate over each of the handlers to enqueue the empty Catch blocks
481 const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item, 0);
482 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
483 for (uint32_t idx = 0; idx < handlers_size; idx++) {
484 CatchHandlerIterator iterator(handlers_ptr);
485 for (; iterator.HasNext(); iterator.Next()) {
486 uint32_t address = iterator.GetHandlerAddress();
buzbeefa57c472012-11-21 12:06:18 -0800487 FindBlock(cu, address, false /* split */, true /*create*/,
488 /* immed_pred_block_p */ NULL);
buzbee67bf8852011-08-17 17:51:35 -0700489 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700490 handlers_ptr = iterator.EndDataPointer();
491 }
buzbee67bf8852011-08-17 17:51:35 -0700492}
493
Elliott Hughesadb8c672012-03-06 16:49:32 -0800494/* Process instructions with the kBranch flag */
buzbeefa57c472012-11-21 12:06:18 -0800495static BasicBlock* ProcessCanBranch(CompilationUnit* cu, BasicBlock* cur_block,
496 MIR* insn, int cur_offset, int width, int flags,
497 const uint16_t* code_ptr, const uint16_t* code_end)
buzbee67bf8852011-08-17 17:51:35 -0700498{
buzbeefa57c472012-11-21 12:06:18 -0800499 int target = cur_offset;
Bill Buzbeea114add2012-05-03 15:00:40 -0700500 switch (insn->dalvikInsn.opcode) {
501 case Instruction::GOTO:
502 case Instruction::GOTO_16:
503 case Instruction::GOTO_32:
buzbeecbd6d442012-11-17 14:11:25 -0800504 target += insn->dalvikInsn.vA;
Bill Buzbeea114add2012-05-03 15:00:40 -0700505 break;
506 case Instruction::IF_EQ:
507 case Instruction::IF_NE:
508 case Instruction::IF_LT:
509 case Instruction::IF_GE:
510 case Instruction::IF_GT:
511 case Instruction::IF_LE:
buzbeefa57c472012-11-21 12:06:18 -0800512 cur_block->conditional_branch = true;
buzbeecbd6d442012-11-17 14:11:25 -0800513 target += insn->dalvikInsn.vC;
Bill Buzbeea114add2012-05-03 15:00:40 -0700514 break;
515 case Instruction::IF_EQZ:
516 case Instruction::IF_NEZ:
517 case Instruction::IF_LTZ:
518 case Instruction::IF_GEZ:
519 case Instruction::IF_GTZ:
520 case Instruction::IF_LEZ:
buzbeefa57c472012-11-21 12:06:18 -0800521 cur_block->conditional_branch = true;
buzbeecbd6d442012-11-17 14:11:25 -0800522 target += insn->dalvikInsn.vB;
Bill Buzbeea114add2012-05-03 15:00:40 -0700523 break;
524 default:
buzbeecbd6d442012-11-17 14:11:25 -0800525 LOG(FATAL) << "Unexpected opcode(" << insn->dalvikInsn.opcode << ") with kBranch set";
Bill Buzbeea114add2012-05-03 15:00:40 -0700526 }
buzbeefa57c472012-11-21 12:06:18 -0800527 BasicBlock *taken_block = FindBlock(cu, target,
Bill Buzbeea114add2012-05-03 15:00:40 -0700528 /* split */
529 true,
530 /* create */
531 true,
buzbeefa57c472012-11-21 12:06:18 -0800532 /* immed_pred_block_p */
533 &cur_block);
534 cur_block->taken = taken_block;
535 InsertGrowableList(cu, taken_block->predecessors, reinterpret_cast<uintptr_t>(cur_block));
buzbee67bf8852011-08-17 17:51:35 -0700536
Bill Buzbeea114add2012-05-03 15:00:40 -0700537 /* Always terminate the current block for conditional branches */
538 if (flags & Instruction::kContinue) {
buzbeefa57c472012-11-21 12:06:18 -0800539 BasicBlock *fallthrough_block = FindBlock(cu,
540 cur_offset + width,
Bill Buzbeea114add2012-05-03 15:00:40 -0700541 /*
542 * If the method is processed
543 * in sequential order from the
544 * beginning, we don't need to
545 * specify split for continue
546 * blocks. However, this
547 * routine can be called by
548 * compileLoop, which starts
549 * parsing the method from an
550 * arbitrary address in the
551 * method body.
552 */
553 true,
554 /* create */
555 true,
buzbeefa57c472012-11-21 12:06:18 -0800556 /* immed_pred_block_p */
557 &cur_block);
558 cur_block->fall_through = fallthrough_block;
559 InsertGrowableList(cu, fallthrough_block->predecessors,
560 reinterpret_cast<uintptr_t>(cur_block));
561 } else if (code_ptr < code_end) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700562 /* Create a fallthrough block for real instructions (incl. NOP) */
buzbeefa57c472012-11-21 12:06:18 -0800563 if (ContentIsInsn(code_ptr)) {
564 FindBlock(cu, cur_offset + width,
Bill Buzbeea114add2012-05-03 15:00:40 -0700565 /* split */
566 false,
567 /* create */
568 true,
buzbeefa57c472012-11-21 12:06:18 -0800569 /* immed_pred_block_p */
Bill Buzbeea114add2012-05-03 15:00:40 -0700570 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700571 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700572 }
buzbeefa57c472012-11-21 12:06:18 -0800573 return cur_block;
buzbee67bf8852011-08-17 17:51:35 -0700574}
575
Elliott Hughesadb8c672012-03-06 16:49:32 -0800576/* Process instructions with the kSwitch flag */
buzbeefa57c472012-11-21 12:06:18 -0800577static void ProcessCanSwitch(CompilationUnit* cu, BasicBlock* cur_block,
578 MIR* insn, int cur_offset, int width, int flags)
buzbee67bf8852011-08-17 17:51:35 -0700579{
buzbeefa57c472012-11-21 12:06:18 -0800580 const uint16_t* switch_data =
581 reinterpret_cast<const uint16_t*>(cu->insns + cur_offset + insn->dalvikInsn.vB);
Bill Buzbeea114add2012-05-03 15:00:40 -0700582 int size;
buzbeecbd6d442012-11-17 14:11:25 -0800583 const int* keyTable;
buzbeefa57c472012-11-21 12:06:18 -0800584 const int* target_table;
Bill Buzbeea114add2012-05-03 15:00:40 -0700585 int i;
buzbeefa57c472012-11-21 12:06:18 -0800586 int first_key;
buzbee67bf8852011-08-17 17:51:35 -0700587
Bill Buzbeea114add2012-05-03 15:00:40 -0700588 /*
589 * Packed switch data format:
590 * ushort ident = 0x0100 magic value
591 * ushort size number of entries in the table
592 * int first_key first (and lowest) switch case value
593 * int targets[size] branch targets, relative to switch opcode
594 *
595 * Total size is (4+size*2) 16-bit code units.
596 */
597 if (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) {
buzbeefa57c472012-11-21 12:06:18 -0800598 DCHECK_EQ(static_cast<int>(switch_data[0]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700599 static_cast<int>(Instruction::kPackedSwitchSignature));
buzbeefa57c472012-11-21 12:06:18 -0800600 size = switch_data[1];
601 first_key = switch_data[2] | (switch_data[3] << 16);
602 target_table = reinterpret_cast<const int*>(&switch_data[4]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700603 keyTable = NULL; // Make the compiler happy
604 /*
605 * Sparse switch data format:
606 * ushort ident = 0x0200 magic value
607 * ushort size number of entries in the table; > 0
608 * int keys[size] keys, sorted low-to-high; 32-bit aligned
609 * int targets[size] branch targets, relative to switch opcode
610 *
611 * Total size is (2+size*4) 16-bit code units.
612 */
613 } else {
buzbeefa57c472012-11-21 12:06:18 -0800614 DCHECK_EQ(static_cast<int>(switch_data[0]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700615 static_cast<int>(Instruction::kSparseSwitchSignature));
buzbeefa57c472012-11-21 12:06:18 -0800616 size = switch_data[1];
617 keyTable = reinterpret_cast<const int*>(&switch_data[2]);
618 target_table = reinterpret_cast<const int*>(&switch_data[2 + size*2]);
619 first_key = 0; // To make the compiler happy
Bill Buzbeea114add2012-05-03 15:00:40 -0700620 }
buzbee67bf8852011-08-17 17:51:35 -0700621
buzbeefa57c472012-11-21 12:06:18 -0800622 if (cur_block->successor_block_list.block_list_type != kNotUsed) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700623 LOG(FATAL) << "Successor block list already in use: "
buzbeefa57c472012-11-21 12:06:18 -0800624 << static_cast<int>(cur_block->successor_block_list.block_list_type);
Bill Buzbeea114add2012-05-03 15:00:40 -0700625 }
buzbeefa57c472012-11-21 12:06:18 -0800626 cur_block->successor_block_list.block_list_type =
Bill Buzbeea114add2012-05-03 15:00:40 -0700627 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
628 kPackedSwitch : kSparseSwitch;
buzbeefa57c472012-11-21 12:06:18 -0800629 CompilerInitGrowableList(cu, &cur_block->successor_block_list.blocks, size,
Bill Buzbeea114add2012-05-03 15:00:40 -0700630 kListSuccessorBlocks);
631
632 for (i = 0; i < size; i++) {
buzbeefa57c472012-11-21 12:06:18 -0800633 BasicBlock *case_block = FindBlock(cu, cur_offset + target_table[i],
Bill Buzbeea114add2012-05-03 15:00:40 -0700634 /* split */
635 true,
636 /* create */
637 true,
buzbeefa57c472012-11-21 12:06:18 -0800638 /* immed_pred_block_p */
639 &cur_block);
640 SuccessorBlockInfo *successor_block_info =
641 static_cast<SuccessorBlockInfo*>(NewMem(cu, sizeof(SuccessorBlockInfo),
buzbeecbd6d442012-11-17 14:11:25 -0800642 false, kAllocSuccessor));
buzbeefa57c472012-11-21 12:06:18 -0800643 successor_block_info->block = case_block;
644 successor_block_info->key =
Elliott Hughesadb8c672012-03-06 16:49:32 -0800645 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
buzbeefa57c472012-11-21 12:06:18 -0800646 first_key + i : keyTable[i];
647 InsertGrowableList(cu, &cur_block->successor_block_list.blocks,
648 reinterpret_cast<uintptr_t>(successor_block_info));
649 InsertGrowableList(cu, case_block->predecessors,
650 reinterpret_cast<uintptr_t>(cur_block));
Bill Buzbeea114add2012-05-03 15:00:40 -0700651 }
652
653 /* Fall-through case */
buzbeefa57c472012-11-21 12:06:18 -0800654 BasicBlock* fallthrough_block = FindBlock(cu,
655 cur_offset + width,
Bill Buzbeea114add2012-05-03 15:00:40 -0700656 /* split */
657 false,
658 /* create */
659 true,
buzbeefa57c472012-11-21 12:06:18 -0800660 /* immed_pred_block_p */
Bill Buzbeea114add2012-05-03 15:00:40 -0700661 NULL);
buzbeefa57c472012-11-21 12:06:18 -0800662 cur_block->fall_through = fallthrough_block;
663 InsertGrowableList(cu, fallthrough_block->predecessors,
664 reinterpret_cast<uintptr_t>(cur_block));
buzbee67bf8852011-08-17 17:51:35 -0700665}
666
Elliott Hughesadb8c672012-03-06 16:49:32 -0800667/* Process instructions with the kThrow flag */
buzbeefa57c472012-11-21 12:06:18 -0800668static BasicBlock* ProcessCanThrow(CompilationUnit* cu, BasicBlock* cur_block,
669 MIR* insn, int cur_offset, int width, int flags,
670 ArenaBitVector* try_block_addr, const uint16_t* code_ptr,
671 const uint16_t* code_end)
buzbee67bf8852011-08-17 17:51:35 -0700672{
buzbeefa57c472012-11-21 12:06:18 -0800673 const DexFile::CodeItem* code_item = cu->code_item;
674 bool in_try_block = IsBitSet(try_block_addr, cur_offset);
buzbee67bf8852011-08-17 17:51:35 -0700675
Bill Buzbeea114add2012-05-03 15:00:40 -0700676 /* In try block */
buzbeefa57c472012-11-21 12:06:18 -0800677 if (in_try_block) {
678 CatchHandlerIterator iterator(*code_item, cur_offset);
buzbee67bf8852011-08-17 17:51:35 -0700679
buzbeefa57c472012-11-21 12:06:18 -0800680 if (cur_block->successor_block_list.block_list_type != kNotUsed) {
681 LOG(INFO) << PrettyMethod(cu->method_idx, *cu->dex_file);
Bill Buzbeea114add2012-05-03 15:00:40 -0700682 LOG(FATAL) << "Successor block list already in use: "
buzbeefa57c472012-11-21 12:06:18 -0800683 << static_cast<int>(cur_block->successor_block_list.block_list_type);
buzbee67bf8852011-08-17 17:51:35 -0700684 }
685
buzbeefa57c472012-11-21 12:06:18 -0800686 cur_block->successor_block_list.block_list_type = kCatch;
687 CompilerInitGrowableList(cu, &cur_block->successor_block_list.blocks, 2,
Bill Buzbeea114add2012-05-03 15:00:40 -0700688 kListSuccessorBlocks);
689
690 for (;iterator.HasNext(); iterator.Next()) {
buzbeefa57c472012-11-21 12:06:18 -0800691 BasicBlock *catch_block = FindBlock(cu, iterator.GetHandlerAddress(),
Bill Buzbeea114add2012-05-03 15:00:40 -0700692 false /* split*/,
693 false /* creat */,
buzbeefa57c472012-11-21 12:06:18 -0800694 NULL /* immed_pred_block_p */);
695 catch_block->catch_entry = true;
696 cu->catches.insert(catch_block->start_offset);
697 SuccessorBlockInfo *successor_block_info = reinterpret_cast<SuccessorBlockInfo*>
698 (NewMem(cu, sizeof(SuccessorBlockInfo), false, kAllocSuccessor));
699 successor_block_info->block = catch_block;
700 successor_block_info->key = iterator.GetHandlerTypeIndex();
701 InsertGrowableList(cu, &cur_block->successor_block_list.blocks,
702 reinterpret_cast<uintptr_t>(successor_block_info));
703 InsertGrowableList(cu, catch_block->predecessors,
704 reinterpret_cast<uintptr_t>(cur_block));
buzbee67bf8852011-08-17 17:51:35 -0700705 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700706 } else {
buzbeefa57c472012-11-21 12:06:18 -0800707 BasicBlock *eh_block = NewMemBB(cu, kExceptionHandling,
708 cu->num_blocks++);
709 cur_block->taken = eh_block;
710 InsertGrowableList(cu, &cu->block_list, reinterpret_cast<uintptr_t>(eh_block));
711 eh_block->start_offset = cur_offset;
712 InsertGrowableList(cu, eh_block->predecessors, reinterpret_cast<uintptr_t>(cur_block));
Bill Buzbeea114add2012-05-03 15:00:40 -0700713 }
714
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700715 if (insn->dalvikInsn.opcode == Instruction::THROW){
buzbeefa57c472012-11-21 12:06:18 -0800716 cur_block->explicit_throw = true;
717 if ((code_ptr < code_end) && ContentIsInsn(code_ptr)) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700718 // Force creation of new block following THROW via side-effect
buzbeefa57c472012-11-21 12:06:18 -0800719 FindBlock(cu, cur_offset + width, /* split */ false,
720 /* create */ true, /* immed_pred_block_p */ NULL);
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700721 }
buzbeefa57c472012-11-21 12:06:18 -0800722 if (!in_try_block) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700723 // Don't split a THROW that can't rethrow - we're done.
buzbeefa57c472012-11-21 12:06:18 -0800724 return cur_block;
Bill Buzbeea114add2012-05-03 15:00:40 -0700725 }
726 }
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700727
728 /*
729 * Split the potentially-throwing instruction into two parts.
730 * The first half will be a pseudo-op that captures the exception
731 * edges and terminates the basic block. It always falls through.
732 * Then, create a new basic block that begins with the throwing instruction
733 * (minus exceptions). Note: this new basic block must NOT be entered into
buzbeefa57c472012-11-21 12:06:18 -0800734 * the block_map. If the potentially-throwing instruction is the target of a
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700735 * future branch, we need to find the check psuedo half. The new
736 * basic block containing the work portion of the instruction should
737 * only be entered via fallthrough from the block containing the
738 * pseudo exception edge MIR. Note also that this new block is
739 * not automatically terminated after the work portion, and may
740 * contain following instructions.
741 */
buzbeefa57c472012-11-21 12:06:18 -0800742 BasicBlock *new_block = NewMemBB(cu, kDalvikByteCode, cu->num_blocks++);
743 InsertGrowableList(cu, &cu->block_list, reinterpret_cast<uintptr_t>(new_block));
744 new_block->start_offset = insn->offset;
745 cur_block->fall_through = new_block;
746 InsertGrowableList(cu, new_block->predecessors, reinterpret_cast<uintptr_t>(cur_block));
747 MIR* new_insn = static_cast<MIR*>(NewMem(cu, sizeof(MIR), true, kAllocMIR));
748 *new_insn = *insn;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700749 insn->dalvikInsn.opcode =
750 static_cast<Instruction::Code>(kMirOpCheck);
751 // Associate the two halves
buzbeefa57c472012-11-21 12:06:18 -0800752 insn->meta.throw_insn = new_insn;
753 new_insn->meta.throw_insn = insn;
754 AppendMIR(new_block, new_insn);
755 return new_block;
buzbee67bf8852011-08-17 17:51:35 -0700756}
757
buzbeefa57c472012-11-21 12:06:18 -0800758void CompilerInit(CompilationUnit* cu, const Compiler& compiler) {
buzbee02031b12012-11-23 09:41:35 -0800759 bool success = false;
760 switch (compiler.GetInstructionSet()) {
761 case kThumb2:
762 success = InitArmCodegen(cu);
763 break;
764 case kMips:
765 success = InitMipsCodegen(cu);
766 break;
767 case kX86:
768 success = InitX86Codegen(cu);
769 break;
770 default:;
771 }
772 if (!success) {
773 LOG(FATAL) << "Failed to initialize codegen for " << compiler.GetInstructionSet();
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800774 }
buzbeefa57c472012-11-21 12:06:18 -0800775 if (!HeapInit(cu)) {
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800776 LOG(FATAL) << "Failed to initialize oat heap";
777 }
778}
779
buzbee52a77fc2012-11-20 19:50:46 -0800780static CompiledMethod* CompileMethod(Compiler& compiler,
buzbeefa57c472012-11-21 12:06:18 -0800781 const CompilerBackend compiler_backend,
buzbee52a77fc2012-11-20 19:50:46 -0800782 const DexFile::CodeItem* code_item,
783 uint32_t access_flags, InvokeType invoke_type,
Ian Rogersfffdb022013-01-04 15:14:08 -0800784 uint32_t class_def_idx, uint32_t method_idx,
785 jobject class_loader, const DexFile& dex_file,
buzbee52a77fc2012-11-20 19:50:46 -0800786 LLVMInfo* llvm_info)
buzbee67bf8852011-08-17 17:51:35 -0700787{
Bill Buzbeea114add2012-05-03 15:00:40 -0700788 VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
Brian Carlstrom94496d32011-08-22 09:22:47 -0700789
buzbeefa57c472012-11-21 12:06:18 -0800790 const uint16_t* code_ptr = code_item->insns_;
791 const uint16_t* code_end = code_item->insns_ + code_item->insns_size_in_code_units_;
792 int num_blocks = 0;
793 unsigned int cur_offset = 0;
buzbee67bf8852011-08-17 17:51:35 -0700794
Bill Buzbeea114add2012-05-03 15:00:40 -0700795 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
buzbeefa57c472012-11-21 12:06:18 -0800796 UniquePtr<CompilationUnit> cu(new CompilationUnit);
buzbeeba938cb2012-02-03 14:47:55 -0800797
buzbeefa57c472012-11-21 12:06:18 -0800798 CompilerInit(cu.get(), compiler);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800799
buzbeefa57c472012-11-21 12:06:18 -0800800 cu->compiler = &compiler;
801 cu->class_linker = class_linker;
802 cu->dex_file = &dex_file;
Ian Rogersfffdb022013-01-04 15:14:08 -0800803 cu->class_def_idx = class_def_idx;
buzbeefa57c472012-11-21 12:06:18 -0800804 cu->method_idx = method_idx;
805 cu->code_item = code_item;
806 cu->access_flags = access_flags;
807 cu->invoke_type = invoke_type;
808 cu->shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
809 cu->instruction_set = compiler.GetInstructionSet();
810 cu->insns = code_item->insns_;
811 cu->insns_size = code_item->insns_size_in_code_units_;
812 cu->num_ins = code_item->ins_size_;
813 cu->num_regs = code_item->registers_size_ - cu->num_ins;
814 cu->num_outs = code_item->outs_size_;
815 DCHECK((cu->instruction_set == kThumb2) ||
816 (cu->instruction_set == kX86) ||
817 (cu->instruction_set == kMips));
818 if ((compiler_backend == kQuickGBC) || (compiler_backend == kPortable)) {
819 cu->gen_bitcode = true;
buzbee85eee022012-07-16 22:12:38 -0700820 }
buzbeefa57c472012-11-21 12:06:18 -0800821 cu->llvm_info = llvm_info;
Bill Buzbeea114add2012-05-03 15:00:40 -0700822 /* Adjust this value accordingly once inlining is performed */
buzbeefa57c472012-11-21 12:06:18 -0800823 cu->num_dalvik_registers = code_item->registers_size_;
Bill Buzbeea114add2012-05-03 15:00:40 -0700824 // TODO: set this from command line
buzbeefa57c472012-11-21 12:06:18 -0800825 cu->compiler_flip_match = false;
826 bool use_match = !cu->compiler_method_match.empty();
827 bool match = use_match && (cu->compiler_flip_match ^
828 (PrettyMethod(method_idx, dex_file).find(cu->compiler_method_match) !=
Bill Buzbeea114add2012-05-03 15:00:40 -0700829 std::string::npos));
buzbeefa57c472012-11-21 12:06:18 -0800830 if (!use_match || match) {
831 cu->disable_opt = kCompilerOptimizerDisableFlags;
832 cu->enable_debug = kCompilerDebugFlags;
833 cu->verbose = VLOG_IS_ON(compiler) ||
834 (cu->enable_debug & (1 << kDebugVerbose));
Bill Buzbeea114add2012-05-03 15:00:40 -0700835 }
buzbee6459e7c2012-10-02 14:42:41 -0700836#ifndef NDEBUG
buzbeefa57c472012-11-21 12:06:18 -0800837 if (cu->gen_bitcode) {
838 cu->enable_debug |= (1 << kDebugVerifyBitcode);
buzbee6969d502012-06-15 16:40:31 -0700839 }
buzbee2cfc6392012-05-07 14:51:40 -0700840#endif
buzbee9281f002012-10-24 12:17:24 -0700841
buzbeefa57c472012-11-21 12:06:18 -0800842 if (cu->instruction_set == kMips) {
jeffhao7fbee072012-08-24 17:56:54 -0700843 // Disable some optimizations for mips for now
buzbeefa57c472012-11-21 12:06:18 -0800844 cu->disable_opt |= (
jeffhao7fbee072012-08-24 17:56:54 -0700845 (1 << kLoadStoreElimination) |
846 (1 << kLoadHoisting) |
847 (1 << kSuppressLoads) |
848 (1 << kNullCheckElimination) |
849 (1 << kPromoteRegs) |
850 (1 << kTrackLiveTemps) |
851 (1 << kSkipLargeMethodOptimization) |
852 (1 << kSafeOptimizations) |
853 (1 << kBBOpt) |
854 (1 << kMatch) |
855 (1 << kPromoteCompilerTemps));
856 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700857
858 /* Gathering opcode stats? */
859 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
buzbeefa57c472012-11-21 12:06:18 -0800860 cu->opcode_count =
861 static_cast<int*>(NewMem(cu.get(), kNumPackedOpcodes * sizeof(int), true, kAllocMisc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700862 }
863
864 /* Assume non-throwing leaf */
buzbeefa57c472012-11-21 12:06:18 -0800865 cu->attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE);
Bill Buzbeea114add2012-05-03 15:00:40 -0700866
buzbeefa57c472012-11-21 12:06:18 -0800867 /* Initialize the block list, estimate size based on insns_size */
868 CompilerInitGrowableList(cu.get(), &cu->block_list, cu->insns_size,
Bill Buzbeea114add2012-05-03 15:00:40 -0700869 kListBlockList);
870
buzbeefa57c472012-11-21 12:06:18 -0800871 /* Initialize the switch_tables list */
872 CompilerInitGrowableList(cu.get(), &cu->switch_tables, 4,
Bill Buzbeea114add2012-05-03 15:00:40 -0700873 kListSwitchTables);
874
buzbeefa57c472012-11-21 12:06:18 -0800875 /* Intialize the fill_array_data list */
876 CompilerInitGrowableList(cu.get(), &cu->fill_array_data, 4,
Bill Buzbeea114add2012-05-03 15:00:40 -0700877 kListFillArrayData);
878
buzbeefa57c472012-11-21 12:06:18 -0800879 /* Intialize the throw_launchpads list, estimate size based on insns_size */
880 CompilerInitGrowableList(cu.get(), &cu->throw_launchpads, cu->insns_size,
Bill Buzbeea114add2012-05-03 15:00:40 -0700881 kListThrowLaunchPads);
882
buzbeefa57c472012-11-21 12:06:18 -0800883 /* Intialize the instrinsic_launchpads list */
884 CompilerInitGrowableList(cu.get(), &cu->intrinsic_launchpads, 4,
Bill Buzbeea114add2012-05-03 15:00:40 -0700885 kListMisc);
886
887
buzbeefa57c472012-11-21 12:06:18 -0800888 /* Intialize the suspend_launchpads list */
889 CompilerInitGrowableList(cu.get(), &cu->suspend_launchpads, 2048,
Bill Buzbeea114add2012-05-03 15:00:40 -0700890 kListSuspendLaunchPads);
891
892 /* Allocate the bit-vector to track the beginning of basic blocks */
buzbeefa57c472012-11-21 12:06:18 -0800893 ArenaBitVector *try_block_addr = AllocBitVector(cu.get(),
894 cu->insns_size,
Bill Buzbeea114add2012-05-03 15:00:40 -0700895 true /* expandable */);
buzbeefa57c472012-11-21 12:06:18 -0800896 cu->try_block_addr = try_block_addr;
Bill Buzbeea114add2012-05-03 15:00:40 -0700897
898 /* Create the default entry and exit blocks and enter them to the list */
buzbeefa57c472012-11-21 12:06:18 -0800899 BasicBlock *entry_block = NewMemBB(cu.get(), kEntryBlock, num_blocks++);
900 BasicBlock *exit_block = NewMemBB(cu.get(), kExitBlock, num_blocks++);
Bill Buzbeea114add2012-05-03 15:00:40 -0700901
buzbeefa57c472012-11-21 12:06:18 -0800902 cu->entry_block = entry_block;
903 cu->exit_block = exit_block;
Bill Buzbeea114add2012-05-03 15:00:40 -0700904
buzbeefa57c472012-11-21 12:06:18 -0800905 InsertGrowableList(cu.get(), &cu->block_list, reinterpret_cast<uintptr_t>(entry_block));
906 InsertGrowableList(cu.get(), &cu->block_list, reinterpret_cast<uintptr_t>(exit_block));
Bill Buzbeea114add2012-05-03 15:00:40 -0700907
908 /* Current block to record parsed instructions */
buzbeefa57c472012-11-21 12:06:18 -0800909 BasicBlock *cur_block = NewMemBB(cu.get(), kDalvikByteCode, num_blocks++);
910 cur_block->start_offset = 0;
911 InsertGrowableList(cu.get(), &cu->block_list, reinterpret_cast<uintptr_t>(cur_block));
Bill Buzbeea114add2012-05-03 15:00:40 -0700912 /* Add first block to the fast lookup cache */
buzbeefa57c472012-11-21 12:06:18 -0800913 cu->block_map.Put(cur_block->start_offset, cur_block);
914 entry_block->fall_through = cur_block;
915 InsertGrowableList(cu.get(), cur_block->predecessors,
916 reinterpret_cast<uintptr_t>(entry_block));
Bill Buzbeea114add2012-05-03 15:00:40 -0700917
918 /*
919 * Store back the number of blocks since new blocks may be created of
buzbeefa57c472012-11-21 12:06:18 -0800920 * accessing cu.
Bill Buzbeea114add2012-05-03 15:00:40 -0700921 */
buzbeefa57c472012-11-21 12:06:18 -0800922 cu->num_blocks = num_blocks;
Bill Buzbeea114add2012-05-03 15:00:40 -0700923
924 /* Identify code range in try blocks and set up the empty catch blocks */
buzbeefa57c472012-11-21 12:06:18 -0800925 ProcessTryCatchBlocks(cu.get());
Bill Buzbeea114add2012-05-03 15:00:40 -0700926
927 /* Set up for simple method detection */
buzbeefa57c472012-11-21 12:06:18 -0800928 int num_patterns = sizeof(special_patterns)/sizeof(special_patterns[0]);
929 bool live_pattern = (num_patterns > 0) && !(cu->disable_opt & (1 << kMatch));
930 bool* dead_pattern =
931 static_cast<bool*>(NewMem(cu.get(), sizeof(bool) * num_patterns, true, kAllocMisc));
932 SpecialCaseHandler special_case = kNoHandler;
933 int pattern_pos = 0;
Bill Buzbeea114add2012-05-03 15:00:40 -0700934
935 /* Parse all instructions and put them into containing basic blocks */
buzbeefa57c472012-11-21 12:06:18 -0800936 while (code_ptr < code_end) {
937 MIR *insn = static_cast<MIR *>(NewMem(cu.get(), sizeof(MIR), true, kAllocMIR));
938 insn->offset = cur_offset;
buzbeea169e1d2012-12-05 14:26:44 -0800939 int width = ParseInsn(cu.get(), code_ptr, &insn->dalvikInsn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700940 insn->width = width;
941 Instruction::Code opcode = insn->dalvikInsn.opcode;
buzbeefa57c472012-11-21 12:06:18 -0800942 if (cu->opcode_count != NULL) {
943 cu->opcode_count[static_cast<int>(opcode)]++;
buzbee44b412b2012-02-04 08:50:53 -0800944 }
945
Bill Buzbeea114add2012-05-03 15:00:40 -0700946 /* Terminate when the data section is seen */
947 if (width == 0)
948 break;
949
950 /* Possible simple method? */
buzbeefa57c472012-11-21 12:06:18 -0800951 if (live_pattern) {
952 live_pattern = false;
953 special_case = kNoHandler;
954 for (int i = 0; i < num_patterns; i++) {
955 if (!dead_pattern[i]) {
956 if (special_patterns[i].opcodes[pattern_pos] == opcode) {
957 live_pattern = true;
958 special_case = special_patterns[i].handler_code;
Bill Buzbeea114add2012-05-03 15:00:40 -0700959 } else {
buzbeefa57c472012-11-21 12:06:18 -0800960 dead_pattern[i] = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700961 }
962 }
963 }
buzbeefa57c472012-11-21 12:06:18 -0800964 pattern_pos++;
buzbeea7c12682012-03-19 13:13:53 -0700965 }
966
buzbeefa57c472012-11-21 12:06:18 -0800967 AppendMIR(cur_block, insn);
buzbeecefd1872011-09-09 09:59:52 -0700968
buzbeefa57c472012-11-21 12:06:18 -0800969 code_ptr += width;
Ian Rogersa75a0132012-09-28 11:41:42 -0700970 int flags = Instruction::FlagsOf(insn->dalvikInsn.opcode);
buzbee67bf8852011-08-17 17:51:35 -0700971
buzbeefa57c472012-11-21 12:06:18 -0800972 int df_flags = oat_data_flow_attributes[insn->dalvikInsn.opcode];
buzbee67bf8852011-08-17 17:51:35 -0700973
buzbeefa57c472012-11-21 12:06:18 -0800974 if (df_flags & DF_HAS_DEFS) {
975 cu->def_count += (df_flags & DF_A_WIDE) ? 2 : 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700976 }
buzbee67bf8852011-08-17 17:51:35 -0700977
Bill Buzbeea114add2012-05-03 15:00:40 -0700978 if (flags & Instruction::kBranch) {
buzbeefa57c472012-11-21 12:06:18 -0800979 cur_block = ProcessCanBranch(cu.get(), cur_block, insn, cur_offset,
980 width, flags, code_ptr, code_end);
Bill Buzbeea114add2012-05-03 15:00:40 -0700981 } else if (flags & Instruction::kReturn) {
buzbeebbdd0532013-02-07 09:33:02 -0800982 cur_block->terminated_by_return = true;
buzbeefa57c472012-11-21 12:06:18 -0800983 cur_block->fall_through = exit_block;
984 InsertGrowableList(cu.get(), exit_block->predecessors,
985 reinterpret_cast<uintptr_t>(cur_block));
Bill Buzbeea114add2012-05-03 15:00:40 -0700986 /*
987 * Terminate the current block if there are instructions
988 * afterwards.
989 */
buzbeefa57c472012-11-21 12:06:18 -0800990 if (code_ptr < code_end) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700991 /*
992 * Create a fallthrough block for real instructions
993 * (incl. NOP).
994 */
buzbeefa57c472012-11-21 12:06:18 -0800995 if (ContentIsInsn(code_ptr)) {
996 FindBlock(cu.get(), cur_offset + width,
Bill Buzbeea114add2012-05-03 15:00:40 -0700997 /* split */
998 false,
999 /* create */
1000 true,
buzbeefa57c472012-11-21 12:06:18 -08001001 /* immed_pred_block_p */
Bill Buzbeea114add2012-05-03 15:00:40 -07001002 NULL);
1003 }
1004 }
1005 } else if (flags & Instruction::kThrow) {
buzbeefa57c472012-11-21 12:06:18 -08001006 cur_block = ProcessCanThrow(cu.get(), cur_block, insn, cur_offset,
1007 width, flags, try_block_addr, code_ptr, code_end);
Bill Buzbeea114add2012-05-03 15:00:40 -07001008 } else if (flags & Instruction::kSwitch) {
buzbeefa57c472012-11-21 12:06:18 -08001009 ProcessCanSwitch(cu.get(), cur_block, insn, cur_offset, width, flags);
Bill Buzbeea114add2012-05-03 15:00:40 -07001010 }
buzbeefa57c472012-11-21 12:06:18 -08001011 cur_offset += width;
1012 BasicBlock *next_block = FindBlock(cu.get(), cur_offset,
Bill Buzbeea114add2012-05-03 15:00:40 -07001013 /* split */
1014 false,
1015 /* create */
1016 false,
buzbeefa57c472012-11-21 12:06:18 -08001017 /* immed_pred_block_p */
Bill Buzbeea114add2012-05-03 15:00:40 -07001018 NULL);
buzbeefa57c472012-11-21 12:06:18 -08001019 if (next_block) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001020 /*
1021 * The next instruction could be the target of a previously parsed
1022 * forward branch so a block is already created. If the current
1023 * instruction is not an unconditional branch, connect them through
1024 * the fall-through link.
1025 */
buzbeefa57c472012-11-21 12:06:18 -08001026 DCHECK(cur_block->fall_through == NULL ||
1027 cur_block->fall_through == next_block ||
1028 cur_block->fall_through == exit_block);
buzbee5ade1d22011-09-09 14:44:52 -07001029
buzbeefa57c472012-11-21 12:06:18 -08001030 if ((cur_block->fall_through == NULL) && (flags & Instruction::kContinue)) {
1031 cur_block->fall_through = next_block;
1032 InsertGrowableList(cu.get(), next_block->predecessors,
1033 reinterpret_cast<uintptr_t>(cur_block));
Bill Buzbeea114add2012-05-03 15:00:40 -07001034 }
buzbeefa57c472012-11-21 12:06:18 -08001035 cur_block = next_block;
Bill Buzbeea114add2012-05-03 15:00:40 -07001036 }
1037 }
buzbeefc9e6fa2012-03-23 15:14:29 -07001038
buzbeed8506212012-12-20 14:15:05 -08001039 if (cu->enable_debug & (1 << kDebugDumpCFG)) {
1040 DumpCFG(cu.get(), "/sdcard/1_post_parse_cfg/", true);
1041 }
1042
buzbeefa57c472012-11-21 12:06:18 -08001043 if (!(cu->disable_opt & (1 << kSkipLargeMethodOptimization))) {
1044 if ((cu->num_blocks > MANY_BLOCKS) ||
1045 ((cu->num_blocks > MANY_BLOCKS_INITIALIZER) &&
Bill Buzbeea114add2012-05-03 15:00:40 -07001046 PrettyMethod(method_idx, dex_file, false).find("init>") !=
1047 std::string::npos)) {
buzbeefa57c472012-11-21 12:06:18 -08001048 cu->qd_mode = true;
Bill Buzbeea114add2012-05-03 15:00:40 -07001049 }
1050 }
buzbeefc9e6fa2012-03-23 15:14:29 -07001051
buzbeefa57c472012-11-21 12:06:18 -08001052 if (cu->qd_mode) {
buzbeed1643e42012-09-05 14:06:51 -07001053 // Bitcode generation requires full dataflow analysis
buzbeefa57c472012-11-21 12:06:18 -08001054 cu->disable_dataflow = !cu->gen_bitcode;
Bill Buzbeea114add2012-05-03 15:00:40 -07001055 // Disable optimization which require dataflow/ssa
buzbeefa57c472012-11-21 12:06:18 -08001056 cu->disable_opt |= (1 << kBBOpt) | (1 << kPromoteRegs) | (1 << kNullCheckElimination);
1057 if (cu->verbose) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001058 LOG(INFO) << "QD mode enabled: "
1059 << PrettyMethod(method_idx, dex_file)
buzbeefa57c472012-11-21 12:06:18 -08001060 << " num blocks: " << cu->num_blocks;
Bill Buzbeea114add2012-05-03 15:00:40 -07001061 }
1062 }
buzbeec1f45042011-09-21 16:03:19 -07001063
buzbeefa57c472012-11-21 12:06:18 -08001064 if (cu->verbose) {
1065 DumpCompilationUnit(cu.get());
Bill Buzbeea114add2012-05-03 15:00:40 -07001066 }
buzbee67bf8852011-08-17 17:51:35 -07001067
buzbee0967a252012-09-14 10:43:54 -07001068 /* Do a code layout pass */
buzbeefa57c472012-11-21 12:06:18 -08001069 CodeLayout(cu.get());
buzbee0967a252012-09-14 10:43:54 -07001070
buzbeed8506212012-12-20 14:15:05 -08001071 if (cu->enable_debug & (1 << kDebugDumpCFG)) {
1072 DumpCFG(cu.get(), "/sdcard/2_post_layout_cfg/", true);
1073 }
1074
buzbeefa57c472012-11-21 12:06:18 -08001075 if (cu->enable_debug & (1 << kDebugVerifyDataflow)) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001076 /* Verify if all blocks are connected as claimed */
buzbeefa57c472012-11-21 12:06:18 -08001077 DataFlowAnalysisDispatcher(cu.get(), VerifyPredInfo, kAllNodes,
1078 false /* is_iterative */);
Bill Buzbeea114add2012-05-03 15:00:40 -07001079 }
buzbee67bf8852011-08-17 17:51:35 -07001080
Bill Buzbeea114add2012-05-03 15:00:40 -07001081 /* Perform SSA transformation for the whole method */
buzbeefa57c472012-11-21 12:06:18 -08001082 SSATransformation(cu.get());
buzbee67bf8852011-08-17 17:51:35 -07001083
buzbeed8506212012-12-20 14:15:05 -08001084 if (cu->enable_debug & (1 << kDebugDumpCFG)) {
1085 DumpCFG(cu.get(), "/sdcard/3_post_ssa_cfg/", false);
1086 }
1087
buzbee2cfc6392012-05-07 14:51:40 -07001088 /* Do constant propagation */
buzbee4ef3e452012-12-14 13:35:28 -08001089 cu->is_constant_v = AllocBitVector(cu.get(), cu->num_ssa_regs, false /* not expandable */);
1090 cu->must_flush_constant_v = AllocBitVector(cu.get(), cu->num_ssa_regs,
1091 false /* not expandable */);
buzbeefa57c472012-11-21 12:06:18 -08001092 cu->constant_values =
1093 static_cast<int*>(NewMem(cu.get(), sizeof(int) * cu->num_ssa_regs, true, kAllocDFInfo));
1094 DataFlowAnalysisDispatcher(cu.get(), DoConstantPropogation,
buzbee2cfc6392012-05-07 14:51:40 -07001095 kAllNodes,
buzbeefa57c472012-11-21 12:06:18 -08001096 false /* is_iterative */);
buzbee2cfc6392012-05-07 14:51:40 -07001097
Bill Buzbeea114add2012-05-03 15:00:40 -07001098 /* Detect loops */
buzbeefa57c472012-11-21 12:06:18 -08001099 LoopDetection(cu.get());
buzbee67bf8852011-08-17 17:51:35 -07001100
Bill Buzbeea114add2012-05-03 15:00:40 -07001101 /* Count uses */
buzbeefa57c472012-11-21 12:06:18 -08001102 MethodUseCount(cu.get());
buzbee67bf8852011-08-17 17:51:35 -07001103
Bill Buzbeea114add2012-05-03 15:00:40 -07001104 /* Perform null check elimination */
buzbeefa57c472012-11-21 12:06:18 -08001105 NullCheckElimination(cu.get());
Bill Buzbeea114add2012-05-03 15:00:40 -07001106
buzbeed8506212012-12-20 14:15:05 -08001107 if (cu->enable_debug & (1 << kDebugDumpCFG)) {
1108 DumpCFG(cu.get(), "/sdcard/4_post_nce_cfg/", false);
1109 }
1110
buzbeed1643e42012-09-05 14:06:51 -07001111 /* Combine basic blocks where possible */
buzbeefa57c472012-11-21 12:06:18 -08001112 BasicBlockCombine(cu.get());
buzbeed1643e42012-09-05 14:06:51 -07001113
buzbeed8506212012-12-20 14:15:05 -08001114 if (cu->enable_debug & (1 << kDebugDumpCFG)) {
1115 DumpCFG(cu.get(), "/sdcard/5_post_bbcombine_cfg/", false);
1116 }
1117
Bill Buzbeea114add2012-05-03 15:00:40 -07001118 /* Do some basic block optimizations */
buzbeefa57c472012-11-21 12:06:18 -08001119 BasicBlockOptimization(cu.get());
Bill Buzbeea114add2012-05-03 15:00:40 -07001120
buzbeed8506212012-12-20 14:15:05 -08001121 // Debugging only
1122 if (cu->enable_debug & (1 << kDebugDumpCFG)) {
1123 DumpCFG(cu.get(), "/sdcard/6_post_bbo_cfg/", false);
1124 }
1125
buzbeefa57c472012-11-21 12:06:18 -08001126 if (cu->enable_debug & (1 << kDebugDumpCheckStats)) {
1127 DumpCheckStats(cu.get());
buzbeed1643e42012-09-05 14:06:51 -07001128 }
1129
buzbee02031b12012-11-23 09:41:35 -08001130 cu.get()->cg->CompilerInitializeRegAlloc(cu.get()); // Needs to happen after SSA naming
Bill Buzbeea114add2012-05-03 15:00:40 -07001131
1132 /* Allocate Registers using simple local allocation scheme */
buzbeefa57c472012-11-21 12:06:18 -08001133 SimpleRegAlloc(cu.get());
Bill Buzbeea114add2012-05-03 15:00:40 -07001134
buzbee2502e002012-12-31 16:05:53 -08001135 if (cu->enable_debug & (1 << kDebugDumpCFG)) {
1136 DumpCFG(cu.get(), "/sdcard/7_post_ralloc_cfg/", true);
1137 }
1138
1139
buzbee2cfc6392012-05-07 14:51:40 -07001140 /* Go the LLVM path? */
buzbeefa57c472012-11-21 12:06:18 -08001141 if (cu->gen_bitcode) {
buzbee2cfc6392012-05-07 14:51:40 -07001142 // MIR->Bitcode
buzbeefa57c472012-11-21 12:06:18 -08001143 MethodMIR2Bitcode(cu.get());
1144 if (compiler_backend == kPortable) {
buzbeeabc4c6b2012-08-23 08:17:15 -07001145 // all done
buzbeefa57c472012-11-21 12:06:18 -08001146 ArenaReset(cu.get());
buzbeeabc4c6b2012-08-23 08:17:15 -07001147 return NULL;
1148 }
buzbee2cfc6392012-05-07 14:51:40 -07001149 // Bitcode->LIR
buzbeefa57c472012-11-21 12:06:18 -08001150 MethodBitcode2LIR(cu.get());
buzbee2cfc6392012-05-07 14:51:40 -07001151 } else {
buzbeefa57c472012-11-21 12:06:18 -08001152 if (special_case != kNoHandler) {
buzbee2cfc6392012-05-07 14:51:40 -07001153 /*
1154 * Custom codegen for special cases. If for any reason the
buzbeefa57c472012-11-21 12:06:18 -08001155 * special codegen doesn't succeed, cu->first_lir_insn will
buzbee2cfc6392012-05-07 14:51:40 -07001156 * set to NULL;
1157 */
buzbeefa57c472012-11-21 12:06:18 -08001158 SpecialMIR2LIR(cu.get(), special_case);
buzbee2cfc6392012-05-07 14:51:40 -07001159 }
buzbee67bf8852011-08-17 17:51:35 -07001160
buzbee2cfc6392012-05-07 14:51:40 -07001161 /* Convert MIR to LIR, etc. */
buzbeefa57c472012-11-21 12:06:18 -08001162 if (cu->first_lir_insn == NULL) {
1163 MethodMIR2LIR(cu.get());
buzbee2cfc6392012-05-07 14:51:40 -07001164 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001165 }
buzbee67bf8852011-08-17 17:51:35 -07001166
Bill Buzbeea114add2012-05-03 15:00:40 -07001167 /* Method is not empty */
buzbeefa57c472012-11-21 12:06:18 -08001168 if (cu->first_lir_insn) {
buzbee67bf8852011-08-17 17:51:35 -07001169
Bill Buzbeea114add2012-05-03 15:00:40 -07001170 // mark the targets of switch statement case labels
buzbeefa57c472012-11-21 12:06:18 -08001171 ProcessSwitchTables(cu.get());
buzbee67bf8852011-08-17 17:51:35 -07001172
Bill Buzbeea114add2012-05-03 15:00:40 -07001173 /* Convert LIR into machine code. */
buzbeefa57c472012-11-21 12:06:18 -08001174 AssembleLIR(cu.get());
buzbee99ba9642012-01-25 14:23:14 -08001175
buzbeefa57c472012-11-21 12:06:18 -08001176 if (cu->verbose) {
1177 CodegenDump(cu.get());
buzbee67bf8852011-08-17 17:51:35 -07001178 }
1179
buzbeefa57c472012-11-21 12:06:18 -08001180 if (cu->opcode_count != NULL) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001181 LOG(INFO) << "Opcode Count";
1182 for (int i = 0; i < kNumPackedOpcodes; i++) {
buzbeefa57c472012-11-21 12:06:18 -08001183 if (cu->opcode_count[i] != 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001184 LOG(INFO) << "-C- "
1185 << Instruction::Name(static_cast<Instruction::Code>(i))
buzbeefa57c472012-11-21 12:06:18 -08001186 << " " << cu->opcode_count[i];
buzbee67bf8852011-08-17 17:51:35 -07001187 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001188 }
1189 }
1190 }
buzbeea7c12682012-03-19 13:13:53 -07001191
buzbeefa57c472012-11-21 12:06:18 -08001192 // Combine vmap tables - core regs, then fp regs - into vmap_table
1193 std::vector<uint16_t> vmap_table;
buzbeeca7a5e42012-08-20 11:12:18 -07001194 // Core regs may have been inserted out of order - sort first
buzbeefa57c472012-11-21 12:06:18 -08001195 std::sort(cu->core_vmap_table.begin(), cu->core_vmap_table.end());
1196 for (size_t i = 0 ; i < cu->core_vmap_table.size(); i++) {
buzbeeca7a5e42012-08-20 11:12:18 -07001197 // Copy, stripping out the phys register sort key
buzbeefa57c472012-11-21 12:06:18 -08001198 vmap_table.push_back(~(-1 << VREG_NUM_WIDTH) & cu->core_vmap_table[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001199 }
1200 // If we have a frame, push a marker to take place of lr
buzbeefa57c472012-11-21 12:06:18 -08001201 if (cu->frame_size > 0) {
1202 vmap_table.push_back(INVALID_VREG);
Bill Buzbeea114add2012-05-03 15:00:40 -07001203 } else {
buzbeefa57c472012-11-21 12:06:18 -08001204 DCHECK_EQ(__builtin_popcount(cu->core_spill_mask), 0);
1205 DCHECK_EQ(__builtin_popcount(cu->fp_spill_mask), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -07001206 }
buzbeeca7a5e42012-08-20 11:12:18 -07001207 // Combine vmap tables - core regs, then fp regs. fp regs already sorted
buzbeefa57c472012-11-21 12:06:18 -08001208 for (uint32_t i = 0; i < cu->fp_vmap_table.size(); i++) {
1209 vmap_table.push_back(cu->fp_vmap_table[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001210 }
1211 CompiledMethod* result =
buzbeefa57c472012-11-21 12:06:18 -08001212 new CompiledMethod(cu->instruction_set, cu->code_buffer,
1213 cu->frame_size, cu->core_spill_mask, cu->fp_spill_mask,
1214 cu->combined_mapping_table, vmap_table, cu->native_gc_map);
buzbee67bf8852011-08-17 17:51:35 -07001215
Bill Buzbeea114add2012-05-03 15:00:40 -07001216 VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file)
buzbeefa57c472012-11-21 12:06:18 -08001217 << " (" << (cu->code_buffer.size() * sizeof(cu->code_buffer[0]))
Bill Buzbeea114add2012-05-03 15:00:40 -07001218 << " bytes)";
buzbee5abfa3e2012-01-31 17:01:43 -08001219
1220#ifdef WITH_MEMSTATS
buzbeefa57c472012-11-21 12:06:18 -08001221 if (cu->enable_debug & (1 << kDebugShowMemoryUsage)) {
1222 DumpMemStats(cu.get());
Bill Buzbeea114add2012-05-03 15:00:40 -07001223 }
buzbee5abfa3e2012-01-31 17:01:43 -08001224#endif
buzbee67bf8852011-08-17 17:51:35 -07001225
buzbeefa57c472012-11-21 12:06:18 -08001226 ArenaReset(cu.get());
buzbeeba938cb2012-02-03 14:47:55 -08001227
Bill Buzbeea114add2012-05-03 15:00:40 -07001228 return result;
buzbee67bf8852011-08-17 17:51:35 -07001229}
1230
buzbee52a77fc2012-11-20 19:50:46 -08001231CompiledMethod* CompileOneMethod(Compiler& compiler,
buzbeec531cef2012-10-18 07:09:20 -07001232 const CompilerBackend backend,
buzbeeabc4c6b2012-08-23 08:17:15 -07001233 const DexFile::CodeItem* code_item,
1234 uint32_t access_flags, InvokeType invoke_type,
Ian Rogersfffdb022013-01-04 15:14:08 -08001235 uint32_t class_def_idx, uint32_t method_idx, jobject class_loader,
buzbeec531cef2012-10-18 07:09:20 -07001236 const DexFile& dex_file,
buzbeefa57c472012-11-21 12:06:18 -08001237 LLVMInfo* llvm_info)
buzbeeabc4c6b2012-08-23 08:17:15 -07001238{
Ian Rogersfffdb022013-01-04 15:14:08 -08001239 return CompileMethod(compiler, backend, code_item, access_flags, invoke_type, class_def_idx,
1240 method_idx, class_loader, dex_file, llvm_info);
buzbeeabc4c6b2012-08-23 08:17:15 -07001241}
1242
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001243} // namespace art
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001244
Bill Buzbeea114add2012-05-03 15:00:40 -07001245extern "C" art::CompiledMethod*
buzbeec531cef2012-10-18 07:09:20 -07001246 ArtQuickCompileMethod(art::Compiler& compiler,
1247 const art::DexFile::CodeItem* code_item,
1248 uint32_t access_flags, art::InvokeType invoke_type,
Ian Rogersfffdb022013-01-04 15:14:08 -08001249 uint32_t class_def_idx, uint32_t method_idx, jobject class_loader,
buzbeec531cef2012-10-18 07:09:20 -07001250 const art::DexFile& dex_file)
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001251{
buzbeec531cef2012-10-18 07:09:20 -07001252 // TODO: check method fingerprint here to determine appropriate backend type. Until then, use build default
1253 art::CompilerBackend backend = compiler.GetCompilerBackend();
buzbee52a77fc2012-11-20 19:50:46 -08001254 return art::CompileOneMethod(compiler, backend, code_item, access_flags, invoke_type,
Ian Rogersfffdb022013-01-04 15:14:08 -08001255 class_def_idx, method_idx, class_loader, dex_file,
1256 NULL /* use thread llvm_info */);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001257}