block_builder.cc revision 92f7f3ce3b01f7c7df1c15b81c900e087248093f
186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil/* 286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil * Copyright (C) 2016 The Android Open Source Project 386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil * 486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil * Licensed under the Apache License, Version 2.0 (the "License"); 586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil * you may not use this file except in compliance with the License. 686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil * You may obtain a copy of the License at 786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil * 886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil * http://www.apache.org/licenses/LICENSE-2.0 986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil * 1086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil * Unless required by applicable law or agreed to in writing, software 1186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil * distributed under the License is distributed on an "AS IS" BASIS, 1286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil * See the License for the specific language governing permissions and 1486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil * limitations under the License. 1586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil */ 1686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 1786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil#include "block_builder.h" 1886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 1986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil#include "bytecode_utils.h" 20de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier#include "quicken_info.h" 2186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 2286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdilnamespace art { 2386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 2486ea7eeabe30c98bbe1651a51d03cb89776724e7David BrazdilHBasicBlock* HBasicBlockBuilder::MaybeCreateBlockAt(uint32_t dex_pc) { 2586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return MaybeCreateBlockAt(dex_pc, dex_pc); 2686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 2786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 2886ea7eeabe30c98bbe1651a51d03cb89776724e7David BrazdilHBasicBlock* HBasicBlockBuilder::MaybeCreateBlockAt(uint32_t semantic_dex_pc, 2986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil uint32_t store_dex_pc) { 3086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil HBasicBlock* block = branch_targets_[store_dex_pc]; 3186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (block == nullptr) { 3269d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko block = new (allocator_) HBasicBlock(graph_, semantic_dex_pc); 3386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil branch_targets_[store_dex_pc] = block; 3486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 3586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil DCHECK_EQ(block->GetDexPc(), semantic_dex_pc); 3686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return block; 3786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 3886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 3986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdilbool HBasicBlockBuilder::CreateBranchTargets() { 4086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Create the first block for the dex instructions, single successor of the entry block. 4186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil MaybeCreateBlockAt(0u); 4286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 4392f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko if (code_item_->tries_size_ != 0) { 4486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Create branch targets at the start/end of the TryItem range. These are 4586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // places where the program might fall through into/out of the a block and 4686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // where TryBoundary instructions will be inserted later. Other edges which 4786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // enter/exit the try blocks are a result of branches/switches. 4892f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko for (size_t idx = 0; idx < code_item_->tries_size_; ++idx) { 4992f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item_, idx); 5086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil uint32_t dex_pc_start = try_item->start_addr_; 5186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil uint32_t dex_pc_end = dex_pc_start + try_item->insn_count_; 5286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil MaybeCreateBlockAt(dex_pc_start); 5392f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko if (dex_pc_end < code_item_->insns_size_in_code_units_) { 5486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // TODO: Do not create block if the last instruction cannot fall through. 5586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil MaybeCreateBlockAt(dex_pc_end); 5692f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko } else if (dex_pc_end == code_item_->insns_size_in_code_units_) { 5786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // The TryItem spans until the very end of the CodeItem and therefore 5886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // cannot have any code afterwards. 5986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } else { 6086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // The TryItem spans beyond the end of the CodeItem. This is invalid code. 6186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return false; 6286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 6386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 6486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 6586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Create branch targets for exception handlers. 6692f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(*code_item_, 0); 6786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr); 6886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (uint32_t idx = 0; idx < handlers_size; ++idx) { 6986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil CatchHandlerIterator iterator(handlers_ptr); 7086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (; iterator.HasNext(); iterator.Next()) { 7186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil MaybeCreateBlockAt(iterator.GetHandlerAddress()); 7286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 7386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil handlers_ptr = iterator.EndDataPointer(); 7486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 7586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 7686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 7786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Iterate over all instructions and find branching instructions. Create blocks for 7886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // the locations these instructions branch to. 7992f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko IterationRange<DexInstructionIterator> instructions = code_item_->Instructions(); 800021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier for (const DexInstructionPcPair& pair : instructions) { 810021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier const uint32_t dex_pc = pair.DexPc(); 820021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier const Instruction& instruction = pair.Inst(); 8386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 8486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (instruction.IsBranch()) { 8586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil number_of_branches_++; 8686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil MaybeCreateBlockAt(dex_pc + instruction.GetTargetOffset()); 8786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } else if (instruction.IsSwitch()) { 8886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil DexSwitchTable table(instruction, dex_pc); 8986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (DexSwitchTableIterator s_it(table); !s_it.Done(); s_it.Advance()) { 9086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil MaybeCreateBlockAt(dex_pc + s_it.CurrentTargetOffset()); 9186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 9286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Create N-1 blocks where we will insert comparisons of the input value 9386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // against the Switch's case keys. 9486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (table.ShouldBuildDecisionTree() && !s_it.IsLast()) { 9586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Store the block under dex_pc of the current key at the switch data 9686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // instruction for uniqueness but give it the dex_pc of the SWITCH 9786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // instruction which it semantically belongs to. 9886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil MaybeCreateBlockAt(dex_pc, s_it.GetDexPcForCurrentIndex()); 9986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 10086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 10186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } else if (instruction.Opcode() == Instruction::MOVE_EXCEPTION) { 10286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // End the basic block after MOVE_EXCEPTION. This simplifies the later 10386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // stage of TryBoundary-block insertion. 10486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } else { 10586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil continue; 10686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 10786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 10886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (instruction.CanFlowThrough()) { 1090021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier DexInstructionIterator next(std::next(DexInstructionIterator(pair))); 1100021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier if (next == instructions.end()) { 11186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // In the normal case we should never hit this but someone can artificially forge a dex 11286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // file to fall-through out the method code. In this case we bail out compilation. 11386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return false; 11486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 1150021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier MaybeCreateBlockAt(next.DexPc()); 11686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 11786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 11886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 11986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return true; 12086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 12186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 12286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdilvoid HBasicBlockBuilder::ConnectBasicBlocks() { 12386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil HBasicBlock* block = graph_->GetEntryBlock(); 12486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil graph_->AddBlock(block); 12586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 126de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier size_t quicken_index = 0; 12786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil bool is_throwing_block = false; 128de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier // Calculate the qucikening index here instead of CreateBranchTargets since it's easier to 129de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier // calculate in dex_pc order. 13092f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko for (const DexInstructionPcPair& pair : code_item_->Instructions()) { 1310021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier const uint32_t dex_pc = pair.DexPc(); 1320021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier const Instruction& instruction = pair.Inst(); 13386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 13486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Check if this dex_pc address starts a new basic block. 13586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil HBasicBlock* next_block = GetBlockAt(dex_pc); 13686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (next_block != nullptr) { 137de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier // We only need quicken index entries for basic block boundaries. 138de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier quicken_index_for_dex_pc_.Put(dex_pc, quicken_index); 13986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (block != nullptr) { 14086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Last instruction did not end its basic block but a new one starts here. 14186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // It must have been a block falling through into the next one. 14286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil block->AddSuccessor(next_block); 14386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 14486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil block = next_block; 14586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil is_throwing_block = false; 14686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil graph_->AddBlock(block); 14786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 148de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier // Make sure to increment this before the continues. 1490021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier if (QuickenInfoTable::NeedsIndexForInstruction(&instruction)) { 150de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier ++quicken_index; 151de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier } 15286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 15386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (block == nullptr) { 15486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Ignore dead code. 15586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil continue; 15686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 15786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 15886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (!is_throwing_block && IsThrowingDexInstruction(instruction)) { 15986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil DCHECK(!ContainsElement(throwing_blocks_, block)); 16086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil is_throwing_block = true; 16186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil throwing_blocks_.push_back(block); 16286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 16386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 16486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (instruction.IsBranch()) { 16586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil uint32_t target_dex_pc = dex_pc + instruction.GetTargetOffset(); 16686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil block->AddSuccessor(GetBlockAt(target_dex_pc)); 16786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } else if (instruction.IsReturn() || (instruction.Opcode() == Instruction::THROW)) { 16886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil block->AddSuccessor(graph_->GetExitBlock()); 16986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } else if (instruction.IsSwitch()) { 17086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil DexSwitchTable table(instruction, dex_pc); 17186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (DexSwitchTableIterator s_it(table); !s_it.Done(); s_it.Advance()) { 17286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil uint32_t target_dex_pc = dex_pc + s_it.CurrentTargetOffset(); 17386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil block->AddSuccessor(GetBlockAt(target_dex_pc)); 17486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 17586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (table.ShouldBuildDecisionTree() && !s_it.IsLast()) { 17686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil uint32_t next_case_dex_pc = s_it.GetDexPcForCurrentIndex(); 17786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil HBasicBlock* next_case_block = GetBlockAt(next_case_dex_pc); 17886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil block->AddSuccessor(next_case_block); 17986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil block = next_case_block; 18086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil graph_->AddBlock(block); 18186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 18286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 18386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } else { 18486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Remaining code only applies to instructions which end their basic block. 18586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil continue; 18686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 18786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 1880021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier // Go to the next instruction in case we read dex PC below. 18986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (instruction.CanFlowThrough()) { 1900021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier block->AddSuccessor(GetBlockAt(std::next(DexInstructionIterator(pair)).DexPc())); 19186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 19286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 19386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // The basic block ends here. Do not add any more instructions. 19486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil block = nullptr; 19586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 19686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 19786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil graph_->AddBlock(graph_->GetExitBlock()); 19886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 19986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 20086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil// Returns the TryItem stored for `block` or nullptr if there is no info for it. 20186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdilstatic const DexFile::TryItem* GetTryItem( 20286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil HBasicBlock* block, 20369d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko const ScopedArenaSafeMap<uint32_t, const DexFile::TryItem*>& try_block_info) { 20486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil auto iterator = try_block_info.find(block->GetBlockId()); 20586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return (iterator == try_block_info.end()) ? nullptr : iterator->second; 20686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 20786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 20886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil// Iterates over the exception handlers of `try_item`, finds the corresponding 20986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil// catch blocks and makes them successors of `try_boundary`. The order of 21086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil// successors matches the order in which runtime exception delivery searches 21186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil// for a handler. 21286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdilstatic void LinkToCatchBlocks(HTryBoundary* try_boundary, 21386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil const DexFile::CodeItem& code_item, 21486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil const DexFile::TryItem* try_item, 21569d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko const ScopedArenaSafeMap<uint32_t, HBasicBlock*>& catch_blocks) { 21686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (CatchHandlerIterator it(code_item, *try_item); it.HasNext(); it.Next()) { 21786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil try_boundary->AddExceptionHandler(catch_blocks.Get(it.GetHandlerAddress())); 21886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 21986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 22086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 22186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdilbool HBasicBlockBuilder::MightHaveLiveNormalPredecessors(HBasicBlock* catch_block) { 22286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (kIsDebugBuild) { 22386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil DCHECK_NE(catch_block->GetDexPc(), kNoDexPc) << "Should not be called on synthetic blocks"; 22486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil DCHECK(!graph_->GetEntryBlock()->GetSuccessors().empty()) 22586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil << "Basic blocks must have been created and connected"; 22686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (HBasicBlock* predecessor : catch_block->GetPredecessors()) { 22786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil DCHECK(!predecessor->IsSingleTryBoundary()) 22886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil << "TryBoundary blocks must not have not been created yet"; 22986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 23086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 23186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 23292f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko const Instruction& first = code_item_->InstructionAt(catch_block->GetDexPc()); 23386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (first.Opcode() == Instruction::MOVE_EXCEPTION) { 23486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Verifier guarantees that if a catch block begins with MOVE_EXCEPTION then 23586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // it has no live normal predecessors. 23686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return false; 23786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } else if (catch_block->GetPredecessors().empty()) { 23886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Normal control-flow edges have already been created. Since block's list of 23986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // predecessors is empty, it cannot have any live or dead normal predecessors. 24086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return false; 24186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 24286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 24386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // The catch block has normal predecessors but we do not know which are live 24486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // and which will be removed during the initial DCE. Return `true` to signal 24586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // that it may have live normal predecessors. 24686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return true; 24786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 24886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 24986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdilvoid HBasicBlockBuilder::InsertTryBoundaryBlocks() { 25092f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko if (code_item_->tries_size_ == 0) { 25186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return; 25286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 25386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 25486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Keep a map of all try blocks and their respective TryItems. We do not use 25586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // the block's pointer but rather its id to ensure deterministic iteration. 25669d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko ScopedArenaSafeMap<uint32_t, const DexFile::TryItem*> try_block_info( 25769d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko std::less<uint32_t>(), local_allocator_->Adapter(kArenaAllocGraphBuilder)); 25886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 25986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Obtain TryItem information for blocks with throwing instructions, and split 26086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // blocks which are both try & catch to simplify the graph. 26186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (HBasicBlock* block : graph_->GetBlocks()) { 26286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (block->GetDexPc() == kNoDexPc) { 26386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil continue; 26486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 26586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 26686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Do not bother creating exceptional edges for try blocks which have no 26786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // throwing instructions. In that case we simply assume that the block is 26886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // not covered by a TryItem. This prevents us from creating a throw-catch 26986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // loop for synchronized blocks. 27086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (ContainsElement(throwing_blocks_, block)) { 27186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Try to find a TryItem covering the block. 27292f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko const int32_t try_item_idx = DexFile::FindTryItem(DexFile::GetTryItems(*code_item_, 0u), 27392f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko code_item_->tries_size_, 2743da1d0f0881e130ebab95e2d06abe7d2beff57f0Mathieu Chartier block->GetDexPc()); 27586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (try_item_idx != -1) { 27686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Block throwing and in a TryItem. Store the try block information. 27792f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko try_block_info.Put(block->GetBlockId(), DexFile::GetTryItems(*code_item_, try_item_idx)); 27886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 27986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 28086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 28186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 28286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Map from a handler dex_pc to the corresponding catch block. 28369d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko ScopedArenaSafeMap<uint32_t, HBasicBlock*> catch_blocks( 28469d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko std::less<uint32_t>(), local_allocator_->Adapter(kArenaAllocGraphBuilder)); 28586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 28686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Iterate over catch blocks, create artifical landing pads if necessary to 28786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // simplify the CFG, and set metadata. 28892f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(*code_item_, 0); 28986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr); 29086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (uint32_t idx = 0; idx < handlers_size; ++idx) { 29186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil CatchHandlerIterator iterator(handlers_ptr); 29286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (; iterator.HasNext(); iterator.Next()) { 29386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil uint32_t address = iterator.GetHandlerAddress(); 29486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (catch_blocks.find(address) != catch_blocks.end()) { 29586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Catch block already processed. 29686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil continue; 29786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 29886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 29986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Check if we should create an artifical landing pad for the catch block. 30086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // We create one if the catch block is also a try block because we do not 30186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // have a strategy for inserting TryBoundaries on exceptional edges. 30286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // We also create one if the block might have normal predecessors so as to 30386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // simplify register allocation. 30486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil HBasicBlock* catch_block = GetBlockAt(address); 30586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil bool is_try_block = (try_block_info.find(catch_block->GetBlockId()) != try_block_info.end()); 30686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (is_try_block || MightHaveLiveNormalPredecessors(catch_block)) { 30769d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko HBasicBlock* new_catch_block = new (allocator_) HBasicBlock(graph_, address); 30869d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko new_catch_block->AddInstruction(new (allocator_) HGoto(address)); 30986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil new_catch_block->AddSuccessor(catch_block); 31086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil graph_->AddBlock(new_catch_block); 31186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil catch_block = new_catch_block; 31286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 31386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 31486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil catch_blocks.Put(address, catch_block); 31586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil catch_block->SetTryCatchInformation( 31669d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko new (allocator_) TryCatchInformation(iterator.GetHandlerTypeIndex(), *dex_file_)); 31786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 31886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil handlers_ptr = iterator.EndDataPointer(); 31986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 32086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 32186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Do a pass over the try blocks and insert entering TryBoundaries where at 32286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // least one predecessor is not covered by the same TryItem as the try block. 32386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // We do not split each edge separately, but rather create one boundary block 32486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // that all predecessors are relinked to. This preserves loop headers (b/23895756). 3257d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko for (const auto& entry : try_block_info) { 3267d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko uint32_t block_id = entry.first; 3277d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko const DexFile::TryItem* try_item = entry.second; 3287d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko HBasicBlock* try_block = graph_->GetBlocks()[block_id]; 32986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (HBasicBlock* predecessor : try_block->GetPredecessors()) { 3307d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko if (GetTryItem(predecessor, try_block_info) != try_item) { 33186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Found a predecessor not covered by the same TryItem. Insert entering 33286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // boundary block. 33369d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko HTryBoundary* try_entry = new (allocator_) HTryBoundary( 33469d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko HTryBoundary::BoundaryKind::kEntry, try_block->GetDexPc()); 33586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil try_block->CreateImmediateDominator()->AddInstruction(try_entry); 33692f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko LinkToCatchBlocks(try_entry, *code_item_, try_item, catch_blocks); 33786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil break; 33886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 33986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 34086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 34186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 34286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Do a second pass over the try blocks and insert exit TryBoundaries where 34386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // the successor is not in the same TryItem. 3447d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko for (const auto& entry : try_block_info) { 3457d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko uint32_t block_id = entry.first; 3467d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko const DexFile::TryItem* try_item = entry.second; 3477d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko HBasicBlock* try_block = graph_->GetBlocks()[block_id]; 34886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // NOTE: Do not use iterators because SplitEdge would invalidate them. 34986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (size_t i = 0, e = try_block->GetSuccessors().size(); i < e; ++i) { 35086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil HBasicBlock* successor = try_block->GetSuccessors()[i]; 35186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 35286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // If the successor is a try block, all of its predecessors must be 35386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // covered by the same TryItem. Otherwise the previous pass would have 35486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // created a non-throwing boundary block. 35586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (GetTryItem(successor, try_block_info) != nullptr) { 3567d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko DCHECK_EQ(try_item, GetTryItem(successor, try_block_info)); 35786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil continue; 35886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 35986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 36086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Insert TryBoundary and link to catch blocks. 36186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil HTryBoundary* try_exit = 36269d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko new (allocator_) HTryBoundary(HTryBoundary::BoundaryKind::kExit, successor->GetDexPc()); 36386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil graph_->SplitEdge(try_block, successor)->AddInstruction(try_exit); 36492f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko LinkToCatchBlocks(try_exit, *code_item_, try_item, catch_blocks); 36586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 36686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 36786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 36886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 36986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdilbool HBasicBlockBuilder::Build() { 37092f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko DCHECK(code_item_ != nullptr); 37186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil DCHECK(graph_->GetBlocks().empty()); 37286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 37369d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko graph_->SetEntryBlock(new (allocator_) HBasicBlock(graph_, kNoDexPc)); 37469d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko graph_->SetExitBlock(new (allocator_) HBasicBlock(graph_, kNoDexPc)); 37586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 37686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // TODO(dbrazdil): Do CreateBranchTargets and ConnectBasicBlocks in one pass. 37786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (!CreateBranchTargets()) { 37886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return false; 37986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 38086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 38186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil ConnectBasicBlocks(); 38286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil InsertTryBoundaryBlocks(); 38386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 38486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return true; 38586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 38686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 38792f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Markovoid HBasicBlockBuilder::BuildIntrinsic() { 38892f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko DCHECK(code_item_ == nullptr); 38992f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko DCHECK(graph_->GetBlocks().empty()); 39092f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko 39192f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko // Create blocks. 39292f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko HBasicBlock* entry_block = new (allocator_) HBasicBlock(graph_, kNoDexPc); 39392f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko HBasicBlock* exit_block = new (allocator_) HBasicBlock(graph_, kNoDexPc); 39492f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko HBasicBlock* body = MaybeCreateBlockAt(/* semantic_dex_pc */ kNoDexPc, /* store_dex_pc */ 0u); 39592f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko 39692f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko // Add blocks to the graph. 39792f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko graph_->AddBlock(entry_block); 39892f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko graph_->AddBlock(body); 39992f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko graph_->AddBlock(exit_block); 40092f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko graph_->SetEntryBlock(entry_block); 40192f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko graph_->SetExitBlock(exit_block); 40292f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko 40392f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko // Connect blocks. 40492f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko entry_block->AddSuccessor(body); 40592f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko body->AddSuccessor(exit_block); 40692f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko} 40792f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko 408de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartiersize_t HBasicBlockBuilder::GetQuickenIndex(uint32_t dex_pc) const { 409de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier return quicken_index_for_dex_pc_.Get(dex_pc); 410de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier} 411de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier 41286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} // namespace art 413