blob: d896e5b6210b14b149414324873d356cd1d72a53 [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"
buzbee02031b12012-11-23 09:41:35 -080025#include "codegen/mir_to_gbc.h"
26#include "codegen/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 {
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);
buzbeefa57c472012-11-21 12:06:18 -080058 LLVMInfo* llvm_info = new LLVMInfo();
59 compiler.SetCompilerContext(llvm_info);
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
buzbeefa57c472012-11-21 12:06:18 -0800101static bool ContentIsInsn(const uint16_t* code_ptr) {
102 uint16_t instr = *code_ptr;
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 */
buzbeefa57c472012-11-21 12:06:18 -0800115static int ParseInsn(CompilationUnit* cu, const uint16_t* code_ptr,
buzbeea169e1d2012-12-05 14:26:44 -0800116 DecodedInstruction* decoded_instruction)
buzbee67bf8852011-08-17 17:51:35 -0700117{
Elliott Hughesadb8c672012-03-06 16:49:32 -0800118 // Don't parse instruction data
buzbeefa57c472012-11-21 12:06:18 -0800119 if (!ContentIsInsn(code_ptr)) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800120 return 0;
121 }
buzbee67bf8852011-08-17 17:51:35 -0700122
buzbeefa57c472012-11-21 12:06:18 -0800123 const Instruction* instruction = Instruction::At(code_ptr);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800124 *decoded_instruction = DecodedInstruction(instruction);
buzbee67bf8852011-08-17 17:51:35 -0700125
Elliott Hughesadb8c672012-03-06 16:49:32 -0800126 return instruction->SizeInCodeUnits();
buzbee67bf8852011-08-17 17:51:35 -0700127}
128
129#define UNKNOWN_TARGET 0xffffffff
130
buzbee67bf8852011-08-17 17:51:35 -0700131/* Split an existing block from the specified code offset into two */
buzbeefa57c472012-11-21 12:06:18 -0800132static BasicBlock *SplitBlock(CompilationUnit* cu, unsigned int code_offset,
133 BasicBlock* orig_block, BasicBlock** immed_pred_block_p)
buzbee67bf8852011-08-17 17:51:35 -0700134{
buzbeefa57c472012-11-21 12:06:18 -0800135 MIR* insn = orig_block->first_mir_insn;
Bill Buzbeea114add2012-05-03 15:00:40 -0700136 while (insn) {
buzbeefa57c472012-11-21 12:06:18 -0800137 if (insn->offset == code_offset) break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700138 insn = insn->next;
139 }
140 if (insn == NULL) {
141 LOG(FATAL) << "Break split failed";
142 }
buzbeefa57c472012-11-21 12:06:18 -0800143 BasicBlock *bottom_block = NewMemBB(cu, kDalvikByteCode,
144 cu->num_blocks++);
145 InsertGrowableList(cu, &cu->block_list, reinterpret_cast<uintptr_t>(bottom_block));
buzbee67bf8852011-08-17 17:51:35 -0700146
buzbeefa57c472012-11-21 12:06:18 -0800147 bottom_block->start_offset = code_offset;
148 bottom_block->first_mir_insn = insn;
149 bottom_block->last_mir_insn = orig_block->last_mir_insn;
buzbee67bf8852011-08-17 17:51:35 -0700150
Bill Buzbeea114add2012-05-03 15:00:40 -0700151 /* Add it to the quick lookup cache */
buzbeefa57c472012-11-21 12:06:18 -0800152 cu->block_map.Put(bottom_block->start_offset, bottom_block);
buzbee5b537102012-01-17 17:33:47 -0800153
Bill Buzbeea114add2012-05-03 15:00:40 -0700154 /* Handle the taken path */
buzbeefa57c472012-11-21 12:06:18 -0800155 bottom_block->taken = orig_block->taken;
156 if (bottom_block->taken) {
157 orig_block->taken = NULL;
158 DeleteGrowableList(bottom_block->taken->predecessors, reinterpret_cast<uintptr_t>(orig_block));
159 InsertGrowableList(cu, bottom_block->taken->predecessors,
160 reinterpret_cast<uintptr_t>(bottom_block));
Bill Buzbeea114add2012-05-03 15:00:40 -0700161 }
162
163 /* Handle the fallthrough path */
buzbeefa57c472012-11-21 12:06:18 -0800164 bottom_block->fall_through = orig_block->fall_through;
165 orig_block->fall_through = bottom_block;
166 InsertGrowableList(cu, bottom_block->predecessors,
167 reinterpret_cast<uintptr_t>(orig_block));
168 if (bottom_block->fall_through) {
169 DeleteGrowableList(bottom_block->fall_through->predecessors,
170 reinterpret_cast<uintptr_t>(orig_block));
171 InsertGrowableList(cu, bottom_block->fall_through->predecessors,
172 reinterpret_cast<uintptr_t>(bottom_block));
Bill Buzbeea114add2012-05-03 15:00:40 -0700173 }
174
175 /* Handle the successor list */
buzbeefa57c472012-11-21 12:06:18 -0800176 if (orig_block->successor_block_list.block_list_type != kNotUsed) {
177 bottom_block->successor_block_list = orig_block->successor_block_list;
178 orig_block->successor_block_list.block_list_type = kNotUsed;
Bill Buzbeea114add2012-05-03 15:00:40 -0700179 GrowableListIterator iterator;
180
buzbeefa57c472012-11-21 12:06:18 -0800181 GrowableListIteratorInit(&bottom_block->successor_block_list.blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700182 &iterator);
183 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800184 SuccessorBlockInfo *successor_block_info =
buzbee52a77fc2012-11-20 19:50:46 -0800185 reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));
buzbeefa57c472012-11-21 12:06:18 -0800186 if (successor_block_info == NULL) break;
187 BasicBlock *bb = successor_block_info->block;
188 DeleteGrowableList(bb->predecessors, reinterpret_cast<uintptr_t>(orig_block));
189 InsertGrowableList(cu, bb->predecessors, reinterpret_cast<uintptr_t>(bottom_block));
buzbee67bf8852011-08-17 17:51:35 -0700190 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700191 }
buzbee67bf8852011-08-17 17:51:35 -0700192
buzbeefa57c472012-11-21 12:06:18 -0800193 orig_block->last_mir_insn = insn->prev;
buzbee67bf8852011-08-17 17:51:35 -0700194
Bill Buzbeea114add2012-05-03 15:00:40 -0700195 insn->prev->next = NULL;
196 insn->prev = NULL;
197 /*
198 * Update the immediate predecessor block pointer so that outgoing edges
199 * can be applied to the proper block.
200 */
buzbeefa57c472012-11-21 12:06:18 -0800201 if (immed_pred_block_p) {
202 DCHECK_EQ(*immed_pred_block_p, orig_block);
203 *immed_pred_block_p = bottom_block;
Bill Buzbeea114add2012-05-03 15:00:40 -0700204 }
buzbeefa57c472012-11-21 12:06:18 -0800205 return bottom_block;
buzbee67bf8852011-08-17 17:51:35 -0700206}
207
208/*
209 * Given a code offset, find out the block that starts with it. If the offset
buzbeefa57c472012-11-21 12:06:18 -0800210 * is in the middle of an existing block, split it into two. If immed_pred_block_p
211 * is not non-null and is the block being split, update *immed_pred_block_p to
buzbee9ab05de2012-01-18 15:43:48 -0800212 * point to the bottom block so that outgoing edges can be set up properly
213 * (by the caller)
buzbee5b537102012-01-17 17:33:47 -0800214 * Utilizes a map for fast lookup of the typical cases.
buzbee67bf8852011-08-17 17:51:35 -0700215 */
buzbeefa57c472012-11-21 12:06:18 -0800216BasicBlock *FindBlock(CompilationUnit* cu, unsigned int code_offset,
217 bool split, bool create, BasicBlock** immed_pred_block_p)
buzbee67bf8852011-08-17 17:51:35 -0700218{
buzbeefa57c472012-11-21 12:06:18 -0800219 GrowableList* block_list = &cu->block_list;
Bill Buzbeea114add2012-05-03 15:00:40 -0700220 BasicBlock* bb;
221 unsigned int i;
222 SafeMap<unsigned int, BasicBlock*>::iterator it;
buzbee67bf8852011-08-17 17:51:35 -0700223
buzbeefa57c472012-11-21 12:06:18 -0800224 it = cu->block_map.find(code_offset);
225 if (it != cu->block_map.end()) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700226 return it->second;
227 } else if (!create) {
228 return NULL;
229 }
230
231 if (split) {
buzbeefa57c472012-11-21 12:06:18 -0800232 for (i = 0; i < block_list->num_used; i++) {
233 bb = reinterpret_cast<BasicBlock*>(block_list->elem_list[i]);
234 if (bb->block_type != kDalvikByteCode) continue;
Bill Buzbeea114add2012-05-03 15:00:40 -0700235 /* Check if a branch jumps into the middle of an existing block */
buzbeefa57c472012-11-21 12:06:18 -0800236 if ((code_offset > bb->start_offset) && (bb->last_mir_insn != NULL) &&
237 (code_offset <= bb->last_mir_insn->offset)) {
238 BasicBlock *new_bb = SplitBlock(cu, code_offset, bb,
239 bb == *immed_pred_block_p ?
240 immed_pred_block_p : NULL);
241 return new_bb;
Bill Buzbeea114add2012-05-03 15:00:40 -0700242 }
buzbee5b537102012-01-17 17:33:47 -0800243 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700244 }
buzbee5b537102012-01-17 17:33:47 -0800245
Bill Buzbeea114add2012-05-03 15:00:40 -0700246 /* Create a new one */
buzbeefa57c472012-11-21 12:06:18 -0800247 bb = NewMemBB(cu, kDalvikByteCode, cu->num_blocks++);
248 InsertGrowableList(cu, &cu->block_list, reinterpret_cast<uintptr_t>(bb));
249 bb->start_offset = code_offset;
250 cu->block_map.Put(bb->start_offset, bb);
Bill Buzbeea114add2012-05-03 15:00:40 -0700251 return bb;
buzbee67bf8852011-08-17 17:51:35 -0700252}
253
buzbeef58c12c2012-07-03 15:06:29 -0700254/* Find existing block */
buzbeefa57c472012-11-21 12:06:18 -0800255BasicBlock* FindBlock(CompilationUnit* cu, unsigned int code_offset)
buzbeef58c12c2012-07-03 15:06:29 -0700256{
buzbeefa57c472012-11-21 12:06:18 -0800257 return FindBlock(cu, code_offset, false, false, NULL);
buzbeef58c12c2012-07-03 15:06:29 -0700258}
259
buzbeead8f15e2012-06-18 14:49:45 -0700260/* Turn method name into a legal Linux file name */
buzbee52a77fc2012-11-20 19:50:46 -0800261void ReplaceSpecialChars(std::string& str)
buzbeead8f15e2012-06-18 14:49:45 -0700262{
263 static const struct { const char before; const char after; } match[] =
264 {{'/','-'}, {';','#'}, {' ','#'}, {'$','+'},
265 {'(','@'}, {')','@'}, {'<','='}, {'>','='}};
266 for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) {
267 std::replace(str.begin(), str.end(), match[i].before, match[i].after);
268 }
269}
270
buzbee67bf8852011-08-17 17:51:35 -0700271/* Dump the CFG into a DOT graph */
buzbeefa57c472012-11-21 12:06:18 -0800272void DumpCFG(CompilationUnit* cu, const char* dir_prefix)
buzbee67bf8852011-08-17 17:51:35 -0700273{
Bill Buzbeea114add2012-05-03 15:00:40 -0700274 FILE* file;
buzbeefa57c472012-11-21 12:06:18 -0800275 std::string fname(PrettyMethod(cu->method_idx, *cu->dex_file));
buzbee52a77fc2012-11-20 19:50:46 -0800276 ReplaceSpecialChars(fname);
buzbeefa57c472012-11-21 12:06:18 -0800277 fname = StringPrintf("%s%s%x.dot", dir_prefix, fname.c_str(),
278 cu->entry_block->fall_through->start_offset);
buzbeead8f15e2012-06-18 14:49:45 -0700279 file = fopen(fname.c_str(), "w");
Bill Buzbeea114add2012-05-03 15:00:40 -0700280 if (file == NULL) {
281 return;
282 }
283 fprintf(file, "digraph G {\n");
284
285 fprintf(file, " rankdir=TB\n");
286
buzbeefa57c472012-11-21 12:06:18 -0800287 int num_reachable_blocks = cu->num_reachable_blocks;
Bill Buzbeea114add2012-05-03 15:00:40 -0700288 int idx;
buzbeefa57c472012-11-21 12:06:18 -0800289 const GrowableList *block_list = &cu->block_list;
Bill Buzbeea114add2012-05-03 15:00:40 -0700290
buzbeefa57c472012-11-21 12:06:18 -0800291 for (idx = 0; idx < num_reachable_blocks; idx++) {
292 int block_idx = cu->dfs_order.elem_list[idx];
293 BasicBlock *bb = reinterpret_cast<BasicBlock*>(GrowableListGetElement(block_list, block_idx));
Bill Buzbeea114add2012-05-03 15:00:40 -0700294 if (bb == NULL) break;
buzbeefa57c472012-11-21 12:06:18 -0800295 if (bb->block_type == kDead) continue;
296 if (bb->block_type == kEntryBlock) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700297 fprintf(file, " entry_%d [shape=Mdiamond];\n", bb->id);
buzbeefa57c472012-11-21 12:06:18 -0800298 } else if (bb->block_type == kExitBlock) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700299 fprintf(file, " exit_%d [shape=Mdiamond];\n", bb->id);
buzbeefa57c472012-11-21 12:06:18 -0800300 } else if (bb->block_type == kDalvikByteCode) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700301 fprintf(file, " block%04x_%d [shape=record,label = \"{ \\\n",
buzbeefa57c472012-11-21 12:06:18 -0800302 bb->start_offset, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700303 const MIR *mir;
304 fprintf(file, " {block id %d\\l}%s\\\n", bb->id,
buzbeefa57c472012-11-21 12:06:18 -0800305 bb->first_mir_insn ? " | " : " ");
306 for (mir = bb->first_mir_insn; mir; mir = mir->next) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700307 fprintf(file, " {%04x %s\\l}%s\\\n", mir->offset,
buzbeea169e1d2012-12-05 14:26:44 -0800308 mir->ssa_rep ? GetDalvikDisassembly(cu, mir) :
Bill Buzbeea114add2012-05-03 15:00:40 -0700309 Instruction::Name(mir->dalvikInsn.opcode),
310 mir->next ? " | " : " ");
311 }
312 fprintf(file, " }\"];\n\n");
buzbeefa57c472012-11-21 12:06:18 -0800313 } else if (bb->block_type == kExceptionHandling) {
314 char block_name[BLOCK_NAME_LEN];
Bill Buzbeea114add2012-05-03 15:00:40 -0700315
buzbeefa57c472012-11-21 12:06:18 -0800316 GetBlockName(bb, block_name);
317 fprintf(file, " %s [shape=invhouse];\n", block_name);
buzbee67bf8852011-08-17 17:51:35 -0700318 }
buzbee67bf8852011-08-17 17:51:35 -0700319
buzbeefa57c472012-11-21 12:06:18 -0800320 char block_name1[BLOCK_NAME_LEN], block_name2[BLOCK_NAME_LEN];
buzbee67bf8852011-08-17 17:51:35 -0700321
Bill Buzbeea114add2012-05-03 15:00:40 -0700322 if (bb->taken) {
buzbeefa57c472012-11-21 12:06:18 -0800323 GetBlockName(bb, block_name1);
324 GetBlockName(bb->taken, block_name2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700325 fprintf(file, " %s:s -> %s:n [style=dotted]\n",
buzbeefa57c472012-11-21 12:06:18 -0800326 block_name1, block_name2);
buzbee67bf8852011-08-17 17:51:35 -0700327 }
buzbeefa57c472012-11-21 12:06:18 -0800328 if (bb->fall_through) {
329 GetBlockName(bb, block_name1);
330 GetBlockName(bb->fall_through, block_name2);
331 fprintf(file, " %s:s -> %s:n\n", block_name1, block_name2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700332 }
333
buzbeefa57c472012-11-21 12:06:18 -0800334 if (bb->successor_block_list.block_list_type != kNotUsed) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700335 fprintf(file, " succ%04x_%d [shape=%s,label = \"{ \\\n",
buzbeefa57c472012-11-21 12:06:18 -0800336 bb->start_offset, bb->id,
337 (bb->successor_block_list.block_list_type == kCatch) ?
Bill Buzbeea114add2012-05-03 15:00:40 -0700338 "Mrecord" : "record");
339 GrowableListIterator iterator;
buzbeefa57c472012-11-21 12:06:18 -0800340 GrowableListIteratorInit(&bb->successor_block_list.blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700341 &iterator);
buzbeefa57c472012-11-21 12:06:18 -0800342 SuccessorBlockInfo *successor_block_info =
buzbee52a77fc2012-11-20 19:50:46 -0800343 reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700344
buzbeefa57c472012-11-21 12:06:18 -0800345 int succ_id = 0;
Bill Buzbeea114add2012-05-03 15:00:40 -0700346 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800347 if (successor_block_info == NULL) break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700348
buzbeefa57c472012-11-21 12:06:18 -0800349 BasicBlock *dest_block = successor_block_info->block;
350 SuccessorBlockInfo *next_successor_block_info =
buzbee52a77fc2012-11-20 19:50:46 -0800351 reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700352
353 fprintf(file, " {<f%d> %04x: %04x\\l}%s\\\n",
buzbeefa57c472012-11-21 12:06:18 -0800354 succ_id++,
355 successor_block_info->key,
356 dest_block->start_offset,
357 (next_successor_block_info != NULL) ? " | " : " ");
Bill Buzbeea114add2012-05-03 15:00:40 -0700358
buzbeefa57c472012-11-21 12:06:18 -0800359 successor_block_info = next_successor_block_info;
Bill Buzbeea114add2012-05-03 15:00:40 -0700360 }
361 fprintf(file, " }\"];\n\n");
362
buzbeefa57c472012-11-21 12:06:18 -0800363 GetBlockName(bb, block_name1);
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700364 fprintf(file, " %s:s -> succ%04x_%d:n [style=dashed]\n",
buzbeefa57c472012-11-21 12:06:18 -0800365 block_name1, bb->start_offset, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700366
buzbeefa57c472012-11-21 12:06:18 -0800367 if (bb->successor_block_list.block_list_type == kPackedSwitch ||
368 bb->successor_block_list.block_list_type == kSparseSwitch) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700369
buzbeefa57c472012-11-21 12:06:18 -0800370 GrowableListIteratorInit(&bb->successor_block_list.blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700371 &iterator);
372
buzbeefa57c472012-11-21 12:06:18 -0800373 succ_id = 0;
Bill Buzbeea114add2012-05-03 15:00:40 -0700374 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800375 SuccessorBlockInfo *successor_block_info =
buzbee52a77fc2012-11-20 19:50:46 -0800376 reinterpret_cast<SuccessorBlockInfo*>( GrowableListIteratorNext(&iterator));
buzbeefa57c472012-11-21 12:06:18 -0800377 if (successor_block_info == NULL) break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700378
buzbeefa57c472012-11-21 12:06:18 -0800379 BasicBlock *dest_block = successor_block_info->block;
Bill Buzbeea114add2012-05-03 15:00:40 -0700380
buzbeefa57c472012-11-21 12:06:18 -0800381 GetBlockName(dest_block, block_name2);
382 fprintf(file, " succ%04x_%d:f%d:e -> %s:n\n", bb->start_offset,
383 bb->id, succ_id++, block_name2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700384 }
385 }
386 }
387 fprintf(file, "\n");
388
389 /* Display the dominator tree */
buzbeefa57c472012-11-21 12:06:18 -0800390 GetBlockName(bb, block_name1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700391 fprintf(file, " cfg%s [label=\"%s\", shape=none];\n",
buzbeefa57c472012-11-21 12:06:18 -0800392 block_name1, block_name1);
393 if (bb->i_dom) {
394 GetBlockName(bb->i_dom, block_name2);
395 fprintf(file, " cfg%s:s -> cfg%s:n\n\n", block_name2, block_name1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700396 }
397 }
398 fprintf(file, "}\n");
399 fclose(file);
buzbee67bf8852011-08-17 17:51:35 -0700400}
401
402/* Verify if all the successor is connected with all the claimed predecessors */
buzbeefa57c472012-11-21 12:06:18 -0800403static bool VerifyPredInfo(CompilationUnit* cu, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700404{
Bill Buzbeea114add2012-05-03 15:00:40 -0700405 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700406
buzbee52a77fc2012-11-20 19:50:46 -0800407 GrowableListIteratorInit(bb->predecessors, &iter);
Bill Buzbeea114add2012-05-03 15:00:40 -0700408 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800409 BasicBlock *pred_bb = reinterpret_cast<BasicBlock*>(GrowableListIteratorNext(&iter));
410 if (!pred_bb) break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700411 bool found = false;
buzbeefa57c472012-11-21 12:06:18 -0800412 if (pred_bb->taken == bb) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700413 found = true;
buzbeefa57c472012-11-21 12:06:18 -0800414 } else if (pred_bb->fall_through == bb) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700415 found = true;
buzbeefa57c472012-11-21 12:06:18 -0800416 } else if (pred_bb->successor_block_list.block_list_type != kNotUsed) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700417 GrowableListIterator iterator;
buzbeefa57c472012-11-21 12:06:18 -0800418 GrowableListIteratorInit(&pred_bb->successor_block_list.blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700419 &iterator);
420 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800421 SuccessorBlockInfo *successor_block_info =
buzbee52a77fc2012-11-20 19:50:46 -0800422 reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));
buzbeefa57c472012-11-21 12:06:18 -0800423 if (successor_block_info == NULL) break;
424 BasicBlock *succ_bb = successor_block_info->block;
425 if (succ_bb == bb) {
buzbee67bf8852011-08-17 17:51:35 -0700426 found = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700427 break;
buzbee67bf8852011-08-17 17:51:35 -0700428 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700429 }
buzbee67bf8852011-08-17 17:51:35 -0700430 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700431 if (found == false) {
buzbeefa57c472012-11-21 12:06:18 -0800432 char block_name1[BLOCK_NAME_LEN], block_name2[BLOCK_NAME_LEN];
433 GetBlockName(bb, block_name1);
434 GetBlockName(pred_bb, block_name2);
435 DumpCFG(cu, "/sdcard/cfg/");
436 LOG(FATAL) << "Successor " << block_name1 << "not found from "
437 << block_name2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700438 }
439 }
440 return true;
buzbee67bf8852011-08-17 17:51:35 -0700441}
442
443/* Identify code range in try blocks and set up the empty catch blocks */
buzbeefa57c472012-11-21 12:06:18 -0800444static void ProcessTryCatchBlocks(CompilationUnit* cu)
buzbee67bf8852011-08-17 17:51:35 -0700445{
buzbeefa57c472012-11-21 12:06:18 -0800446 const DexFile::CodeItem* code_item = cu->code_item;
447 int tries_size = code_item->tries_size_;
Bill Buzbeea114add2012-05-03 15:00:40 -0700448 int offset;
buzbee67bf8852011-08-17 17:51:35 -0700449
buzbeefa57c472012-11-21 12:06:18 -0800450 if (tries_size == 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700451 return;
452 }
453
buzbeefa57c472012-11-21 12:06:18 -0800454 ArenaBitVector* try_block_addr = cu->try_block_addr;
Bill Buzbeea114add2012-05-03 15:00:40 -0700455
buzbeefa57c472012-11-21 12:06:18 -0800456 for (int i = 0; i < tries_size; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700457 const DexFile::TryItem* pTry =
458 DexFile::GetTryItems(*code_item, i);
buzbeefa57c472012-11-21 12:06:18 -0800459 int start_offset = pTry->start_addr_;
460 int end_offset = start_offset + pTry->insn_count_;
461 for (offset = start_offset; offset < end_offset; offset++) {
462 SetBit(cu, try_block_addr, offset);
buzbee67bf8852011-08-17 17:51:35 -0700463 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700464 }
buzbee67bf8852011-08-17 17:51:35 -0700465
Bill Buzbeea114add2012-05-03 15:00:40 -0700466 // Iterate over each of the handlers to enqueue the empty Catch blocks
467 const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item, 0);
468 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
469 for (uint32_t idx = 0; idx < handlers_size; idx++) {
470 CatchHandlerIterator iterator(handlers_ptr);
471 for (; iterator.HasNext(); iterator.Next()) {
472 uint32_t address = iterator.GetHandlerAddress();
buzbeefa57c472012-11-21 12:06:18 -0800473 FindBlock(cu, address, false /* split */, true /*create*/,
474 /* immed_pred_block_p */ NULL);
buzbee67bf8852011-08-17 17:51:35 -0700475 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700476 handlers_ptr = iterator.EndDataPointer();
477 }
buzbee67bf8852011-08-17 17:51:35 -0700478}
479
Elliott Hughesadb8c672012-03-06 16:49:32 -0800480/* Process instructions with the kBranch flag */
buzbeefa57c472012-11-21 12:06:18 -0800481static BasicBlock* ProcessCanBranch(CompilationUnit* cu, BasicBlock* cur_block,
482 MIR* insn, int cur_offset, int width, int flags,
483 const uint16_t* code_ptr, const uint16_t* code_end)
buzbee67bf8852011-08-17 17:51:35 -0700484{
buzbeefa57c472012-11-21 12:06:18 -0800485 int target = cur_offset;
Bill Buzbeea114add2012-05-03 15:00:40 -0700486 switch (insn->dalvikInsn.opcode) {
487 case Instruction::GOTO:
488 case Instruction::GOTO_16:
489 case Instruction::GOTO_32:
buzbeecbd6d442012-11-17 14:11:25 -0800490 target += insn->dalvikInsn.vA;
Bill Buzbeea114add2012-05-03 15:00:40 -0700491 break;
492 case Instruction::IF_EQ:
493 case Instruction::IF_NE:
494 case Instruction::IF_LT:
495 case Instruction::IF_GE:
496 case Instruction::IF_GT:
497 case Instruction::IF_LE:
buzbeefa57c472012-11-21 12:06:18 -0800498 cur_block->conditional_branch = true;
buzbeecbd6d442012-11-17 14:11:25 -0800499 target += insn->dalvikInsn.vC;
Bill Buzbeea114add2012-05-03 15:00:40 -0700500 break;
501 case Instruction::IF_EQZ:
502 case Instruction::IF_NEZ:
503 case Instruction::IF_LTZ:
504 case Instruction::IF_GEZ:
505 case Instruction::IF_GTZ:
506 case Instruction::IF_LEZ:
buzbeefa57c472012-11-21 12:06:18 -0800507 cur_block->conditional_branch = true;
buzbeecbd6d442012-11-17 14:11:25 -0800508 target += insn->dalvikInsn.vB;
Bill Buzbeea114add2012-05-03 15:00:40 -0700509 break;
510 default:
buzbeecbd6d442012-11-17 14:11:25 -0800511 LOG(FATAL) << "Unexpected opcode(" << insn->dalvikInsn.opcode << ") with kBranch set";
Bill Buzbeea114add2012-05-03 15:00:40 -0700512 }
buzbeefa57c472012-11-21 12:06:18 -0800513 BasicBlock *taken_block = FindBlock(cu, target,
Bill Buzbeea114add2012-05-03 15:00:40 -0700514 /* split */
515 true,
516 /* create */
517 true,
buzbeefa57c472012-11-21 12:06:18 -0800518 /* immed_pred_block_p */
519 &cur_block);
520 cur_block->taken = taken_block;
521 InsertGrowableList(cu, taken_block->predecessors, reinterpret_cast<uintptr_t>(cur_block));
buzbee67bf8852011-08-17 17:51:35 -0700522
Bill Buzbeea114add2012-05-03 15:00:40 -0700523 /* Always terminate the current block for conditional branches */
524 if (flags & Instruction::kContinue) {
buzbeefa57c472012-11-21 12:06:18 -0800525 BasicBlock *fallthrough_block = FindBlock(cu,
526 cur_offset + width,
Bill Buzbeea114add2012-05-03 15:00:40 -0700527 /*
528 * If the method is processed
529 * in sequential order from the
530 * beginning, we don't need to
531 * specify split for continue
532 * blocks. However, this
533 * routine can be called by
534 * compileLoop, which starts
535 * parsing the method from an
536 * arbitrary address in the
537 * method body.
538 */
539 true,
540 /* create */
541 true,
buzbeefa57c472012-11-21 12:06:18 -0800542 /* immed_pred_block_p */
543 &cur_block);
544 cur_block->fall_through = fallthrough_block;
545 InsertGrowableList(cu, fallthrough_block->predecessors,
546 reinterpret_cast<uintptr_t>(cur_block));
547 } else if (code_ptr < code_end) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700548 /* Create a fallthrough block for real instructions (incl. NOP) */
buzbeefa57c472012-11-21 12:06:18 -0800549 if (ContentIsInsn(code_ptr)) {
550 FindBlock(cu, cur_offset + width,
Bill Buzbeea114add2012-05-03 15:00:40 -0700551 /* split */
552 false,
553 /* create */
554 true,
buzbeefa57c472012-11-21 12:06:18 -0800555 /* immed_pred_block_p */
Bill Buzbeea114add2012-05-03 15:00:40 -0700556 NULL);
buzbee67bf8852011-08-17 17:51:35 -0700557 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700558 }
buzbeefa57c472012-11-21 12:06:18 -0800559 return cur_block;
buzbee67bf8852011-08-17 17:51:35 -0700560}
561
Elliott Hughesadb8c672012-03-06 16:49:32 -0800562/* Process instructions with the kSwitch flag */
buzbeefa57c472012-11-21 12:06:18 -0800563static void ProcessCanSwitch(CompilationUnit* cu, BasicBlock* cur_block,
564 MIR* insn, int cur_offset, int width, int flags)
buzbee67bf8852011-08-17 17:51:35 -0700565{
buzbeefa57c472012-11-21 12:06:18 -0800566 const uint16_t* switch_data =
567 reinterpret_cast<const uint16_t*>(cu->insns + cur_offset + insn->dalvikInsn.vB);
Bill Buzbeea114add2012-05-03 15:00:40 -0700568 int size;
buzbeecbd6d442012-11-17 14:11:25 -0800569 const int* keyTable;
buzbeefa57c472012-11-21 12:06:18 -0800570 const int* target_table;
Bill Buzbeea114add2012-05-03 15:00:40 -0700571 int i;
buzbeefa57c472012-11-21 12:06:18 -0800572 int first_key;
buzbee67bf8852011-08-17 17:51:35 -0700573
Bill Buzbeea114add2012-05-03 15:00:40 -0700574 /*
575 * Packed switch data format:
576 * ushort ident = 0x0100 magic value
577 * ushort size number of entries in the table
578 * int first_key first (and lowest) switch case value
579 * int targets[size] branch targets, relative to switch opcode
580 *
581 * Total size is (4+size*2) 16-bit code units.
582 */
583 if (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) {
buzbeefa57c472012-11-21 12:06:18 -0800584 DCHECK_EQ(static_cast<int>(switch_data[0]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700585 static_cast<int>(Instruction::kPackedSwitchSignature));
buzbeefa57c472012-11-21 12:06:18 -0800586 size = switch_data[1];
587 first_key = switch_data[2] | (switch_data[3] << 16);
588 target_table = reinterpret_cast<const int*>(&switch_data[4]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700589 keyTable = NULL; // Make the compiler happy
590 /*
591 * Sparse switch data format:
592 * ushort ident = 0x0200 magic value
593 * ushort size number of entries in the table; > 0
594 * int keys[size] keys, sorted low-to-high; 32-bit aligned
595 * int targets[size] branch targets, relative to switch opcode
596 *
597 * Total size is (2+size*4) 16-bit code units.
598 */
599 } else {
buzbeefa57c472012-11-21 12:06:18 -0800600 DCHECK_EQ(static_cast<int>(switch_data[0]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700601 static_cast<int>(Instruction::kSparseSwitchSignature));
buzbeefa57c472012-11-21 12:06:18 -0800602 size = switch_data[1];
603 keyTable = reinterpret_cast<const int*>(&switch_data[2]);
604 target_table = reinterpret_cast<const int*>(&switch_data[2 + size*2]);
605 first_key = 0; // To make the compiler happy
Bill Buzbeea114add2012-05-03 15:00:40 -0700606 }
buzbee67bf8852011-08-17 17:51:35 -0700607
buzbeefa57c472012-11-21 12:06:18 -0800608 if (cur_block->successor_block_list.block_list_type != kNotUsed) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700609 LOG(FATAL) << "Successor block list already in use: "
buzbeefa57c472012-11-21 12:06:18 -0800610 << static_cast<int>(cur_block->successor_block_list.block_list_type);
Bill Buzbeea114add2012-05-03 15:00:40 -0700611 }
buzbeefa57c472012-11-21 12:06:18 -0800612 cur_block->successor_block_list.block_list_type =
Bill Buzbeea114add2012-05-03 15:00:40 -0700613 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
614 kPackedSwitch : kSparseSwitch;
buzbeefa57c472012-11-21 12:06:18 -0800615 CompilerInitGrowableList(cu, &cur_block->successor_block_list.blocks, size,
Bill Buzbeea114add2012-05-03 15:00:40 -0700616 kListSuccessorBlocks);
617
618 for (i = 0; i < size; i++) {
buzbeefa57c472012-11-21 12:06:18 -0800619 BasicBlock *case_block = FindBlock(cu, cur_offset + target_table[i],
Bill Buzbeea114add2012-05-03 15:00:40 -0700620 /* split */
621 true,
622 /* create */
623 true,
buzbeefa57c472012-11-21 12:06:18 -0800624 /* immed_pred_block_p */
625 &cur_block);
626 SuccessorBlockInfo *successor_block_info =
627 static_cast<SuccessorBlockInfo*>(NewMem(cu, sizeof(SuccessorBlockInfo),
buzbeecbd6d442012-11-17 14:11:25 -0800628 false, kAllocSuccessor));
buzbeefa57c472012-11-21 12:06:18 -0800629 successor_block_info->block = case_block;
630 successor_block_info->key =
Elliott Hughesadb8c672012-03-06 16:49:32 -0800631 (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
buzbeefa57c472012-11-21 12:06:18 -0800632 first_key + i : keyTable[i];
633 InsertGrowableList(cu, &cur_block->successor_block_list.blocks,
634 reinterpret_cast<uintptr_t>(successor_block_info));
635 InsertGrowableList(cu, case_block->predecessors,
636 reinterpret_cast<uintptr_t>(cur_block));
Bill Buzbeea114add2012-05-03 15:00:40 -0700637 }
638
639 /* Fall-through case */
buzbeefa57c472012-11-21 12:06:18 -0800640 BasicBlock* fallthrough_block = FindBlock(cu,
641 cur_offset + width,
Bill Buzbeea114add2012-05-03 15:00:40 -0700642 /* split */
643 false,
644 /* create */
645 true,
buzbeefa57c472012-11-21 12:06:18 -0800646 /* immed_pred_block_p */
Bill Buzbeea114add2012-05-03 15:00:40 -0700647 NULL);
buzbeefa57c472012-11-21 12:06:18 -0800648 cur_block->fall_through = fallthrough_block;
649 InsertGrowableList(cu, fallthrough_block->predecessors,
650 reinterpret_cast<uintptr_t>(cur_block));
buzbee67bf8852011-08-17 17:51:35 -0700651}
652
Elliott Hughesadb8c672012-03-06 16:49:32 -0800653/* Process instructions with the kThrow flag */
buzbeefa57c472012-11-21 12:06:18 -0800654static BasicBlock* ProcessCanThrow(CompilationUnit* cu, BasicBlock* cur_block,
655 MIR* insn, int cur_offset, int width, int flags,
656 ArenaBitVector* try_block_addr, const uint16_t* code_ptr,
657 const uint16_t* code_end)
buzbee67bf8852011-08-17 17:51:35 -0700658{
buzbeefa57c472012-11-21 12:06:18 -0800659 const DexFile::CodeItem* code_item = cu->code_item;
660 bool in_try_block = IsBitSet(try_block_addr, cur_offset);
buzbee67bf8852011-08-17 17:51:35 -0700661
Bill Buzbeea114add2012-05-03 15:00:40 -0700662 /* In try block */
buzbeefa57c472012-11-21 12:06:18 -0800663 if (in_try_block) {
664 CatchHandlerIterator iterator(*code_item, cur_offset);
buzbee67bf8852011-08-17 17:51:35 -0700665
buzbeefa57c472012-11-21 12:06:18 -0800666 if (cur_block->successor_block_list.block_list_type != kNotUsed) {
667 LOG(INFO) << PrettyMethod(cu->method_idx, *cu->dex_file);
Bill Buzbeea114add2012-05-03 15:00:40 -0700668 LOG(FATAL) << "Successor block list already in use: "
buzbeefa57c472012-11-21 12:06:18 -0800669 << static_cast<int>(cur_block->successor_block_list.block_list_type);
buzbee67bf8852011-08-17 17:51:35 -0700670 }
671
buzbeefa57c472012-11-21 12:06:18 -0800672 cur_block->successor_block_list.block_list_type = kCatch;
673 CompilerInitGrowableList(cu, &cur_block->successor_block_list.blocks, 2,
Bill Buzbeea114add2012-05-03 15:00:40 -0700674 kListSuccessorBlocks);
675
676 for (;iterator.HasNext(); iterator.Next()) {
buzbeefa57c472012-11-21 12:06:18 -0800677 BasicBlock *catch_block = FindBlock(cu, iterator.GetHandlerAddress(),
Bill Buzbeea114add2012-05-03 15:00:40 -0700678 false /* split*/,
679 false /* creat */,
buzbeefa57c472012-11-21 12:06:18 -0800680 NULL /* immed_pred_block_p */);
681 catch_block->catch_entry = true;
682 cu->catches.insert(catch_block->start_offset);
683 SuccessorBlockInfo *successor_block_info = reinterpret_cast<SuccessorBlockInfo*>
684 (NewMem(cu, sizeof(SuccessorBlockInfo), false, kAllocSuccessor));
685 successor_block_info->block = catch_block;
686 successor_block_info->key = iterator.GetHandlerTypeIndex();
687 InsertGrowableList(cu, &cur_block->successor_block_list.blocks,
688 reinterpret_cast<uintptr_t>(successor_block_info));
689 InsertGrowableList(cu, catch_block->predecessors,
690 reinterpret_cast<uintptr_t>(cur_block));
buzbee67bf8852011-08-17 17:51:35 -0700691 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700692 } else {
buzbeefa57c472012-11-21 12:06:18 -0800693 BasicBlock *eh_block = NewMemBB(cu, kExceptionHandling,
694 cu->num_blocks++);
695 cur_block->taken = eh_block;
696 InsertGrowableList(cu, &cu->block_list, reinterpret_cast<uintptr_t>(eh_block));
697 eh_block->start_offset = cur_offset;
698 InsertGrowableList(cu, eh_block->predecessors, reinterpret_cast<uintptr_t>(cur_block));
Bill Buzbeea114add2012-05-03 15:00:40 -0700699 }
700
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700701 if (insn->dalvikInsn.opcode == Instruction::THROW){
buzbeefa57c472012-11-21 12:06:18 -0800702 cur_block->explicit_throw = true;
703 if ((code_ptr < code_end) && ContentIsInsn(code_ptr)) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700704 // Force creation of new block following THROW via side-effect
buzbeefa57c472012-11-21 12:06:18 -0800705 FindBlock(cu, cur_offset + width, /* split */ false,
706 /* create */ true, /* immed_pred_block_p */ NULL);
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700707 }
buzbeefa57c472012-11-21 12:06:18 -0800708 if (!in_try_block) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700709 // Don't split a THROW that can't rethrow - we're done.
buzbeefa57c472012-11-21 12:06:18 -0800710 return cur_block;
Bill Buzbeea114add2012-05-03 15:00:40 -0700711 }
712 }
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700713
714 /*
715 * Split the potentially-throwing instruction into two parts.
716 * The first half will be a pseudo-op that captures the exception
717 * edges and terminates the basic block. It always falls through.
718 * Then, create a new basic block that begins with the throwing instruction
719 * (minus exceptions). Note: this new basic block must NOT be entered into
buzbeefa57c472012-11-21 12:06:18 -0800720 * the block_map. If the potentially-throwing instruction is the target of a
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700721 * future branch, we need to find the check psuedo half. The new
722 * basic block containing the work portion of the instruction should
723 * only be entered via fallthrough from the block containing the
724 * pseudo exception edge MIR. Note also that this new block is
725 * not automatically terminated after the work portion, and may
726 * contain following instructions.
727 */
buzbeefa57c472012-11-21 12:06:18 -0800728 BasicBlock *new_block = NewMemBB(cu, kDalvikByteCode, cu->num_blocks++);
729 InsertGrowableList(cu, &cu->block_list, reinterpret_cast<uintptr_t>(new_block));
730 new_block->start_offset = insn->offset;
731 cur_block->fall_through = new_block;
732 InsertGrowableList(cu, new_block->predecessors, reinterpret_cast<uintptr_t>(cur_block));
733 MIR* new_insn = static_cast<MIR*>(NewMem(cu, sizeof(MIR), true, kAllocMIR));
734 *new_insn = *insn;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700735 insn->dalvikInsn.opcode =
736 static_cast<Instruction::Code>(kMirOpCheck);
737 // Associate the two halves
buzbeefa57c472012-11-21 12:06:18 -0800738 insn->meta.throw_insn = new_insn;
739 new_insn->meta.throw_insn = insn;
740 AppendMIR(new_block, new_insn);
741 return new_block;
buzbee67bf8852011-08-17 17:51:35 -0700742}
743
buzbeefa57c472012-11-21 12:06:18 -0800744void CompilerInit(CompilationUnit* cu, const Compiler& compiler) {
buzbee02031b12012-11-23 09:41:35 -0800745 bool success = false;
746 switch (compiler.GetInstructionSet()) {
747 case kThumb2:
748 success = InitArmCodegen(cu);
749 break;
750 case kMips:
751 success = InitMipsCodegen(cu);
752 break;
753 case kX86:
754 success = InitX86Codegen(cu);
755 break;
756 default:;
757 }
758 if (!success) {
759 LOG(FATAL) << "Failed to initialize codegen for " << compiler.GetInstructionSet();
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800760 }
buzbeefa57c472012-11-21 12:06:18 -0800761 if (!HeapInit(cu)) {
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800762 LOG(FATAL) << "Failed to initialize oat heap";
763 }
764}
765
buzbee52a77fc2012-11-20 19:50:46 -0800766static CompiledMethod* CompileMethod(Compiler& compiler,
buzbeefa57c472012-11-21 12:06:18 -0800767 const CompilerBackend compiler_backend,
buzbee52a77fc2012-11-20 19:50:46 -0800768 const DexFile::CodeItem* code_item,
769 uint32_t access_flags, InvokeType invoke_type,
770 uint32_t method_idx, jobject class_loader,
771 const DexFile& dex_file,
772 LLVMInfo* llvm_info)
buzbee67bf8852011-08-17 17:51:35 -0700773{
Bill Buzbeea114add2012-05-03 15:00:40 -0700774 VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
Brian Carlstrom94496d32011-08-22 09:22:47 -0700775
buzbeefa57c472012-11-21 12:06:18 -0800776 const uint16_t* code_ptr = code_item->insns_;
777 const uint16_t* code_end = code_item->insns_ + code_item->insns_size_in_code_units_;
778 int num_blocks = 0;
779 unsigned int cur_offset = 0;
buzbee67bf8852011-08-17 17:51:35 -0700780
Bill Buzbeea114add2012-05-03 15:00:40 -0700781 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
buzbeefa57c472012-11-21 12:06:18 -0800782 UniquePtr<CompilationUnit> cu(new CompilationUnit);
buzbeeba938cb2012-02-03 14:47:55 -0800783
buzbeefa57c472012-11-21 12:06:18 -0800784 CompilerInit(cu.get(), compiler);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800785
buzbeefa57c472012-11-21 12:06:18 -0800786 cu->compiler = &compiler;
787 cu->class_linker = class_linker;
788 cu->dex_file = &dex_file;
789 cu->method_idx = method_idx;
790 cu->code_item = code_item;
791 cu->access_flags = access_flags;
792 cu->invoke_type = invoke_type;
793 cu->shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
794 cu->instruction_set = compiler.GetInstructionSet();
795 cu->insns = code_item->insns_;
796 cu->insns_size = code_item->insns_size_in_code_units_;
797 cu->num_ins = code_item->ins_size_;
798 cu->num_regs = code_item->registers_size_ - cu->num_ins;
799 cu->num_outs = code_item->outs_size_;
800 DCHECK((cu->instruction_set == kThumb2) ||
801 (cu->instruction_set == kX86) ||
802 (cu->instruction_set == kMips));
803 if ((compiler_backend == kQuickGBC) || (compiler_backend == kPortable)) {
804 cu->gen_bitcode = true;
buzbee85eee022012-07-16 22:12:38 -0700805 }
buzbeefa57c472012-11-21 12:06:18 -0800806 DCHECK_NE(compiler_backend, kIceland); // TODO: remove when Portable/Iceland merge complete
buzbeec531cef2012-10-18 07:09:20 -0700807 // TODO: remove this once x86 is tested
buzbeefa57c472012-11-21 12:06:18 -0800808 if (cu->gen_bitcode && (cu->instruction_set != kThumb2)) {
buzbeec531cef2012-10-18 07:09:20 -0700809 UNIMPLEMENTED(WARNING) << "GBC generation untested for non-Thumb targets";
810 }
buzbeefa57c472012-11-21 12:06:18 -0800811 cu->llvm_info = llvm_info;
Bill Buzbeea114add2012-05-03 15:00:40 -0700812 /* Adjust this value accordingly once inlining is performed */
buzbeefa57c472012-11-21 12:06:18 -0800813 cu->num_dalvik_registers = code_item->registers_size_;
Bill Buzbeea114add2012-05-03 15:00:40 -0700814 // TODO: set this from command line
buzbeefa57c472012-11-21 12:06:18 -0800815 cu->compiler_flip_match = false;
816 bool use_match = !cu->compiler_method_match.empty();
817 bool match = use_match && (cu->compiler_flip_match ^
818 (PrettyMethod(method_idx, dex_file).find(cu->compiler_method_match) !=
Bill Buzbeea114add2012-05-03 15:00:40 -0700819 std::string::npos));
buzbeefa57c472012-11-21 12:06:18 -0800820 if (!use_match || match) {
821 cu->disable_opt = kCompilerOptimizerDisableFlags;
822 cu->enable_debug = kCompilerDebugFlags;
823 cu->verbose = VLOG_IS_ON(compiler) ||
824 (cu->enable_debug & (1 << kDebugVerbose));
Bill Buzbeea114add2012-05-03 15:00:40 -0700825 }
buzbee6459e7c2012-10-02 14:42:41 -0700826#ifndef NDEBUG
buzbeefa57c472012-11-21 12:06:18 -0800827 if (cu->gen_bitcode) {
828 cu->enable_debug |= (1 << kDebugVerifyBitcode);
buzbee6969d502012-06-15 16:40:31 -0700829 }
buzbee2cfc6392012-05-07 14:51:40 -0700830#endif
buzbee9281f002012-10-24 12:17:24 -0700831
buzbeefa57c472012-11-21 12:06:18 -0800832 if (cu->instruction_set == kMips) {
jeffhao7fbee072012-08-24 17:56:54 -0700833 // Disable some optimizations for mips for now
buzbeefa57c472012-11-21 12:06:18 -0800834 cu->disable_opt |= (
jeffhao7fbee072012-08-24 17:56:54 -0700835 (1 << kLoadStoreElimination) |
836 (1 << kLoadHoisting) |
837 (1 << kSuppressLoads) |
838 (1 << kNullCheckElimination) |
839 (1 << kPromoteRegs) |
840 (1 << kTrackLiveTemps) |
841 (1 << kSkipLargeMethodOptimization) |
842 (1 << kSafeOptimizations) |
843 (1 << kBBOpt) |
844 (1 << kMatch) |
845 (1 << kPromoteCompilerTemps));
846 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700847
848 /* Gathering opcode stats? */
849 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
buzbeefa57c472012-11-21 12:06:18 -0800850 cu->opcode_count =
851 static_cast<int*>(NewMem(cu.get(), kNumPackedOpcodes * sizeof(int), true, kAllocMisc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700852 }
853
854 /* Assume non-throwing leaf */
buzbeefa57c472012-11-21 12:06:18 -0800855 cu->attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE);
Bill Buzbeea114add2012-05-03 15:00:40 -0700856
buzbeefa57c472012-11-21 12:06:18 -0800857 /* Initialize the block list, estimate size based on insns_size */
858 CompilerInitGrowableList(cu.get(), &cu->block_list, cu->insns_size,
Bill Buzbeea114add2012-05-03 15:00:40 -0700859 kListBlockList);
860
buzbeefa57c472012-11-21 12:06:18 -0800861 /* Initialize the switch_tables list */
862 CompilerInitGrowableList(cu.get(), &cu->switch_tables, 4,
Bill Buzbeea114add2012-05-03 15:00:40 -0700863 kListSwitchTables);
864
buzbeefa57c472012-11-21 12:06:18 -0800865 /* Intialize the fill_array_data list */
866 CompilerInitGrowableList(cu.get(), &cu->fill_array_data, 4,
Bill Buzbeea114add2012-05-03 15:00:40 -0700867 kListFillArrayData);
868
buzbeefa57c472012-11-21 12:06:18 -0800869 /* Intialize the throw_launchpads list, estimate size based on insns_size */
870 CompilerInitGrowableList(cu.get(), &cu->throw_launchpads, cu->insns_size,
Bill Buzbeea114add2012-05-03 15:00:40 -0700871 kListThrowLaunchPads);
872
buzbeefa57c472012-11-21 12:06:18 -0800873 /* Intialize the instrinsic_launchpads list */
874 CompilerInitGrowableList(cu.get(), &cu->intrinsic_launchpads, 4,
Bill Buzbeea114add2012-05-03 15:00:40 -0700875 kListMisc);
876
877
buzbeefa57c472012-11-21 12:06:18 -0800878 /* Intialize the suspend_launchpads list */
879 CompilerInitGrowableList(cu.get(), &cu->suspend_launchpads, 2048,
Bill Buzbeea114add2012-05-03 15:00:40 -0700880 kListSuspendLaunchPads);
881
882 /* Allocate the bit-vector to track the beginning of basic blocks */
buzbeefa57c472012-11-21 12:06:18 -0800883 ArenaBitVector *try_block_addr = AllocBitVector(cu.get(),
884 cu->insns_size,
Bill Buzbeea114add2012-05-03 15:00:40 -0700885 true /* expandable */);
buzbeefa57c472012-11-21 12:06:18 -0800886 cu->try_block_addr = try_block_addr;
Bill Buzbeea114add2012-05-03 15:00:40 -0700887
888 /* Create the default entry and exit blocks and enter them to the list */
buzbeefa57c472012-11-21 12:06:18 -0800889 BasicBlock *entry_block = NewMemBB(cu.get(), kEntryBlock, num_blocks++);
890 BasicBlock *exit_block = NewMemBB(cu.get(), kExitBlock, num_blocks++);
Bill Buzbeea114add2012-05-03 15:00:40 -0700891
buzbeefa57c472012-11-21 12:06:18 -0800892 cu->entry_block = entry_block;
893 cu->exit_block = exit_block;
Bill Buzbeea114add2012-05-03 15:00:40 -0700894
buzbeefa57c472012-11-21 12:06:18 -0800895 InsertGrowableList(cu.get(), &cu->block_list, reinterpret_cast<uintptr_t>(entry_block));
896 InsertGrowableList(cu.get(), &cu->block_list, reinterpret_cast<uintptr_t>(exit_block));
Bill Buzbeea114add2012-05-03 15:00:40 -0700897
898 /* Current block to record parsed instructions */
buzbeefa57c472012-11-21 12:06:18 -0800899 BasicBlock *cur_block = NewMemBB(cu.get(), kDalvikByteCode, num_blocks++);
900 cur_block->start_offset = 0;
901 InsertGrowableList(cu.get(), &cu->block_list, reinterpret_cast<uintptr_t>(cur_block));
Bill Buzbeea114add2012-05-03 15:00:40 -0700902 /* Add first block to the fast lookup cache */
buzbeefa57c472012-11-21 12:06:18 -0800903 cu->block_map.Put(cur_block->start_offset, cur_block);
904 entry_block->fall_through = cur_block;
905 InsertGrowableList(cu.get(), cur_block->predecessors,
906 reinterpret_cast<uintptr_t>(entry_block));
Bill Buzbeea114add2012-05-03 15:00:40 -0700907
908 /*
909 * Store back the number of blocks since new blocks may be created of
buzbeefa57c472012-11-21 12:06:18 -0800910 * accessing cu.
Bill Buzbeea114add2012-05-03 15:00:40 -0700911 */
buzbeefa57c472012-11-21 12:06:18 -0800912 cu->num_blocks = num_blocks;
Bill Buzbeea114add2012-05-03 15:00:40 -0700913
914 /* Identify code range in try blocks and set up the empty catch blocks */
buzbeefa57c472012-11-21 12:06:18 -0800915 ProcessTryCatchBlocks(cu.get());
Bill Buzbeea114add2012-05-03 15:00:40 -0700916
917 /* Set up for simple method detection */
buzbeefa57c472012-11-21 12:06:18 -0800918 int num_patterns = sizeof(special_patterns)/sizeof(special_patterns[0]);
919 bool live_pattern = (num_patterns > 0) && !(cu->disable_opt & (1 << kMatch));
920 bool* dead_pattern =
921 static_cast<bool*>(NewMem(cu.get(), sizeof(bool) * num_patterns, true, kAllocMisc));
922 SpecialCaseHandler special_case = kNoHandler;
923 int pattern_pos = 0;
Bill Buzbeea114add2012-05-03 15:00:40 -0700924
925 /* Parse all instructions and put them into containing basic blocks */
buzbeefa57c472012-11-21 12:06:18 -0800926 while (code_ptr < code_end) {
927 MIR *insn = static_cast<MIR *>(NewMem(cu.get(), sizeof(MIR), true, kAllocMIR));
928 insn->offset = cur_offset;
buzbeea169e1d2012-12-05 14:26:44 -0800929 int width = ParseInsn(cu.get(), code_ptr, &insn->dalvikInsn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700930 insn->width = width;
931 Instruction::Code opcode = insn->dalvikInsn.opcode;
buzbeefa57c472012-11-21 12:06:18 -0800932 if (cu->opcode_count != NULL) {
933 cu->opcode_count[static_cast<int>(opcode)]++;
buzbee44b412b2012-02-04 08:50:53 -0800934 }
935
Bill Buzbeea114add2012-05-03 15:00:40 -0700936 /* Terminate when the data section is seen */
937 if (width == 0)
938 break;
939
940 /* Possible simple method? */
buzbeefa57c472012-11-21 12:06:18 -0800941 if (live_pattern) {
942 live_pattern = false;
943 special_case = kNoHandler;
944 for (int i = 0; i < num_patterns; i++) {
945 if (!dead_pattern[i]) {
946 if (special_patterns[i].opcodes[pattern_pos] == opcode) {
947 live_pattern = true;
948 special_case = special_patterns[i].handler_code;
Bill Buzbeea114add2012-05-03 15:00:40 -0700949 } else {
buzbeefa57c472012-11-21 12:06:18 -0800950 dead_pattern[i] = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700951 }
952 }
953 }
buzbeefa57c472012-11-21 12:06:18 -0800954 pattern_pos++;
buzbeea7c12682012-03-19 13:13:53 -0700955 }
956
buzbeefa57c472012-11-21 12:06:18 -0800957 AppendMIR(cur_block, insn);
buzbeecefd1872011-09-09 09:59:52 -0700958
buzbeefa57c472012-11-21 12:06:18 -0800959 code_ptr += width;
Ian Rogersa75a0132012-09-28 11:41:42 -0700960 int flags = Instruction::FlagsOf(insn->dalvikInsn.opcode);
buzbee67bf8852011-08-17 17:51:35 -0700961
buzbeefa57c472012-11-21 12:06:18 -0800962 int df_flags = oat_data_flow_attributes[insn->dalvikInsn.opcode];
buzbee67bf8852011-08-17 17:51:35 -0700963
buzbeefa57c472012-11-21 12:06:18 -0800964 if (df_flags & DF_HAS_DEFS) {
965 cu->def_count += (df_flags & DF_A_WIDE) ? 2 : 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700966 }
buzbee67bf8852011-08-17 17:51:35 -0700967
Bill Buzbeea114add2012-05-03 15:00:40 -0700968 if (flags & Instruction::kBranch) {
buzbeefa57c472012-11-21 12:06:18 -0800969 cur_block = ProcessCanBranch(cu.get(), cur_block, insn, cur_offset,
970 width, flags, code_ptr, code_end);
Bill Buzbeea114add2012-05-03 15:00:40 -0700971 } else if (flags & Instruction::kReturn) {
buzbeefa57c472012-11-21 12:06:18 -0800972 cur_block->fall_through = exit_block;
973 InsertGrowableList(cu.get(), exit_block->predecessors,
974 reinterpret_cast<uintptr_t>(cur_block));
Bill Buzbeea114add2012-05-03 15:00:40 -0700975 /*
976 * Terminate the current block if there are instructions
977 * afterwards.
978 */
buzbeefa57c472012-11-21 12:06:18 -0800979 if (code_ptr < code_end) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700980 /*
981 * Create a fallthrough block for real instructions
982 * (incl. NOP).
983 */
buzbeefa57c472012-11-21 12:06:18 -0800984 if (ContentIsInsn(code_ptr)) {
985 FindBlock(cu.get(), cur_offset + width,
Bill Buzbeea114add2012-05-03 15:00:40 -0700986 /* split */
987 false,
988 /* create */
989 true,
buzbeefa57c472012-11-21 12:06:18 -0800990 /* immed_pred_block_p */
Bill Buzbeea114add2012-05-03 15:00:40 -0700991 NULL);
992 }
993 }
994 } else if (flags & Instruction::kThrow) {
buzbeefa57c472012-11-21 12:06:18 -0800995 cur_block = ProcessCanThrow(cu.get(), cur_block, insn, cur_offset,
996 width, flags, try_block_addr, code_ptr, code_end);
Bill Buzbeea114add2012-05-03 15:00:40 -0700997 } else if (flags & Instruction::kSwitch) {
buzbeefa57c472012-11-21 12:06:18 -0800998 ProcessCanSwitch(cu.get(), cur_block, insn, cur_offset, width, flags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700999 }
buzbeefa57c472012-11-21 12:06:18 -08001000 cur_offset += width;
1001 BasicBlock *next_block = FindBlock(cu.get(), cur_offset,
Bill Buzbeea114add2012-05-03 15:00:40 -07001002 /* split */
1003 false,
1004 /* create */
1005 false,
buzbeefa57c472012-11-21 12:06:18 -08001006 /* immed_pred_block_p */
Bill Buzbeea114add2012-05-03 15:00:40 -07001007 NULL);
buzbeefa57c472012-11-21 12:06:18 -08001008 if (next_block) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001009 /*
1010 * The next instruction could be the target of a previously parsed
1011 * forward branch so a block is already created. If the current
1012 * instruction is not an unconditional branch, connect them through
1013 * the fall-through link.
1014 */
buzbeefa57c472012-11-21 12:06:18 -08001015 DCHECK(cur_block->fall_through == NULL ||
1016 cur_block->fall_through == next_block ||
1017 cur_block->fall_through == exit_block);
buzbee5ade1d22011-09-09 14:44:52 -07001018
buzbeefa57c472012-11-21 12:06:18 -08001019 if ((cur_block->fall_through == NULL) && (flags & Instruction::kContinue)) {
1020 cur_block->fall_through = next_block;
1021 InsertGrowableList(cu.get(), next_block->predecessors,
1022 reinterpret_cast<uintptr_t>(cur_block));
Bill Buzbeea114add2012-05-03 15:00:40 -07001023 }
buzbeefa57c472012-11-21 12:06:18 -08001024 cur_block = next_block;
Bill Buzbeea114add2012-05-03 15:00:40 -07001025 }
1026 }
buzbeefc9e6fa2012-03-23 15:14:29 -07001027
buzbeefa57c472012-11-21 12:06:18 -08001028 if (!(cu->disable_opt & (1 << kSkipLargeMethodOptimization))) {
1029 if ((cu->num_blocks > MANY_BLOCKS) ||
1030 ((cu->num_blocks > MANY_BLOCKS_INITIALIZER) &&
Bill Buzbeea114add2012-05-03 15:00:40 -07001031 PrettyMethod(method_idx, dex_file, false).find("init>") !=
1032 std::string::npos)) {
buzbeefa57c472012-11-21 12:06:18 -08001033 cu->qd_mode = true;
Bill Buzbeea114add2012-05-03 15:00:40 -07001034 }
1035 }
buzbeefc9e6fa2012-03-23 15:14:29 -07001036
buzbeefa57c472012-11-21 12:06:18 -08001037 if (cu->qd_mode) {
buzbeed1643e42012-09-05 14:06:51 -07001038 // Bitcode generation requires full dataflow analysis
buzbeefa57c472012-11-21 12:06:18 -08001039 cu->disable_dataflow = !cu->gen_bitcode;
Bill Buzbeea114add2012-05-03 15:00:40 -07001040 // Disable optimization which require dataflow/ssa
buzbeefa57c472012-11-21 12:06:18 -08001041 cu->disable_opt |= (1 << kBBOpt) | (1 << kPromoteRegs) | (1 << kNullCheckElimination);
1042 if (cu->verbose) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001043 LOG(INFO) << "QD mode enabled: "
1044 << PrettyMethod(method_idx, dex_file)
buzbeefa57c472012-11-21 12:06:18 -08001045 << " num blocks: " << cu->num_blocks;
Bill Buzbeea114add2012-05-03 15:00:40 -07001046 }
1047 }
buzbeec1f45042011-09-21 16:03:19 -07001048
buzbeefa57c472012-11-21 12:06:18 -08001049 if (cu->verbose) {
1050 DumpCompilationUnit(cu.get());
Bill Buzbeea114add2012-05-03 15:00:40 -07001051 }
buzbee67bf8852011-08-17 17:51:35 -07001052
buzbee0967a252012-09-14 10:43:54 -07001053 /* Do a code layout pass */
buzbeefa57c472012-11-21 12:06:18 -08001054 CodeLayout(cu.get());
buzbee0967a252012-09-14 10:43:54 -07001055
buzbeefa57c472012-11-21 12:06:18 -08001056 if (cu->enable_debug & (1 << kDebugVerifyDataflow)) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001057 /* Verify if all blocks are connected as claimed */
buzbeefa57c472012-11-21 12:06:18 -08001058 DataFlowAnalysisDispatcher(cu.get(), VerifyPredInfo, kAllNodes,
1059 false /* is_iterative */);
Bill Buzbeea114add2012-05-03 15:00:40 -07001060 }
buzbee67bf8852011-08-17 17:51:35 -07001061
Bill Buzbeea114add2012-05-03 15:00:40 -07001062 /* Perform SSA transformation for the whole method */
buzbeefa57c472012-11-21 12:06:18 -08001063 SSATransformation(cu.get());
buzbee67bf8852011-08-17 17:51:35 -07001064
buzbee2cfc6392012-05-07 14:51:40 -07001065 /* Do constant propagation */
1066 // TODO: Probably need to make these expandable to support new ssa names
1067 // introducted during MIR optimization passes
buzbeefa57c472012-11-21 12:06:18 -08001068 cu->is_constant_v = AllocBitVector(cu.get(), cu->num_ssa_regs,
buzbee2cfc6392012-05-07 14:51:40 -07001069 false /* not expandable */);
buzbeefa57c472012-11-21 12:06:18 -08001070 cu->constant_values =
1071 static_cast<int*>(NewMem(cu.get(), sizeof(int) * cu->num_ssa_regs, true, kAllocDFInfo));
1072 DataFlowAnalysisDispatcher(cu.get(), DoConstantPropogation,
buzbee2cfc6392012-05-07 14:51:40 -07001073 kAllNodes,
buzbeefa57c472012-11-21 12:06:18 -08001074 false /* is_iterative */);
buzbee2cfc6392012-05-07 14:51:40 -07001075
Bill Buzbeea114add2012-05-03 15:00:40 -07001076 /* Detect loops */
buzbeefa57c472012-11-21 12:06:18 -08001077 LoopDetection(cu.get());
buzbee67bf8852011-08-17 17:51:35 -07001078
Bill Buzbeea114add2012-05-03 15:00:40 -07001079 /* Count uses */
buzbeefa57c472012-11-21 12:06:18 -08001080 MethodUseCount(cu.get());
buzbee67bf8852011-08-17 17:51:35 -07001081
Bill Buzbeea114add2012-05-03 15:00:40 -07001082 /* Perform null check elimination */
buzbeefa57c472012-11-21 12:06:18 -08001083 NullCheckElimination(cu.get());
Bill Buzbeea114add2012-05-03 15:00:40 -07001084
buzbeed1643e42012-09-05 14:06:51 -07001085 /* Combine basic blocks where possible */
buzbeefa57c472012-11-21 12:06:18 -08001086 BasicBlockCombine(cu.get());
buzbeed1643e42012-09-05 14:06:51 -07001087
Bill Buzbeea114add2012-05-03 15:00:40 -07001088 /* Do some basic block optimizations */
buzbeefa57c472012-11-21 12:06:18 -08001089 BasicBlockOptimization(cu.get());
Bill Buzbeea114add2012-05-03 15:00:40 -07001090
buzbeefa57c472012-11-21 12:06:18 -08001091 if (cu->enable_debug & (1 << kDebugDumpCheckStats)) {
1092 DumpCheckStats(cu.get());
buzbeed1643e42012-09-05 14:06:51 -07001093 }
1094
buzbee02031b12012-11-23 09:41:35 -08001095 cu.get()->cg->CompilerInitializeRegAlloc(cu.get()); // Needs to happen after SSA naming
Bill Buzbeea114add2012-05-03 15:00:40 -07001096
1097 /* Allocate Registers using simple local allocation scheme */
buzbeefa57c472012-11-21 12:06:18 -08001098 SimpleRegAlloc(cu.get());
Bill Buzbeea114add2012-05-03 15:00:40 -07001099
buzbee2cfc6392012-05-07 14:51:40 -07001100 /* Go the LLVM path? */
buzbeefa57c472012-11-21 12:06:18 -08001101 if (cu->gen_bitcode) {
buzbee2cfc6392012-05-07 14:51:40 -07001102 // MIR->Bitcode
buzbeefa57c472012-11-21 12:06:18 -08001103 MethodMIR2Bitcode(cu.get());
1104 if (compiler_backend == kPortable) {
buzbeeabc4c6b2012-08-23 08:17:15 -07001105 // all done
buzbeefa57c472012-11-21 12:06:18 -08001106 ArenaReset(cu.get());
buzbeeabc4c6b2012-08-23 08:17:15 -07001107 return NULL;
1108 }
buzbee2cfc6392012-05-07 14:51:40 -07001109 // Bitcode->LIR
buzbeefa57c472012-11-21 12:06:18 -08001110 MethodBitcode2LIR(cu.get());
buzbee2cfc6392012-05-07 14:51:40 -07001111 } else {
buzbeefa57c472012-11-21 12:06:18 -08001112 if (special_case != kNoHandler) {
buzbee2cfc6392012-05-07 14:51:40 -07001113 /*
1114 * Custom codegen for special cases. If for any reason the
buzbeefa57c472012-11-21 12:06:18 -08001115 * special codegen doesn't succeed, cu->first_lir_insn will
buzbee2cfc6392012-05-07 14:51:40 -07001116 * set to NULL;
1117 */
buzbeefa57c472012-11-21 12:06:18 -08001118 SpecialMIR2LIR(cu.get(), special_case);
buzbee2cfc6392012-05-07 14:51:40 -07001119 }
buzbee67bf8852011-08-17 17:51:35 -07001120
buzbee2cfc6392012-05-07 14:51:40 -07001121 /* Convert MIR to LIR, etc. */
buzbeefa57c472012-11-21 12:06:18 -08001122 if (cu->first_lir_insn == NULL) {
1123 MethodMIR2LIR(cu.get());
buzbee2cfc6392012-05-07 14:51:40 -07001124 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001125 }
buzbee67bf8852011-08-17 17:51:35 -07001126
Bill Buzbeea114add2012-05-03 15:00:40 -07001127 // Debugging only
buzbeefa57c472012-11-21 12:06:18 -08001128 if (cu->enable_debug & (1 << kDebugDumpCFG)) {
1129 DumpCFG(cu.get(), "/sdcard/cfg/");
Bill Buzbeea114add2012-05-03 15:00:40 -07001130 }
buzbee16da88c2012-03-20 10:38:17 -07001131
Bill Buzbeea114add2012-05-03 15:00:40 -07001132 /* Method is not empty */
buzbeefa57c472012-11-21 12:06:18 -08001133 if (cu->first_lir_insn) {
buzbee67bf8852011-08-17 17:51:35 -07001134
Bill Buzbeea114add2012-05-03 15:00:40 -07001135 // mark the targets of switch statement case labels
buzbeefa57c472012-11-21 12:06:18 -08001136 ProcessSwitchTables(cu.get());
buzbee67bf8852011-08-17 17:51:35 -07001137
Bill Buzbeea114add2012-05-03 15:00:40 -07001138 /* Convert LIR into machine code. */
buzbeefa57c472012-11-21 12:06:18 -08001139 AssembleLIR(cu.get());
buzbee99ba9642012-01-25 14:23:14 -08001140
buzbeefa57c472012-11-21 12:06:18 -08001141 if (cu->verbose) {
1142 CodegenDump(cu.get());
buzbee67bf8852011-08-17 17:51:35 -07001143 }
1144
buzbeefa57c472012-11-21 12:06:18 -08001145 if (cu->opcode_count != NULL) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001146 LOG(INFO) << "Opcode Count";
1147 for (int i = 0; i < kNumPackedOpcodes; i++) {
buzbeefa57c472012-11-21 12:06:18 -08001148 if (cu->opcode_count[i] != 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001149 LOG(INFO) << "-C- "
1150 << Instruction::Name(static_cast<Instruction::Code>(i))
buzbeefa57c472012-11-21 12:06:18 -08001151 << " " << cu->opcode_count[i];
buzbee67bf8852011-08-17 17:51:35 -07001152 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001153 }
1154 }
1155 }
buzbeea7c12682012-03-19 13:13:53 -07001156
buzbeefa57c472012-11-21 12:06:18 -08001157 // Combine vmap tables - core regs, then fp regs - into vmap_table
1158 std::vector<uint16_t> vmap_table;
buzbeeca7a5e42012-08-20 11:12:18 -07001159 // Core regs may have been inserted out of order - sort first
buzbeefa57c472012-11-21 12:06:18 -08001160 std::sort(cu->core_vmap_table.begin(), cu->core_vmap_table.end());
1161 for (size_t i = 0 ; i < cu->core_vmap_table.size(); i++) {
buzbeeca7a5e42012-08-20 11:12:18 -07001162 // Copy, stripping out the phys register sort key
buzbeefa57c472012-11-21 12:06:18 -08001163 vmap_table.push_back(~(-1 << VREG_NUM_WIDTH) & cu->core_vmap_table[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001164 }
1165 // If we have a frame, push a marker to take place of lr
buzbeefa57c472012-11-21 12:06:18 -08001166 if (cu->frame_size > 0) {
1167 vmap_table.push_back(INVALID_VREG);
Bill Buzbeea114add2012-05-03 15:00:40 -07001168 } else {
buzbeefa57c472012-11-21 12:06:18 -08001169 DCHECK_EQ(__builtin_popcount(cu->core_spill_mask), 0);
1170 DCHECK_EQ(__builtin_popcount(cu->fp_spill_mask), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -07001171 }
buzbeeca7a5e42012-08-20 11:12:18 -07001172 // Combine vmap tables - core regs, then fp regs. fp regs already sorted
buzbeefa57c472012-11-21 12:06:18 -08001173 for (uint32_t i = 0; i < cu->fp_vmap_table.size(); i++) {
1174 vmap_table.push_back(cu->fp_vmap_table[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001175 }
1176 CompiledMethod* result =
buzbeefa57c472012-11-21 12:06:18 -08001177 new CompiledMethod(cu->instruction_set, cu->code_buffer,
1178 cu->frame_size, cu->core_spill_mask, cu->fp_spill_mask,
1179 cu->combined_mapping_table, vmap_table, cu->native_gc_map);
buzbee67bf8852011-08-17 17:51:35 -07001180
Bill Buzbeea114add2012-05-03 15:00:40 -07001181 VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file)
buzbeefa57c472012-11-21 12:06:18 -08001182 << " (" << (cu->code_buffer.size() * sizeof(cu->code_buffer[0]))
Bill Buzbeea114add2012-05-03 15:00:40 -07001183 << " bytes)";
buzbee5abfa3e2012-01-31 17:01:43 -08001184
1185#ifdef WITH_MEMSTATS
buzbeefa57c472012-11-21 12:06:18 -08001186 if (cu->enable_debug & (1 << kDebugShowMemoryUsage)) {
1187 DumpMemStats(cu.get());
Bill Buzbeea114add2012-05-03 15:00:40 -07001188 }
buzbee5abfa3e2012-01-31 17:01:43 -08001189#endif
buzbee67bf8852011-08-17 17:51:35 -07001190
buzbeefa57c472012-11-21 12:06:18 -08001191 ArenaReset(cu.get());
buzbeeba938cb2012-02-03 14:47:55 -08001192
Bill Buzbeea114add2012-05-03 15:00:40 -07001193 return result;
buzbee67bf8852011-08-17 17:51:35 -07001194}
1195
buzbee52a77fc2012-11-20 19:50:46 -08001196CompiledMethod* CompileOneMethod(Compiler& compiler,
buzbeec531cef2012-10-18 07:09:20 -07001197 const CompilerBackend backend,
buzbeeabc4c6b2012-08-23 08:17:15 -07001198 const DexFile::CodeItem* code_item,
1199 uint32_t access_flags, InvokeType invoke_type,
1200 uint32_t method_idx, jobject class_loader,
buzbeec531cef2012-10-18 07:09:20 -07001201 const DexFile& dex_file,
buzbeefa57c472012-11-21 12:06:18 -08001202 LLVMInfo* llvm_info)
buzbeeabc4c6b2012-08-23 08:17:15 -07001203{
buzbee52a77fc2012-11-20 19:50:46 -08001204 return CompileMethod(compiler, backend, code_item, access_flags, invoke_type, method_idx, class_loader,
buzbeefa57c472012-11-21 12:06:18 -08001205 dex_file, llvm_info);
buzbeeabc4c6b2012-08-23 08:17:15 -07001206}
1207
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001208} // namespace art
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001209
Bill Buzbeea114add2012-05-03 15:00:40 -07001210extern "C" art::CompiledMethod*
buzbeec531cef2012-10-18 07:09:20 -07001211 ArtQuickCompileMethod(art::Compiler& compiler,
1212 const art::DexFile::CodeItem* code_item,
1213 uint32_t access_flags, art::InvokeType invoke_type,
1214 uint32_t method_idx, jobject class_loader,
1215 const art::DexFile& dex_file)
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001216{
buzbeec531cef2012-10-18 07:09:20 -07001217 // TODO: check method fingerprint here to determine appropriate backend type. Until then, use build default
1218 art::CompilerBackend backend = compiler.GetCompilerBackend();
buzbee52a77fc2012-11-20 19:50:46 -08001219 return art::CompileOneMethod(compiler, backend, code_item, access_flags, invoke_type,
buzbeefa57c472012-11-21 12:06:18 -08001220 method_idx, class_loader, dex_file, NULL /* use thread llvm_info */);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -08001221}