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 "base/logging.h" // FOR VLOG. 20 #include "dex/bytecode_utils.h" 21 #include "dex/code_item_accessors-inl.h" 22 #include "dex/dex_file_exception_helpers.h" 23 #include "quicken_info.h" 24 25 namespace art { 26 27 HBasicBlockBuilder::HBasicBlockBuilder(HGraph* graph, 28 const DexFile* const dex_file, 29 const CodeItemDebugInfoAccessor& accessor, 30 ScopedArenaAllocator* local_allocator) 31 : allocator_(graph->GetAllocator()), 32 graph_(graph), 33 dex_file_(dex_file), 34 code_item_accessor_(accessor), 35 local_allocator_(local_allocator), 36 branch_targets_(code_item_accessor_.HasCodeItem() 37 ? code_item_accessor_.InsnsSizeInCodeUnits() 38 : /* fake dex_pc=0 for intrinsic graph */ 1u, 39 nullptr, 40 local_allocator->Adapter(kArenaAllocGraphBuilder)), 41 throwing_blocks_(kDefaultNumberOfThrowingBlocks, 42 local_allocator->Adapter(kArenaAllocGraphBuilder)), 43 number_of_branches_(0u), 44 quicken_index_for_dex_pc_(std::less<uint32_t>(), 45 local_allocator->Adapter(kArenaAllocGraphBuilder)) {} 46 47 HBasicBlock* HBasicBlockBuilder::MaybeCreateBlockAt(uint32_t dex_pc) { 48 return MaybeCreateBlockAt(dex_pc, dex_pc); 49 } 50 51 HBasicBlock* HBasicBlockBuilder::MaybeCreateBlockAt(uint32_t semantic_dex_pc, 52 uint32_t store_dex_pc) { 53 HBasicBlock* block = branch_targets_[store_dex_pc]; 54 if (block == nullptr) { 55 block = new (allocator_) HBasicBlock(graph_, semantic_dex_pc); 56 branch_targets_[store_dex_pc] = block; 57 } 58 DCHECK_EQ(block->GetDexPc(), semantic_dex_pc); 59 return block; 60 } 61 62 bool HBasicBlockBuilder::CreateBranchTargets() { 63 // Create the first block for the dex instructions, single successor of the entry block. 64 MaybeCreateBlockAt(0u); 65 66 if (code_item_accessor_.TriesSize() != 0) { 67 // Create branch targets at the start/end of the TryItem range. These are 68 // places where the program might fall through into/out of the a block and 69 // where TryBoundary instructions will be inserted later. Other edges which 70 // enter/exit the try blocks are a result of branches/switches. 71 for (const dex::TryItem& try_item : code_item_accessor_.TryItems()) { 72 uint32_t dex_pc_start = try_item.start_addr_; 73 uint32_t dex_pc_end = dex_pc_start + try_item.insn_count_; 74 MaybeCreateBlockAt(dex_pc_start); 75 if (dex_pc_end < code_item_accessor_.InsnsSizeInCodeUnits()) { 76 // TODO: Do not create block if the last instruction cannot fall through. 77 MaybeCreateBlockAt(dex_pc_end); 78 } else if (dex_pc_end == code_item_accessor_.InsnsSizeInCodeUnits()) { 79 // The TryItem spans until the very end of the CodeItem and therefore 80 // cannot have any code afterwards. 81 } else { 82 // The TryItem spans beyond the end of the CodeItem. This is invalid code. 83 VLOG(compiler) << "Not compiled: TryItem spans beyond the end of the CodeItem"; 84 return false; 85 } 86 } 87 88 // Create branch targets for exception handlers. 89 const uint8_t* handlers_ptr = code_item_accessor_.GetCatchHandlerData(); 90 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr); 91 for (uint32_t idx = 0; idx < handlers_size; ++idx) { 92 CatchHandlerIterator iterator(handlers_ptr); 93 for (; iterator.HasNext(); iterator.Next()) { 94 MaybeCreateBlockAt(iterator.GetHandlerAddress()); 95 } 96 handlers_ptr = iterator.EndDataPointer(); 97 } 98 } 99 100 // Iterate over all instructions and find branching instructions. Create blocks for 101 // the locations these instructions branch to. 102 for (const DexInstructionPcPair& pair : code_item_accessor_) { 103 const uint32_t dex_pc = pair.DexPc(); 104 const Instruction& instruction = pair.Inst(); 105 106 if (instruction.IsBranch()) { 107 number_of_branches_++; 108 MaybeCreateBlockAt(dex_pc + instruction.GetTargetOffset()); 109 } else if (instruction.IsSwitch()) { 110 number_of_branches_++; // count as at least one branch (b/77652521) 111 DexSwitchTable table(instruction, dex_pc); 112 for (DexSwitchTableIterator s_it(table); !s_it.Done(); s_it.Advance()) { 113 MaybeCreateBlockAt(dex_pc + s_it.CurrentTargetOffset()); 114 115 // Create N-1 blocks where we will insert comparisons of the input value 116 // against the Switch's case keys. 117 if (table.ShouldBuildDecisionTree() && !s_it.IsLast()) { 118 // Store the block under dex_pc of the current key at the switch data 119 // instruction for uniqueness but give it the dex_pc of the SWITCH 120 // instruction which it semantically belongs to. 121 MaybeCreateBlockAt(dex_pc, s_it.GetDexPcForCurrentIndex()); 122 } 123 } 124 } else if (instruction.Opcode() == Instruction::MOVE_EXCEPTION) { 125 // End the basic block after MOVE_EXCEPTION. This simplifies the later 126 // stage of TryBoundary-block insertion. 127 } else { 128 continue; 129 } 130 131 if (instruction.CanFlowThrough()) { 132 DexInstructionIterator next(std::next(DexInstructionIterator(pair))); 133 if (next == code_item_accessor_.end()) { 134 // In the normal case we should never hit this but someone can artificially forge a dex 135 // file to fall-through out the method code. In this case we bail out compilation. 136 VLOG(compiler) << "Not compiled: Fall-through beyond the CodeItem"; 137 return false; 138 } 139 MaybeCreateBlockAt(next.DexPc()); 140 } 141 } 142 143 return true; 144 } 145 146 void HBasicBlockBuilder::ConnectBasicBlocks() { 147 HBasicBlock* block = graph_->GetEntryBlock(); 148 graph_->AddBlock(block); 149 150 size_t quicken_index = 0; 151 bool is_throwing_block = false; 152 // Calculate the qucikening index here instead of CreateBranchTargets since it's easier to 153 // calculate in dex_pc order. 154 for (const DexInstructionPcPair& pair : code_item_accessor_) { 155 const uint32_t dex_pc = pair.DexPc(); 156 const Instruction& instruction = pair.Inst(); 157 158 // Check if this dex_pc address starts a new basic block. 159 HBasicBlock* next_block = GetBlockAt(dex_pc); 160 if (next_block != nullptr) { 161 // We only need quicken index entries for basic block boundaries. 162 quicken_index_for_dex_pc_.Put(dex_pc, quicken_index); 163 if (block != nullptr) { 164 // Last instruction did not end its basic block but a new one starts here. 165 // It must have been a block falling through into the next one. 166 block->AddSuccessor(next_block); 167 } 168 block = next_block; 169 is_throwing_block = false; 170 graph_->AddBlock(block); 171 } 172 // Make sure to increment this before the continues. 173 if (QuickenInfoTable::NeedsIndexForInstruction(&instruction)) { 174 ++quicken_index; 175 } 176 177 if (block == nullptr) { 178 // Ignore dead code. 179 continue; 180 } 181 182 if (!is_throwing_block && IsThrowingDexInstruction(instruction)) { 183 DCHECK(!ContainsElement(throwing_blocks_, block)); 184 is_throwing_block = true; 185 throwing_blocks_.push_back(block); 186 } 187 188 if (instruction.IsBranch()) { 189 uint32_t target_dex_pc = dex_pc + instruction.GetTargetOffset(); 190 block->AddSuccessor(GetBlockAt(target_dex_pc)); 191 } else if (instruction.IsReturn() || (instruction.Opcode() == Instruction::THROW)) { 192 block->AddSuccessor(graph_->GetExitBlock()); 193 } else if (instruction.IsSwitch()) { 194 DexSwitchTable table(instruction, dex_pc); 195 for (DexSwitchTableIterator s_it(table); !s_it.Done(); s_it.Advance()) { 196 uint32_t target_dex_pc = dex_pc + s_it.CurrentTargetOffset(); 197 block->AddSuccessor(GetBlockAt(target_dex_pc)); 198 199 if (table.ShouldBuildDecisionTree() && !s_it.IsLast()) { 200 uint32_t next_case_dex_pc = s_it.GetDexPcForCurrentIndex(); 201 HBasicBlock* next_case_block = GetBlockAt(next_case_dex_pc); 202 block->AddSuccessor(next_case_block); 203 block = next_case_block; 204 graph_->AddBlock(block); 205 } 206 } 207 } else { 208 // Remaining code only applies to instructions which end their basic block. 209 continue; 210 } 211 212 // Go to the next instruction in case we read dex PC below. 213 if (instruction.CanFlowThrough()) { 214 block->AddSuccessor(GetBlockAt(std::next(DexInstructionIterator(pair)).DexPc())); 215 } 216 217 // The basic block ends here. Do not add any more instructions. 218 block = nullptr; 219 } 220 221 graph_->AddBlock(graph_->GetExitBlock()); 222 } 223 224 // Returns the TryItem stored for `block` or nullptr if there is no info for it. 225 static const dex::TryItem* GetTryItem( 226 HBasicBlock* block, 227 const ScopedArenaSafeMap<uint32_t, const dex::TryItem*>& try_block_info) { 228 auto iterator = try_block_info.find(block->GetBlockId()); 229 return (iterator == try_block_info.end()) ? nullptr : iterator->second; 230 } 231 232 // Iterates over the exception handlers of `try_item`, finds the corresponding 233 // catch blocks and makes them successors of `try_boundary`. The order of 234 // successors matches the order in which runtime exception delivery searches 235 // for a handler. 236 static void LinkToCatchBlocks(HTryBoundary* try_boundary, 237 const CodeItemDataAccessor& accessor, 238 const dex::TryItem* try_item, 239 const ScopedArenaSafeMap<uint32_t, HBasicBlock*>& catch_blocks) { 240 for (CatchHandlerIterator it(accessor.GetCatchHandlerData(try_item->handler_off_)); 241 it.HasNext(); 242 it.Next()) { 243 try_boundary->AddExceptionHandler(catch_blocks.Get(it.GetHandlerAddress())); 244 } 245 } 246 247 bool HBasicBlockBuilder::MightHaveLiveNormalPredecessors(HBasicBlock* catch_block) { 248 if (kIsDebugBuild) { 249 DCHECK_NE(catch_block->GetDexPc(), kNoDexPc) << "Should not be called on synthetic blocks"; 250 DCHECK(!graph_->GetEntryBlock()->GetSuccessors().empty()) 251 << "Basic blocks must have been created and connected"; 252 for (HBasicBlock* predecessor : catch_block->GetPredecessors()) { 253 DCHECK(!predecessor->IsSingleTryBoundary()) 254 << "TryBoundary blocks must not have not been created yet"; 255 } 256 } 257 258 const Instruction& first = code_item_accessor_.InstructionAt(catch_block->GetDexPc()); 259 if (first.Opcode() == Instruction::MOVE_EXCEPTION) { 260 // Verifier guarantees that if a catch block begins with MOVE_EXCEPTION then 261 // it has no live normal predecessors. 262 return false; 263 } else if (catch_block->GetPredecessors().empty()) { 264 // Normal control-flow edges have already been created. Since block's list of 265 // predecessors is empty, it cannot have any live or dead normal predecessors. 266 return false; 267 } 268 269 // The catch block has normal predecessors but we do not know which are live 270 // and which will be removed during the initial DCE. Return `true` to signal 271 // that it may have live normal predecessors. 272 return true; 273 } 274 275 void HBasicBlockBuilder::InsertTryBoundaryBlocks() { 276 if (code_item_accessor_.TriesSize() == 0) { 277 return; 278 } 279 280 // Keep a map of all try blocks and their respective TryItems. We do not use 281 // the block's pointer but rather its id to ensure deterministic iteration. 282 ScopedArenaSafeMap<uint32_t, const dex::TryItem*> try_block_info( 283 std::less<uint32_t>(), local_allocator_->Adapter(kArenaAllocGraphBuilder)); 284 285 // Obtain TryItem information for blocks with throwing instructions, and split 286 // blocks which are both try & catch to simplify the graph. 287 for (HBasicBlock* block : graph_->GetBlocks()) { 288 if (block->GetDexPc() == kNoDexPc) { 289 continue; 290 } 291 292 // Do not bother creating exceptional edges for try blocks which have no 293 // throwing instructions. In that case we simply assume that the block is 294 // not covered by a TryItem. This prevents us from creating a throw-catch 295 // loop for synchronized blocks. 296 if (ContainsElement(throwing_blocks_, block)) { 297 // Try to find a TryItem covering the block. 298 const dex::TryItem* try_item = code_item_accessor_.FindTryItem(block->GetDexPc()); 299 if (try_item != nullptr) { 300 // Block throwing and in a TryItem. Store the try block information. 301 try_block_info.Put(block->GetBlockId(), try_item); 302 } 303 } 304 } 305 306 // Map from a handler dex_pc to the corresponding catch block. 307 ScopedArenaSafeMap<uint32_t, HBasicBlock*> catch_blocks( 308 std::less<uint32_t>(), local_allocator_->Adapter(kArenaAllocGraphBuilder)); 309 310 // Iterate over catch blocks, create artifical landing pads if necessary to 311 // simplify the CFG, and set metadata. 312 const uint8_t* handlers_ptr = code_item_accessor_.GetCatchHandlerData(); 313 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr); 314 for (uint32_t idx = 0; idx < handlers_size; ++idx) { 315 CatchHandlerIterator iterator(handlers_ptr); 316 for (; iterator.HasNext(); iterator.Next()) { 317 uint32_t address = iterator.GetHandlerAddress(); 318 auto existing = catch_blocks.find(address); 319 if (existing != catch_blocks.end()) { 320 // Catch block already processed. 321 TryCatchInformation* info = existing->second->GetTryCatchInformation(); 322 if (iterator.GetHandlerTypeIndex() != info->GetCatchTypeIndex()) { 323 // The handler is for multiple types. We could record all the types, but 324 // doing class resolution here isn't ideal, and it's unclear whether wasting 325 // the space in TryCatchInformation is worth it. 326 info->SetInvalidTypeIndex(); 327 } 328 continue; 329 } 330 331 // Check if we should create an artifical landing pad for the catch block. 332 // We create one if the catch block is also a try block because we do not 333 // have a strategy for inserting TryBoundaries on exceptional edges. 334 // We also create one if the block might have normal predecessors so as to 335 // simplify register allocation. 336 HBasicBlock* catch_block = GetBlockAt(address); 337 bool is_try_block = (try_block_info.find(catch_block->GetBlockId()) != try_block_info.end()); 338 if (is_try_block || MightHaveLiveNormalPredecessors(catch_block)) { 339 HBasicBlock* new_catch_block = new (allocator_) HBasicBlock(graph_, address); 340 new_catch_block->AddInstruction(new (allocator_) HGoto(address)); 341 new_catch_block->AddSuccessor(catch_block); 342 graph_->AddBlock(new_catch_block); 343 catch_block = new_catch_block; 344 } 345 346 catch_blocks.Put(address, catch_block); 347 catch_block->SetTryCatchInformation( 348 new (allocator_) TryCatchInformation(iterator.GetHandlerTypeIndex(), *dex_file_)); 349 } 350 handlers_ptr = iterator.EndDataPointer(); 351 } 352 353 // Do a pass over the try blocks and insert entering TryBoundaries where at 354 // least one predecessor is not covered by the same TryItem as the try block. 355 // We do not split each edge separately, but rather create one boundary block 356 // that all predecessors are relinked to. This preserves loop headers (b/23895756). 357 for (const auto& entry : try_block_info) { 358 uint32_t block_id = entry.first; 359 const dex::TryItem* try_item = entry.second; 360 HBasicBlock* try_block = graph_->GetBlocks()[block_id]; 361 for (HBasicBlock* predecessor : try_block->GetPredecessors()) { 362 if (GetTryItem(predecessor, try_block_info) != try_item) { 363 // Found a predecessor not covered by the same TryItem. Insert entering 364 // boundary block. 365 HTryBoundary* try_entry = new (allocator_) HTryBoundary( 366 HTryBoundary::BoundaryKind::kEntry, try_block->GetDexPc()); 367 try_block->CreateImmediateDominator()->AddInstruction(try_entry); 368 LinkToCatchBlocks(try_entry, code_item_accessor_, try_item, catch_blocks); 369 break; 370 } 371 } 372 } 373 374 // Do a second pass over the try blocks and insert exit TryBoundaries where 375 // the successor is not in the same TryItem. 376 for (const auto& entry : try_block_info) { 377 uint32_t block_id = entry.first; 378 const dex::TryItem* try_item = entry.second; 379 HBasicBlock* try_block = graph_->GetBlocks()[block_id]; 380 // NOTE: Do not use iterators because SplitEdge would invalidate them. 381 for (size_t i = 0, e = try_block->GetSuccessors().size(); i < e; ++i) { 382 HBasicBlock* successor = try_block->GetSuccessors()[i]; 383 384 // If the successor is a try block, all of its predecessors must be 385 // covered by the same TryItem. Otherwise the previous pass would have 386 // created a non-throwing boundary block. 387 if (GetTryItem(successor, try_block_info) != nullptr) { 388 DCHECK_EQ(try_item, GetTryItem(successor, try_block_info)); 389 continue; 390 } 391 392 // Insert TryBoundary and link to catch blocks. 393 HTryBoundary* try_exit = 394 new (allocator_) HTryBoundary(HTryBoundary::BoundaryKind::kExit, successor->GetDexPc()); 395 graph_->SplitEdge(try_block, successor)->AddInstruction(try_exit); 396 LinkToCatchBlocks(try_exit, code_item_accessor_, try_item, catch_blocks); 397 } 398 } 399 } 400 401 bool HBasicBlockBuilder::Build() { 402 DCHECK(code_item_accessor_.HasCodeItem()); 403 DCHECK(graph_->GetBlocks().empty()); 404 405 graph_->SetEntryBlock(new (allocator_) HBasicBlock(graph_, kNoDexPc)); 406 graph_->SetExitBlock(new (allocator_) HBasicBlock(graph_, kNoDexPc)); 407 408 // TODO(dbrazdil): Do CreateBranchTargets and ConnectBasicBlocks in one pass. 409 if (!CreateBranchTargets()) { 410 return false; 411 } 412 413 ConnectBasicBlocks(); 414 InsertTryBoundaryBlocks(); 415 416 return true; 417 } 418 419 void HBasicBlockBuilder::BuildIntrinsic() { 420 DCHECK(!code_item_accessor_.HasCodeItem()); 421 DCHECK(graph_->GetBlocks().empty()); 422 423 // Create blocks. 424 HBasicBlock* entry_block = new (allocator_) HBasicBlock(graph_, kNoDexPc); 425 HBasicBlock* exit_block = new (allocator_) HBasicBlock(graph_, kNoDexPc); 426 HBasicBlock* body = MaybeCreateBlockAt(/* semantic_dex_pc= */ kNoDexPc, /* store_dex_pc= */ 0u); 427 428 // Add blocks to the graph. 429 graph_->AddBlock(entry_block); 430 graph_->AddBlock(body); 431 graph_->AddBlock(exit_block); 432 graph_->SetEntryBlock(entry_block); 433 graph_->SetExitBlock(exit_block); 434 435 // Connect blocks. 436 entry_block->AddSuccessor(body); 437 body->AddSuccessor(exit_block); 438 } 439 440 size_t HBasicBlockBuilder::GetQuickenIndex(uint32_t dex_pc) const { 441 return quicken_index_for_dex_pc_.Get(dex_pc); 442 } 443 444 } // namespace art 445