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