block_builder.cc revision e6564f4efe74b2bb505a5810852141404b82a4a9
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 1957943810cfc789da890d73621741729da5feaaf8Andreas Gampe#include "base/logging.h" // FOR VLOG. 20e6564f4efe74b2bb505a5810852141404b82a4a9David Sehr#include "dex/bytecode_utils.h" 219e734c7ab4599d7747a05db0dc73c7b668cb6683David Sehr#include "dex/code_item_accessors-inl.h" 229e734c7ab4599d7747a05db0dc73c7b668cb6683David Sehr#include "dex/dex_file_exception_helpers.h" 23de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier#include "quicken_info.h" 2486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 2586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdilnamespace art { 2686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 27808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu ChartierHBasicBlockBuilder::HBasicBlockBuilder(HGraph* graph, 28808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier const DexFile* const dex_file, 29808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier const CodeItemDebugInfoAccessor& accessor, 30808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier ScopedArenaAllocator* local_allocator) 31808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier : allocator_(graph->GetAllocator()), 32808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier graph_(graph), 33808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier dex_file_(dex_file), 34808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier code_item_accessor_(accessor), 35808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier local_allocator_(local_allocator), 36808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier branch_targets_(code_item_accessor_.HasCodeItem() 37808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier ? code_item_accessor_.InsnsSizeInCodeUnits() 38808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier : /* fake dex_pc=0 for intrinsic graph */ 1u, 39808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier nullptr, 40808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier local_allocator->Adapter(kArenaAllocGraphBuilder)), 41808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier throwing_blocks_(kDefaultNumberOfThrowingBlocks, 42808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier local_allocator->Adapter(kArenaAllocGraphBuilder)), 43808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier number_of_branches_(0u), 44808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier quicken_index_for_dex_pc_(std::less<uint32_t>(), 45808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier local_allocator->Adapter(kArenaAllocGraphBuilder)) {} 46808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier 4786ea7eeabe30c98bbe1651a51d03cb89776724e7David BrazdilHBasicBlock* HBasicBlockBuilder::MaybeCreateBlockAt(uint32_t dex_pc) { 4886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return MaybeCreateBlockAt(dex_pc, dex_pc); 4986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 5086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 5186ea7eeabe30c98bbe1651a51d03cb89776724e7David BrazdilHBasicBlock* HBasicBlockBuilder::MaybeCreateBlockAt(uint32_t semantic_dex_pc, 5286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil uint32_t store_dex_pc) { 5386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil HBasicBlock* block = branch_targets_[store_dex_pc]; 5486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (block == nullptr) { 5569d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko block = new (allocator_) HBasicBlock(graph_, semantic_dex_pc); 5686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil branch_targets_[store_dex_pc] = block; 5786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 5886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil DCHECK_EQ(block->GetDexPc(), semantic_dex_pc); 5986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return block; 6086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 6186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 6286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdilbool HBasicBlockBuilder::CreateBranchTargets() { 6386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Create the first block for the dex instructions, single successor of the entry block. 6486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil MaybeCreateBlockAt(0u); 6586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 66808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier if (code_item_accessor_.TriesSize() != 0) { 6786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Create branch targets at the start/end of the TryItem range. These are 6886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // places where the program might fall through into/out of the a block and 6986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // where TryBoundary instructions will be inserted later. Other edges which 7086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // enter/exit the try blocks are a result of branches/switches. 71808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier for (const DexFile::TryItem& try_item : code_item_accessor_.TryItems()) { 72808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier uint32_t dex_pc_start = try_item.start_addr_; 73808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier uint32_t dex_pc_end = dex_pc_start + try_item.insn_count_; 7486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil MaybeCreateBlockAt(dex_pc_start); 75808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier if (dex_pc_end < code_item_accessor_.InsnsSizeInCodeUnits()) { 7686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // TODO: Do not create block if the last instruction cannot fall through. 7786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil MaybeCreateBlockAt(dex_pc_end); 78808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier } else if (dex_pc_end == code_item_accessor_.InsnsSizeInCodeUnits()) { 7986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // The TryItem spans until the very end of the CodeItem and therefore 8086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // cannot have any code afterwards. 8186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } else { 8286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // The TryItem spans beyond the end of the CodeItem. This is invalid code. 83dbb9aef046301940d0b253c918a5c78b277330baNicolas Geoffray VLOG(compiler) << "Not compiled: TryItem spans beyond the end of the CodeItem"; 8486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return false; 8586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 8686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 8786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 8886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Create branch targets for exception handlers. 89808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier const uint8_t* handlers_ptr = code_item_accessor_.GetCatchHandlerData(); 9086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr); 9186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (uint32_t idx = 0; idx < handlers_size; ++idx) { 9286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil CatchHandlerIterator iterator(handlers_ptr); 9386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (; iterator.HasNext(); iterator.Next()) { 9486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil MaybeCreateBlockAt(iterator.GetHandlerAddress()); 9586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 9686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil handlers_ptr = iterator.EndDataPointer(); 9786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 9886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 9986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 10086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Iterate over all instructions and find branching instructions. Create blocks for 10186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // the locations these instructions branch to. 102808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier for (const DexInstructionPcPair& pair : code_item_accessor_) { 1030021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier const uint32_t dex_pc = pair.DexPc(); 1040021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier const Instruction& instruction = pair.Inst(); 10586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 10686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (instruction.IsBranch()) { 10786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil number_of_branches_++; 10886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil MaybeCreateBlockAt(dex_pc + instruction.GetTargetOffset()); 10986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } else if (instruction.IsSwitch()) { 11086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil DexSwitchTable table(instruction, dex_pc); 11186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (DexSwitchTableIterator s_it(table); !s_it.Done(); s_it.Advance()) { 11286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil MaybeCreateBlockAt(dex_pc + s_it.CurrentTargetOffset()); 11386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 11486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Create N-1 blocks where we will insert comparisons of the input value 11586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // against the Switch's case keys. 11686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (table.ShouldBuildDecisionTree() && !s_it.IsLast()) { 11786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Store the block under dex_pc of the current key at the switch data 11886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // instruction for uniqueness but give it the dex_pc of the SWITCH 11986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // instruction which it semantically belongs to. 12086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil MaybeCreateBlockAt(dex_pc, s_it.GetDexPcForCurrentIndex()); 12186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 12286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 12386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } else if (instruction.Opcode() == Instruction::MOVE_EXCEPTION) { 12486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // End the basic block after MOVE_EXCEPTION. This simplifies the later 12586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // stage of TryBoundary-block insertion. 12686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } else { 12786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil continue; 12886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 12986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 13086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (instruction.CanFlowThrough()) { 1310021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier DexInstructionIterator next(std::next(DexInstructionIterator(pair))); 132808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier if (next == code_item_accessor_.end()) { 13386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // In the normal case we should never hit this but someone can artificially forge a dex 13486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // file to fall-through out the method code. In this case we bail out compilation. 135dbb9aef046301940d0b253c918a5c78b277330baNicolas Geoffray VLOG(compiler) << "Not compiled: Fall-through beyond the CodeItem"; 13686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return false; 13786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 1380021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier MaybeCreateBlockAt(next.DexPc()); 13986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 14086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 14186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 14286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return true; 14386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 14486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 14586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdilvoid HBasicBlockBuilder::ConnectBasicBlocks() { 14686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil HBasicBlock* block = graph_->GetEntryBlock(); 14786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil graph_->AddBlock(block); 14886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 149de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier size_t quicken_index = 0; 15086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil bool is_throwing_block = false; 151de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier // Calculate the qucikening index here instead of CreateBranchTargets since it's easier to 152de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier // calculate in dex_pc order. 153808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier for (const DexInstructionPcPair& pair : code_item_accessor_) { 1540021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier const uint32_t dex_pc = pair.DexPc(); 1550021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier const Instruction& instruction = pair.Inst(); 15686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 15786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Check if this dex_pc address starts a new basic block. 15886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil HBasicBlock* next_block = GetBlockAt(dex_pc); 15986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (next_block != nullptr) { 160de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier // We only need quicken index entries for basic block boundaries. 161de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier quicken_index_for_dex_pc_.Put(dex_pc, quicken_index); 16286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (block != nullptr) { 16386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Last instruction did not end its basic block but a new one starts here. 16486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // It must have been a block falling through into the next one. 16586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil block->AddSuccessor(next_block); 16686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 16786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil block = next_block; 16886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil is_throwing_block = false; 16986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil graph_->AddBlock(block); 17086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 171de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier // Make sure to increment this before the continues. 1720021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier if (QuickenInfoTable::NeedsIndexForInstruction(&instruction)) { 173de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier ++quicken_index; 174de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier } 17586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 17686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (block == nullptr) { 17786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Ignore dead code. 17886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil continue; 17986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 18086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 18186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (!is_throwing_block && IsThrowingDexInstruction(instruction)) { 18286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil DCHECK(!ContainsElement(throwing_blocks_, block)); 18386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil is_throwing_block = true; 18486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil throwing_blocks_.push_back(block); 18586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 18686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 18786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (instruction.IsBranch()) { 18886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil uint32_t target_dex_pc = dex_pc + instruction.GetTargetOffset(); 18986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil block->AddSuccessor(GetBlockAt(target_dex_pc)); 19086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } else if (instruction.IsReturn() || (instruction.Opcode() == Instruction::THROW)) { 19186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil block->AddSuccessor(graph_->GetExitBlock()); 19286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } else if (instruction.IsSwitch()) { 19386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil DexSwitchTable table(instruction, dex_pc); 19486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (DexSwitchTableIterator s_it(table); !s_it.Done(); s_it.Advance()) { 19586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil uint32_t target_dex_pc = dex_pc + s_it.CurrentTargetOffset(); 19686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil block->AddSuccessor(GetBlockAt(target_dex_pc)); 19786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 19886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (table.ShouldBuildDecisionTree() && !s_it.IsLast()) { 19986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil uint32_t next_case_dex_pc = s_it.GetDexPcForCurrentIndex(); 20086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil HBasicBlock* next_case_block = GetBlockAt(next_case_dex_pc); 20186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil block->AddSuccessor(next_case_block); 20286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil block = next_case_block; 20386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil graph_->AddBlock(block); 20486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 20586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 20686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } else { 20786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Remaining code only applies to instructions which end their basic block. 20886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil continue; 20986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 21086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 2110021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier // Go to the next instruction in case we read dex PC below. 21286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (instruction.CanFlowThrough()) { 2130021feb36ca7021e2c255e6eaf16b967180290c6Mathieu Chartier block->AddSuccessor(GetBlockAt(std::next(DexInstructionIterator(pair)).DexPc())); 21486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 21586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 21686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // The basic block ends here. Do not add any more instructions. 21786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil block = nullptr; 21886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 21986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 22086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil graph_->AddBlock(graph_->GetExitBlock()); 22186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 22286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 22386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil// Returns the TryItem stored for `block` or nullptr if there is no info for it. 22486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdilstatic const DexFile::TryItem* GetTryItem( 22586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil HBasicBlock* block, 22669d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko const ScopedArenaSafeMap<uint32_t, const DexFile::TryItem*>& try_block_info) { 22786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil auto iterator = try_block_info.find(block->GetBlockId()); 22886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return (iterator == try_block_info.end()) ? nullptr : iterator->second; 22986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 23086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 23186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil// Iterates over the exception handlers of `try_item`, finds the corresponding 23286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil// catch blocks and makes them successors of `try_boundary`. The order of 23386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil// successors matches the order in which runtime exception delivery searches 23486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil// for a handler. 23586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdilstatic void LinkToCatchBlocks(HTryBoundary* try_boundary, 236808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier const CodeItemDataAccessor& accessor, 23786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil const DexFile::TryItem* try_item, 23869d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko const ScopedArenaSafeMap<uint32_t, HBasicBlock*>& catch_blocks) { 239808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier for (CatchHandlerIterator it(accessor.GetCatchHandlerData(try_item->handler_off_)); 240808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier it.HasNext(); 241808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier it.Next()) { 24286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil try_boundary->AddExceptionHandler(catch_blocks.Get(it.GetHandlerAddress())); 24386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 24486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 24586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 24686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdilbool HBasicBlockBuilder::MightHaveLiveNormalPredecessors(HBasicBlock* catch_block) { 24786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (kIsDebugBuild) { 24886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil DCHECK_NE(catch_block->GetDexPc(), kNoDexPc) << "Should not be called on synthetic blocks"; 24986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil DCHECK(!graph_->GetEntryBlock()->GetSuccessors().empty()) 25086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil << "Basic blocks must have been created and connected"; 25186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (HBasicBlock* predecessor : catch_block->GetPredecessors()) { 25286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil DCHECK(!predecessor->IsSingleTryBoundary()) 25386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil << "TryBoundary blocks must not have not been created yet"; 25486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 25586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 25686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 257808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier const Instruction& first = code_item_accessor_.InstructionAt(catch_block->GetDexPc()); 25886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (first.Opcode() == Instruction::MOVE_EXCEPTION) { 25986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Verifier guarantees that if a catch block begins with MOVE_EXCEPTION then 26086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // it has no live normal predecessors. 26186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return false; 26286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } else if (catch_block->GetPredecessors().empty()) { 26386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Normal control-flow edges have already been created. Since block's list of 26486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // predecessors is empty, it cannot have any live or dead normal predecessors. 26586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return false; 26686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 26786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 26886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // The catch block has normal predecessors but we do not know which are live 26986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // and which will be removed during the initial DCE. Return `true` to signal 27086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // that it may have live normal predecessors. 27186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return true; 27286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 27386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 27486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdilvoid HBasicBlockBuilder::InsertTryBoundaryBlocks() { 275808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier if (code_item_accessor_.TriesSize() == 0) { 27686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return; 27786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 27886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 27986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Keep a map of all try blocks and their respective TryItems. We do not use 28086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // the block's pointer but rather its id to ensure deterministic iteration. 28169d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko ScopedArenaSafeMap<uint32_t, const DexFile::TryItem*> try_block_info( 28269d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko std::less<uint32_t>(), local_allocator_->Adapter(kArenaAllocGraphBuilder)); 28386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 28486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Obtain TryItem information for blocks with throwing instructions, and split 28586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // blocks which are both try & catch to simplify the graph. 28686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (HBasicBlock* block : graph_->GetBlocks()) { 28786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (block->GetDexPc() == kNoDexPc) { 28886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil continue; 28986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 29086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 29186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Do not bother creating exceptional edges for try blocks which have no 29286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // throwing instructions. In that case we simply assume that the block is 29386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // not covered by a TryItem. This prevents us from creating a throw-catch 29486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // loop for synchronized blocks. 29586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (ContainsElement(throwing_blocks_, block)) { 29686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Try to find a TryItem covering the block. 297808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier const DexFile::TryItem* try_item = code_item_accessor_.FindTryItem(block->GetDexPc()); 298808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier if (try_item != nullptr) { 29986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Block throwing and in a TryItem. Store the try block information. 300808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier try_block_info.Put(block->GetBlockId(), try_item); 30186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 30286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 30386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 30486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 30586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Map from a handler dex_pc to the corresponding catch block. 30669d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko ScopedArenaSafeMap<uint32_t, HBasicBlock*> catch_blocks( 30769d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko std::less<uint32_t>(), local_allocator_->Adapter(kArenaAllocGraphBuilder)); 30886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 30986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Iterate over catch blocks, create artifical landing pads if necessary to 31086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // simplify the CFG, and set metadata. 311808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier const uint8_t* handlers_ptr = code_item_accessor_.GetCatchHandlerData(); 31286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr); 31386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (uint32_t idx = 0; idx < handlers_size; ++idx) { 31486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil CatchHandlerIterator iterator(handlers_ptr); 31586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (; iterator.HasNext(); iterator.Next()) { 31686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil uint32_t address = iterator.GetHandlerAddress(); 31786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (catch_blocks.find(address) != catch_blocks.end()) { 31886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Catch block already processed. 31986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil continue; 32086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 32186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 32286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Check if we should create an artifical landing pad for the catch block. 32386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // We create one if the catch block is also a try block because we do not 32486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // have a strategy for inserting TryBoundaries on exceptional edges. 32586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // We also create one if the block might have normal predecessors so as to 32686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // simplify register allocation. 32786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil HBasicBlock* catch_block = GetBlockAt(address); 32886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil bool is_try_block = (try_block_info.find(catch_block->GetBlockId()) != try_block_info.end()); 32986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (is_try_block || MightHaveLiveNormalPredecessors(catch_block)) { 33069d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko HBasicBlock* new_catch_block = new (allocator_) HBasicBlock(graph_, address); 33169d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko new_catch_block->AddInstruction(new (allocator_) HGoto(address)); 33286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil new_catch_block->AddSuccessor(catch_block); 33386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil graph_->AddBlock(new_catch_block); 33486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil catch_block = new_catch_block; 33586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 33686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 33786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil catch_blocks.Put(address, catch_block); 33886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil catch_block->SetTryCatchInformation( 33969d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko new (allocator_) TryCatchInformation(iterator.GetHandlerTypeIndex(), *dex_file_)); 34086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 34186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil handlers_ptr = iterator.EndDataPointer(); 34286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 34386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 34486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Do a pass over the try blocks and insert entering TryBoundaries where at 34586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // least one predecessor is not covered by the same TryItem as the try block. 34686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // We do not split each edge separately, but rather create one boundary block 34786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // that all predecessors are relinked to. This preserves loop headers (b/23895756). 3487d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko for (const auto& entry : try_block_info) { 3497d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko uint32_t block_id = entry.first; 3507d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko const DexFile::TryItem* try_item = entry.second; 3517d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko HBasicBlock* try_block = graph_->GetBlocks()[block_id]; 35286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (HBasicBlock* predecessor : try_block->GetPredecessors()) { 3537d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko if (GetTryItem(predecessor, try_block_info) != try_item) { 35486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Found a predecessor not covered by the same TryItem. Insert entering 35586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // boundary block. 35669d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko HTryBoundary* try_entry = new (allocator_) HTryBoundary( 35769d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko HTryBoundary::BoundaryKind::kEntry, try_block->GetDexPc()); 35886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil try_block->CreateImmediateDominator()->AddInstruction(try_entry); 359808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier LinkToCatchBlocks(try_entry, code_item_accessor_, try_item, catch_blocks); 36086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil break; 36186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 36286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 36386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 36486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 36586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Do a second pass over the try blocks and insert exit TryBoundaries where 36686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // the successor is not in the same TryItem. 3677d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko for (const auto& entry : try_block_info) { 3687d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko uint32_t block_id = entry.first; 3697d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko const DexFile::TryItem* try_item = entry.second; 3707d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko HBasicBlock* try_block = graph_->GetBlocks()[block_id]; 37186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // NOTE: Do not use iterators because SplitEdge would invalidate them. 37286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil for (size_t i = 0, e = try_block->GetSuccessors().size(); i < e; ++i) { 37386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil HBasicBlock* successor = try_block->GetSuccessors()[i]; 37486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 37586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // If the successor is a try block, all of its predecessors must be 37686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // covered by the same TryItem. Otherwise the previous pass would have 37786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // created a non-throwing boundary block. 37886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (GetTryItem(successor, try_block_info) != nullptr) { 3797d157fcaaae137cc98dbfb872aa1bdc0105a898fVladimir Marko DCHECK_EQ(try_item, GetTryItem(successor, try_block_info)); 38086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil continue; 38186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 38286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 38386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // Insert TryBoundary and link to catch blocks. 38486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil HTryBoundary* try_exit = 38569d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko new (allocator_) HTryBoundary(HTryBoundary::BoundaryKind::kExit, successor->GetDexPc()); 38686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil graph_->SplitEdge(try_block, successor)->AddInstruction(try_exit); 387808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier LinkToCatchBlocks(try_exit, code_item_accessor_, try_item, catch_blocks); 38886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 38986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 39086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 39186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 39286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdilbool HBasicBlockBuilder::Build() { 393808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier DCHECK(code_item_accessor_.HasCodeItem()); 39486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil DCHECK(graph_->GetBlocks().empty()); 39586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 39669d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko graph_->SetEntryBlock(new (allocator_) HBasicBlock(graph_, kNoDexPc)); 39769d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko graph_->SetExitBlock(new (allocator_) HBasicBlock(graph_, kNoDexPc)); 39886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 39986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil // TODO(dbrazdil): Do CreateBranchTargets and ConnectBasicBlocks in one pass. 40086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil if (!CreateBranchTargets()) { 40186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return false; 40286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil } 40386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 40486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil ConnectBasicBlocks(); 40586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil InsertTryBoundaryBlocks(); 40686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 40786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil return true; 40886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} 40986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil 41092f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Markovoid HBasicBlockBuilder::BuildIntrinsic() { 411808c7a57bb913b13c22884f57cdacd59bf1fdb3fMathieu Chartier DCHECK(!code_item_accessor_.HasCodeItem()); 41292f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko DCHECK(graph_->GetBlocks().empty()); 41392f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko 41492f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko // Create blocks. 41592f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko HBasicBlock* entry_block = new (allocator_) HBasicBlock(graph_, kNoDexPc); 41692f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko HBasicBlock* exit_block = new (allocator_) HBasicBlock(graph_, kNoDexPc); 41792f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko HBasicBlock* body = MaybeCreateBlockAt(/* semantic_dex_pc */ kNoDexPc, /* store_dex_pc */ 0u); 41892f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko 41992f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko // Add blocks to the graph. 42092f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko graph_->AddBlock(entry_block); 42192f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko graph_->AddBlock(body); 42292f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko graph_->AddBlock(exit_block); 42392f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko graph_->SetEntryBlock(entry_block); 42492f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko graph_->SetExitBlock(exit_block); 42592f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko 42692f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko // Connect blocks. 42792f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko entry_block->AddSuccessor(body); 42892f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko body->AddSuccessor(exit_block); 42992f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko} 43092f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko 431de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartiersize_t HBasicBlockBuilder::GetQuickenIndex(uint32_t dex_pc) const { 432de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier return quicken_index_for_dex_pc_.Get(dex_pc); 433de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier} 434de4b08ff24c330d5b36b5c4dc8664ed4848eeca6Mathieu Chartier 43586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil} // namespace art 436