mir_graph.cc revision 5816ed48bc339c983b40dc493e96b97821ce7966
1311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* 2311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Copyright (C) 2013 The Android Open Source Project 3311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * 4311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Licensed under the Apache License, Version 2.0 (the "License"); 5311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * you may not use this file except in compliance with the License. 6311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * You may obtain a copy of the License at 7311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * 8311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * http://www.apache.org/licenses/LICENSE-2.0 9311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * 10311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Unless required by applicable law or agreed to in writing, software 11311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * distributed under the License is distributed on an "AS IS" BASIS, 12311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * See the License for the specific language governing permissions and 14311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * limitations under the License. 15311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee */ 16311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 176282dc12440a2072dc06a616160027ff21bd895eIan Rogers#include "base/stl_util.h" 18311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee#include "compiler_internals.h" 19311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee#include "dex_file-inl.h" 206282dc12440a2072dc06a616160027ff21bd895eIan Rogers#include "leb128.h" 216282dc12440a2072dc06a616160027ff21bd895eIan Rogers#include "mir_graph.h" 22311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 235816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko#include "dex/quick/dex_file_to_method_inliner_map.h" 245816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko#include "dex/quick/dex_file_method_inliner.h" 255816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko 26311ca169f4727d46a55bdc8dfa0059719fa72b65buzbeenamespace art { 27311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 28311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee#define MAX_PATTERN_LEN 5 29311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 301fd3346740dfb7f47be9922312b68a4227fada96buzbeeconst char* MIRGraph::extended_mir_op_names_[kMirOpLast - kMirOpFirst] = { 311fd3346740dfb7f47be9922312b68a4227fada96buzbee "Phi", 321fd3346740dfb7f47be9922312b68a4227fada96buzbee "Copy", 331fd3346740dfb7f47be9922312b68a4227fada96buzbee "FusedCmplFloat", 341fd3346740dfb7f47be9922312b68a4227fada96buzbee "FusedCmpgFloat", 351fd3346740dfb7f47be9922312b68a4227fada96buzbee "FusedCmplDouble", 361fd3346740dfb7f47be9922312b68a4227fada96buzbee "FusedCmpgDouble", 371fd3346740dfb7f47be9922312b68a4227fada96buzbee "FusedCmpLong", 381fd3346740dfb7f47be9922312b68a4227fada96buzbee "Nop", 391fd3346740dfb7f47be9922312b68a4227fada96buzbee "OpNullCheck", 401fd3346740dfb7f47be9922312b68a4227fada96buzbee "OpRangeCheck", 411fd3346740dfb7f47be9922312b68a4227fada96buzbee "OpDivZeroCheck", 421fd3346740dfb7f47be9922312b68a4227fada96buzbee "Check1", 431fd3346740dfb7f47be9922312b68a4227fada96buzbee "Check2", 441fd3346740dfb7f47be9922312b68a4227fada96buzbee "Select", 451fd3346740dfb7f47be9922312b68a4227fada96buzbee}; 461fd3346740dfb7f47be9922312b68a4227fada96buzbee 47862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbeeMIRGraph::MIRGraph(CompilationUnit* cu, ArenaAllocator* arena) 481fd3346740dfb7f47be9922312b68a4227fada96buzbee : reg_location_(NULL), 49862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee compiler_temps_(arena, 6, kGrowableArrayMisc), 501fd3346740dfb7f47be9922312b68a4227fada96buzbee cu_(cu), 51311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee ssa_base_vregs_(NULL), 52311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee ssa_subscripts_(NULL), 53311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee vreg_to_ssa_map_(NULL), 54311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee ssa_last_defs_(NULL), 55311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee is_constant_v_(NULL), 56311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee constant_values_(NULL), 57862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee use_counts_(arena, 256, kGrowableArrayMisc), 58862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee raw_use_counts_(arena, 256, kGrowableArrayMisc), 59311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee num_reachable_blocks_(0), 60862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee dfs_order_(NULL), 61862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee dfs_post_order_(NULL), 62862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee dom_post_order_traversal_(NULL), 63311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee i_dom_list_(NULL), 64311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee def_block_matrix_(NULL), 65311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee temp_block_v_(NULL), 66311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee temp_dalvik_register_v_(NULL), 67311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee temp_ssa_register_v_(NULL), 68862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee block_list_(arena, 100, kGrowableArrayBlockList), 69311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee try_block_addr_(NULL), 70311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee entry_block_(NULL), 71311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee exit_block_(NULL), 72311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee num_blocks_(0), 73311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee current_code_item_(NULL), 74b48819db07f9a0992a72173380c24249d7fc648abuzbee dex_pc_to_block_map_(arena, 0, kGrowableArrayMisc), 75311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee current_method_(kInvalidEntry), 76311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee current_offset_(kInvalidEntry), 77311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee def_count_(0), 78311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee opcode_count_(NULL), 791fd3346740dfb7f47be9922312b68a4227fada96buzbee num_ssa_regs_(0), 801fd3346740dfb7f47be9922312b68a4227fada96buzbee method_sreg_(0), 81862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee attributes_(METHOD_IS_LEAF), // Start with leaf assumption, change on encountering invoke. 82862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee checkstats_(NULL), 83b48819db07f9a0992a72173380c24249d7fc648abuzbee arena_(arena), 84b48819db07f9a0992a72173380c24249d7fc648abuzbee backward_branches_(0), 85b48819db07f9a0992a72173380c24249d7fc648abuzbee forward_branches_(0) { 86862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee try_block_addr_ = new (arena_) ArenaBitVector(arena_, 0, true /* expandable */); 87311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee} 88311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 896282dc12440a2072dc06a616160027ff21bd895eIan RogersMIRGraph::~MIRGraph() { 906282dc12440a2072dc06a616160027ff21bd895eIan Rogers STLDeleteElements(&m_units_); 916282dc12440a2072dc06a616160027ff21bd895eIan Rogers} 926282dc12440a2072dc06a616160027ff21bd895eIan Rogers 93311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* 94311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Parse an instruction, return the length of the instruction 95311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee */ 962ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromint MIRGraph::ParseInsn(const uint16_t* code_ptr, DecodedInstruction* decoded_instruction) { 97311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee const Instruction* instruction = Instruction::At(code_ptr); 98311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee *decoded_instruction = DecodedInstruction(instruction); 99311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 100311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee return instruction->SizeInCodeUnits(); 101311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee} 102311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 103311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 104311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Split an existing block from the specified code offset into two */ 1050d82948094d9a198e01aa95f64012bdedd5b6fc9buzbeeBasicBlock* MIRGraph::SplitBlock(DexOffset code_offset, 1062ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom BasicBlock* orig_block, BasicBlock** immed_pred_block_p) { 1070d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee DCHECK_GT(code_offset, orig_block->start_offset); 108311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee MIR* insn = orig_block->first_mir_insn; 1090d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee MIR* prev = NULL; 110311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee while (insn) { 111311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (insn->offset == code_offset) break; 1120d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee prev = insn; 113311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee insn = insn->next; 114311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 115311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (insn == NULL) { 116311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee LOG(FATAL) << "Break split failed"; 117311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 118862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee BasicBlock *bottom_block = NewMemBB(kDalvikByteCode, num_blocks_++); 119862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee block_list_.Insert(bottom_block); 120311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 121311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee bottom_block->start_offset = code_offset; 122311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee bottom_block->first_mir_insn = insn; 123311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee bottom_block->last_mir_insn = orig_block->last_mir_insn; 124311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 125311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* If this block was terminated by a return, the flag needs to go with the bottom block */ 126311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee bottom_block->terminated_by_return = orig_block->terminated_by_return; 127311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee orig_block->terminated_by_return = false; 128311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 129311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* Add it to the quick lookup cache */ 130b48819db07f9a0992a72173380c24249d7fc648abuzbee dex_pc_to_block_map_.Put(bottom_block->start_offset, bottom_block->id); 131311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 132311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* Handle the taken path */ 133311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee bottom_block->taken = orig_block->taken; 1340d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee if (bottom_block->taken != NullBasicBlockId) { 1350d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee orig_block->taken = NullBasicBlockId; 1360d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee BasicBlock* bb_taken = GetBasicBlock(bottom_block->taken); 1370d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee bb_taken->predecessors->Delete(orig_block->id); 1380d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee bb_taken->predecessors->Insert(bottom_block->id); 139311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 140311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 141311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* Handle the fallthrough path */ 142311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee bottom_block->fall_through = orig_block->fall_through; 1430d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee orig_block->fall_through = bottom_block->id; 1440d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee bottom_block->predecessors->Insert(orig_block->id); 1450d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee if (bottom_block->fall_through != NullBasicBlockId) { 1460d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee BasicBlock* bb_fall_through = GetBasicBlock(bottom_block->fall_through); 1470d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee bb_fall_through->predecessors->Delete(orig_block->id); 1480d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee bb_fall_through->predecessors->Insert(bottom_block->id); 149311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 150311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 151311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* Handle the successor list */ 1520d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee if (orig_block->successor_block_list_type != kNotUsed) { 1530d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee bottom_block->successor_block_list_type = orig_block->successor_block_list_type; 1540d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee bottom_block->successor_blocks = orig_block->successor_blocks; 1550d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee orig_block->successor_block_list_type = kNotUsed; 1560d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee orig_block->successor_blocks = NULL; 1570d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee GrowableArray<SuccessorBlockInfo*>::Iterator iterator(bottom_block->successor_blocks); 158311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee while (true) { 159862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee SuccessorBlockInfo *successor_block_info = iterator.Next(); 160311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (successor_block_info == NULL) break; 1610d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee BasicBlock *bb = GetBasicBlock(successor_block_info->block); 1620d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee bb->predecessors->Delete(orig_block->id); 1630d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee bb->predecessors->Insert(bottom_block->id); 164311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 165311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 166311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 1670d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee orig_block->last_mir_insn = prev; 1680d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee prev->next = NULL; 169311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 170311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* 171311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Update the immediate predecessor block pointer so that outgoing edges 172311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * can be applied to the proper block. 173311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee */ 174311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (immed_pred_block_p) { 175311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee DCHECK_EQ(*immed_pred_block_p, orig_block); 176311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee *immed_pred_block_p = bottom_block; 177311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 178b48819db07f9a0992a72173380c24249d7fc648abuzbee 179b48819db07f9a0992a72173380c24249d7fc648abuzbee // Associate dex instructions in the bottom block with the new container. 180b48819db07f9a0992a72173380c24249d7fc648abuzbee MIR* p = bottom_block->first_mir_insn; 181b48819db07f9a0992a72173380c24249d7fc648abuzbee while (p != NULL) { 182b48819db07f9a0992a72173380c24249d7fc648abuzbee int opcode = p->dalvikInsn.opcode; 183b48819db07f9a0992a72173380c24249d7fc648abuzbee /* 184b48819db07f9a0992a72173380c24249d7fc648abuzbee * Some messiness here to ensure that we only enter real opcodes and only the 185b48819db07f9a0992a72173380c24249d7fc648abuzbee * first half of a potentially throwing instruction that has been split into 186b48819db07f9a0992a72173380c24249d7fc648abuzbee * CHECK and work portions. The 2nd half of a split operation will have a non-null 187b48819db07f9a0992a72173380c24249d7fc648abuzbee * throw_insn pointer that refers to the 1st half. 188b48819db07f9a0992a72173380c24249d7fc648abuzbee */ 189b48819db07f9a0992a72173380c24249d7fc648abuzbee if ((opcode == kMirOpCheck) || (!IsPseudoMirOp(opcode) && (p->meta.throw_insn == NULL))) { 190b48819db07f9a0992a72173380c24249d7fc648abuzbee dex_pc_to_block_map_.Put(p->offset, bottom_block->id); 191b48819db07f9a0992a72173380c24249d7fc648abuzbee } 192b48819db07f9a0992a72173380c24249d7fc648abuzbee p = (p == bottom_block->last_mir_insn) ? NULL : p->next; 193b48819db07f9a0992a72173380c24249d7fc648abuzbee } 194b48819db07f9a0992a72173380c24249d7fc648abuzbee 195311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee return bottom_block; 196311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee} 197311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 198311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* 199311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Given a code offset, find out the block that starts with it. If the offset 200311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * is in the middle of an existing block, split it into two. If immed_pred_block_p 201311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * is not non-null and is the block being split, update *immed_pred_block_p to 202311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * point to the bottom block so that outgoing edges can be set up properly 203311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * (by the caller) 204311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Utilizes a map for fast lookup of the typical cases. 205311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee */ 2060d82948094d9a198e01aa95f64012bdedd5b6fc9buzbeeBasicBlock* MIRGraph::FindBlock(DexOffset code_offset, bool split, bool create, 2072ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom BasicBlock** immed_pred_block_p) { 208bd663de599b16229085759366c56e2ed5a1dc7ecbuzbee if (code_offset >= cu_->code_item->insns_size_in_code_units_) { 209311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee return NULL; 210311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 211b48819db07f9a0992a72173380c24249d7fc648abuzbee 212b48819db07f9a0992a72173380c24249d7fc648abuzbee int block_id = dex_pc_to_block_map_.Get(code_offset); 213b48819db07f9a0992a72173380c24249d7fc648abuzbee BasicBlock* bb = (block_id == 0) ? NULL : block_list_.Get(block_id); 214b48819db07f9a0992a72173380c24249d7fc648abuzbee 215b48819db07f9a0992a72173380c24249d7fc648abuzbee if ((bb != NULL) && (bb->start_offset == code_offset)) { 216b48819db07f9a0992a72173380c24249d7fc648abuzbee // Does this containing block start with the desired instruction? 217bd663de599b16229085759366c56e2ed5a1dc7ecbuzbee return bb; 218bd663de599b16229085759366c56e2ed5a1dc7ecbuzbee } 219311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 220b48819db07f9a0992a72173380c24249d7fc648abuzbee // No direct hit. 221b48819db07f9a0992a72173380c24249d7fc648abuzbee if (!create) { 222b48819db07f9a0992a72173380c24249d7fc648abuzbee return NULL; 223b48819db07f9a0992a72173380c24249d7fc648abuzbee } 224b48819db07f9a0992a72173380c24249d7fc648abuzbee 225b48819db07f9a0992a72173380c24249d7fc648abuzbee if (bb != NULL) { 226b48819db07f9a0992a72173380c24249d7fc648abuzbee // The target exists somewhere in an existing block. 227b48819db07f9a0992a72173380c24249d7fc648abuzbee return SplitBlock(code_offset, bb, bb == *immed_pred_block_p ? immed_pred_block_p : NULL); 228311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 229311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 230b48819db07f9a0992a72173380c24249d7fc648abuzbee // Create a new block. 231862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee bb = NewMemBB(kDalvikByteCode, num_blocks_++); 232862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee block_list_.Insert(bb); 233311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee bb->start_offset = code_offset; 234b48819db07f9a0992a72173380c24249d7fc648abuzbee dex_pc_to_block_map_.Put(bb->start_offset, bb->id); 235311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee return bb; 236311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee} 237311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 238b48819db07f9a0992a72173380c24249d7fc648abuzbee 239311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Identify code range in try blocks and set up the empty catch blocks */ 2402ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::ProcessTryCatchBlocks() { 241311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee int tries_size = current_code_item_->tries_size_; 2420d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee DexOffset offset; 243311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 244311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (tries_size == 0) { 245311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee return; 246311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 247311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 248311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee for (int i = 0; i < tries_size; i++) { 249311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee const DexFile::TryItem* pTry = 250311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee DexFile::GetTryItems(*current_code_item_, i); 2510d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee DexOffset start_offset = pTry->start_addr_; 2520d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee DexOffset end_offset = start_offset + pTry->insn_count_; 253311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee for (offset = start_offset; offset < end_offset; offset++) { 254862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee try_block_addr_->SetBit(offset); 255311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 256311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 257311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 258311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee // Iterate over each of the handlers to enqueue the empty Catch blocks 259311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee const byte* handlers_ptr = DexFile::GetCatchHandlerData(*current_code_item_, 0); 260311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr); 261311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee for (uint32_t idx = 0; idx < handlers_size; idx++) { 262311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee CatchHandlerIterator iterator(handlers_ptr); 263311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee for (; iterator.HasNext(); iterator.Next()) { 264311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee uint32_t address = iterator.GetHandlerAddress(); 265311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee FindBlock(address, false /* split */, true /*create*/, 266311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* immed_pred_block_p */ NULL); 267311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 268311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee handlers_ptr = iterator.EndDataPointer(); 269311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 270311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee} 271311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 272311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Process instructions with the kBranch flag */ 2730d82948094d9a198e01aa95f64012bdedd5b6fc9buzbeeBasicBlock* MIRGraph::ProcessCanBranch(BasicBlock* cur_block, MIR* insn, DexOffset cur_offset, 2740d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee int width, int flags, const uint16_t* code_ptr, 2752ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom const uint16_t* code_end) { 2760d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee DexOffset target = cur_offset; 277311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee switch (insn->dalvikInsn.opcode) { 278311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee case Instruction::GOTO: 279311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee case Instruction::GOTO_16: 280311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee case Instruction::GOTO_32: 281311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee target += insn->dalvikInsn.vA; 282311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee break; 283311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee case Instruction::IF_EQ: 284311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee case Instruction::IF_NE: 285311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee case Instruction::IF_LT: 286311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee case Instruction::IF_GE: 287311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee case Instruction::IF_GT: 288311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee case Instruction::IF_LE: 289311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cur_block->conditional_branch = true; 290311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee target += insn->dalvikInsn.vC; 291311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee break; 292311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee case Instruction::IF_EQZ: 293311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee case Instruction::IF_NEZ: 294311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee case Instruction::IF_LTZ: 295311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee case Instruction::IF_GEZ: 296311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee case Instruction::IF_GTZ: 297311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee case Instruction::IF_LEZ: 298311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cur_block->conditional_branch = true; 299311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee target += insn->dalvikInsn.vB; 300311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee break; 301311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee default: 302311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee LOG(FATAL) << "Unexpected opcode(" << insn->dalvikInsn.opcode << ") with kBranch set"; 303311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 304b48819db07f9a0992a72173380c24249d7fc648abuzbee CountBranch(target); 305311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee BasicBlock *taken_block = FindBlock(target, /* split */ true, /* create */ true, 306311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* immed_pred_block_p */ &cur_block); 3070d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee cur_block->taken = taken_block->id; 3080d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee taken_block->predecessors->Insert(cur_block->id); 309311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 310311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* Always terminate the current block for conditional branches */ 311311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (flags & Instruction::kContinue) { 312311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee BasicBlock *fallthrough_block = FindBlock(cur_offset + width, 313311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* 314311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * If the method is processed 315311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * in sequential order from the 316311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * beginning, we don't need to 317311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * specify split for continue 318311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * blocks. However, this 319311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * routine can be called by 320311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * compileLoop, which starts 321311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * parsing the method from an 322311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * arbitrary address in the 323311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * method body. 324311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee */ 325311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee true, 326311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* create */ 327311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee true, 328311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* immed_pred_block_p */ 329311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee &cur_block); 3300d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee cur_block->fall_through = fallthrough_block->id; 3310d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee fallthrough_block->predecessors->Insert(cur_block->id); 332311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } else if (code_ptr < code_end) { 3332724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee FindBlock(cur_offset + width, /* split */ false, /* create */ true, 334311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* immed_pred_block_p */ NULL); 335311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 336311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee return cur_block; 337311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee} 338311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 339311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Process instructions with the kSwitch flag */ 34017189ac098b2f156713db1821b49db7b2f018bbebuzbeeBasicBlock* MIRGraph::ProcessCanSwitch(BasicBlock* cur_block, MIR* insn, DexOffset cur_offset, 34117189ac098b2f156713db1821b49db7b2f018bbebuzbee int width, int flags) { 342311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee const uint16_t* switch_data = 343311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee reinterpret_cast<const uint16_t*>(GetCurrentInsns() + cur_offset + insn->dalvikInsn.vB); 344311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee int size; 345311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee const int* keyTable; 346311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee const int* target_table; 347311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee int i; 348311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee int first_key; 349311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 350311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* 351311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Packed switch data format: 352311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * ushort ident = 0x0100 magic value 353311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * ushort size number of entries in the table 354311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * int first_key first (and lowest) switch case value 355311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * int targets[size] branch targets, relative to switch opcode 356311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * 357311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Total size is (4+size*2) 16-bit code units. 358311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee */ 359311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) { 360311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee DCHECK_EQ(static_cast<int>(switch_data[0]), 361311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee static_cast<int>(Instruction::kPackedSwitchSignature)); 362311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee size = switch_data[1]; 363311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee first_key = switch_data[2] | (switch_data[3] << 16); 364311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee target_table = reinterpret_cast<const int*>(&switch_data[4]); 365311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee keyTable = NULL; // Make the compiler happy 366311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* 367311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Sparse switch data format: 368311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * ushort ident = 0x0200 magic value 369311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * ushort size number of entries in the table; > 0 370311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * int keys[size] keys, sorted low-to-high; 32-bit aligned 371311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * int targets[size] branch targets, relative to switch opcode 372311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * 373311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Total size is (2+size*4) 16-bit code units. 374311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee */ 375311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } else { 376311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee DCHECK_EQ(static_cast<int>(switch_data[0]), 377311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee static_cast<int>(Instruction::kSparseSwitchSignature)); 378311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee size = switch_data[1]; 379311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee keyTable = reinterpret_cast<const int*>(&switch_data[2]); 380311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee target_table = reinterpret_cast<const int*>(&switch_data[2 + size*2]); 381311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee first_key = 0; // To make the compiler happy 382311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 383311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 3840d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee if (cur_block->successor_block_list_type != kNotUsed) { 385311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee LOG(FATAL) << "Successor block list already in use: " 3860d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee << static_cast<int>(cur_block->successor_block_list_type); 387311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 3880d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee cur_block->successor_block_list_type = 3890d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ? kPackedSwitch : kSparseSwitch; 3900d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee cur_block->successor_blocks = 391df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom new (arena_) GrowableArray<SuccessorBlockInfo*>(arena_, size, kGrowableArraySuccessorBlocks); 392311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 393311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee for (i = 0; i < size; i++) { 394311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee BasicBlock *case_block = FindBlock(cur_offset + target_table[i], /* split */ true, 395311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* create */ true, /* immed_pred_block_p */ &cur_block); 396311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee SuccessorBlockInfo *successor_block_info = 397f6c4b3ba3825de1dbb3e747a68b809c6cc8eb4dbMathieu Chartier static_cast<SuccessorBlockInfo*>(arena_->Alloc(sizeof(SuccessorBlockInfo), 398f6c4b3ba3825de1dbb3e747a68b809c6cc8eb4dbMathieu Chartier ArenaAllocator::kAllocSuccessor)); 3990d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee successor_block_info->block = case_block->id; 400311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee successor_block_info->key = 401311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ? 402311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee first_key + i : keyTable[i]; 4030d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee cur_block->successor_blocks->Insert(successor_block_info); 4040d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee case_block->predecessors->Insert(cur_block->id); 405311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 406311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 407311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* Fall-through case */ 408df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom BasicBlock* fallthrough_block = FindBlock(cur_offset + width, /* split */ false, 409df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom /* create */ true, /* immed_pred_block_p */ NULL); 4100d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee cur_block->fall_through = fallthrough_block->id; 4110d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee fallthrough_block->predecessors->Insert(cur_block->id); 41217189ac098b2f156713db1821b49db7b2f018bbebuzbee return cur_block; 413311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee} 414311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 415311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Process instructions with the kThrow flag */ 4160d82948094d9a198e01aa95f64012bdedd5b6fc9buzbeeBasicBlock* MIRGraph::ProcessCanThrow(BasicBlock* cur_block, MIR* insn, DexOffset cur_offset, 4170d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee int width, int flags, ArenaBitVector* try_block_addr, 4182ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom const uint16_t* code_ptr, const uint16_t* code_end) { 419862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee bool in_try_block = try_block_addr->IsBitSet(cur_offset); 42017189ac098b2f156713db1821b49db7b2f018bbebuzbee bool is_throw = (insn->dalvikInsn.opcode == Instruction::THROW); 42117189ac098b2f156713db1821b49db7b2f018bbebuzbee bool build_all_edges = 42217189ac098b2f156713db1821b49db7b2f018bbebuzbee (cu_->disable_opt & (1 << kSuppressExceptionEdges)) || is_throw || in_try_block; 423311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 424311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* In try block */ 425311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (in_try_block) { 426311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee CatchHandlerIterator iterator(*current_code_item_, cur_offset); 427311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 4280d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee if (cur_block->successor_block_list_type != kNotUsed) { 429311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee LOG(INFO) << PrettyMethod(cu_->method_idx, *cu_->dex_file); 430311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee LOG(FATAL) << "Successor block list already in use: " 4310d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee << static_cast<int>(cur_block->successor_block_list_type); 432311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 433311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 4340d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee cur_block->successor_block_list_type = kCatch; 4350d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee cur_block->successor_blocks = 436862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee new (arena_) GrowableArray<SuccessorBlockInfo*>(arena_, 2, kGrowableArraySuccessorBlocks); 437311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 43802c8cc6d1312a2b55533f02f6369dc7c94672f90Brian Carlstrom for (; iterator.HasNext(); iterator.Next()) { 439311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee BasicBlock *catch_block = FindBlock(iterator.GetHandlerAddress(), false /* split*/, 440311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee false /* creat */, NULL /* immed_pred_block_p */); 441311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee catch_block->catch_entry = true; 442311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (kIsDebugBuild) { 443311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee catches_.insert(catch_block->start_offset); 444311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 445311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee SuccessorBlockInfo *successor_block_info = reinterpret_cast<SuccessorBlockInfo*> 446f6c4b3ba3825de1dbb3e747a68b809c6cc8eb4dbMathieu Chartier (arena_->Alloc(sizeof(SuccessorBlockInfo), ArenaAllocator::kAllocSuccessor)); 4470d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee successor_block_info->block = catch_block->id; 448311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee successor_block_info->key = iterator.GetHandlerTypeIndex(); 4490d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee cur_block->successor_blocks->Insert(successor_block_info); 4500d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee catch_block->predecessors->Insert(cur_block->id); 451311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 45217189ac098b2f156713db1821b49db7b2f018bbebuzbee } else if (build_all_edges) { 453862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee BasicBlock *eh_block = NewMemBB(kExceptionHandling, num_blocks_++); 4540d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee cur_block->taken = eh_block->id; 455862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee block_list_.Insert(eh_block); 456311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee eh_block->start_offset = cur_offset; 4570d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee eh_block->predecessors->Insert(cur_block->id); 458311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 459311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 46017189ac098b2f156713db1821b49db7b2f018bbebuzbee if (is_throw) { 461311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cur_block->explicit_throw = true; 4622724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee if (code_ptr < code_end) { 463311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee // Force creation of new block following THROW via side-effect 464311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee FindBlock(cur_offset + width, /* split */ false, /* create */ true, 465311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* immed_pred_block_p */ NULL); 466311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 467311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (!in_try_block) { 468311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee // Don't split a THROW that can't rethrow - we're done. 469311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee return cur_block; 470311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 471311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 472311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 47317189ac098b2f156713db1821b49db7b2f018bbebuzbee if (!build_all_edges) { 47417189ac098b2f156713db1821b49db7b2f018bbebuzbee /* 47517189ac098b2f156713db1821b49db7b2f018bbebuzbee * Even though there is an exception edge here, control cannot return to this 47617189ac098b2f156713db1821b49db7b2f018bbebuzbee * method. Thus, for the purposes of dataflow analysis and optimization, we can 47717189ac098b2f156713db1821b49db7b2f018bbebuzbee * ignore the edge. Doing this reduces compile time, and increases the scope 47817189ac098b2f156713db1821b49db7b2f018bbebuzbee * of the basic-block level optimization pass. 47917189ac098b2f156713db1821b49db7b2f018bbebuzbee */ 48017189ac098b2f156713db1821b49db7b2f018bbebuzbee return cur_block; 48117189ac098b2f156713db1821b49db7b2f018bbebuzbee } 48217189ac098b2f156713db1821b49db7b2f018bbebuzbee 483311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* 484311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Split the potentially-throwing instruction into two parts. 485311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * The first half will be a pseudo-op that captures the exception 486311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * edges and terminates the basic block. It always falls through. 487311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Then, create a new basic block that begins with the throwing instruction 488311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * (minus exceptions). Note: this new basic block must NOT be entered into 489311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * the block_map. If the potentially-throwing instruction is the target of a 490311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * future branch, we need to find the check psuedo half. The new 491311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * basic block containing the work portion of the instruction should 492311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * only be entered via fallthrough from the block containing the 493311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * pseudo exception edge MIR. Note also that this new block is 494311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * not automatically terminated after the work portion, and may 495311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * contain following instructions. 496b48819db07f9a0992a72173380c24249d7fc648abuzbee * 497b48819db07f9a0992a72173380c24249d7fc648abuzbee * Note also that the dex_pc_to_block_map_ entry for the potentially 498b48819db07f9a0992a72173380c24249d7fc648abuzbee * throwing instruction will refer to the original basic block. 499311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee */ 500862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee BasicBlock *new_block = NewMemBB(kDalvikByteCode, num_blocks_++); 501862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee block_list_.Insert(new_block); 502311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee new_block->start_offset = insn->offset; 5030d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee cur_block->fall_through = new_block->id; 5040d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee new_block->predecessors->Insert(cur_block->id); 505f6c4b3ba3825de1dbb3e747a68b809c6cc8eb4dbMathieu Chartier MIR* new_insn = static_cast<MIR*>(arena_->Alloc(sizeof(MIR), ArenaAllocator::kAllocMIR)); 506311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee *new_insn = *insn; 507311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee insn->dalvikInsn.opcode = 508311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee static_cast<Instruction::Code>(kMirOpCheck); 509311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee // Associate the two halves 510311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee insn->meta.throw_insn = new_insn; 511311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee new_insn->meta.throw_insn = insn; 512311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee AppendMIR(new_block, new_insn); 513311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee return new_block; 514311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee} 515311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 516311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Parse a Dex method and insert it into the MIRGraph at the current insert point. */ 517311ca169f4727d46a55bdc8dfa0059719fa72b65buzbeevoid MIRGraph::InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_flags, 5188b2c0b9abc3f520495f4387ea040132ba85cae69Ian Rogers InvokeType invoke_type, uint16_t class_def_idx, 5192ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom uint32_t method_idx, jobject class_loader, const DexFile& dex_file) { 520311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee current_code_item_ = code_item; 521311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee method_stack_.push_back(std::make_pair(current_method_, current_offset_)); 522311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee current_method_ = m_units_.size(); 523311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee current_offset_ = 0; 524311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee // TODO: will need to snapshot stack image and use that as the mir context identification. 525311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee m_units_.push_back(new DexCompilationUnit(cu_, class_loader, Runtime::Current()->GetClassLinker(), 526311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee dex_file, current_code_item_, class_def_idx, method_idx, access_flags)); 527311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee const uint16_t* code_ptr = current_code_item_->insns_; 528311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee const uint16_t* code_end = 529311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee current_code_item_->insns_ + current_code_item_->insns_size_in_code_units_; 530311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 531311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee // TODO: need to rework expansion of block list & try_block_addr when inlining activated. 532b48819db07f9a0992a72173380c24249d7fc648abuzbee // TUNING: use better estimate of basic blocks for following resize. 533862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee block_list_.Resize(block_list_.Size() + current_code_item_->insns_size_in_code_units_); 534b48819db07f9a0992a72173380c24249d7fc648abuzbee dex_pc_to_block_map_.SetSize(dex_pc_to_block_map_.Size() + current_code_item_->insns_size_in_code_units_); 535bd663de599b16229085759366c56e2ed5a1dc7ecbuzbee 536311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee // TODO: replace with explicit resize routine. Using automatic extension side effect for now. 537862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee try_block_addr_->SetBit(current_code_item_->insns_size_in_code_units_); 538862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee try_block_addr_->ClearBit(current_code_item_->insns_size_in_code_units_); 539311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 540311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee // If this is the first method, set up default entry and exit blocks. 541311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (current_method_ == 0) { 542311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee DCHECK(entry_block_ == NULL); 543311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee DCHECK(exit_block_ == NULL); 5444274889d48ef82369bf2c1ca70d84689b4f9e93aBrian Carlstrom DCHECK_EQ(num_blocks_, 0); 5450d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee // Use id 0 to represent a null block. 5460d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee BasicBlock* null_block = NewMemBB(kNullBlock, num_blocks_++); 5470d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee DCHECK_EQ(null_block->id, NullBasicBlockId); 5480d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee null_block->hidden = true; 5490d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee block_list_.Insert(null_block); 550862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee entry_block_ = NewMemBB(kEntryBlock, num_blocks_++); 551862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee block_list_.Insert(entry_block_); 5520d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee exit_block_ = NewMemBB(kExitBlock, num_blocks_++); 553862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee block_list_.Insert(exit_block_); 554311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee // TODO: deprecate all "cu->" fields; move what's left to wherever CompilationUnit is allocated. 555311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cu_->dex_file = &dex_file; 556311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cu_->class_def_idx = class_def_idx; 557311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cu_->method_idx = method_idx; 558311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cu_->access_flags = access_flags; 559311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cu_->invoke_type = invoke_type; 560311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cu_->shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx)); 561311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cu_->num_ins = current_code_item_->ins_size_; 562311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cu_->num_regs = current_code_item_->registers_size_ - cu_->num_ins; 563311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cu_->num_outs = current_code_item_->outs_size_; 564311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cu_->num_dalvik_registers = current_code_item_->registers_size_; 565311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cu_->insns = current_code_item_->insns_; 566311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cu_->code_item = current_code_item_; 567311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } else { 568311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee UNIMPLEMENTED(FATAL) << "Nested inlining not implemented."; 569311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* 570311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Will need to manage storage for ins & outs, push prevous state and update 571311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * insert point. 572311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee */ 573311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 574311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 575311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* Current block to record parsed instructions */ 576862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee BasicBlock *cur_block = NewMemBB(kDalvikByteCode, num_blocks_++); 5770d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee DCHECK_EQ(current_offset_, 0U); 578311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cur_block->start_offset = current_offset_; 579862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee block_list_.Insert(cur_block); 5800d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee // TODO: for inlining support, insert at the insert point rather than entry block. 5810d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee entry_block_->fall_through = cur_block->id; 5820d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee cur_block->predecessors->Insert(entry_block_->id); 583311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 584311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* Identify code range in try blocks and set up the empty catch blocks */ 585311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee ProcessTryCatchBlocks(); 586311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 587311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* Parse all instructions and put them into containing basic blocks */ 588311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee while (code_ptr < code_end) { 589f6c4b3ba3825de1dbb3e747a68b809c6cc8eb4dbMathieu Chartier MIR *insn = static_cast<MIR *>(arena_->Alloc(sizeof(MIR), ArenaAllocator::kAllocMIR)); 590311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee insn->offset = current_offset_; 591311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee insn->m_unit_index = current_method_; 592311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee int width = ParseInsn(code_ptr, &insn->dalvikInsn); 593311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee insn->width = width; 594311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee Instruction::Code opcode = insn->dalvikInsn.opcode; 595311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (opcode_count_ != NULL) { 596311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee opcode_count_[static_cast<int>(opcode)]++; 597311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 598311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 599311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee int flags = Instruction::FlagsOf(insn->dalvikInsn.opcode); 600311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 6011da1e2fceb0030b4b76b43510b1710a9613e0c2ebuzbee uint64_t df_flags = oat_data_flow_attributes_[insn->dalvikInsn.opcode]; 602311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 603311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (df_flags & DF_HAS_DEFS) { 604311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee def_count_ += (df_flags & DF_A_WIDE) ? 2 : 1; 605311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 606311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 6071da1e2fceb0030b4b76b43510b1710a9613e0c2ebuzbee if (df_flags & DF_LVN) { 6081da1e2fceb0030b4b76b43510b1710a9613e0c2ebuzbee cur_block->use_lvn = true; // Run local value numbering on this basic block. 6091da1e2fceb0030b4b76b43510b1710a9613e0c2ebuzbee } 6101da1e2fceb0030b4b76b43510b1710a9613e0c2ebuzbee 6112724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee // Check for inline data block signatures 6122724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee if (opcode == Instruction::NOP) { 6132724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee // A simple NOP will have a width of 1 at this point, embedded data NOP > 1. 6142724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee if ((width == 1) && ((current_offset_ & 0x1) == 0x1) && ((code_end - code_ptr) > 1)) { 6152724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee // Could be an aligning nop. If an embedded data NOP follows, treat pair as single unit. 6162724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee uint16_t following_raw_instruction = code_ptr[1]; 6172724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee if ((following_raw_instruction == Instruction::kSparseSwitchSignature) || 6182724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee (following_raw_instruction == Instruction::kPackedSwitchSignature) || 6192724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee (following_raw_instruction == Instruction::kArrayDataSignature)) { 6202724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee width += Instruction::At(code_ptr + 1)->SizeInCodeUnits(); 6212724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee } 6222724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee } 6232724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee if (width == 1) { 6242724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee // It is a simple nop - treat normally. 6252724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee AppendMIR(cur_block, insn); 6262724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee } else { 6270d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee DCHECK(cur_block->fall_through == NullBasicBlockId); 6280d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee DCHECK(cur_block->taken == NullBasicBlockId); 6292724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee // Unreachable instruction, mark for no continuation. 6302724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee flags &= ~Instruction::kContinue; 6312724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee } 6322724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee } else { 6332724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee AppendMIR(cur_block, insn); 6342724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee } 6352724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee 636b48819db07f9a0992a72173380c24249d7fc648abuzbee // Associate the starting dex_pc for this opcode with its containing basic block. 637b48819db07f9a0992a72173380c24249d7fc648abuzbee dex_pc_to_block_map_.Put(insn->offset, cur_block->id); 638b48819db07f9a0992a72173380c24249d7fc648abuzbee 6392724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee code_ptr += width; 6402724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee 641311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (flags & Instruction::kBranch) { 642311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cur_block = ProcessCanBranch(cur_block, insn, current_offset_, 643311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee width, flags, code_ptr, code_end); 644311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } else if (flags & Instruction::kReturn) { 645311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cur_block->terminated_by_return = true; 6460d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee cur_block->fall_through = exit_block_->id; 6470d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee exit_block_->predecessors->Insert(cur_block->id); 648311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* 649311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Terminate the current block if there are instructions 650311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * afterwards. 651311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee */ 652311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (code_ptr < code_end) { 653311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* 654311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Create a fallthrough block for real instructions 655311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * (incl. NOP). 656311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee */ 6572724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee FindBlock(current_offset_ + width, /* split */ false, /* create */ true, 6582724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee /* immed_pred_block_p */ NULL); 659311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 660311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } else if (flags & Instruction::kThrow) { 661311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cur_block = ProcessCanThrow(cur_block, insn, current_offset_, width, flags, try_block_addr_, 662311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee code_ptr, code_end); 663311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } else if (flags & Instruction::kSwitch) { 66417189ac098b2f156713db1821b49db7b2f018bbebuzbee cur_block = ProcessCanSwitch(cur_block, insn, current_offset_, width, flags); 665311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 666311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee current_offset_ += width; 667311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee BasicBlock *next_block = FindBlock(current_offset_, /* split */ false, /* create */ 668311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee false, /* immed_pred_block_p */ NULL); 669311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (next_block) { 670311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* 671311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * The next instruction could be the target of a previously parsed 672311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * forward branch so a block is already created. If the current 673311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * instruction is not an unconditional branch, connect them through 674311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * the fall-through link. 675311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee */ 6760d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee DCHECK(cur_block->fall_through == NullBasicBlockId || 6770d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee GetBasicBlock(cur_block->fall_through) == next_block || 6780d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee GetBasicBlock(cur_block->fall_through) == exit_block_); 679311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 6800d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee if ((cur_block->fall_through == NullBasicBlockId) && (flags & Instruction::kContinue)) { 6810d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee cur_block->fall_through = next_block->id; 6820d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee next_block->predecessors->Insert(cur_block->id); 683311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 684311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee cur_block = next_block; 685311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 686311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 6875816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko 688311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (cu_->enable_debug & (1 << kDebugDumpCFG)) { 689311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee DumpCFG("/sdcard/1_post_parse_cfg/", true); 690311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 691311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 692311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (cu_->verbose) { 6931fd3346740dfb7f47be9922312b68a4227fada96buzbee DumpMIRGraph(); 694311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 695311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee} 696311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 6972ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::ShowOpcodeStats() { 698311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee DCHECK(opcode_count_ != NULL); 699311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee LOG(INFO) << "Opcode Count"; 700311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee for (int i = 0; i < kNumPackedOpcodes; i++) { 701311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (opcode_count_[i] != 0) { 702311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee LOG(INFO) << "-C- " << Instruction::Name(static_cast<Instruction::Code>(i)) 703311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee << " " << opcode_count_[i]; 704311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 705311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 706311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee} 707311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 708311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee// TODO: use a configurable base prefix, and adjust callers to supply pass name. 709311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Dump the CFG into a DOT graph */ 7102ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::DumpCFG(const char* dir_prefix, bool all_blocks) { 711311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee FILE* file; 712311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee std::string fname(PrettyMethod(cu_->method_idx, *cu_->dex_file)); 713311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee ReplaceSpecialChars(fname); 714311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fname = StringPrintf("%s%s%x.dot", dir_prefix, fname.c_str(), 7150d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee GetBasicBlock(GetEntryBlock()->fall_through)->start_offset); 716311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee file = fopen(fname.c_str(), "w"); 717311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (file == NULL) { 718311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee return; 719311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 720311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, "digraph G {\n"); 721311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 722311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, " rankdir=TB\n"); 723311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 724311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee int num_blocks = all_blocks ? GetNumBlocks() : num_reachable_blocks_; 725311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee int idx; 726311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 727311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee for (idx = 0; idx < num_blocks; idx++) { 728862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee int block_idx = all_blocks ? idx : dfs_order_->Get(idx); 729311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee BasicBlock *bb = GetBasicBlock(block_idx); 730311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (bb == NULL) break; 731311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (bb->block_type == kDead) continue; 732311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (bb->block_type == kEntryBlock) { 733311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, " entry_%d [shape=Mdiamond];\n", bb->id); 734311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } else if (bb->block_type == kExitBlock) { 735311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, " exit_%d [shape=Mdiamond];\n", bb->id); 736311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } else if (bb->block_type == kDalvikByteCode) { 737311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, " block%04x_%d [shape=record,label = \"{ \\\n", 738311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee bb->start_offset, bb->id); 739311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee const MIR *mir; 740311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, " {block id %d\\l}%s\\\n", bb->id, 741311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee bb->first_mir_insn ? " | " : " "); 742311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee for (mir = bb->first_mir_insn; mir; mir = mir->next) { 743311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee int opcode = mir->dalvikInsn.opcode; 744311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, " {%04x %s %s %s\\l}%s\\\n", mir->offset, 7451fd3346740dfb7f47be9922312b68a4227fada96buzbee mir->ssa_rep ? GetDalvikDisassembly(mir) : 746311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee (opcode < kMirOpFirst) ? Instruction::Name(mir->dalvikInsn.opcode) : 7471fd3346740dfb7f47be9922312b68a4227fada96buzbee extended_mir_op_names_[opcode - kMirOpFirst], 748311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee (mir->optimization_flags & MIR_IGNORE_RANGE_CHECK) != 0 ? " no_rangecheck" : " ", 749311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee (mir->optimization_flags & MIR_IGNORE_NULL_CHECK) != 0 ? " no_nullcheck" : " ", 750311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee mir->next ? " | " : " "); 751311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 752311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, " }\"];\n\n"); 753311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } else if (bb->block_type == kExceptionHandling) { 754311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee char block_name[BLOCK_NAME_LEN]; 755311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 756311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee GetBlockName(bb, block_name); 757311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, " %s [shape=invhouse];\n", block_name); 758311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 759311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 760311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee char block_name1[BLOCK_NAME_LEN], block_name2[BLOCK_NAME_LEN]; 761311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 7620d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee if (bb->taken != NullBasicBlockId) { 763311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee GetBlockName(bb, block_name1); 7640d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee GetBlockName(GetBasicBlock(bb->taken), block_name2); 765311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, " %s:s -> %s:n [style=dotted]\n", 766311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee block_name1, block_name2); 767311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 7680d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee if (bb->fall_through != NullBasicBlockId) { 769311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee GetBlockName(bb, block_name1); 7700d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee GetBlockName(GetBasicBlock(bb->fall_through), block_name2); 771311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, " %s:s -> %s:n\n", block_name1, block_name2); 772311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 773311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 7740d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee if (bb->successor_block_list_type != kNotUsed) { 775311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, " succ%04x_%d [shape=%s,label = \"{ \\\n", 776311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee bb->start_offset, bb->id, 7770d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee (bb->successor_block_list_type == kCatch) ? "Mrecord" : "record"); 7780d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee GrowableArray<SuccessorBlockInfo*>::Iterator iterator(bb->successor_blocks); 779862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee SuccessorBlockInfo *successor_block_info = iterator.Next(); 780311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 781311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee int succ_id = 0; 782311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee while (true) { 783311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (successor_block_info == NULL) break; 784311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 7850d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee BasicBlock *dest_block = GetBasicBlock(successor_block_info->block); 786862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee SuccessorBlockInfo *next_successor_block_info = iterator.Next(); 787311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 788311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, " {<f%d> %04x: %04x\\l}%s\\\n", 789311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee succ_id++, 790311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee successor_block_info->key, 791311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee dest_block->start_offset, 792311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee (next_successor_block_info != NULL) ? " | " : " "); 793311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 794311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee successor_block_info = next_successor_block_info; 795311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 796311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, " }\"];\n\n"); 797311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 798311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee GetBlockName(bb, block_name1); 799311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, " %s:s -> succ%04x_%d:n [style=dashed]\n", 800311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee block_name1, bb->start_offset, bb->id); 801311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 8020d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee if (bb->successor_block_list_type == kPackedSwitch || 8030d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee bb->successor_block_list_type == kSparseSwitch) { 8040d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee GrowableArray<SuccessorBlockInfo*>::Iterator iter(bb->successor_blocks); 805311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 806311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee succ_id = 0; 807311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee while (true) { 808862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee SuccessorBlockInfo *successor_block_info = iter.Next(); 809311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (successor_block_info == NULL) break; 810311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 8110d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee BasicBlock* dest_block = GetBasicBlock(successor_block_info->block); 812311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 813311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee GetBlockName(dest_block, block_name2); 814311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, " succ%04x_%d:f%d:e -> %s:n\n", bb->start_offset, 815311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee bb->id, succ_id++, block_name2); 816311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 817311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 818311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 819311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, "\n"); 820311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 821311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (cu_->verbose) { 822311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee /* Display the dominator tree */ 823311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee GetBlockName(bb, block_name1); 824311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, " cfg%s [label=\"%s\", shape=none];\n", 825311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee block_name1, block_name1); 826311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (bb->i_dom) { 8270d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee GetBlockName(GetBasicBlock(bb->i_dom), block_name2); 828311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, " cfg%s:s -> cfg%s:n\n\n", block_name2, block_name1); 829311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 830311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 831311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 832311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fprintf(file, "}\n"); 833311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee fclose(file); 834311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee} 835311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 8361fd3346740dfb7f47be9922312b68a4227fada96buzbee/* Insert an MIR instruction to the end of a basic block */ 8372ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::AppendMIR(BasicBlock* bb, MIR* mir) { 8381fd3346740dfb7f47be9922312b68a4227fada96buzbee if (bb->first_mir_insn == NULL) { 8391fd3346740dfb7f47be9922312b68a4227fada96buzbee DCHECK(bb->last_mir_insn == NULL); 8401fd3346740dfb7f47be9922312b68a4227fada96buzbee bb->last_mir_insn = bb->first_mir_insn = mir; 8410d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee mir->next = NULL; 8421fd3346740dfb7f47be9922312b68a4227fada96buzbee } else { 8431fd3346740dfb7f47be9922312b68a4227fada96buzbee bb->last_mir_insn->next = mir; 8441fd3346740dfb7f47be9922312b68a4227fada96buzbee mir->next = NULL; 8451fd3346740dfb7f47be9922312b68a4227fada96buzbee bb->last_mir_insn = mir; 8461fd3346740dfb7f47be9922312b68a4227fada96buzbee } 8471fd3346740dfb7f47be9922312b68a4227fada96buzbee} 8481fd3346740dfb7f47be9922312b68a4227fada96buzbee 8491fd3346740dfb7f47be9922312b68a4227fada96buzbee/* Insert an MIR instruction to the head of a basic block */ 8502ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::PrependMIR(BasicBlock* bb, MIR* mir) { 8511fd3346740dfb7f47be9922312b68a4227fada96buzbee if (bb->first_mir_insn == NULL) { 8521fd3346740dfb7f47be9922312b68a4227fada96buzbee DCHECK(bb->last_mir_insn == NULL); 8531fd3346740dfb7f47be9922312b68a4227fada96buzbee bb->last_mir_insn = bb->first_mir_insn = mir; 8540d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee mir->next = NULL; 8551fd3346740dfb7f47be9922312b68a4227fada96buzbee } else { 8561fd3346740dfb7f47be9922312b68a4227fada96buzbee mir->next = bb->first_mir_insn; 8571fd3346740dfb7f47be9922312b68a4227fada96buzbee bb->first_mir_insn = mir; 8581fd3346740dfb7f47be9922312b68a4227fada96buzbee } 8591fd3346740dfb7f47be9922312b68a4227fada96buzbee} 8601fd3346740dfb7f47be9922312b68a4227fada96buzbee 8611fd3346740dfb7f47be9922312b68a4227fada96buzbee/* Insert a MIR instruction after the specified MIR */ 8622ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::InsertMIRAfter(BasicBlock* bb, MIR* current_mir, MIR* new_mir) { 8631fd3346740dfb7f47be9922312b68a4227fada96buzbee new_mir->next = current_mir->next; 8641fd3346740dfb7f47be9922312b68a4227fada96buzbee current_mir->next = new_mir; 8651fd3346740dfb7f47be9922312b68a4227fada96buzbee 8660d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee if (bb->last_mir_insn == current_mir) { 8671fd3346740dfb7f47be9922312b68a4227fada96buzbee /* Is the last MIR in the block */ 8681fd3346740dfb7f47be9922312b68a4227fada96buzbee bb->last_mir_insn = new_mir; 8691fd3346740dfb7f47be9922312b68a4227fada96buzbee } 8701fd3346740dfb7f47be9922312b68a4227fada96buzbee} 8711fd3346740dfb7f47be9922312b68a4227fada96buzbee 8722ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromchar* MIRGraph::GetDalvikDisassembly(const MIR* mir) { 8731fd3346740dfb7f47be9922312b68a4227fada96buzbee DecodedInstruction insn = mir->dalvikInsn; 8741fd3346740dfb7f47be9922312b68a4227fada96buzbee std::string str; 8751fd3346740dfb7f47be9922312b68a4227fada96buzbee int flags = 0; 8761fd3346740dfb7f47be9922312b68a4227fada96buzbee int opcode = insn.opcode; 8771fd3346740dfb7f47be9922312b68a4227fada96buzbee char* ret; 8781fd3346740dfb7f47be9922312b68a4227fada96buzbee bool nop = false; 8791fd3346740dfb7f47be9922312b68a4227fada96buzbee SSARepresentation* ssa_rep = mir->ssa_rep; 8801fd3346740dfb7f47be9922312b68a4227fada96buzbee Instruction::Format dalvik_format = Instruction::k10x; // Default to no-operand format 8811fd3346740dfb7f47be9922312b68a4227fada96buzbee int defs = (ssa_rep != NULL) ? ssa_rep->num_defs : 0; 8821fd3346740dfb7f47be9922312b68a4227fada96buzbee int uses = (ssa_rep != NULL) ? ssa_rep->num_uses : 0; 8831fd3346740dfb7f47be9922312b68a4227fada96buzbee 8841fd3346740dfb7f47be9922312b68a4227fada96buzbee // Handle special cases. 8851fd3346740dfb7f47be9922312b68a4227fada96buzbee if ((opcode == kMirOpCheck) || (opcode == kMirOpCheckPart2)) { 8861fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(extended_mir_op_names_[opcode - kMirOpFirst]); 8871fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(": "); 8881fd3346740dfb7f47be9922312b68a4227fada96buzbee // Recover the original Dex instruction 8891fd3346740dfb7f47be9922312b68a4227fada96buzbee insn = mir->meta.throw_insn->dalvikInsn; 8901fd3346740dfb7f47be9922312b68a4227fada96buzbee ssa_rep = mir->meta.throw_insn->ssa_rep; 8911fd3346740dfb7f47be9922312b68a4227fada96buzbee defs = ssa_rep->num_defs; 8921fd3346740dfb7f47be9922312b68a4227fada96buzbee uses = ssa_rep->num_uses; 8931fd3346740dfb7f47be9922312b68a4227fada96buzbee opcode = insn.opcode; 8941fd3346740dfb7f47be9922312b68a4227fada96buzbee } else if (opcode == kMirOpNop) { 8951fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append("["); 8960d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee // Recover original opcode. 8970d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee insn.opcode = Instruction::At(current_code_item_->insns_ + mir->offset)->Opcode(); 8980d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee opcode = insn.opcode; 8991fd3346740dfb7f47be9922312b68a4227fada96buzbee nop = true; 9001fd3346740dfb7f47be9922312b68a4227fada96buzbee } 9011fd3346740dfb7f47be9922312b68a4227fada96buzbee 9021fd3346740dfb7f47be9922312b68a4227fada96buzbee if (opcode >= kMirOpFirst) { 9031fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(extended_mir_op_names_[opcode - kMirOpFirst]); 9041fd3346740dfb7f47be9922312b68a4227fada96buzbee } else { 9051fd3346740dfb7f47be9922312b68a4227fada96buzbee dalvik_format = Instruction::FormatOf(insn.opcode); 9061fd3346740dfb7f47be9922312b68a4227fada96buzbee flags = Instruction::FlagsOf(insn.opcode); 9071fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(Instruction::Name(insn.opcode)); 9081fd3346740dfb7f47be9922312b68a4227fada96buzbee } 9091fd3346740dfb7f47be9922312b68a4227fada96buzbee 9101fd3346740dfb7f47be9922312b68a4227fada96buzbee if (opcode == kMirOpPhi) { 9110d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee BasicBlockId* incoming = mir->meta.phi_incoming; 9121fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(StringPrintf(" %s = (%s", 9131fd3346740dfb7f47be9922312b68a4227fada96buzbee GetSSANameWithConst(ssa_rep->defs[0], true).c_str(), 9141fd3346740dfb7f47be9922312b68a4227fada96buzbee GetSSANameWithConst(ssa_rep->uses[0], true).c_str())); 915b1eba213afaf7fa6445de863ddc9680ab99762eaBrian Carlstrom str.append(StringPrintf(":%d", incoming[0])); 9161fd3346740dfb7f47be9922312b68a4227fada96buzbee int i; 9171fd3346740dfb7f47be9922312b68a4227fada96buzbee for (i = 1; i < uses; i++) { 9181fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(StringPrintf(", %s:%d", 9191fd3346740dfb7f47be9922312b68a4227fada96buzbee GetSSANameWithConst(ssa_rep->uses[i], true).c_str(), 9201fd3346740dfb7f47be9922312b68a4227fada96buzbee incoming[i])); 9211fd3346740dfb7f47be9922312b68a4227fada96buzbee } 9221fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(")"); 9231fd3346740dfb7f47be9922312b68a4227fada96buzbee } else if ((flags & Instruction::kBranch) != 0) { 9241fd3346740dfb7f47be9922312b68a4227fada96buzbee // For branches, decode the instructions to print out the branch targets. 9251fd3346740dfb7f47be9922312b68a4227fada96buzbee int offset = 0; 9261fd3346740dfb7f47be9922312b68a4227fada96buzbee switch (dalvik_format) { 9271fd3346740dfb7f47be9922312b68a4227fada96buzbee case Instruction::k21t: 9281fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(StringPrintf(" %s,", GetSSANameWithConst(ssa_rep->uses[0], false).c_str())); 9291fd3346740dfb7f47be9922312b68a4227fada96buzbee offset = insn.vB; 9301fd3346740dfb7f47be9922312b68a4227fada96buzbee break; 9311fd3346740dfb7f47be9922312b68a4227fada96buzbee case Instruction::k22t: 9321fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(StringPrintf(" %s, %s,", GetSSANameWithConst(ssa_rep->uses[0], false).c_str(), 9331fd3346740dfb7f47be9922312b68a4227fada96buzbee GetSSANameWithConst(ssa_rep->uses[1], false).c_str())); 9341fd3346740dfb7f47be9922312b68a4227fada96buzbee offset = insn.vC; 9351fd3346740dfb7f47be9922312b68a4227fada96buzbee break; 9361fd3346740dfb7f47be9922312b68a4227fada96buzbee case Instruction::k10t: 9371fd3346740dfb7f47be9922312b68a4227fada96buzbee case Instruction::k20t: 9381fd3346740dfb7f47be9922312b68a4227fada96buzbee case Instruction::k30t: 9391fd3346740dfb7f47be9922312b68a4227fada96buzbee offset = insn.vA; 9401fd3346740dfb7f47be9922312b68a4227fada96buzbee break; 9411fd3346740dfb7f47be9922312b68a4227fada96buzbee default: 9421fd3346740dfb7f47be9922312b68a4227fada96buzbee LOG(FATAL) << "Unexpected branch format " << dalvik_format << " from " << insn.opcode; 9431fd3346740dfb7f47be9922312b68a4227fada96buzbee } 9441fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(StringPrintf(" 0x%x (%c%x)", mir->offset + offset, 9451fd3346740dfb7f47be9922312b68a4227fada96buzbee offset > 0 ? '+' : '-', offset > 0 ? offset : -offset)); 9461fd3346740dfb7f47be9922312b68a4227fada96buzbee } else { 9471fd3346740dfb7f47be9922312b68a4227fada96buzbee // For invokes-style formats, treat wide regs as a pair of singles 9481fd3346740dfb7f47be9922312b68a4227fada96buzbee bool show_singles = ((dalvik_format == Instruction::k35c) || 9491fd3346740dfb7f47be9922312b68a4227fada96buzbee (dalvik_format == Instruction::k3rc)); 9501fd3346740dfb7f47be9922312b68a4227fada96buzbee if (defs != 0) { 9511fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(StringPrintf(" %s", GetSSANameWithConst(ssa_rep->defs[0], false).c_str())); 9521fd3346740dfb7f47be9922312b68a4227fada96buzbee if (uses != 0) { 9531fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(", "); 9541fd3346740dfb7f47be9922312b68a4227fada96buzbee } 9551fd3346740dfb7f47be9922312b68a4227fada96buzbee } 9561fd3346740dfb7f47be9922312b68a4227fada96buzbee for (int i = 0; i < uses; i++) { 9571fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append( 9581fd3346740dfb7f47be9922312b68a4227fada96buzbee StringPrintf(" %s", GetSSANameWithConst(ssa_rep->uses[i], show_singles).c_str())); 9591fd3346740dfb7f47be9922312b68a4227fada96buzbee if (!show_singles && (reg_location_ != NULL) && reg_location_[i].wide) { 9601fd3346740dfb7f47be9922312b68a4227fada96buzbee // For the listing, skip the high sreg. 9611fd3346740dfb7f47be9922312b68a4227fada96buzbee i++; 9621fd3346740dfb7f47be9922312b68a4227fada96buzbee } 9631fd3346740dfb7f47be9922312b68a4227fada96buzbee if (i != (uses -1)) { 9641fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(","); 9651fd3346740dfb7f47be9922312b68a4227fada96buzbee } 9661fd3346740dfb7f47be9922312b68a4227fada96buzbee } 9671fd3346740dfb7f47be9922312b68a4227fada96buzbee switch (dalvik_format) { 9687934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom case Instruction::k11n: // Add one immediate from vB 9691fd3346740dfb7f47be9922312b68a4227fada96buzbee case Instruction::k21s: 9701fd3346740dfb7f47be9922312b68a4227fada96buzbee case Instruction::k31i: 9711fd3346740dfb7f47be9922312b68a4227fada96buzbee case Instruction::k21h: 9721fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(StringPrintf(", #%d", insn.vB)); 9731fd3346740dfb7f47be9922312b68a4227fada96buzbee break; 9747934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom case Instruction::k51l: // Add one wide immediate 9751fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(StringPrintf(", #%lld", insn.vB_wide)); 9761fd3346740dfb7f47be9922312b68a4227fada96buzbee break; 9777934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom case Instruction::k21c: // One register, one string/type/method index 9781fd3346740dfb7f47be9922312b68a4227fada96buzbee case Instruction::k31c: 9791fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(StringPrintf(", index #%d", insn.vB)); 9801fd3346740dfb7f47be9922312b68a4227fada96buzbee break; 9817934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom case Instruction::k22c: // Two registers, one string/type/method index 9821fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(StringPrintf(", index #%d", insn.vC)); 9831fd3346740dfb7f47be9922312b68a4227fada96buzbee break; 9847934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom case Instruction::k22s: // Add one immediate from vC 9851fd3346740dfb7f47be9922312b68a4227fada96buzbee case Instruction::k22b: 9861fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append(StringPrintf(", #%d", insn.vC)); 9871fd3346740dfb7f47be9922312b68a4227fada96buzbee break; 98802c8cc6d1312a2b55533f02f6369dc7c94672f90Brian Carlstrom default: { 98902c8cc6d1312a2b55533f02f6369dc7c94672f90Brian Carlstrom // Nothing left to print 9901fd3346740dfb7f47be9922312b68a4227fada96buzbee } 99102c8cc6d1312a2b55533f02f6369dc7c94672f90Brian Carlstrom } 9921fd3346740dfb7f47be9922312b68a4227fada96buzbee } 9931fd3346740dfb7f47be9922312b68a4227fada96buzbee if (nop) { 9941fd3346740dfb7f47be9922312b68a4227fada96buzbee str.append("]--optimized away"); 9951fd3346740dfb7f47be9922312b68a4227fada96buzbee } 9961fd3346740dfb7f47be9922312b68a4227fada96buzbee int length = str.length() + 1; 997f6c4b3ba3825de1dbb3e747a68b809c6cc8eb4dbMathieu Chartier ret = static_cast<char*>(arena_->Alloc(length, ArenaAllocator::kAllocDFInfo)); 9981fd3346740dfb7f47be9922312b68a4227fada96buzbee strncpy(ret, str.c_str(), length); 9991fd3346740dfb7f47be9922312b68a4227fada96buzbee return ret; 10001fd3346740dfb7f47be9922312b68a4227fada96buzbee} 10011fd3346740dfb7f47be9922312b68a4227fada96buzbee 10021fd3346740dfb7f47be9922312b68a4227fada96buzbee/* Turn method name into a legal Linux file name */ 10032ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::ReplaceSpecialChars(std::string& str) { 10049b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom static const struct { const char before; const char after; } match[] = { 10059b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom {'/', '-'}, {';', '#'}, {' ', '#'}, {'$', '+'}, 10069b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom {'(', '@'}, {')', '@'}, {'<', '='}, {'>', '='} 10079b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom }; 10081fd3346740dfb7f47be9922312b68a4227fada96buzbee for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) { 10091fd3346740dfb7f47be9922312b68a4227fada96buzbee std::replace(str.begin(), str.end(), match[i].before, match[i].after); 10101fd3346740dfb7f47be9922312b68a4227fada96buzbee } 10111fd3346740dfb7f47be9922312b68a4227fada96buzbee} 10121fd3346740dfb7f47be9922312b68a4227fada96buzbee 10132ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromstd::string MIRGraph::GetSSAName(int ssa_reg) { 101439ebcb800aabedd0ffa6aa4aeac8aa4194c66e61Ian Rogers // TODO: This value is needed for LLVM and debugging. Currently, we compute this and then copy to 101539ebcb800aabedd0ffa6aa4aeac8aa4194c66e61Ian Rogers // the arena. We should be smarter and just place straight into the arena, or compute the 101639ebcb800aabedd0ffa6aa4aeac8aa4194c66e61Ian Rogers // value more lazily. 10171fd3346740dfb7f47be9922312b68a4227fada96buzbee return StringPrintf("v%d_%d", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg)); 10181fd3346740dfb7f47be9922312b68a4227fada96buzbee} 10191fd3346740dfb7f47be9922312b68a4227fada96buzbee 10201fd3346740dfb7f47be9922312b68a4227fada96buzbee// Similar to GetSSAName, but if ssa name represents an immediate show that as well. 10212ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromstd::string MIRGraph::GetSSANameWithConst(int ssa_reg, bool singles_only) { 10221fd3346740dfb7f47be9922312b68a4227fada96buzbee if (reg_location_ == NULL) { 10231fd3346740dfb7f47be9922312b68a4227fada96buzbee // Pre-SSA - just use the standard name 10241fd3346740dfb7f47be9922312b68a4227fada96buzbee return GetSSAName(ssa_reg); 10251fd3346740dfb7f47be9922312b68a4227fada96buzbee } 10261fd3346740dfb7f47be9922312b68a4227fada96buzbee if (IsConst(reg_location_[ssa_reg])) { 10271fd3346740dfb7f47be9922312b68a4227fada96buzbee if (!singles_only && reg_location_[ssa_reg].wide) { 10281fd3346740dfb7f47be9922312b68a4227fada96buzbee return StringPrintf("v%d_%d#0x%llx", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg), 10291fd3346740dfb7f47be9922312b68a4227fada96buzbee ConstantValueWide(reg_location_[ssa_reg])); 10301fd3346740dfb7f47be9922312b68a4227fada96buzbee } else { 1031b1eba213afaf7fa6445de863ddc9680ab99762eaBrian Carlstrom return StringPrintf("v%d_%d#0x%x", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg), 10321fd3346740dfb7f47be9922312b68a4227fada96buzbee ConstantValue(reg_location_[ssa_reg])); 10331fd3346740dfb7f47be9922312b68a4227fada96buzbee } 10341fd3346740dfb7f47be9922312b68a4227fada96buzbee } else { 10351fd3346740dfb7f47be9922312b68a4227fada96buzbee return StringPrintf("v%d_%d", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg)); 10361fd3346740dfb7f47be9922312b68a4227fada96buzbee } 10371fd3346740dfb7f47be9922312b68a4227fada96buzbee} 10381fd3346740dfb7f47be9922312b68a4227fada96buzbee 10392ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::GetBlockName(BasicBlock* bb, char* name) { 10401fd3346740dfb7f47be9922312b68a4227fada96buzbee switch (bb->block_type) { 10411fd3346740dfb7f47be9922312b68a4227fada96buzbee case kEntryBlock: 10421fd3346740dfb7f47be9922312b68a4227fada96buzbee snprintf(name, BLOCK_NAME_LEN, "entry_%d", bb->id); 10431fd3346740dfb7f47be9922312b68a4227fada96buzbee break; 10441fd3346740dfb7f47be9922312b68a4227fada96buzbee case kExitBlock: 10451fd3346740dfb7f47be9922312b68a4227fada96buzbee snprintf(name, BLOCK_NAME_LEN, "exit_%d", bb->id); 10461fd3346740dfb7f47be9922312b68a4227fada96buzbee break; 10471fd3346740dfb7f47be9922312b68a4227fada96buzbee case kDalvikByteCode: 10481fd3346740dfb7f47be9922312b68a4227fada96buzbee snprintf(name, BLOCK_NAME_LEN, "block%04x_%d", bb->start_offset, bb->id); 10491fd3346740dfb7f47be9922312b68a4227fada96buzbee break; 10501fd3346740dfb7f47be9922312b68a4227fada96buzbee case kExceptionHandling: 10511fd3346740dfb7f47be9922312b68a4227fada96buzbee snprintf(name, BLOCK_NAME_LEN, "exception%04x_%d", bb->start_offset, 10521fd3346740dfb7f47be9922312b68a4227fada96buzbee bb->id); 10531fd3346740dfb7f47be9922312b68a4227fada96buzbee break; 10541fd3346740dfb7f47be9922312b68a4227fada96buzbee default: 10551fd3346740dfb7f47be9922312b68a4227fada96buzbee snprintf(name, BLOCK_NAME_LEN, "_%d", bb->id); 10561fd3346740dfb7f47be9922312b68a4227fada96buzbee break; 10571fd3346740dfb7f47be9922312b68a4227fada96buzbee } 10581fd3346740dfb7f47be9922312b68a4227fada96buzbee} 10591fd3346740dfb7f47be9922312b68a4227fada96buzbee 10602ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* MIRGraph::GetShortyFromTargetIdx(int target_idx) { 10610d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee // TODO: for inlining support, use current code unit. 10621fd3346740dfb7f47be9922312b68a4227fada96buzbee const DexFile::MethodId& method_id = cu_->dex_file->GetMethodId(target_idx); 10631fd3346740dfb7f47be9922312b68a4227fada96buzbee return cu_->dex_file->GetShorty(method_id.proto_idx_); 10641fd3346740dfb7f47be9922312b68a4227fada96buzbee} 10651fd3346740dfb7f47be9922312b68a4227fada96buzbee 10661fd3346740dfb7f47be9922312b68a4227fada96buzbee/* Debug Utility - dump a compilation unit */ 10672ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::DumpMIRGraph() { 10681fd3346740dfb7f47be9922312b68a4227fada96buzbee BasicBlock* bb; 10691fd3346740dfb7f47be9922312b68a4227fada96buzbee const char* block_type_names[] = { 107017189ac098b2f156713db1821b49db7b2f018bbebuzbee "Null Block", 10711fd3346740dfb7f47be9922312b68a4227fada96buzbee "Entry Block", 10721fd3346740dfb7f47be9922312b68a4227fada96buzbee "Code Block", 10731fd3346740dfb7f47be9922312b68a4227fada96buzbee "Exit Block", 10741fd3346740dfb7f47be9922312b68a4227fada96buzbee "Exception Handling", 10751fd3346740dfb7f47be9922312b68a4227fada96buzbee "Catch Block" 10761fd3346740dfb7f47be9922312b68a4227fada96buzbee }; 10771fd3346740dfb7f47be9922312b68a4227fada96buzbee 10781fd3346740dfb7f47be9922312b68a4227fada96buzbee LOG(INFO) << "Compiling " << PrettyMethod(cu_->method_idx, *cu_->dex_file); 10791fd3346740dfb7f47be9922312b68a4227fada96buzbee LOG(INFO) << cu_->insns << " insns"; 10801fd3346740dfb7f47be9922312b68a4227fada96buzbee LOG(INFO) << GetNumBlocks() << " blocks in total"; 1081862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee GrowableArray<BasicBlock*>::Iterator iterator(&block_list_); 10821fd3346740dfb7f47be9922312b68a4227fada96buzbee 10831fd3346740dfb7f47be9922312b68a4227fada96buzbee while (true) { 1084862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee bb = iterator.Next(); 10851fd3346740dfb7f47be9922312b68a4227fada96buzbee if (bb == NULL) break; 10861fd3346740dfb7f47be9922312b68a4227fada96buzbee LOG(INFO) << StringPrintf("Block %d (%s) (insn %04x - %04x%s)", 10871fd3346740dfb7f47be9922312b68a4227fada96buzbee bb->id, 10881fd3346740dfb7f47be9922312b68a4227fada96buzbee block_type_names[bb->block_type], 10891fd3346740dfb7f47be9922312b68a4227fada96buzbee bb->start_offset, 10901fd3346740dfb7f47be9922312b68a4227fada96buzbee bb->last_mir_insn ? bb->last_mir_insn->offset : bb->start_offset, 10911fd3346740dfb7f47be9922312b68a4227fada96buzbee bb->last_mir_insn ? "" : " empty"); 10920d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee if (bb->taken != NullBasicBlockId) { 10930d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee LOG(INFO) << " Taken branch: block " << bb->taken 10940d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee << "(0x" << std::hex << GetBasicBlock(bb->taken)->start_offset << ")"; 10951fd3346740dfb7f47be9922312b68a4227fada96buzbee } 10960d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee if (bb->fall_through != NullBasicBlockId) { 10970d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee LOG(INFO) << " Fallthrough : block " << bb->fall_through 10980d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee << " (0x" << std::hex << GetBasicBlock(bb->fall_through)->start_offset << ")"; 10991fd3346740dfb7f47be9922312b68a4227fada96buzbee } 11001fd3346740dfb7f47be9922312b68a4227fada96buzbee } 11011fd3346740dfb7f47be9922312b68a4227fada96buzbee} 11021fd3346740dfb7f47be9922312b68a4227fada96buzbee 11031fd3346740dfb7f47be9922312b68a4227fada96buzbee/* 11041fd3346740dfb7f47be9922312b68a4227fada96buzbee * Build an array of location records for the incoming arguments. 11051fd3346740dfb7f47be9922312b68a4227fada96buzbee * Note: one location record per word of arguments, with dummy 11061fd3346740dfb7f47be9922312b68a4227fada96buzbee * high-word loc for wide arguments. Also pull up any following 11071fd3346740dfb7f47be9922312b68a4227fada96buzbee * MOVE_RESULT and incorporate it into the invoke. 11081fd3346740dfb7f47be9922312b68a4227fada96buzbee */ 11091fd3346740dfb7f47be9922312b68a4227fada96buzbeeCallInfo* MIRGraph::NewMemCallInfo(BasicBlock* bb, MIR* mir, InvokeType type, 11102ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom bool is_range) { 1111f6c4b3ba3825de1dbb3e747a68b809c6cc8eb4dbMathieu Chartier CallInfo* info = static_cast<CallInfo*>(arena_->Alloc(sizeof(CallInfo), 1112f6c4b3ba3825de1dbb3e747a68b809c6cc8eb4dbMathieu Chartier ArenaAllocator::kAllocMisc)); 11131fd3346740dfb7f47be9922312b68a4227fada96buzbee MIR* move_result_mir = FindMoveResult(bb, mir); 11141fd3346740dfb7f47be9922312b68a4227fada96buzbee if (move_result_mir == NULL) { 11151fd3346740dfb7f47be9922312b68a4227fada96buzbee info->result.location = kLocInvalid; 11161fd3346740dfb7f47be9922312b68a4227fada96buzbee } else { 11171fd3346740dfb7f47be9922312b68a4227fada96buzbee info->result = GetRawDest(move_result_mir); 11181fd3346740dfb7f47be9922312b68a4227fada96buzbee move_result_mir->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop); 11191fd3346740dfb7f47be9922312b68a4227fada96buzbee } 11201fd3346740dfb7f47be9922312b68a4227fada96buzbee info->num_arg_words = mir->ssa_rep->num_uses; 11211fd3346740dfb7f47be9922312b68a4227fada96buzbee info->args = (info->num_arg_words == 0) ? NULL : static_cast<RegLocation*> 1122f6c4b3ba3825de1dbb3e747a68b809c6cc8eb4dbMathieu Chartier (arena_->Alloc(sizeof(RegLocation) * info->num_arg_words, ArenaAllocator::kAllocMisc)); 11231fd3346740dfb7f47be9922312b68a4227fada96buzbee for (int i = 0; i < info->num_arg_words; i++) { 11241fd3346740dfb7f47be9922312b68a4227fada96buzbee info->args[i] = GetRawSrc(mir, i); 11251fd3346740dfb7f47be9922312b68a4227fada96buzbee } 11261fd3346740dfb7f47be9922312b68a4227fada96buzbee info->opt_flags = mir->optimization_flags; 11271fd3346740dfb7f47be9922312b68a4227fada96buzbee info->type = type; 11281fd3346740dfb7f47be9922312b68a4227fada96buzbee info->is_range = is_range; 11291fd3346740dfb7f47be9922312b68a4227fada96buzbee info->index = mir->dalvikInsn.vB; 11301fd3346740dfb7f47be9922312b68a4227fada96buzbee info->offset = mir->offset; 11311fd3346740dfb7f47be9922312b68a4227fada96buzbee return info; 11321fd3346740dfb7f47be9922312b68a4227fada96buzbee} 11331fd3346740dfb7f47be9922312b68a4227fada96buzbee 1134862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee// Allocate a new basic block. 11352ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromBasicBlock* MIRGraph::NewMemBB(BBType block_type, int block_id) { 1136f6c4b3ba3825de1dbb3e747a68b809c6cc8eb4dbMathieu Chartier BasicBlock* bb = static_cast<BasicBlock*>(arena_->Alloc(sizeof(BasicBlock), 1137f6c4b3ba3825de1dbb3e747a68b809c6cc8eb4dbMathieu Chartier ArenaAllocator::kAllocBB)); 1138862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee bb->block_type = block_type; 1139862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee bb->id = block_id; 1140862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee // TUNING: better estimate of the exit block predecessors? 11410d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee bb->predecessors = new (arena_) GrowableArray<BasicBlockId>(arena_, 1142df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom (block_type == kExitBlock) ? 2048 : 2, 1143df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom kGrowableArrayPredecessors); 11440d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee bb->successor_block_list_type = kNotUsed; 1145862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee block_id_map_.Put(block_id, block_id); 1146862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee return bb; 1147862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee} 11481fd3346740dfb7f47be9922312b68a4227fada96buzbee 11497934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom} // namespace art 1150