Home | History | Annotate | Download | only in optimizing
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "block_builder.h"
     18 
     19 #include "bytecode_utils.h"
     20 
     21 namespace art {
     22 
     23 HBasicBlock* HBasicBlockBuilder::MaybeCreateBlockAt(uint32_t dex_pc) {
     24   return MaybeCreateBlockAt(dex_pc, dex_pc);
     25 }
     26 
     27 HBasicBlock* HBasicBlockBuilder::MaybeCreateBlockAt(uint32_t semantic_dex_pc,
     28                                                     uint32_t store_dex_pc) {
     29   HBasicBlock* block = branch_targets_[store_dex_pc];
     30   if (block == nullptr) {
     31     block = new (arena_) HBasicBlock(graph_, semantic_dex_pc);
     32     branch_targets_[store_dex_pc] = block;
     33   }
     34   DCHECK_EQ(block->GetDexPc(), semantic_dex_pc);
     35   return block;
     36 }
     37 
     38 bool HBasicBlockBuilder::CreateBranchTargets() {
     39   // Create the first block for the dex instructions, single successor of the entry block.
     40   MaybeCreateBlockAt(0u);
     41 
     42   if (code_item_.tries_size_ != 0) {
     43     // Create branch targets at the start/end of the TryItem range. These are
     44     // places where the program might fall through into/out of the a block and
     45     // where TryBoundary instructions will be inserted later. Other edges which
     46     // enter/exit the try blocks are a result of branches/switches.
     47     for (size_t idx = 0; idx < code_item_.tries_size_; ++idx) {
     48       const DexFile::TryItem* try_item = DexFile::GetTryItems(code_item_, idx);
     49       uint32_t dex_pc_start = try_item->start_addr_;
     50       uint32_t dex_pc_end = dex_pc_start + try_item->insn_count_;
     51       MaybeCreateBlockAt(dex_pc_start);
     52       if (dex_pc_end < code_item_.insns_size_in_code_units_) {
     53         // TODO: Do not create block if the last instruction cannot fall through.
     54         MaybeCreateBlockAt(dex_pc_end);
     55       } else if (dex_pc_end == code_item_.insns_size_in_code_units_) {
     56         // The TryItem spans until the very end of the CodeItem and therefore
     57         // cannot have any code afterwards.
     58       } else {
     59         // The TryItem spans beyond the end of the CodeItem. This is invalid code.
     60         return false;
     61       }
     62     }
     63 
     64     // Create branch targets for exception handlers.
     65     const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(code_item_, 0);
     66     uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
     67     for (uint32_t idx = 0; idx < handlers_size; ++idx) {
     68       CatchHandlerIterator iterator(handlers_ptr);
     69       for (; iterator.HasNext(); iterator.Next()) {
     70         MaybeCreateBlockAt(iterator.GetHandlerAddress());
     71       }
     72       handlers_ptr = iterator.EndDataPointer();
     73     }
     74   }
     75 
     76   // Iterate over all instructions and find branching instructions. Create blocks for
     77   // the locations these instructions branch to.
     78   for (CodeItemIterator it(code_item_); !it.Done(); it.Advance()) {
     79     uint32_t dex_pc = it.CurrentDexPc();
     80     const Instruction& instruction = it.CurrentInstruction();
     81 
     82     if (instruction.IsBranch()) {
     83       number_of_branches_++;
     84       MaybeCreateBlockAt(dex_pc + instruction.GetTargetOffset());
     85     } else if (instruction.IsSwitch()) {
     86       DexSwitchTable table(instruction, dex_pc);
     87       for (DexSwitchTableIterator s_it(table); !s_it.Done(); s_it.Advance()) {
     88         MaybeCreateBlockAt(dex_pc + s_it.CurrentTargetOffset());
     89 
     90         // Create N-1 blocks where we will insert comparisons of the input value
     91         // against the Switch's case keys.
     92         if (table.ShouldBuildDecisionTree() && !s_it.IsLast()) {
     93           // Store the block under dex_pc of the current key at the switch data
     94           // instruction for uniqueness but give it the dex_pc of the SWITCH
     95           // instruction which it semantically belongs to.
     96           MaybeCreateBlockAt(dex_pc, s_it.GetDexPcForCurrentIndex());
     97         }
     98       }
     99     } else if (instruction.Opcode() == Instruction::MOVE_EXCEPTION) {
    100       // End the basic block after MOVE_EXCEPTION. This simplifies the later
    101       // stage of TryBoundary-block insertion.
    102     } else {
    103       continue;
    104     }
    105 
    106     if (instruction.CanFlowThrough()) {
    107       if (it.IsLast()) {
    108         // In the normal case we should never hit this but someone can artificially forge a dex
    109         // file to fall-through out the method code. In this case we bail out compilation.
    110         return false;
    111       } else {
    112         MaybeCreateBlockAt(dex_pc + it.CurrentInstruction().SizeInCodeUnits());
    113       }
    114     }
    115   }
    116 
    117   return true;
    118 }
    119 
    120 void HBasicBlockBuilder::ConnectBasicBlocks() {
    121   HBasicBlock* block = graph_->GetEntryBlock();
    122   graph_->AddBlock(block);
    123 
    124   bool is_throwing_block = false;
    125   for (CodeItemIterator it(code_item_); !it.Done(); it.Advance()) {
    126     uint32_t dex_pc = it.CurrentDexPc();
    127 
    128     // Check if this dex_pc address starts a new basic block.
    129     HBasicBlock* next_block = GetBlockAt(dex_pc);
    130     if (next_block != nullptr) {
    131       if (block != nullptr) {
    132         // Last instruction did not end its basic block but a new one starts here.
    133         // It must have been a block falling through into the next one.
    134         block->AddSuccessor(next_block);
    135       }
    136       block = next_block;
    137       is_throwing_block = false;
    138       graph_->AddBlock(block);
    139     }
    140 
    141     if (block == nullptr) {
    142       // Ignore dead code.
    143       continue;
    144     }
    145 
    146     const Instruction& instruction = it.CurrentInstruction();
    147 
    148     if (!is_throwing_block && IsThrowingDexInstruction(instruction)) {
    149       DCHECK(!ContainsElement(throwing_blocks_, block));
    150       is_throwing_block = true;
    151       throwing_blocks_.push_back(block);
    152     }
    153 
    154     if (instruction.IsBranch()) {
    155       uint32_t target_dex_pc = dex_pc + instruction.GetTargetOffset();
    156       block->AddSuccessor(GetBlockAt(target_dex_pc));
    157     } else if (instruction.IsReturn() || (instruction.Opcode() == Instruction::THROW)) {
    158       block->AddSuccessor(graph_->GetExitBlock());
    159     } else if (instruction.IsSwitch()) {
    160       DexSwitchTable table(instruction, dex_pc);
    161       for (DexSwitchTableIterator s_it(table); !s_it.Done(); s_it.Advance()) {
    162         uint32_t target_dex_pc = dex_pc + s_it.CurrentTargetOffset();
    163         block->AddSuccessor(GetBlockAt(target_dex_pc));
    164 
    165         if (table.ShouldBuildDecisionTree() && !s_it.IsLast()) {
    166           uint32_t next_case_dex_pc = s_it.GetDexPcForCurrentIndex();
    167           HBasicBlock* next_case_block = GetBlockAt(next_case_dex_pc);
    168           block->AddSuccessor(next_case_block);
    169           block = next_case_block;
    170           graph_->AddBlock(block);
    171         }
    172       }
    173     } else {
    174       // Remaining code only applies to instructions which end their basic block.
    175       continue;
    176     }
    177 
    178     if (instruction.CanFlowThrough()) {
    179       uint32_t next_dex_pc = dex_pc + instruction.SizeInCodeUnits();
    180       block->AddSuccessor(GetBlockAt(next_dex_pc));
    181     }
    182 
    183     // The basic block ends here. Do not add any more instructions.
    184     block = nullptr;
    185   }
    186 
    187   graph_->AddBlock(graph_->GetExitBlock());
    188 }
    189 
    190 // Returns the TryItem stored for `block` or nullptr if there is no info for it.
    191 static const DexFile::TryItem* GetTryItem(
    192     HBasicBlock* block,
    193     const ArenaSafeMap<uint32_t, const DexFile::TryItem*>& try_block_info) {
    194   auto iterator = try_block_info.find(block->GetBlockId());
    195   return (iterator == try_block_info.end()) ? nullptr : iterator->second;
    196 }
    197 
    198 // Iterates over the exception handlers of `try_item`, finds the corresponding
    199 // catch blocks and makes them successors of `try_boundary`. The order of
    200 // successors matches the order in which runtime exception delivery searches
    201 // for a handler.
    202 static void LinkToCatchBlocks(HTryBoundary* try_boundary,
    203                               const DexFile::CodeItem& code_item,
    204                               const DexFile::TryItem* try_item,
    205                               const ArenaSafeMap<uint32_t, HBasicBlock*>& catch_blocks) {
    206   for (CatchHandlerIterator it(code_item, *try_item); it.HasNext(); it.Next()) {
    207     try_boundary->AddExceptionHandler(catch_blocks.Get(it.GetHandlerAddress()));
    208   }
    209 }
    210 
    211 bool HBasicBlockBuilder::MightHaveLiveNormalPredecessors(HBasicBlock* catch_block) {
    212   if (kIsDebugBuild) {
    213     DCHECK_NE(catch_block->GetDexPc(), kNoDexPc) << "Should not be called on synthetic blocks";
    214     DCHECK(!graph_->GetEntryBlock()->GetSuccessors().empty())
    215         << "Basic blocks must have been created and connected";
    216     for (HBasicBlock* predecessor : catch_block->GetPredecessors()) {
    217       DCHECK(!predecessor->IsSingleTryBoundary())
    218           << "TryBoundary blocks must not have not been created yet";
    219     }
    220   }
    221 
    222   const Instruction& first = GetDexInstructionAt(code_item_, catch_block->GetDexPc());
    223   if (first.Opcode() == Instruction::MOVE_EXCEPTION) {
    224     // Verifier guarantees that if a catch block begins with MOVE_EXCEPTION then
    225     // it has no live normal predecessors.
    226     return false;
    227   } else if (catch_block->GetPredecessors().empty()) {
    228     // Normal control-flow edges have already been created. Since block's list of
    229     // predecessors is empty, it cannot have any live or dead normal predecessors.
    230     return false;
    231   }
    232 
    233   // The catch block has normal predecessors but we do not know which are live
    234   // and which will be removed during the initial DCE. Return `true` to signal
    235   // that it may have live normal predecessors.
    236   return true;
    237 }
    238 
    239 void HBasicBlockBuilder::InsertTryBoundaryBlocks() {
    240   if (code_item_.tries_size_ == 0) {
    241     return;
    242   }
    243 
    244   // Keep a map of all try blocks and their respective TryItems. We do not use
    245   // the block's pointer but rather its id to ensure deterministic iteration.
    246   ArenaSafeMap<uint32_t, const DexFile::TryItem*> try_block_info(
    247       std::less<uint32_t>(), arena_->Adapter(kArenaAllocGraphBuilder));
    248 
    249   // Obtain TryItem information for blocks with throwing instructions, and split
    250   // blocks which are both try & catch to simplify the graph.
    251   for (HBasicBlock* block : graph_->GetBlocks()) {
    252     if (block->GetDexPc() == kNoDexPc) {
    253       continue;
    254     }
    255 
    256     // Do not bother creating exceptional edges for try blocks which have no
    257     // throwing instructions. In that case we simply assume that the block is
    258     // not covered by a TryItem. This prevents us from creating a throw-catch
    259     // loop for synchronized blocks.
    260     if (ContainsElement(throwing_blocks_, block)) {
    261       // Try to find a TryItem covering the block.
    262       const int32_t try_item_idx = DexFile::FindTryItem(code_item_, block->GetDexPc());
    263       if (try_item_idx != -1) {
    264         // Block throwing and in a TryItem. Store the try block information.
    265         try_block_info.Put(block->GetBlockId(), DexFile::GetTryItems(code_item_, try_item_idx));
    266       }
    267     }
    268   }
    269 
    270   // Map from a handler dex_pc to the corresponding catch block.
    271   ArenaSafeMap<uint32_t, HBasicBlock*> catch_blocks(
    272       std::less<uint32_t>(), arena_->Adapter(kArenaAllocGraphBuilder));
    273 
    274   // Iterate over catch blocks, create artifical landing pads if necessary to
    275   // simplify the CFG, and set metadata.
    276   const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(code_item_, 0);
    277   uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
    278   for (uint32_t idx = 0; idx < handlers_size; ++idx) {
    279     CatchHandlerIterator iterator(handlers_ptr);
    280     for (; iterator.HasNext(); iterator.Next()) {
    281       uint32_t address = iterator.GetHandlerAddress();
    282       if (catch_blocks.find(address) != catch_blocks.end()) {
    283         // Catch block already processed.
    284         continue;
    285       }
    286 
    287       // Check if we should create an artifical landing pad for the catch block.
    288       // We create one if the catch block is also a try block because we do not
    289       // have a strategy for inserting TryBoundaries on exceptional edges.
    290       // We also create one if the block might have normal predecessors so as to
    291       // simplify register allocation.
    292       HBasicBlock* catch_block = GetBlockAt(address);
    293       bool is_try_block = (try_block_info.find(catch_block->GetBlockId()) != try_block_info.end());
    294       if (is_try_block || MightHaveLiveNormalPredecessors(catch_block)) {
    295         HBasicBlock* new_catch_block = new (arena_) HBasicBlock(graph_, address);
    296         new_catch_block->AddInstruction(new (arena_) HGoto(address));
    297         new_catch_block->AddSuccessor(catch_block);
    298         graph_->AddBlock(new_catch_block);
    299         catch_block = new_catch_block;
    300       }
    301 
    302       catch_blocks.Put(address, catch_block);
    303       catch_block->SetTryCatchInformation(
    304         new (arena_) TryCatchInformation(iterator.GetHandlerTypeIndex(), *dex_file_));
    305     }
    306     handlers_ptr = iterator.EndDataPointer();
    307   }
    308 
    309   // Do a pass over the try blocks and insert entering TryBoundaries where at
    310   // least one predecessor is not covered by the same TryItem as the try block.
    311   // We do not split each edge separately, but rather create one boundary block
    312   // that all predecessors are relinked to. This preserves loop headers (b/23895756).
    313   for (auto entry : try_block_info) {
    314     HBasicBlock* try_block = graph_->GetBlocks()[entry.first];
    315     for (HBasicBlock* predecessor : try_block->GetPredecessors()) {
    316       if (GetTryItem(predecessor, try_block_info) != entry.second) {
    317         // Found a predecessor not covered by the same TryItem. Insert entering
    318         // boundary block.
    319         HTryBoundary* try_entry =
    320             new (arena_) HTryBoundary(HTryBoundary::BoundaryKind::kEntry, try_block->GetDexPc());
    321         try_block->CreateImmediateDominator()->AddInstruction(try_entry);
    322         LinkToCatchBlocks(try_entry, code_item_, entry.second, catch_blocks);
    323         break;
    324       }
    325     }
    326   }
    327 
    328   // Do a second pass over the try blocks and insert exit TryBoundaries where
    329   // the successor is not in the same TryItem.
    330   for (auto entry : try_block_info) {
    331     HBasicBlock* try_block = graph_->GetBlocks()[entry.first];
    332     // NOTE: Do not use iterators because SplitEdge would invalidate them.
    333     for (size_t i = 0, e = try_block->GetSuccessors().size(); i < e; ++i) {
    334       HBasicBlock* successor = try_block->GetSuccessors()[i];
    335 
    336       // If the successor is a try block, all of its predecessors must be
    337       // covered by the same TryItem. Otherwise the previous pass would have
    338       // created a non-throwing boundary block.
    339       if (GetTryItem(successor, try_block_info) != nullptr) {
    340         DCHECK_EQ(entry.second, GetTryItem(successor, try_block_info));
    341         continue;
    342       }
    343 
    344       // Insert TryBoundary and link to catch blocks.
    345       HTryBoundary* try_exit =
    346           new (arena_) HTryBoundary(HTryBoundary::BoundaryKind::kExit, successor->GetDexPc());
    347       graph_->SplitEdge(try_block, successor)->AddInstruction(try_exit);
    348       LinkToCatchBlocks(try_exit, code_item_, entry.second, catch_blocks);
    349     }
    350   }
    351 }
    352 
    353 bool HBasicBlockBuilder::Build() {
    354   DCHECK(graph_->GetBlocks().empty());
    355 
    356   graph_->SetEntryBlock(new (arena_) HBasicBlock(graph_, kNoDexPc));
    357   graph_->SetExitBlock(new (arena_) HBasicBlock(graph_, kNoDexPc));
    358 
    359   // TODO(dbrazdil): Do CreateBranchTargets and ConnectBasicBlocks in one pass.
    360   if (!CreateBranchTargets()) {
    361     return false;
    362   }
    363 
    364   ConnectBasicBlocks();
    365   InsertTryBoundaryBlocks();
    366 
    367   return true;
    368 }
    369 
    370 }  // namespace art
    371