builder.cc revision e460d1df1f789c7c8bb97024a8efbd713ac175e9
1/* 2 * Copyright (C) 2014 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 "builder.h" 18 19#include "art_field-inl.h" 20#include "base/logging.h" 21#include "class_linker.h" 22#include "dex/verified_method.h" 23#include "dex_file-inl.h" 24#include "dex_instruction-inl.h" 25#include "dex/verified_method.h" 26#include "driver/compiler_driver-inl.h" 27#include "driver/compiler_options.h" 28#include "mirror/class_loader.h" 29#include "mirror/dex_cache.h" 30#include "nodes.h" 31#include "primitive.h" 32#include "scoped_thread_state_change.h" 33#include "thread.h" 34#include "utils/dex_cache_arrays_layout-inl.h" 35 36namespace art { 37 38/** 39 * Helper class to add HTemporary instructions. This class is used when 40 * converting a DEX instruction to multiple HInstruction, and where those 41 * instructions do not die at the following instruction, but instead spans 42 * multiple instructions. 43 */ 44class Temporaries : public ValueObject { 45 public: 46 explicit Temporaries(HGraph* graph) : graph_(graph), index_(0) {} 47 48 void Add(HInstruction* instruction) { 49 HInstruction* temp = new (graph_->GetArena()) HTemporary(index_, instruction->GetDexPc()); 50 instruction->GetBlock()->AddInstruction(temp); 51 52 DCHECK(temp->GetPrevious() == instruction); 53 54 size_t offset; 55 if (instruction->GetType() == Primitive::kPrimLong 56 || instruction->GetType() == Primitive::kPrimDouble) { 57 offset = 2; 58 } else { 59 offset = 1; 60 } 61 index_ += offset; 62 63 graph_->UpdateTemporariesVRegSlots(index_); 64 } 65 66 private: 67 HGraph* const graph_; 68 69 // Current index in the temporary stack, updated by `Add`. 70 size_t index_; 71}; 72 73class SwitchTable : public ValueObject { 74 public: 75 SwitchTable(const Instruction& instruction, uint32_t dex_pc, bool sparse) 76 : instruction_(instruction), dex_pc_(dex_pc), sparse_(sparse) { 77 int32_t table_offset = instruction.VRegB_31t(); 78 const uint16_t* table = reinterpret_cast<const uint16_t*>(&instruction) + table_offset; 79 if (sparse) { 80 CHECK_EQ(table[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature)); 81 } else { 82 CHECK_EQ(table[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature)); 83 } 84 num_entries_ = table[1]; 85 values_ = reinterpret_cast<const int32_t*>(&table[2]); 86 } 87 88 uint16_t GetNumEntries() const { 89 return num_entries_; 90 } 91 92 void CheckIndex(size_t index) const { 93 if (sparse_) { 94 // In a sparse table, we have num_entries_ keys and num_entries_ values, in that order. 95 DCHECK_LT(index, 2 * static_cast<size_t>(num_entries_)); 96 } else { 97 // In a packed table, we have the starting key and num_entries_ values. 98 DCHECK_LT(index, 1 + static_cast<size_t>(num_entries_)); 99 } 100 } 101 102 int32_t GetEntryAt(size_t index) const { 103 CheckIndex(index); 104 return values_[index]; 105 } 106 107 uint32_t GetDexPcForIndex(size_t index) const { 108 CheckIndex(index); 109 return dex_pc_ + 110 (reinterpret_cast<const int16_t*>(values_ + index) - 111 reinterpret_cast<const int16_t*>(&instruction_)); 112 } 113 114 // Index of the first value in the table. 115 size_t GetFirstValueIndex() const { 116 if (sparse_) { 117 // In a sparse table, we have num_entries_ keys and num_entries_ values, in that order. 118 return num_entries_; 119 } else { 120 // In a packed table, we have the starting key and num_entries_ values. 121 return 1; 122 } 123 } 124 125 private: 126 const Instruction& instruction_; 127 const uint32_t dex_pc_; 128 129 // Whether this is a sparse-switch table (or a packed-switch one). 130 const bool sparse_; 131 132 // This can't be const as it needs to be computed off of the given instruction, and complicated 133 // expressions in the initializer list seemed very ugly. 134 uint16_t num_entries_; 135 136 const int32_t* values_; 137 138 DISALLOW_COPY_AND_ASSIGN(SwitchTable); 139}; 140 141void HGraphBuilder::InitializeLocals(uint16_t count) { 142 graph_->SetNumberOfVRegs(count); 143 locals_.resize(count); 144 for (int i = 0; i < count; i++) { 145 HLocal* local = new (arena_) HLocal(i); 146 entry_block_->AddInstruction(local); 147 locals_[i] = local; 148 } 149} 150 151void HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) { 152 // dex_compilation_unit_ is null only when unit testing. 153 if (dex_compilation_unit_ == nullptr) { 154 return; 155 } 156 157 graph_->SetNumberOfInVRegs(number_of_parameters); 158 const char* shorty = dex_compilation_unit_->GetShorty(); 159 int locals_index = locals_.size() - number_of_parameters; 160 int parameter_index = 0; 161 162 if (!dex_compilation_unit_->IsStatic()) { 163 // Add the implicit 'this' argument, not expressed in the signature. 164 HParameterValue* parameter = new (arena_) HParameterValue(parameter_index++, 165 Primitive::kPrimNot, 166 true); 167 entry_block_->AddInstruction(parameter); 168 HLocal* local = GetLocalAt(locals_index++); 169 entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter, local->GetDexPc())); 170 number_of_parameters--; 171 } 172 173 uint32_t pos = 1; 174 for (int i = 0; i < number_of_parameters; i++) { 175 HParameterValue* parameter = new (arena_) HParameterValue(parameter_index++, 176 Primitive::GetType(shorty[pos++]), 177 false); 178 entry_block_->AddInstruction(parameter); 179 HLocal* local = GetLocalAt(locals_index++); 180 // Store the parameter value in the local that the dex code will use 181 // to reference that parameter. 182 entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter, local->GetDexPc())); 183 bool is_wide = (parameter->GetType() == Primitive::kPrimLong) 184 || (parameter->GetType() == Primitive::kPrimDouble); 185 if (is_wide) { 186 i++; 187 locals_index++; 188 parameter_index++; 189 } 190 } 191} 192 193template<typename T> 194void HGraphBuilder::If_22t(const Instruction& instruction, uint32_t dex_pc) { 195 int32_t target_offset = instruction.GetTargetOffset(); 196 HBasicBlock* branch_target = FindBlockStartingAt(dex_pc + target_offset); 197 HBasicBlock* fallthrough_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits()); 198 DCHECK(branch_target != nullptr); 199 DCHECK(fallthrough_target != nullptr); 200 PotentiallyAddSuspendCheck(branch_target, dex_pc); 201 HInstruction* first = LoadLocal(instruction.VRegA(), Primitive::kPrimInt, dex_pc); 202 HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt, dex_pc); 203 T* comparison = new (arena_) T(first, second, dex_pc); 204 current_block_->AddInstruction(comparison); 205 HInstruction* ifinst = new (arena_) HIf(comparison, dex_pc); 206 current_block_->AddInstruction(ifinst); 207 current_block_->AddSuccessor(branch_target); 208 current_block_->AddSuccessor(fallthrough_target); 209 current_block_ = nullptr; 210} 211 212template<typename T> 213void HGraphBuilder::If_21t(const Instruction& instruction, uint32_t dex_pc) { 214 int32_t target_offset = instruction.GetTargetOffset(); 215 HBasicBlock* branch_target = FindBlockStartingAt(dex_pc + target_offset); 216 HBasicBlock* fallthrough_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits()); 217 DCHECK(branch_target != nullptr); 218 DCHECK(fallthrough_target != nullptr); 219 PotentiallyAddSuspendCheck(branch_target, dex_pc); 220 HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt, dex_pc); 221 T* comparison = new (arena_) T(value, graph_->GetIntConstant(0, dex_pc), dex_pc); 222 current_block_->AddInstruction(comparison); 223 HInstruction* ifinst = new (arena_) HIf(comparison, dex_pc); 224 current_block_->AddInstruction(ifinst); 225 current_block_->AddSuccessor(branch_target); 226 current_block_->AddSuccessor(fallthrough_target); 227 current_block_ = nullptr; 228} 229 230void HGraphBuilder::MaybeRecordStat(MethodCompilationStat compilation_stat) { 231 if (compilation_stats_ != nullptr) { 232 compilation_stats_->RecordStat(compilation_stat); 233 } 234} 235 236bool HGraphBuilder::SkipCompilation(const DexFile::CodeItem& code_item, 237 size_t number_of_branches) { 238 const CompilerOptions& compiler_options = compiler_driver_->GetCompilerOptions(); 239 CompilerOptions::CompilerFilter compiler_filter = compiler_options.GetCompilerFilter(); 240 if (compiler_filter == CompilerOptions::kEverything) { 241 return false; 242 } 243 244 if (compiler_options.IsHugeMethod(code_item.insns_size_in_code_units_)) { 245 VLOG(compiler) << "Skip compilation of huge method " 246 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_) 247 << ": " << code_item.insns_size_in_code_units_ << " code units"; 248 MaybeRecordStat(MethodCompilationStat::kNotCompiledHugeMethod); 249 return true; 250 } 251 252 // If it's large and contains no branches, it's likely to be machine generated initialization. 253 if (compiler_options.IsLargeMethod(code_item.insns_size_in_code_units_) 254 && (number_of_branches == 0)) { 255 VLOG(compiler) << "Skip compilation of large method with no branch " 256 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_) 257 << ": " << code_item.insns_size_in_code_units_ << " code units"; 258 MaybeRecordStat(MethodCompilationStat::kNotCompiledLargeMethodNoBranches); 259 return true; 260 } 261 262 return false; 263} 264 265void HGraphBuilder::CreateBlocksForTryCatch(const DexFile::CodeItem& code_item) { 266 if (code_item.tries_size_ == 0) { 267 return; 268 } 269 270 // Create branch targets at the start/end of the TryItem range. These are 271 // places where the program might fall through into/out of the a block and 272 // where TryBoundary instructions will be inserted later. Other edges which 273 // enter/exit the try blocks are a result of branches/switches. 274 for (size_t idx = 0; idx < code_item.tries_size_; ++idx) { 275 const DexFile::TryItem* try_item = DexFile::GetTryItems(code_item, idx); 276 uint32_t dex_pc_start = try_item->start_addr_; 277 uint32_t dex_pc_end = dex_pc_start + try_item->insn_count_; 278 FindOrCreateBlockStartingAt(dex_pc_start); 279 if (dex_pc_end < code_item.insns_size_in_code_units_) { 280 // TODO: Do not create block if the last instruction cannot fall through. 281 FindOrCreateBlockStartingAt(dex_pc_end); 282 } else { 283 // The TryItem spans until the very end of the CodeItem (or beyond if 284 // invalid) and therefore cannot have any code afterwards. 285 } 286 } 287 288 // Create branch targets for exception handlers. 289 const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(code_item, 0); 290 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr); 291 for (uint32_t idx = 0; idx < handlers_size; ++idx) { 292 CatchHandlerIterator iterator(handlers_ptr); 293 for (; iterator.HasNext(); iterator.Next()) { 294 uint32_t address = iterator.GetHandlerAddress(); 295 HBasicBlock* block = FindOrCreateBlockStartingAt(address); 296 block->SetTryCatchInformation( 297 new (arena_) TryCatchInformation(iterator.GetHandlerTypeIndex(), *dex_file_)); 298 } 299 handlers_ptr = iterator.EndDataPointer(); 300 } 301} 302 303// Returns the TryItem stored for `block` or nullptr if there is no info for it. 304static const DexFile::TryItem* GetTryItem( 305 HBasicBlock* block, 306 const ArenaSafeMap<uint32_t, const DexFile::TryItem*>& try_block_info) { 307 auto iterator = try_block_info.find(block->GetBlockId()); 308 return (iterator == try_block_info.end()) ? nullptr : iterator->second; 309} 310 311void HGraphBuilder::LinkToCatchBlocks(HTryBoundary* try_boundary, 312 const DexFile::CodeItem& code_item, 313 const DexFile::TryItem* try_item) { 314 for (CatchHandlerIterator it(code_item, *try_item); it.HasNext(); it.Next()) { 315 try_boundary->AddExceptionHandler(FindBlockStartingAt(it.GetHandlerAddress())); 316 } 317} 318 319void HGraphBuilder::InsertTryBoundaryBlocks(const DexFile::CodeItem& code_item) { 320 if (code_item.tries_size_ == 0) { 321 return; 322 } 323 324 // Keep a map of all try blocks and their respective TryItems. We do not use 325 // the block's pointer but rather its id to ensure deterministic iteration. 326 ArenaSafeMap<uint32_t, const DexFile::TryItem*> try_block_info( 327 std::less<uint32_t>(), arena_->Adapter(kArenaAllocGraphBuilder)); 328 329 // Obtain TryItem information for blocks with throwing instructions, and split 330 // blocks which are both try & catch to simplify the graph. 331 // NOTE: We are appending new blocks inside the loop, so we need to use index 332 // because iterators can be invalidated. We remember the initial size to avoid 333 // iterating over the new blocks which cannot throw. 334 for (size_t i = 0, e = graph_->GetBlocks().size(); i < e; ++i) { 335 HBasicBlock* block = graph_->GetBlocks()[i]; 336 337 // Do not bother creating exceptional edges for try blocks which have no 338 // throwing instructions. In that case we simply assume that the block is 339 // not covered by a TryItem. This prevents us from creating a throw-catch 340 // loop for synchronized blocks. 341 if (block->HasThrowingInstructions()) { 342 // Try to find a TryItem covering the block. 343 DCHECK_NE(block->GetDexPc(), kNoDexPc) << "Block must have a dec_pc to find its TryItem."; 344 const int32_t try_item_idx = DexFile::FindTryItem(code_item, block->GetDexPc()); 345 if (try_item_idx != -1) { 346 // Block throwing and in a TryItem. Store the try block information. 347 HBasicBlock* throwing_block = block; 348 if (block->IsCatchBlock()) { 349 // Simplify blocks which are both try and catch, otherwise we would 350 // need a strategy for splitting exceptional edges. We split the block 351 // after the move-exception (if present) and mark the first part not 352 // throwing. The normal-flow edge between them will be split later. 353 HInstruction* first_insn = block->GetFirstInstruction(); 354 if (first_insn->IsLoadException()) { 355 // Catch block starts with a LoadException. Split the block after 356 // the StoreLocal and ClearException which must come after the load. 357 DCHECK(first_insn->GetNext()->IsStoreLocal()); 358 DCHECK(first_insn->GetNext()->GetNext()->IsClearException()); 359 throwing_block = block->SplitBefore(first_insn->GetNext()->GetNext()->GetNext()); 360 } else { 361 // Catch block does not load the exception. Split at the beginning 362 // to create an empty catch block. 363 throwing_block = block->SplitBefore(first_insn); 364 } 365 } 366 367 try_block_info.Put(throwing_block->GetBlockId(), 368 DexFile::GetTryItems(code_item, try_item_idx)); 369 } 370 } 371 } 372 373 // Do a pass over the try blocks and insert entering TryBoundaries where at 374 // least one predecessor is not covered by the same TryItem as the try block. 375 // We do not split each edge separately, but rather create one boundary block 376 // that all predecessors are relinked to. This preserves loop headers (b/23895756). 377 for (auto entry : try_block_info) { 378 HBasicBlock* try_block = graph_->GetBlock(entry.first); 379 for (HBasicBlock* predecessor : try_block->GetPredecessors()) { 380 if (GetTryItem(predecessor, try_block_info) != entry.second) { 381 // Found a predecessor not covered by the same TryItem. Insert entering 382 // boundary block. 383 HTryBoundary* try_entry = 384 new (arena_) HTryBoundary(HTryBoundary::kEntry, try_block->GetDexPc()); 385 try_block->CreateImmediateDominator()->AddInstruction(try_entry); 386 LinkToCatchBlocks(try_entry, code_item, entry.second); 387 break; 388 } 389 } 390 } 391 392 // Do a second pass over the try blocks and insert exit TryBoundaries where 393 // the successor is not in the same TryItem. 394 for (auto entry : try_block_info) { 395 HBasicBlock* try_block = graph_->GetBlock(entry.first); 396 // NOTE: Do not use iterators because SplitEdge would invalidate them. 397 for (size_t i = 0, e = try_block->GetSuccessors().size(); i < e; ++i) { 398 HBasicBlock* successor = try_block->GetSuccessor(i); 399 400 // If the successor is a try block, all of its predecessors must be 401 // covered by the same TryItem. Otherwise the previous pass would have 402 // created a non-throwing boundary block. 403 if (GetTryItem(successor, try_block_info) != nullptr) { 404 DCHECK_EQ(entry.second, GetTryItem(successor, try_block_info)); 405 continue; 406 } 407 408 // Preserve the invariant that Return(Void) always jumps to Exit by moving 409 // it outside the try block if necessary. 410 HInstruction* last_instruction = try_block->GetLastInstruction(); 411 if (last_instruction->IsReturn() || last_instruction->IsReturnVoid()) { 412 DCHECK_EQ(successor, exit_block_); 413 successor = try_block->SplitBefore(last_instruction); 414 } 415 416 // Insert TryBoundary and link to catch blocks. 417 HTryBoundary* try_exit = 418 new (arena_) HTryBoundary(HTryBoundary::kExit, successor->GetDexPc()); 419 graph_->SplitEdge(try_block, successor)->AddInstruction(try_exit); 420 LinkToCatchBlocks(try_exit, code_item, entry.second); 421 } 422 } 423} 424 425bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) { 426 DCHECK(graph_->GetBlocks().empty()); 427 428 const uint16_t* code_ptr = code_item.insns_; 429 const uint16_t* code_end = code_item.insns_ + code_item.insns_size_in_code_units_; 430 code_start_ = code_ptr; 431 432 // Setup the graph with the entry block and exit block. 433 entry_block_ = new (arena_) HBasicBlock(graph_, 0); 434 graph_->AddBlock(entry_block_); 435 exit_block_ = new (arena_) HBasicBlock(graph_, kNoDexPc); 436 graph_->SetEntryBlock(entry_block_); 437 graph_->SetExitBlock(exit_block_); 438 439 graph_->SetHasTryCatch(code_item.tries_size_ != 0); 440 441 InitializeLocals(code_item.registers_size_); 442 graph_->SetMaximumNumberOfOutVRegs(code_item.outs_size_); 443 444 // Compute the number of dex instructions, blocks, and branches. We will 445 // check these values against limits given to the compiler. 446 size_t number_of_branches = 0; 447 448 // To avoid splitting blocks, we compute ahead of time the instructions that 449 // start a new block, and create these blocks. 450 if (!ComputeBranchTargets(code_ptr, code_end, &number_of_branches)) { 451 MaybeRecordStat(MethodCompilationStat::kNotCompiledBranchOutsideMethodCode); 452 return false; 453 } 454 455 // Note that the compiler driver is null when unit testing. 456 if ((compiler_driver_ != nullptr) && SkipCompilation(code_item, number_of_branches)) { 457 return false; 458 } 459 460 CreateBlocksForTryCatch(code_item); 461 462 InitializeParameters(code_item.ins_size_); 463 464 size_t dex_pc = 0; 465 while (code_ptr < code_end) { 466 // Update the current block if dex_pc starts a new block. 467 MaybeUpdateCurrentBlock(dex_pc); 468 const Instruction& instruction = *Instruction::At(code_ptr); 469 if (!AnalyzeDexInstruction(instruction, dex_pc)) { 470 return false; 471 } 472 dex_pc += instruction.SizeInCodeUnits(); 473 code_ptr += instruction.SizeInCodeUnits(); 474 } 475 476 // Add Exit to the exit block. 477 exit_block_->AddInstruction(new (arena_) HExit()); 478 // Add the suspend check to the entry block. 479 entry_block_->AddInstruction(new (arena_) HSuspendCheck(0)); 480 entry_block_->AddInstruction(new (arena_) HGoto()); 481 // Add the exit block at the end. 482 graph_->AddBlock(exit_block_); 483 484 // Iterate over blocks covered by TryItems and insert TryBoundaries at entry 485 // and exit points. This requires all control-flow instructions and 486 // non-exceptional edges to have been created. 487 InsertTryBoundaryBlocks(code_item); 488 489 return true; 490} 491 492void HGraphBuilder::MaybeUpdateCurrentBlock(size_t dex_pc) { 493 HBasicBlock* block = FindBlockStartingAt(dex_pc); 494 if (block == nullptr) { 495 return; 496 } 497 498 if (current_block_ != nullptr) { 499 // Branching instructions clear current_block, so we know 500 // the last instruction of the current block is not a branching 501 // instruction. We add an unconditional goto to the found block. 502 current_block_->AddInstruction(new (arena_) HGoto(dex_pc)); 503 current_block_->AddSuccessor(block); 504 } 505 graph_->AddBlock(block); 506 current_block_ = block; 507} 508 509bool HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr, 510 const uint16_t* code_end, 511 size_t* number_of_branches) { 512 branch_targets_.resize(code_end - code_ptr, nullptr); 513 514 // Create the first block for the dex instructions, single successor of the entry block. 515 HBasicBlock* block = new (arena_) HBasicBlock(graph_, 0); 516 branch_targets_[0] = block; 517 entry_block_->AddSuccessor(block); 518 519 // Iterate over all instructions and find branching instructions. Create blocks for 520 // the locations these instructions branch to. 521 uint32_t dex_pc = 0; 522 while (code_ptr < code_end) { 523 const Instruction& instruction = *Instruction::At(code_ptr); 524 if (instruction.IsBranch()) { 525 (*number_of_branches)++; 526 int32_t target = instruction.GetTargetOffset() + dex_pc; 527 // Create a block for the target instruction. 528 FindOrCreateBlockStartingAt(target); 529 530 dex_pc += instruction.SizeInCodeUnits(); 531 code_ptr += instruction.SizeInCodeUnits(); 532 533 if (instruction.CanFlowThrough()) { 534 if (code_ptr >= code_end) { 535 // In the normal case we should never hit this but someone can artificially forge a dex 536 // file to fall-through out the method code. In this case we bail out compilation. 537 return false; 538 } else { 539 FindOrCreateBlockStartingAt(dex_pc); 540 } 541 } 542 } else if (instruction.IsSwitch()) { 543 SwitchTable table(instruction, dex_pc, instruction.Opcode() == Instruction::SPARSE_SWITCH); 544 545 uint16_t num_entries = table.GetNumEntries(); 546 547 // In a packed-switch, the entry at index 0 is the starting key. In a sparse-switch, the 548 // entry at index 0 is the first key, and values are after *all* keys. 549 size_t offset = table.GetFirstValueIndex(); 550 551 // Use a larger loop counter type to avoid overflow issues. 552 for (size_t i = 0; i < num_entries; ++i) { 553 // The target of the case. 554 uint32_t target = dex_pc + table.GetEntryAt(i + offset); 555 FindOrCreateBlockStartingAt(target); 556 557 // Create a block for the switch-case logic. The block gets the dex_pc 558 // of the SWITCH instruction because it is part of its semantics. 559 block = new (arena_) HBasicBlock(graph_, dex_pc); 560 branch_targets_[table.GetDexPcForIndex(i)] = block; 561 } 562 563 // Fall-through. Add a block if there is more code afterwards. 564 dex_pc += instruction.SizeInCodeUnits(); 565 code_ptr += instruction.SizeInCodeUnits(); 566 if (code_ptr >= code_end) { 567 // In the normal case we should never hit this but someone can artificially forge a dex 568 // file to fall-through out the method code. In this case we bail out compilation. 569 // (A switch can fall-through so we don't need to check CanFlowThrough().) 570 return false; 571 } else { 572 FindOrCreateBlockStartingAt(dex_pc); 573 } 574 } else { 575 code_ptr += instruction.SizeInCodeUnits(); 576 dex_pc += instruction.SizeInCodeUnits(); 577 } 578 } 579 return true; 580} 581 582HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t dex_pc) const { 583 DCHECK_GE(dex_pc, 0); 584 DCHECK_LT(static_cast<size_t>(dex_pc), branch_targets_.size()); 585 return branch_targets_[dex_pc]; 586} 587 588HBasicBlock* HGraphBuilder::FindOrCreateBlockStartingAt(int32_t dex_pc) { 589 HBasicBlock* block = FindBlockStartingAt(dex_pc); 590 if (block == nullptr) { 591 block = new (arena_) HBasicBlock(graph_, dex_pc); 592 branch_targets_[dex_pc] = block; 593 } 594 return block; 595} 596 597template<typename T> 598void HGraphBuilder::Unop_12x(const Instruction& instruction, 599 Primitive::Type type, 600 uint32_t dex_pc) { 601 HInstruction* first = LoadLocal(instruction.VRegB(), type, dex_pc); 602 current_block_->AddInstruction(new (arena_) T(type, first, dex_pc)); 603 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc); 604} 605 606void HGraphBuilder::Conversion_12x(const Instruction& instruction, 607 Primitive::Type input_type, 608 Primitive::Type result_type, 609 uint32_t dex_pc) { 610 HInstruction* first = LoadLocal(instruction.VRegB(), input_type, dex_pc); 611 current_block_->AddInstruction(new (arena_) HTypeConversion(result_type, first, dex_pc)); 612 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc); 613} 614 615template<typename T> 616void HGraphBuilder::Binop_23x(const Instruction& instruction, 617 Primitive::Type type, 618 uint32_t dex_pc) { 619 HInstruction* first = LoadLocal(instruction.VRegB(), type, dex_pc); 620 HInstruction* second = LoadLocal(instruction.VRegC(), type, dex_pc); 621 current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc)); 622 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc); 623} 624 625template<typename T> 626void HGraphBuilder::Binop_23x_shift(const Instruction& instruction, 627 Primitive::Type type, 628 uint32_t dex_pc) { 629 HInstruction* first = LoadLocal(instruction.VRegB(), type, dex_pc); 630 HInstruction* second = LoadLocal(instruction.VRegC(), Primitive::kPrimInt, dex_pc); 631 current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc)); 632 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc); 633} 634 635void HGraphBuilder::Binop_23x_cmp(const Instruction& instruction, 636 Primitive::Type type, 637 ComparisonBias bias, 638 uint32_t dex_pc) { 639 HInstruction* first = LoadLocal(instruction.VRegB(), type, dex_pc); 640 HInstruction* second = LoadLocal(instruction.VRegC(), type, dex_pc); 641 current_block_->AddInstruction(new (arena_) HCompare(type, first, second, bias, dex_pc)); 642 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc); 643} 644 645template<typename T> 646void HGraphBuilder::Binop_12x_shift(const Instruction& instruction, Primitive::Type type, 647 uint32_t dex_pc) { 648 HInstruction* first = LoadLocal(instruction.VRegA(), type, dex_pc); 649 HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt, dex_pc); 650 current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc)); 651 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc); 652} 653 654template<typename T> 655void HGraphBuilder::Binop_12x(const Instruction& instruction, 656 Primitive::Type type, 657 uint32_t dex_pc) { 658 HInstruction* first = LoadLocal(instruction.VRegA(), type, dex_pc); 659 HInstruction* second = LoadLocal(instruction.VRegB(), type, dex_pc); 660 current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc)); 661 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc); 662} 663 664template<typename T> 665void HGraphBuilder::Binop_22s(const Instruction& instruction, bool reverse, uint32_t dex_pc) { 666 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt, dex_pc); 667 HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22s(), dex_pc); 668 if (reverse) { 669 std::swap(first, second); 670 } 671 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second, dex_pc)); 672 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc); 673} 674 675template<typename T> 676void HGraphBuilder::Binop_22b(const Instruction& instruction, bool reverse, uint32_t dex_pc) { 677 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt, dex_pc); 678 HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22b(), dex_pc); 679 if (reverse) { 680 std::swap(first, second); 681 } 682 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second, dex_pc)); 683 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc); 684} 685 686static bool RequiresConstructorBarrier(const DexCompilationUnit* cu, const CompilerDriver& driver) { 687 Thread* self = Thread::Current(); 688 return cu->IsConstructor() 689 && driver.RequiresConstructorBarrier(self, cu->GetDexFile(), cu->GetClassDefIndex()); 690} 691 692void HGraphBuilder::BuildReturn(const Instruction& instruction, 693 Primitive::Type type, 694 uint32_t dex_pc) { 695 if (type == Primitive::kPrimVoid) { 696 if (graph_->ShouldGenerateConstructorBarrier()) { 697 // The compilation unit is null during testing. 698 if (dex_compilation_unit_ != nullptr) { 699 DCHECK(RequiresConstructorBarrier(dex_compilation_unit_, *compiler_driver_)) 700 << "Inconsistent use of ShouldGenerateConstructorBarrier. Should not generate a barrier."; 701 } 702 current_block_->AddInstruction(new (arena_) HMemoryBarrier(kStoreStore, dex_pc)); 703 } 704 current_block_->AddInstruction(new (arena_) HReturnVoid(dex_pc)); 705 } else { 706 HInstruction* value = LoadLocal(instruction.VRegA(), type, dex_pc); 707 current_block_->AddInstruction(new (arena_) HReturn(value, dex_pc)); 708 } 709 current_block_->AddSuccessor(exit_block_); 710 current_block_ = nullptr; 711} 712 713static InvokeType GetInvokeTypeFromOpCode(Instruction::Code opcode) { 714 switch (opcode) { 715 case Instruction::INVOKE_STATIC: 716 case Instruction::INVOKE_STATIC_RANGE: 717 return kStatic; 718 case Instruction::INVOKE_DIRECT: 719 case Instruction::INVOKE_DIRECT_RANGE: 720 return kDirect; 721 case Instruction::INVOKE_VIRTUAL: 722 case Instruction::INVOKE_VIRTUAL_QUICK: 723 case Instruction::INVOKE_VIRTUAL_RANGE: 724 case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: 725 return kVirtual; 726 case Instruction::INVOKE_INTERFACE: 727 case Instruction::INVOKE_INTERFACE_RANGE: 728 return kInterface; 729 case Instruction::INVOKE_SUPER_RANGE: 730 case Instruction::INVOKE_SUPER: 731 return kSuper; 732 default: 733 LOG(FATAL) << "Unexpected invoke opcode: " << opcode; 734 UNREACHABLE(); 735 } 736} 737 738bool HGraphBuilder::BuildInvoke(const Instruction& instruction, 739 uint32_t dex_pc, 740 uint32_t method_idx, 741 uint32_t number_of_vreg_arguments, 742 bool is_range, 743 uint32_t* args, 744 uint32_t register_index) { 745 InvokeType original_invoke_type = GetInvokeTypeFromOpCode(instruction.Opcode()); 746 InvokeType optimized_invoke_type = original_invoke_type; 747 const char* descriptor = dex_file_->GetMethodShorty(method_idx); 748 Primitive::Type return_type = Primitive::GetType(descriptor[0]); 749 750 // Remove the return type from the 'proto'. 751 size_t number_of_arguments = strlen(descriptor) - 1; 752 if (original_invoke_type != kStatic) { // instance call 753 // One extra argument for 'this'. 754 number_of_arguments++; 755 } 756 757 MethodReference target_method(dex_file_, method_idx); 758 int32_t table_index = 0; 759 uintptr_t direct_code = 0; 760 uintptr_t direct_method = 0; 761 762 // Special handling for string init. 763 int32_t string_init_offset = 0; 764 bool is_string_init = compiler_driver_->IsStringInit(method_idx, 765 dex_file_, 766 &string_init_offset); 767 // Replace calls to String.<init> with StringFactory. 768 if (is_string_init) { 769 HInvokeStaticOrDirect::DispatchInfo dispatch_info = ComputeDispatchInfo(is_string_init, 770 string_init_offset, 771 target_method, 772 direct_method, 773 direct_code); 774 HInvoke* invoke = new (arena_) HInvokeStaticOrDirect( 775 arena_, 776 number_of_arguments - 1, 777 Primitive::kPrimNot /*return_type */, 778 dex_pc, 779 method_idx, 780 target_method, 781 dispatch_info, 782 original_invoke_type, 783 kStatic /* optimized_invoke_type */, 784 HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit); 785 return HandleStringInit(invoke, 786 number_of_vreg_arguments, 787 args, 788 register_index, 789 is_range, 790 descriptor); 791 } 792 793 // Handle unresolved methods. 794 if (!compiler_driver_->ComputeInvokeInfo(dex_compilation_unit_, 795 dex_pc, 796 true /* update_stats */, 797 true /* enable_devirtualization */, 798 &optimized_invoke_type, 799 &target_method, 800 &table_index, 801 &direct_code, 802 &direct_method)) { 803 MaybeRecordStat(MethodCompilationStat::kUnresolvedMethod); 804 HInvoke* invoke = new (arena_) HInvokeUnresolved(arena_, 805 number_of_arguments, 806 return_type, 807 dex_pc, 808 method_idx, 809 original_invoke_type); 810 return HandleInvoke(invoke, 811 number_of_vreg_arguments, 812 args, 813 register_index, 814 is_range, 815 descriptor, 816 nullptr /* clinit_check */); 817 } 818 819 // Handle resolved methods (non string init). 820 821 DCHECK(optimized_invoke_type != kSuper); 822 823 // Potential class initialization check, in the case of a static method call. 824 HClinitCheck* clinit_check = nullptr; 825 HInvoke* invoke = nullptr; 826 827 if (optimized_invoke_type == kDirect || optimized_invoke_type == kStatic) { 828 // By default, consider that the called method implicitly requires 829 // an initialization check of its declaring method. 830 HInvokeStaticOrDirect::ClinitCheckRequirement clinit_check_requirement 831 = HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit; 832 if (optimized_invoke_type == kStatic) { 833 clinit_check = ProcessClinitCheckForInvoke(dex_pc, method_idx, &clinit_check_requirement); 834 } 835 836 HInvokeStaticOrDirect::DispatchInfo dispatch_info = ComputeDispatchInfo(is_string_init, 837 string_init_offset, 838 target_method, 839 direct_method, 840 direct_code); 841 invoke = new (arena_) HInvokeStaticOrDirect(arena_, 842 number_of_arguments, 843 return_type, 844 dex_pc, 845 method_idx, 846 target_method, 847 dispatch_info, 848 original_invoke_type, 849 optimized_invoke_type, 850 clinit_check_requirement); 851 } else if (optimized_invoke_type == kVirtual) { 852 invoke = new (arena_) HInvokeVirtual(arena_, 853 number_of_arguments, 854 return_type, 855 dex_pc, 856 method_idx, 857 table_index); 858 } else { 859 DCHECK_EQ(optimized_invoke_type, kInterface); 860 invoke = new (arena_) HInvokeInterface(arena_, 861 number_of_arguments, 862 return_type, 863 dex_pc, 864 method_idx, 865 table_index); 866 } 867 868 return HandleInvoke(invoke, 869 number_of_vreg_arguments, 870 args, 871 register_index, 872 is_range, 873 descriptor, 874 clinit_check); 875} 876 877HClinitCheck* HGraphBuilder::ProcessClinitCheckForInvoke( 878 uint32_t dex_pc, 879 uint32_t method_idx, 880 HInvokeStaticOrDirect::ClinitCheckRequirement* clinit_check_requirement) { 881 ScopedObjectAccess soa(Thread::Current()); 882 StackHandleScope<4> hs(soa.Self()); 883 Handle<mirror::DexCache> dex_cache(hs.NewHandle( 884 dex_compilation_unit_->GetClassLinker()->FindDexCache( 885 soa.Self(), *dex_compilation_unit_->GetDexFile()))); 886 Handle<mirror::ClassLoader> class_loader(hs.NewHandle( 887 soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader()))); 888 ArtMethod* resolved_method = compiler_driver_->ResolveMethod( 889 soa, dex_cache, class_loader, dex_compilation_unit_, method_idx, InvokeType::kStatic); 890 891 DCHECK(resolved_method != nullptr); 892 893 const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile(); 894 Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle( 895 outer_compilation_unit_->GetClassLinker()->FindDexCache(soa.Self(), outer_dex_file))); 896 Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass())); 897 898 // The index at which the method's class is stored in the DexCache's type array. 899 uint32_t storage_index = DexFile::kDexNoIndex; 900 bool is_outer_class = (resolved_method->GetDeclaringClass() == outer_class.Get()); 901 if (is_outer_class) { 902 storage_index = outer_class->GetDexTypeIndex(); 903 } else if (outer_dex_cache.Get() == dex_cache.Get()) { 904 // Get `storage_index` from IsClassOfStaticMethodAvailableToReferrer. 905 compiler_driver_->IsClassOfStaticMethodAvailableToReferrer(outer_dex_cache.Get(), 906 GetCompilingClass(), 907 resolved_method, 908 method_idx, 909 &storage_index); 910 } 911 912 HClinitCheck* clinit_check = nullptr; 913 914 if (!outer_class->IsInterface() 915 && outer_class->IsSubClass(resolved_method->GetDeclaringClass())) { 916 // If the outer class is the declaring class or a subclass 917 // of the declaring class, no class initialization is needed 918 // before the static method call. 919 // Note that in case of inlining, we do not need to add clinit checks 920 // to calls that satisfy this subclass check with any inlined methods. This 921 // will be detected by the optimization passes. 922 *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone; 923 } else if (storage_index != DexFile::kDexNoIndex) { 924 // If the method's class type index is available, check 925 // whether we should add an explicit class initialization 926 // check for its declaring class before the static method call. 927 928 // TODO: find out why this check is needed. 929 bool is_in_dex_cache = compiler_driver_->CanAssumeTypeIsPresentInDexCache( 930 *outer_compilation_unit_->GetDexFile(), storage_index); 931 bool is_initialized = 932 resolved_method->GetDeclaringClass()->IsInitialized() && is_in_dex_cache; 933 934 if (is_initialized) { 935 *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone; 936 } else { 937 *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit; 938 HLoadClass* load_class = new (arena_) HLoadClass( 939 graph_->GetCurrentMethod(), 940 storage_index, 941 *dex_compilation_unit_->GetDexFile(), 942 is_outer_class, 943 dex_pc); 944 current_block_->AddInstruction(load_class); 945 clinit_check = new (arena_) HClinitCheck(load_class, dex_pc); 946 current_block_->AddInstruction(clinit_check); 947 } 948 } 949 return clinit_check; 950} 951 952HInvokeStaticOrDirect::DispatchInfo HGraphBuilder::ComputeDispatchInfo( 953 bool is_string_init, 954 int32_t string_init_offset, 955 MethodReference target_method, 956 uintptr_t direct_method, 957 uintptr_t direct_code) { 958 HInvokeStaticOrDirect::MethodLoadKind method_load_kind; 959 HInvokeStaticOrDirect::CodePtrLocation code_ptr_location; 960 uint64_t method_load_data = 0u; 961 uint64_t direct_code_ptr = 0u; 962 963 if (is_string_init) { 964 // TODO: Use direct_method and direct_code for the appropriate StringFactory method. 965 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kStringInit; 966 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod; 967 method_load_data = string_init_offset; 968 } else if (target_method.dex_file == outer_compilation_unit_->GetDexFile() && 969 target_method.dex_method_index == outer_compilation_unit_->GetDexMethodIndex()) { 970 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kRecursive; 971 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallSelf; 972 } else { 973 if (direct_method != 0u) { // Should we use a direct pointer to the method? 974 if (direct_method != static_cast<uintptr_t>(-1)) { // Is the method pointer known now? 975 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress; 976 method_load_data = direct_method; 977 } else { // The direct pointer will be known at link time. 978 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDirectAddressWithFixup; 979 } 980 } else { // Use dex cache. 981 DCHECK(target_method.dex_file == dex_compilation_unit_->GetDexFile()); 982 DexCacheArraysLayout layout = 983 compiler_driver_->GetDexCacheArraysLayout(target_method.dex_file); 984 if (layout.Valid()) { // Can we use PC-relative access to the dex cache arrays? 985 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative; 986 method_load_data = layout.MethodOffset(target_method.dex_method_index); 987 } else { // We must go through the ArtMethod's pointer to resolved methods. 988 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod; 989 } 990 } 991 if (direct_code != 0u) { // Should we use a direct pointer to the code? 992 if (direct_code != static_cast<uintptr_t>(-1)) { // Is the code pointer known now? 993 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallDirect; 994 direct_code_ptr = direct_code; 995 } else if (compiler_driver_->IsImage() || 996 target_method.dex_file == dex_compilation_unit_->GetDexFile()) { 997 // Use PC-relative calls for invokes within a multi-dex oat file. 998 // TODO: Recognize when the target dex file is within the current oat file for 999 // app compilation. At the moment we recognize only the boot image as multi-dex. 1000 // NOTE: This will require changing the ARM backend which currently falls 1001 // through from kCallPCRelative to kDirectCodeFixup for different dex files. 1002 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallPCRelative; 1003 } else { // The direct pointer will be known at link time. 1004 // NOTE: This is used for app->boot calls when compiling an app against 1005 // a relocatable but not yet relocated image. 1006 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallDirectWithFixup; 1007 } 1008 } else { // We must use the code pointer from the ArtMethod. 1009 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod; 1010 } 1011 } 1012 1013 if (graph_->IsDebuggable()) { 1014 // For debuggable apps always use the code pointer from ArtMethod 1015 // so that we don't circumvent instrumentation stubs if installed. 1016 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod; 1017 } 1018 1019 return HInvokeStaticOrDirect::DispatchInfo { 1020 method_load_kind, code_ptr_location, method_load_data, direct_code_ptr }; 1021} 1022 1023bool HGraphBuilder::SetupInvokeArguments(HInvoke* invoke, 1024 uint32_t number_of_vreg_arguments, 1025 uint32_t* args, 1026 uint32_t register_index, 1027 bool is_range, 1028 const char* descriptor, 1029 size_t start_index, 1030 size_t* argument_index) { 1031 uint32_t descriptor_index = 1; // Skip the return type. 1032 uint32_t dex_pc = invoke->GetDexPc(); 1033 1034 for (size_t i = start_index; 1035 // Make sure we don't go over the expected arguments or over the number of 1036 // dex registers given. If the instruction was seen as dead by the verifier, 1037 // it hasn't been properly checked. 1038 (i < number_of_vreg_arguments) && (*argument_index < invoke->GetNumberOfArguments()); 1039 i++, (*argument_index)++) { 1040 Primitive::Type type = Primitive::GetType(descriptor[descriptor_index++]); 1041 bool is_wide = (type == Primitive::kPrimLong) || (type == Primitive::kPrimDouble); 1042 if (!is_range 1043 && is_wide 1044 && ((i + 1 == number_of_vreg_arguments) || (args[i] + 1 != args[i + 1]))) { 1045 // Longs and doubles should be in pairs, that is, sequential registers. The verifier should 1046 // reject any class where this is violated. However, the verifier only does these checks 1047 // on non trivially dead instructions, so we just bailout the compilation. 1048 VLOG(compiler) << "Did not compile " 1049 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_) 1050 << " because of non-sequential dex register pair in wide argument"; 1051 MaybeRecordStat(MethodCompilationStat::kNotCompiledMalformedOpcode); 1052 return false; 1053 } 1054 HInstruction* arg = LoadLocal(is_range ? register_index + i : args[i], type, dex_pc); 1055 invoke->SetArgumentAt(*argument_index, arg); 1056 if (is_wide) { 1057 i++; 1058 } 1059 } 1060 1061 if (*argument_index != invoke->GetNumberOfArguments()) { 1062 VLOG(compiler) << "Did not compile " 1063 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_) 1064 << " because of wrong number of arguments in invoke instruction"; 1065 MaybeRecordStat(MethodCompilationStat::kNotCompiledMalformedOpcode); 1066 return false; 1067 } 1068 1069 if (invoke->IsInvokeStaticOrDirect()) { 1070 invoke->SetArgumentAt(*argument_index, graph_->GetCurrentMethod()); 1071 (*argument_index)++; 1072 } 1073 1074 return true; 1075} 1076 1077bool HGraphBuilder::HandleInvoke(HInvoke* invoke, 1078 uint32_t number_of_vreg_arguments, 1079 uint32_t* args, 1080 uint32_t register_index, 1081 bool is_range, 1082 const char* descriptor, 1083 HClinitCheck* clinit_check) { 1084 DCHECK(!invoke->IsInvokeStaticOrDirect() || !invoke->AsInvokeStaticOrDirect()->IsStringInit()); 1085 1086 size_t start_index = 0; 1087 size_t argument_index = 0; 1088 if (invoke->GetOriginalInvokeType() != InvokeType::kStatic) { // Instance call. 1089 Temporaries temps(graph_); 1090 HInstruction* arg = LoadLocal( 1091 is_range ? register_index : args[0], Primitive::kPrimNot, invoke->GetDexPc()); 1092 HNullCheck* null_check = new (arena_) HNullCheck(arg, invoke->GetDexPc()); 1093 current_block_->AddInstruction(null_check); 1094 temps.Add(null_check); 1095 invoke->SetArgumentAt(0, null_check); 1096 start_index = 1; 1097 argument_index = 1; 1098 } 1099 1100 if (!SetupInvokeArguments(invoke, 1101 number_of_vreg_arguments, 1102 args, 1103 register_index, 1104 is_range, 1105 descriptor, 1106 start_index, 1107 &argument_index)) { 1108 return false; 1109 } 1110 1111 if (clinit_check != nullptr) { 1112 // Add the class initialization check as last input of `invoke`. 1113 DCHECK(invoke->IsInvokeStaticOrDirect()); 1114 DCHECK(invoke->AsInvokeStaticOrDirect()->GetClinitCheckRequirement() 1115 == HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit); 1116 invoke->SetArgumentAt(argument_index, clinit_check); 1117 argument_index++; 1118 } 1119 1120 current_block_->AddInstruction(invoke); 1121 latest_result_ = invoke; 1122 1123 return true; 1124} 1125 1126bool HGraphBuilder::HandleStringInit(HInvoke* invoke, 1127 uint32_t number_of_vreg_arguments, 1128 uint32_t* args, 1129 uint32_t register_index, 1130 bool is_range, 1131 const char* descriptor) { 1132 DCHECK(invoke->IsInvokeStaticOrDirect()); 1133 DCHECK(invoke->AsInvokeStaticOrDirect()->IsStringInit()); 1134 1135 size_t start_index = 1; 1136 size_t argument_index = 0; 1137 if (!SetupInvokeArguments(invoke, 1138 number_of_vreg_arguments, 1139 args, 1140 register_index, 1141 is_range, 1142 descriptor, 1143 start_index, 1144 &argument_index)) { 1145 return false; 1146 } 1147 1148 // Add move-result for StringFactory method. 1149 uint32_t orig_this_reg = is_range ? register_index : args[0]; 1150 HInstruction* fake_string = LoadLocal(orig_this_reg, Primitive::kPrimNot, invoke->GetDexPc()); 1151 invoke->SetArgumentAt(argument_index, fake_string); 1152 current_block_->AddInstruction(invoke); 1153 PotentiallySimplifyFakeString(orig_this_reg, invoke->GetDexPc(), invoke); 1154 1155 latest_result_ = invoke; 1156 1157 return true; 1158} 1159 1160void HGraphBuilder::PotentiallySimplifyFakeString(uint16_t original_dex_register, 1161 uint32_t dex_pc, 1162 HInvoke* actual_string) { 1163 if (!graph_->IsDebuggable()) { 1164 // Notify that we cannot compile with baseline. The dex registers aliasing 1165 // with `original_dex_register` will be handled when we optimize 1166 // (see HInstructionSimplifer::VisitFakeString). 1167 can_use_baseline_for_string_init_ = false; 1168 return; 1169 } 1170 const VerifiedMethod* verified_method = 1171 compiler_driver_->GetVerifiedMethod(dex_file_, dex_compilation_unit_->GetDexMethodIndex()); 1172 if (verified_method != nullptr) { 1173 UpdateLocal(original_dex_register, actual_string, dex_pc); 1174 const SafeMap<uint32_t, std::set<uint32_t>>& string_init_map = 1175 verified_method->GetStringInitPcRegMap(); 1176 auto map_it = string_init_map.find(dex_pc); 1177 if (map_it != string_init_map.end()) { 1178 std::set<uint32_t> reg_set = map_it->second; 1179 for (auto set_it = reg_set.begin(); set_it != reg_set.end(); ++set_it) { 1180 HInstruction* load_local = LoadLocal(original_dex_register, Primitive::kPrimNot, dex_pc); 1181 UpdateLocal(*set_it, load_local, dex_pc); 1182 } 1183 } 1184 } else { 1185 can_use_baseline_for_string_init_ = false; 1186 } 1187} 1188 1189static Primitive::Type GetFieldAccessType(const DexFile& dex_file, uint16_t field_index) { 1190 const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index); 1191 const char* type = dex_file.GetFieldTypeDescriptor(field_id); 1192 return Primitive::GetType(type[0]); 1193} 1194 1195bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction, 1196 uint32_t dex_pc, 1197 bool is_put) { 1198 uint32_t source_or_dest_reg = instruction.VRegA_22c(); 1199 uint32_t obj_reg = instruction.VRegB_22c(); 1200 uint16_t field_index; 1201 if (instruction.IsQuickened()) { 1202 if (!CanDecodeQuickenedInfo()) { 1203 return false; 1204 } 1205 field_index = LookupQuickenedInfo(dex_pc); 1206 } else { 1207 field_index = instruction.VRegC_22c(); 1208 } 1209 1210 ScopedObjectAccess soa(Thread::Current()); 1211 ArtField* resolved_field = 1212 compiler_driver_->ComputeInstanceFieldInfo(field_index, dex_compilation_unit_, is_put, soa); 1213 1214 1215 HInstruction* object = LoadLocal(obj_reg, Primitive::kPrimNot, dex_pc); 1216 HInstruction* null_check = new (arena_) HNullCheck(object, dex_pc); 1217 current_block_->AddInstruction(null_check); 1218 1219 Primitive::Type field_type = (resolved_field == nullptr) 1220 ? GetFieldAccessType(*dex_file_, field_index) 1221 : resolved_field->GetTypeAsPrimitiveType(); 1222 if (is_put) { 1223 Temporaries temps(graph_); 1224 // We need one temporary for the null check. 1225 temps.Add(null_check); 1226 HInstruction* value = LoadLocal(source_or_dest_reg, field_type, dex_pc); 1227 HInstruction* field_set = nullptr; 1228 if (resolved_field == nullptr) { 1229 MaybeRecordStat(MethodCompilationStat::kUnresolvedField); 1230 field_set = new (arena_) HUnresolvedInstanceFieldSet(null_check, 1231 value, 1232 field_type, 1233 field_index, 1234 dex_pc); 1235 } else { 1236 field_set = new (arena_) HInstanceFieldSet(null_check, 1237 value, 1238 field_type, 1239 resolved_field->GetOffset(), 1240 resolved_field->IsVolatile(), 1241 field_index, 1242 *dex_file_, 1243 dex_compilation_unit_->GetDexCache(), 1244 dex_pc); 1245 } 1246 current_block_->AddInstruction(field_set); 1247 } else { 1248 HInstruction* field_get = nullptr; 1249 if (resolved_field == nullptr) { 1250 MaybeRecordStat(MethodCompilationStat::kUnresolvedField); 1251 field_get = new (arena_) HUnresolvedInstanceFieldGet(null_check, 1252 field_type, 1253 field_index, 1254 dex_pc); 1255 } else { 1256 field_get = new (arena_) HInstanceFieldGet(null_check, 1257 field_type, 1258 resolved_field->GetOffset(), 1259 resolved_field->IsVolatile(), 1260 field_index, 1261 *dex_file_, 1262 dex_compilation_unit_->GetDexCache(), 1263 dex_pc); 1264 } 1265 current_block_->AddInstruction(field_get); 1266 UpdateLocal(source_or_dest_reg, field_get, dex_pc); 1267 } 1268 1269 return true; 1270} 1271 1272static mirror::Class* GetClassFrom(CompilerDriver* driver, 1273 const DexCompilationUnit& compilation_unit) { 1274 ScopedObjectAccess soa(Thread::Current()); 1275 StackHandleScope<2> hs(soa.Self()); 1276 const DexFile& dex_file = *compilation_unit.GetDexFile(); 1277 Handle<mirror::ClassLoader> class_loader(hs.NewHandle( 1278 soa.Decode<mirror::ClassLoader*>(compilation_unit.GetClassLoader()))); 1279 Handle<mirror::DexCache> dex_cache(hs.NewHandle( 1280 compilation_unit.GetClassLinker()->FindDexCache(soa.Self(), dex_file))); 1281 1282 return driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, &compilation_unit); 1283} 1284 1285mirror::Class* HGraphBuilder::GetOutermostCompilingClass() const { 1286 return GetClassFrom(compiler_driver_, *outer_compilation_unit_); 1287} 1288 1289mirror::Class* HGraphBuilder::GetCompilingClass() const { 1290 return GetClassFrom(compiler_driver_, *dex_compilation_unit_); 1291} 1292 1293bool HGraphBuilder::IsOutermostCompilingClass(uint16_t type_index) const { 1294 ScopedObjectAccess soa(Thread::Current()); 1295 StackHandleScope<4> hs(soa.Self()); 1296 Handle<mirror::DexCache> dex_cache(hs.NewHandle( 1297 dex_compilation_unit_->GetClassLinker()->FindDexCache( 1298 soa.Self(), *dex_compilation_unit_->GetDexFile()))); 1299 Handle<mirror::ClassLoader> class_loader(hs.NewHandle( 1300 soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader()))); 1301 Handle<mirror::Class> cls(hs.NewHandle(compiler_driver_->ResolveClass( 1302 soa, dex_cache, class_loader, type_index, dex_compilation_unit_))); 1303 Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass())); 1304 1305 return outer_class.Get() == cls.Get(); 1306} 1307 1308bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, 1309 uint32_t dex_pc, 1310 bool is_put) { 1311 uint32_t source_or_dest_reg = instruction.VRegA_21c(); 1312 uint16_t field_index = instruction.VRegB_21c(); 1313 1314 ScopedObjectAccess soa(Thread::Current()); 1315 StackHandleScope<4> hs(soa.Self()); 1316 Handle<mirror::DexCache> dex_cache(hs.NewHandle( 1317 dex_compilation_unit_->GetClassLinker()->FindDexCache( 1318 soa.Self(), *dex_compilation_unit_->GetDexFile()))); 1319 Handle<mirror::ClassLoader> class_loader(hs.NewHandle( 1320 soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader()))); 1321 ArtField* resolved_field = compiler_driver_->ResolveField( 1322 soa, dex_cache, class_loader, dex_compilation_unit_, field_index, true); 1323 1324 if (resolved_field == nullptr) { 1325 MaybeRecordStat(MethodCompilationStat::kUnresolvedField); 1326 Primitive::Type field_type = GetFieldAccessType(*dex_file_, field_index); 1327 if (is_put) { 1328 HInstruction* value = LoadLocal(source_or_dest_reg, field_type, dex_pc); 1329 current_block_->AddInstruction( 1330 new (arena_) HUnresolvedStaticFieldSet(value, field_type, field_index, dex_pc)); 1331 } else { 1332 current_block_->AddInstruction( 1333 new (arena_) HUnresolvedStaticFieldGet(field_type, field_index, dex_pc)); 1334 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction(), dex_pc); 1335 } 1336 return true; 1337 } 1338 1339 const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile(); 1340 Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle( 1341 outer_compilation_unit_->GetClassLinker()->FindDexCache(soa.Self(), outer_dex_file))); 1342 Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass())); 1343 1344 // The index at which the field's class is stored in the DexCache's type array. 1345 uint32_t storage_index; 1346 bool is_outer_class = (outer_class.Get() == resolved_field->GetDeclaringClass()); 1347 if (is_outer_class) { 1348 storage_index = outer_class->GetDexTypeIndex(); 1349 } else if (outer_dex_cache.Get() != dex_cache.Get()) { 1350 // The compiler driver cannot currently understand multiple dex caches involved. Just bailout. 1351 return false; 1352 } else { 1353 std::pair<bool, bool> pair = compiler_driver_->IsFastStaticField( 1354 outer_dex_cache.Get(), 1355 GetCompilingClass(), 1356 resolved_field, 1357 field_index, 1358 &storage_index); 1359 bool can_easily_access = is_put ? pair.second : pair.first; 1360 if (!can_easily_access) { 1361 return false; 1362 } 1363 } 1364 1365 // TODO: find out why this check is needed. 1366 bool is_in_dex_cache = compiler_driver_->CanAssumeTypeIsPresentInDexCache( 1367 *outer_compilation_unit_->GetDexFile(), storage_index); 1368 bool is_initialized = resolved_field->GetDeclaringClass()->IsInitialized() && is_in_dex_cache; 1369 1370 HLoadClass* constant = new (arena_) HLoadClass(graph_->GetCurrentMethod(), 1371 storage_index, 1372 *dex_compilation_unit_->GetDexFile(), 1373 is_outer_class, 1374 dex_pc); 1375 current_block_->AddInstruction(constant); 1376 1377 HInstruction* cls = constant; 1378 if (!is_initialized && !is_outer_class) { 1379 cls = new (arena_) HClinitCheck(constant, dex_pc); 1380 current_block_->AddInstruction(cls); 1381 } 1382 1383 Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType(); 1384 if (is_put) { 1385 // We need to keep the class alive before loading the value. 1386 Temporaries temps(graph_); 1387 temps.Add(cls); 1388 HInstruction* value = LoadLocal(source_or_dest_reg, field_type, dex_pc); 1389 DCHECK_EQ(value->GetType(), field_type); 1390 current_block_->AddInstruction(new (arena_) HStaticFieldSet(cls, 1391 value, 1392 field_type, 1393 resolved_field->GetOffset(), 1394 resolved_field->IsVolatile(), 1395 field_index, 1396 *dex_file_, 1397 dex_cache_, 1398 dex_pc)); 1399 } else { 1400 current_block_->AddInstruction(new (arena_) HStaticFieldGet(cls, 1401 field_type, 1402 resolved_field->GetOffset(), 1403 resolved_field->IsVolatile(), 1404 field_index, 1405 *dex_file_, 1406 dex_cache_, 1407 dex_pc)); 1408 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction(), dex_pc); 1409 } 1410 return true; 1411} 1412 1413void HGraphBuilder::BuildCheckedDivRem(uint16_t out_vreg, 1414 uint16_t first_vreg, 1415 int64_t second_vreg_or_constant, 1416 uint32_t dex_pc, 1417 Primitive::Type type, 1418 bool second_is_constant, 1419 bool isDiv) { 1420 DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); 1421 1422 HInstruction* first = LoadLocal(first_vreg, type, dex_pc); 1423 HInstruction* second = nullptr; 1424 if (second_is_constant) { 1425 if (type == Primitive::kPrimInt) { 1426 second = graph_->GetIntConstant(second_vreg_or_constant, dex_pc); 1427 } else { 1428 second = graph_->GetLongConstant(second_vreg_or_constant, dex_pc); 1429 } 1430 } else { 1431 second = LoadLocal(second_vreg_or_constant, type, dex_pc); 1432 } 1433 1434 if (!second_is_constant 1435 || (type == Primitive::kPrimInt && second->AsIntConstant()->GetValue() == 0) 1436 || (type == Primitive::kPrimLong && second->AsLongConstant()->GetValue() == 0)) { 1437 second = new (arena_) HDivZeroCheck(second, dex_pc); 1438 Temporaries temps(graph_); 1439 current_block_->AddInstruction(second); 1440 temps.Add(current_block_->GetLastInstruction()); 1441 } 1442 1443 if (isDiv) { 1444 current_block_->AddInstruction(new (arena_) HDiv(type, first, second, dex_pc)); 1445 } else { 1446 current_block_->AddInstruction(new (arena_) HRem(type, first, second, dex_pc)); 1447 } 1448 UpdateLocal(out_vreg, current_block_->GetLastInstruction(), dex_pc); 1449} 1450 1451void HGraphBuilder::BuildArrayAccess(const Instruction& instruction, 1452 uint32_t dex_pc, 1453 bool is_put, 1454 Primitive::Type anticipated_type) { 1455 uint8_t source_or_dest_reg = instruction.VRegA_23x(); 1456 uint8_t array_reg = instruction.VRegB_23x(); 1457 uint8_t index_reg = instruction.VRegC_23x(); 1458 1459 // We need one temporary for the null check, one for the index, and one for the length. 1460 Temporaries temps(graph_); 1461 1462 HInstruction* object = LoadLocal(array_reg, Primitive::kPrimNot, dex_pc); 1463 object = new (arena_) HNullCheck(object, dex_pc); 1464 current_block_->AddInstruction(object); 1465 temps.Add(object); 1466 1467 HInstruction* length = new (arena_) HArrayLength(object, dex_pc); 1468 current_block_->AddInstruction(length); 1469 temps.Add(length); 1470 HInstruction* index = LoadLocal(index_reg, Primitive::kPrimInt, dex_pc); 1471 index = new (arena_) HBoundsCheck(index, length, dex_pc); 1472 current_block_->AddInstruction(index); 1473 temps.Add(index); 1474 if (is_put) { 1475 HInstruction* value = LoadLocal(source_or_dest_reg, anticipated_type, dex_pc); 1476 // TODO: Insert a type check node if the type is Object. 1477 current_block_->AddInstruction(new (arena_) HArraySet( 1478 object, index, value, anticipated_type, dex_pc)); 1479 } else { 1480 current_block_->AddInstruction(new (arena_) HArrayGet(object, index, anticipated_type, dex_pc)); 1481 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction(), dex_pc); 1482 } 1483 graph_->SetHasBoundsChecks(true); 1484} 1485 1486void HGraphBuilder::BuildFilledNewArray(uint32_t dex_pc, 1487 uint32_t type_index, 1488 uint32_t number_of_vreg_arguments, 1489 bool is_range, 1490 uint32_t* args, 1491 uint32_t register_index) { 1492 HInstruction* length = graph_->GetIntConstant(number_of_vreg_arguments, dex_pc); 1493 QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index) 1494 ? kQuickAllocArrayWithAccessCheck 1495 : kQuickAllocArray; 1496 HInstruction* object = new (arena_) HNewArray(length, 1497 graph_->GetCurrentMethod(), 1498 dex_pc, 1499 type_index, 1500 *dex_compilation_unit_->GetDexFile(), 1501 entrypoint); 1502 current_block_->AddInstruction(object); 1503 1504 const char* descriptor = dex_file_->StringByTypeIdx(type_index); 1505 DCHECK_EQ(descriptor[0], '[') << descriptor; 1506 char primitive = descriptor[1]; 1507 DCHECK(primitive == 'I' 1508 || primitive == 'L' 1509 || primitive == '[') << descriptor; 1510 bool is_reference_array = (primitive == 'L') || (primitive == '['); 1511 Primitive::Type type = is_reference_array ? Primitive::kPrimNot : Primitive::kPrimInt; 1512 1513 Temporaries temps(graph_); 1514 temps.Add(object); 1515 for (size_t i = 0; i < number_of_vreg_arguments; ++i) { 1516 HInstruction* value = LoadLocal(is_range ? register_index + i : args[i], type, dex_pc); 1517 HInstruction* index = graph_->GetIntConstant(i, dex_pc); 1518 current_block_->AddInstruction( 1519 new (arena_) HArraySet(object, index, value, type, dex_pc)); 1520 } 1521 latest_result_ = object; 1522} 1523 1524template <typename T> 1525void HGraphBuilder::BuildFillArrayData(HInstruction* object, 1526 const T* data, 1527 uint32_t element_count, 1528 Primitive::Type anticipated_type, 1529 uint32_t dex_pc) { 1530 for (uint32_t i = 0; i < element_count; ++i) { 1531 HInstruction* index = graph_->GetIntConstant(i, dex_pc); 1532 HInstruction* value = graph_->GetIntConstant(data[i], dex_pc); 1533 current_block_->AddInstruction(new (arena_) HArraySet( 1534 object, index, value, anticipated_type, dex_pc)); 1535 } 1536} 1537 1538void HGraphBuilder::BuildFillArrayData(const Instruction& instruction, uint32_t dex_pc) { 1539 Temporaries temps(graph_); 1540 HInstruction* array = LoadLocal(instruction.VRegA_31t(), Primitive::kPrimNot, dex_pc); 1541 HNullCheck* null_check = new (arena_) HNullCheck(array, dex_pc); 1542 current_block_->AddInstruction(null_check); 1543 temps.Add(null_check); 1544 1545 HInstruction* length = new (arena_) HArrayLength(null_check, dex_pc); 1546 current_block_->AddInstruction(length); 1547 1548 int32_t payload_offset = instruction.VRegB_31t() + dex_pc; 1549 const Instruction::ArrayDataPayload* payload = 1550 reinterpret_cast<const Instruction::ArrayDataPayload*>(code_start_ + payload_offset); 1551 const uint8_t* data = payload->data; 1552 uint32_t element_count = payload->element_count; 1553 1554 // Implementation of this DEX instruction seems to be that the bounds check is 1555 // done before doing any stores. 1556 HInstruction* last_index = graph_->GetIntConstant(payload->element_count - 1, dex_pc); 1557 current_block_->AddInstruction(new (arena_) HBoundsCheck(last_index, length, dex_pc)); 1558 1559 switch (payload->element_width) { 1560 case 1: 1561 BuildFillArrayData(null_check, 1562 reinterpret_cast<const int8_t*>(data), 1563 element_count, 1564 Primitive::kPrimByte, 1565 dex_pc); 1566 break; 1567 case 2: 1568 BuildFillArrayData(null_check, 1569 reinterpret_cast<const int16_t*>(data), 1570 element_count, 1571 Primitive::kPrimShort, 1572 dex_pc); 1573 break; 1574 case 4: 1575 BuildFillArrayData(null_check, 1576 reinterpret_cast<const int32_t*>(data), 1577 element_count, 1578 Primitive::kPrimInt, 1579 dex_pc); 1580 break; 1581 case 8: 1582 BuildFillWideArrayData(null_check, 1583 reinterpret_cast<const int64_t*>(data), 1584 element_count, 1585 dex_pc); 1586 break; 1587 default: 1588 LOG(FATAL) << "Unknown element width for " << payload->element_width; 1589 } 1590 graph_->SetHasBoundsChecks(true); 1591} 1592 1593void HGraphBuilder::BuildFillWideArrayData(HInstruction* object, 1594 const int64_t* data, 1595 uint32_t element_count, 1596 uint32_t dex_pc) { 1597 for (uint32_t i = 0; i < element_count; ++i) { 1598 HInstruction* index = graph_->GetIntConstant(i, dex_pc); 1599 HInstruction* value = graph_->GetLongConstant(data[i], dex_pc); 1600 current_block_->AddInstruction(new (arena_) HArraySet( 1601 object, index, value, Primitive::kPrimLong, dex_pc)); 1602 } 1603} 1604 1605static TypeCheckKind ComputeTypeCheckKind(Handle<mirror::Class> cls) 1606 SHARED_REQUIRES(Locks::mutator_lock_) { 1607 if (cls->IsInterface()) { 1608 return TypeCheckKind::kInterfaceCheck; 1609 } else if (cls->IsArrayClass()) { 1610 if (cls->GetComponentType()->IsObjectClass()) { 1611 return TypeCheckKind::kArrayObjectCheck; 1612 } else if (cls->CannotBeAssignedFromOtherTypes()) { 1613 return TypeCheckKind::kExactCheck; 1614 } else { 1615 return TypeCheckKind::kArrayCheck; 1616 } 1617 } else if (cls->IsFinal()) { 1618 return TypeCheckKind::kExactCheck; 1619 } else if (cls->IsAbstract()) { 1620 return TypeCheckKind::kAbstractClassCheck; 1621 } else { 1622 return TypeCheckKind::kClassHierarchyCheck; 1623 } 1624} 1625 1626bool HGraphBuilder::BuildTypeCheck(const Instruction& instruction, 1627 uint8_t destination, 1628 uint8_t reference, 1629 uint16_t type_index, 1630 uint32_t dex_pc) { 1631 ScopedObjectAccess soa(Thread::Current()); 1632 StackHandleScope<2> hs(soa.Self()); 1633 Handle<mirror::DexCache> dex_cache(hs.NewHandle( 1634 dex_compilation_unit_->GetClassLinker()->FindDexCache( 1635 soa.Self(), *dex_compilation_unit_->GetDexFile()))); 1636 Handle<mirror::Class> resolved_class(hs.NewHandle(dex_cache->GetResolvedType(type_index))); 1637 1638 if ((resolved_class.Get() == nullptr) || 1639 // TODO: Remove this check once the compiler actually knows which 1640 // ArtMethod it is compiling. 1641 (GetCompilingClass() == nullptr) || 1642 !GetCompilingClass()->CanAccess(resolved_class.Get())) { 1643 MaybeRecordStat(MethodCompilationStat::kNotCompiledCantAccesType); 1644 return false; 1645 } 1646 1647 HInstruction* object = LoadLocal(reference, Primitive::kPrimNot, dex_pc); 1648 HLoadClass* cls = new (arena_) HLoadClass( 1649 graph_->GetCurrentMethod(), 1650 type_index, 1651 *dex_compilation_unit_->GetDexFile(), 1652 IsOutermostCompilingClass(type_index), 1653 dex_pc); 1654 current_block_->AddInstruction(cls); 1655 1656 // The class needs a temporary before being used by the type check. 1657 Temporaries temps(graph_); 1658 temps.Add(cls); 1659 1660 TypeCheckKind check_kind = ComputeTypeCheckKind(resolved_class); 1661 if (instruction.Opcode() == Instruction::INSTANCE_OF) { 1662 current_block_->AddInstruction(new (arena_) HInstanceOf(object, cls, check_kind, dex_pc)); 1663 UpdateLocal(destination, current_block_->GetLastInstruction(), dex_pc); 1664 } else { 1665 DCHECK_EQ(instruction.Opcode(), Instruction::CHECK_CAST); 1666 current_block_->AddInstruction(new (arena_) HCheckCast(object, cls, check_kind, dex_pc)); 1667 } 1668 return true; 1669} 1670 1671bool HGraphBuilder::NeedsAccessCheck(uint32_t type_index) const { 1672 return !compiler_driver_->CanAccessInstantiableTypeWithoutChecks( 1673 dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index); 1674} 1675 1676void HGraphBuilder::BuildSwitchJumpTable(const SwitchTable& table, 1677 const Instruction& instruction, 1678 HInstruction* value, 1679 uint32_t dex_pc) { 1680 // Add the successor blocks to the current block. 1681 uint16_t num_entries = table.GetNumEntries(); 1682 for (size_t i = 1; i <= num_entries; i++) { 1683 int32_t target_offset = table.GetEntryAt(i); 1684 HBasicBlock* case_target = FindBlockStartingAt(dex_pc + target_offset); 1685 DCHECK(case_target != nullptr); 1686 1687 // Add the target block as a successor. 1688 current_block_->AddSuccessor(case_target); 1689 } 1690 1691 // Add the default target block as the last successor. 1692 HBasicBlock* default_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits()); 1693 DCHECK(default_target != nullptr); 1694 current_block_->AddSuccessor(default_target); 1695 1696 // Now add the Switch instruction. 1697 int32_t starting_key = table.GetEntryAt(0); 1698 current_block_->AddInstruction( 1699 new (arena_) HPackedSwitch(starting_key, num_entries, value, dex_pc)); 1700 // This block ends with control flow. 1701 current_block_ = nullptr; 1702} 1703 1704void HGraphBuilder::BuildPackedSwitch(const Instruction& instruction, uint32_t dex_pc) { 1705 // Verifier guarantees that the payload for PackedSwitch contains: 1706 // (a) number of entries (may be zero) 1707 // (b) first and lowest switch case value (entry 0, always present) 1708 // (c) list of target pcs (entries 1 <= i <= N) 1709 SwitchTable table(instruction, dex_pc, false); 1710 1711 // Value to test against. 1712 HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt, dex_pc); 1713 1714 // Starting key value. 1715 int32_t starting_key = table.GetEntryAt(0); 1716 1717 // Retrieve number of entries. 1718 uint16_t num_entries = table.GetNumEntries(); 1719 if (num_entries == 0) { 1720 return; 1721 } 1722 1723 // Don't use a packed switch if there are very few entries. 1724 if (num_entries > kSmallSwitchThreshold) { 1725 BuildSwitchJumpTable(table, instruction, value, dex_pc); 1726 } else { 1727 // Chained cmp-and-branch, starting from starting_key. 1728 for (size_t i = 1; i <= num_entries; i++) { 1729 BuildSwitchCaseHelper(instruction, 1730 i, 1731 i == num_entries, 1732 table, 1733 value, 1734 starting_key + i - 1, 1735 table.GetEntryAt(i), 1736 dex_pc); 1737 } 1738 } 1739} 1740 1741void HGraphBuilder::BuildSparseSwitch(const Instruction& instruction, uint32_t dex_pc) { 1742 // Verifier guarantees that the payload for SparseSwitch contains: 1743 // (a) number of entries (may be zero) 1744 // (b) sorted key values (entries 0 <= i < N) 1745 // (c) target pcs corresponding to the switch values (entries N <= i < 2*N) 1746 SwitchTable table(instruction, dex_pc, true); 1747 1748 // Value to test against. 1749 HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt, dex_pc); 1750 1751 uint16_t num_entries = table.GetNumEntries(); 1752 1753 for (size_t i = 0; i < num_entries; i++) { 1754 BuildSwitchCaseHelper(instruction, i, i == static_cast<size_t>(num_entries) - 1, table, value, 1755 table.GetEntryAt(i), table.GetEntryAt(i + num_entries), dex_pc); 1756 } 1757} 1758 1759void HGraphBuilder::BuildSwitchCaseHelper(const Instruction& instruction, size_t index, 1760 bool is_last_case, const SwitchTable& table, 1761 HInstruction* value, int32_t case_value_int, 1762 int32_t target_offset, uint32_t dex_pc) { 1763 HBasicBlock* case_target = FindBlockStartingAt(dex_pc + target_offset); 1764 DCHECK(case_target != nullptr); 1765 PotentiallyAddSuspendCheck(case_target, dex_pc); 1766 1767 // The current case's value. 1768 HInstruction* this_case_value = graph_->GetIntConstant(case_value_int, dex_pc); 1769 1770 // Compare value and this_case_value. 1771 HEqual* comparison = new (arena_) HEqual(value, this_case_value, dex_pc); 1772 current_block_->AddInstruction(comparison); 1773 HInstruction* ifinst = new (arena_) HIf(comparison, dex_pc); 1774 current_block_->AddInstruction(ifinst); 1775 1776 // Case hit: use the target offset to determine where to go. 1777 current_block_->AddSuccessor(case_target); 1778 1779 // Case miss: go to the next case (or default fall-through). 1780 // When there is a next case, we use the block stored with the table offset representing this 1781 // case (that is where we registered them in ComputeBranchTargets). 1782 // When there is no next case, we use the following instruction. 1783 // TODO: Find a good way to peel the last iteration to avoid conditional, but still have re-use. 1784 if (!is_last_case) { 1785 HBasicBlock* next_case_target = FindBlockStartingAt(table.GetDexPcForIndex(index)); 1786 DCHECK(next_case_target != nullptr); 1787 current_block_->AddSuccessor(next_case_target); 1788 1789 // Need to manually add the block, as there is no dex-pc transition for the cases. 1790 graph_->AddBlock(next_case_target); 1791 1792 current_block_ = next_case_target; 1793 } else { 1794 HBasicBlock* default_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits()); 1795 DCHECK(default_target != nullptr); 1796 current_block_->AddSuccessor(default_target); 1797 current_block_ = nullptr; 1798 } 1799} 1800 1801void HGraphBuilder::PotentiallyAddSuspendCheck(HBasicBlock* target, uint32_t dex_pc) { 1802 int32_t target_offset = target->GetDexPc() - dex_pc; 1803 if (target_offset <= 0) { 1804 // DX generates back edges to the first encountered return. We can save 1805 // time of later passes by not adding redundant suspend checks. 1806 HInstruction* last_in_target = target->GetLastInstruction(); 1807 if (last_in_target != nullptr && 1808 (last_in_target->IsReturn() || last_in_target->IsReturnVoid())) { 1809 return; 1810 } 1811 1812 // Add a suspend check to backward branches which may potentially loop. We 1813 // can remove them after we recognize loops in the graph. 1814 current_block_->AddInstruction(new (arena_) HSuspendCheck(dex_pc)); 1815 } 1816} 1817 1818bool HGraphBuilder::CanDecodeQuickenedInfo() const { 1819 return interpreter_metadata_ != nullptr; 1820} 1821 1822uint16_t HGraphBuilder::LookupQuickenedInfo(uint32_t dex_pc) { 1823 DCHECK(interpreter_metadata_ != nullptr); 1824 uint32_t dex_pc_in_map = DecodeUnsignedLeb128(&interpreter_metadata_); 1825 DCHECK_EQ(dex_pc, dex_pc_in_map); 1826 return DecodeUnsignedLeb128(&interpreter_metadata_); 1827} 1828 1829bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32_t dex_pc) { 1830 if (current_block_ == nullptr) { 1831 return true; // Dead code 1832 } 1833 1834 switch (instruction.Opcode()) { 1835 case Instruction::CONST_4: { 1836 int32_t register_index = instruction.VRegA(); 1837 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_11n(), dex_pc); 1838 UpdateLocal(register_index, constant, dex_pc); 1839 break; 1840 } 1841 1842 case Instruction::CONST_16: { 1843 int32_t register_index = instruction.VRegA(); 1844 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21s(), dex_pc); 1845 UpdateLocal(register_index, constant, dex_pc); 1846 break; 1847 } 1848 1849 case Instruction::CONST: { 1850 int32_t register_index = instruction.VRegA(); 1851 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_31i(), dex_pc); 1852 UpdateLocal(register_index, constant, dex_pc); 1853 break; 1854 } 1855 1856 case Instruction::CONST_HIGH16: { 1857 int32_t register_index = instruction.VRegA(); 1858 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21h() << 16, dex_pc); 1859 UpdateLocal(register_index, constant, dex_pc); 1860 break; 1861 } 1862 1863 case Instruction::CONST_WIDE_16: { 1864 int32_t register_index = instruction.VRegA(); 1865 // Get 16 bits of constant value, sign extended to 64 bits. 1866 int64_t value = instruction.VRegB_21s(); 1867 value <<= 48; 1868 value >>= 48; 1869 HLongConstant* constant = graph_->GetLongConstant(value, dex_pc); 1870 UpdateLocal(register_index, constant, dex_pc); 1871 break; 1872 } 1873 1874 case Instruction::CONST_WIDE_32: { 1875 int32_t register_index = instruction.VRegA(); 1876 // Get 32 bits of constant value, sign extended to 64 bits. 1877 int64_t value = instruction.VRegB_31i(); 1878 value <<= 32; 1879 value >>= 32; 1880 HLongConstant* constant = graph_->GetLongConstant(value, dex_pc); 1881 UpdateLocal(register_index, constant, dex_pc); 1882 break; 1883 } 1884 1885 case Instruction::CONST_WIDE: { 1886 int32_t register_index = instruction.VRegA(); 1887 HLongConstant* constant = graph_->GetLongConstant(instruction.VRegB_51l(), dex_pc); 1888 UpdateLocal(register_index, constant, dex_pc); 1889 break; 1890 } 1891 1892 case Instruction::CONST_WIDE_HIGH16: { 1893 int32_t register_index = instruction.VRegA(); 1894 int64_t value = static_cast<int64_t>(instruction.VRegB_21h()) << 48; 1895 HLongConstant* constant = graph_->GetLongConstant(value, dex_pc); 1896 UpdateLocal(register_index, constant, dex_pc); 1897 break; 1898 } 1899 1900 // Note that the SSA building will refine the types. 1901 case Instruction::MOVE: 1902 case Instruction::MOVE_FROM16: 1903 case Instruction::MOVE_16: { 1904 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimInt, dex_pc); 1905 UpdateLocal(instruction.VRegA(), value, dex_pc); 1906 break; 1907 } 1908 1909 // Note that the SSA building will refine the types. 1910 case Instruction::MOVE_WIDE: 1911 case Instruction::MOVE_WIDE_FROM16: 1912 case Instruction::MOVE_WIDE_16: { 1913 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimLong, dex_pc); 1914 UpdateLocal(instruction.VRegA(), value, dex_pc); 1915 break; 1916 } 1917 1918 case Instruction::MOVE_OBJECT: 1919 case Instruction::MOVE_OBJECT_16: 1920 case Instruction::MOVE_OBJECT_FROM16: { 1921 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimNot, dex_pc); 1922 UpdateLocal(instruction.VRegA(), value, dex_pc); 1923 break; 1924 } 1925 1926 case Instruction::RETURN_VOID_NO_BARRIER: 1927 case Instruction::RETURN_VOID: { 1928 BuildReturn(instruction, Primitive::kPrimVoid, dex_pc); 1929 break; 1930 } 1931 1932#define IF_XX(comparison, cond) \ 1933 case Instruction::IF_##cond: If_22t<comparison>(instruction, dex_pc); break; \ 1934 case Instruction::IF_##cond##Z: If_21t<comparison>(instruction, dex_pc); break 1935 1936 IF_XX(HEqual, EQ); 1937 IF_XX(HNotEqual, NE); 1938 IF_XX(HLessThan, LT); 1939 IF_XX(HLessThanOrEqual, LE); 1940 IF_XX(HGreaterThan, GT); 1941 IF_XX(HGreaterThanOrEqual, GE); 1942 1943 case Instruction::GOTO: 1944 case Instruction::GOTO_16: 1945 case Instruction::GOTO_32: { 1946 int32_t offset = instruction.GetTargetOffset(); 1947 HBasicBlock* target = FindBlockStartingAt(offset + dex_pc); 1948 DCHECK(target != nullptr); 1949 PotentiallyAddSuspendCheck(target, dex_pc); 1950 current_block_->AddInstruction(new (arena_) HGoto(dex_pc)); 1951 current_block_->AddSuccessor(target); 1952 current_block_ = nullptr; 1953 break; 1954 } 1955 1956 case Instruction::RETURN: { 1957 BuildReturn(instruction, return_type_, dex_pc); 1958 break; 1959 } 1960 1961 case Instruction::RETURN_OBJECT: { 1962 BuildReturn(instruction, return_type_, dex_pc); 1963 break; 1964 } 1965 1966 case Instruction::RETURN_WIDE: { 1967 BuildReturn(instruction, return_type_, dex_pc); 1968 break; 1969 } 1970 1971 case Instruction::INVOKE_DIRECT: 1972 case Instruction::INVOKE_INTERFACE: 1973 case Instruction::INVOKE_STATIC: 1974 case Instruction::INVOKE_SUPER: 1975 case Instruction::INVOKE_VIRTUAL: 1976 case Instruction::INVOKE_VIRTUAL_QUICK: { 1977 uint16_t method_idx; 1978 if (instruction.Opcode() == Instruction::INVOKE_VIRTUAL_QUICK) { 1979 if (!CanDecodeQuickenedInfo()) { 1980 return false; 1981 } 1982 method_idx = LookupQuickenedInfo(dex_pc); 1983 } else { 1984 method_idx = instruction.VRegB_35c(); 1985 } 1986 uint32_t number_of_vreg_arguments = instruction.VRegA_35c(); 1987 uint32_t args[5]; 1988 instruction.GetVarArgs(args); 1989 if (!BuildInvoke(instruction, dex_pc, method_idx, 1990 number_of_vreg_arguments, false, args, -1)) { 1991 return false; 1992 } 1993 break; 1994 } 1995 1996 case Instruction::INVOKE_DIRECT_RANGE: 1997 case Instruction::INVOKE_INTERFACE_RANGE: 1998 case Instruction::INVOKE_STATIC_RANGE: 1999 case Instruction::INVOKE_SUPER_RANGE: 2000 case Instruction::INVOKE_VIRTUAL_RANGE: 2001 case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: { 2002 uint16_t method_idx; 2003 if (instruction.Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK) { 2004 if (!CanDecodeQuickenedInfo()) { 2005 return false; 2006 } 2007 method_idx = LookupQuickenedInfo(dex_pc); 2008 } else { 2009 method_idx = instruction.VRegB_3rc(); 2010 } 2011 uint32_t number_of_vreg_arguments = instruction.VRegA_3rc(); 2012 uint32_t register_index = instruction.VRegC(); 2013 if (!BuildInvoke(instruction, dex_pc, method_idx, 2014 number_of_vreg_arguments, true, nullptr, register_index)) { 2015 return false; 2016 } 2017 break; 2018 } 2019 2020 case Instruction::NEG_INT: { 2021 Unop_12x<HNeg>(instruction, Primitive::kPrimInt, dex_pc); 2022 break; 2023 } 2024 2025 case Instruction::NEG_LONG: { 2026 Unop_12x<HNeg>(instruction, Primitive::kPrimLong, dex_pc); 2027 break; 2028 } 2029 2030 case Instruction::NEG_FLOAT: { 2031 Unop_12x<HNeg>(instruction, Primitive::kPrimFloat, dex_pc); 2032 break; 2033 } 2034 2035 case Instruction::NEG_DOUBLE: { 2036 Unop_12x<HNeg>(instruction, Primitive::kPrimDouble, dex_pc); 2037 break; 2038 } 2039 2040 case Instruction::NOT_INT: { 2041 Unop_12x<HNot>(instruction, Primitive::kPrimInt, dex_pc); 2042 break; 2043 } 2044 2045 case Instruction::NOT_LONG: { 2046 Unop_12x<HNot>(instruction, Primitive::kPrimLong, dex_pc); 2047 break; 2048 } 2049 2050 case Instruction::INT_TO_LONG: { 2051 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimLong, dex_pc); 2052 break; 2053 } 2054 2055 case Instruction::INT_TO_FLOAT: { 2056 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimFloat, dex_pc); 2057 break; 2058 } 2059 2060 case Instruction::INT_TO_DOUBLE: { 2061 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimDouble, dex_pc); 2062 break; 2063 } 2064 2065 case Instruction::LONG_TO_INT: { 2066 Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimInt, dex_pc); 2067 break; 2068 } 2069 2070 case Instruction::LONG_TO_FLOAT: { 2071 Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimFloat, dex_pc); 2072 break; 2073 } 2074 2075 case Instruction::LONG_TO_DOUBLE: { 2076 Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimDouble, dex_pc); 2077 break; 2078 } 2079 2080 case Instruction::FLOAT_TO_INT: { 2081 Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimInt, dex_pc); 2082 break; 2083 } 2084 2085 case Instruction::FLOAT_TO_LONG: { 2086 Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimLong, dex_pc); 2087 break; 2088 } 2089 2090 case Instruction::FLOAT_TO_DOUBLE: { 2091 Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimDouble, dex_pc); 2092 break; 2093 } 2094 2095 case Instruction::DOUBLE_TO_INT: { 2096 Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimInt, dex_pc); 2097 break; 2098 } 2099 2100 case Instruction::DOUBLE_TO_LONG: { 2101 Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimLong, dex_pc); 2102 break; 2103 } 2104 2105 case Instruction::DOUBLE_TO_FLOAT: { 2106 Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimFloat, dex_pc); 2107 break; 2108 } 2109 2110 case Instruction::INT_TO_BYTE: { 2111 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimByte, dex_pc); 2112 break; 2113 } 2114 2115 case Instruction::INT_TO_SHORT: { 2116 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimShort, dex_pc); 2117 break; 2118 } 2119 2120 case Instruction::INT_TO_CHAR: { 2121 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimChar, dex_pc); 2122 break; 2123 } 2124 2125 case Instruction::ADD_INT: { 2126 Binop_23x<HAdd>(instruction, Primitive::kPrimInt, dex_pc); 2127 break; 2128 } 2129 2130 case Instruction::ADD_LONG: { 2131 Binop_23x<HAdd>(instruction, Primitive::kPrimLong, dex_pc); 2132 break; 2133 } 2134 2135 case Instruction::ADD_DOUBLE: { 2136 Binop_23x<HAdd>(instruction, Primitive::kPrimDouble, dex_pc); 2137 break; 2138 } 2139 2140 case Instruction::ADD_FLOAT: { 2141 Binop_23x<HAdd>(instruction, Primitive::kPrimFloat, dex_pc); 2142 break; 2143 } 2144 2145 case Instruction::SUB_INT: { 2146 Binop_23x<HSub>(instruction, Primitive::kPrimInt, dex_pc); 2147 break; 2148 } 2149 2150 case Instruction::SUB_LONG: { 2151 Binop_23x<HSub>(instruction, Primitive::kPrimLong, dex_pc); 2152 break; 2153 } 2154 2155 case Instruction::SUB_FLOAT: { 2156 Binop_23x<HSub>(instruction, Primitive::kPrimFloat, dex_pc); 2157 break; 2158 } 2159 2160 case Instruction::SUB_DOUBLE: { 2161 Binop_23x<HSub>(instruction, Primitive::kPrimDouble, dex_pc); 2162 break; 2163 } 2164 2165 case Instruction::ADD_INT_2ADDR: { 2166 Binop_12x<HAdd>(instruction, Primitive::kPrimInt, dex_pc); 2167 break; 2168 } 2169 2170 case Instruction::MUL_INT: { 2171 Binop_23x<HMul>(instruction, Primitive::kPrimInt, dex_pc); 2172 break; 2173 } 2174 2175 case Instruction::MUL_LONG: { 2176 Binop_23x<HMul>(instruction, Primitive::kPrimLong, dex_pc); 2177 break; 2178 } 2179 2180 case Instruction::MUL_FLOAT: { 2181 Binop_23x<HMul>(instruction, Primitive::kPrimFloat, dex_pc); 2182 break; 2183 } 2184 2185 case Instruction::MUL_DOUBLE: { 2186 Binop_23x<HMul>(instruction, Primitive::kPrimDouble, dex_pc); 2187 break; 2188 } 2189 2190 case Instruction::DIV_INT: { 2191 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(), 2192 dex_pc, Primitive::kPrimInt, false, true); 2193 break; 2194 } 2195 2196 case Instruction::DIV_LONG: { 2197 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(), 2198 dex_pc, Primitive::kPrimLong, false, true); 2199 break; 2200 } 2201 2202 case Instruction::DIV_FLOAT: { 2203 Binop_23x<HDiv>(instruction, Primitive::kPrimFloat, dex_pc); 2204 break; 2205 } 2206 2207 case Instruction::DIV_DOUBLE: { 2208 Binop_23x<HDiv>(instruction, Primitive::kPrimDouble, dex_pc); 2209 break; 2210 } 2211 2212 case Instruction::REM_INT: { 2213 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(), 2214 dex_pc, Primitive::kPrimInt, false, false); 2215 break; 2216 } 2217 2218 case Instruction::REM_LONG: { 2219 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(), 2220 dex_pc, Primitive::kPrimLong, false, false); 2221 break; 2222 } 2223 2224 case Instruction::REM_FLOAT: { 2225 Binop_23x<HRem>(instruction, Primitive::kPrimFloat, dex_pc); 2226 break; 2227 } 2228 2229 case Instruction::REM_DOUBLE: { 2230 Binop_23x<HRem>(instruction, Primitive::kPrimDouble, dex_pc); 2231 break; 2232 } 2233 2234 case Instruction::AND_INT: { 2235 Binop_23x<HAnd>(instruction, Primitive::kPrimInt, dex_pc); 2236 break; 2237 } 2238 2239 case Instruction::AND_LONG: { 2240 Binop_23x<HAnd>(instruction, Primitive::kPrimLong, dex_pc); 2241 break; 2242 } 2243 2244 case Instruction::SHL_INT: { 2245 Binop_23x_shift<HShl>(instruction, Primitive::kPrimInt, dex_pc); 2246 break; 2247 } 2248 2249 case Instruction::SHL_LONG: { 2250 Binop_23x_shift<HShl>(instruction, Primitive::kPrimLong, dex_pc); 2251 break; 2252 } 2253 2254 case Instruction::SHR_INT: { 2255 Binop_23x_shift<HShr>(instruction, Primitive::kPrimInt, dex_pc); 2256 break; 2257 } 2258 2259 case Instruction::SHR_LONG: { 2260 Binop_23x_shift<HShr>(instruction, Primitive::kPrimLong, dex_pc); 2261 break; 2262 } 2263 2264 case Instruction::USHR_INT: { 2265 Binop_23x_shift<HUShr>(instruction, Primitive::kPrimInt, dex_pc); 2266 break; 2267 } 2268 2269 case Instruction::USHR_LONG: { 2270 Binop_23x_shift<HUShr>(instruction, Primitive::kPrimLong, dex_pc); 2271 break; 2272 } 2273 2274 case Instruction::OR_INT: { 2275 Binop_23x<HOr>(instruction, Primitive::kPrimInt, dex_pc); 2276 break; 2277 } 2278 2279 case Instruction::OR_LONG: { 2280 Binop_23x<HOr>(instruction, Primitive::kPrimLong, dex_pc); 2281 break; 2282 } 2283 2284 case Instruction::XOR_INT: { 2285 Binop_23x<HXor>(instruction, Primitive::kPrimInt, dex_pc); 2286 break; 2287 } 2288 2289 case Instruction::XOR_LONG: { 2290 Binop_23x<HXor>(instruction, Primitive::kPrimLong, dex_pc); 2291 break; 2292 } 2293 2294 case Instruction::ADD_LONG_2ADDR: { 2295 Binop_12x<HAdd>(instruction, Primitive::kPrimLong, dex_pc); 2296 break; 2297 } 2298 2299 case Instruction::ADD_DOUBLE_2ADDR: { 2300 Binop_12x<HAdd>(instruction, Primitive::kPrimDouble, dex_pc); 2301 break; 2302 } 2303 2304 case Instruction::ADD_FLOAT_2ADDR: { 2305 Binop_12x<HAdd>(instruction, Primitive::kPrimFloat, dex_pc); 2306 break; 2307 } 2308 2309 case Instruction::SUB_INT_2ADDR: { 2310 Binop_12x<HSub>(instruction, Primitive::kPrimInt, dex_pc); 2311 break; 2312 } 2313 2314 case Instruction::SUB_LONG_2ADDR: { 2315 Binop_12x<HSub>(instruction, Primitive::kPrimLong, dex_pc); 2316 break; 2317 } 2318 2319 case Instruction::SUB_FLOAT_2ADDR: { 2320 Binop_12x<HSub>(instruction, Primitive::kPrimFloat, dex_pc); 2321 break; 2322 } 2323 2324 case Instruction::SUB_DOUBLE_2ADDR: { 2325 Binop_12x<HSub>(instruction, Primitive::kPrimDouble, dex_pc); 2326 break; 2327 } 2328 2329 case Instruction::MUL_INT_2ADDR: { 2330 Binop_12x<HMul>(instruction, Primitive::kPrimInt, dex_pc); 2331 break; 2332 } 2333 2334 case Instruction::MUL_LONG_2ADDR: { 2335 Binop_12x<HMul>(instruction, Primitive::kPrimLong, dex_pc); 2336 break; 2337 } 2338 2339 case Instruction::MUL_FLOAT_2ADDR: { 2340 Binop_12x<HMul>(instruction, Primitive::kPrimFloat, dex_pc); 2341 break; 2342 } 2343 2344 case Instruction::MUL_DOUBLE_2ADDR: { 2345 Binop_12x<HMul>(instruction, Primitive::kPrimDouble, dex_pc); 2346 break; 2347 } 2348 2349 case Instruction::DIV_INT_2ADDR: { 2350 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(), 2351 dex_pc, Primitive::kPrimInt, false, true); 2352 break; 2353 } 2354 2355 case Instruction::DIV_LONG_2ADDR: { 2356 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(), 2357 dex_pc, Primitive::kPrimLong, false, true); 2358 break; 2359 } 2360 2361 case Instruction::REM_INT_2ADDR: { 2362 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(), 2363 dex_pc, Primitive::kPrimInt, false, false); 2364 break; 2365 } 2366 2367 case Instruction::REM_LONG_2ADDR: { 2368 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(), 2369 dex_pc, Primitive::kPrimLong, false, false); 2370 break; 2371 } 2372 2373 case Instruction::REM_FLOAT_2ADDR: { 2374 Binop_12x<HRem>(instruction, Primitive::kPrimFloat, dex_pc); 2375 break; 2376 } 2377 2378 case Instruction::REM_DOUBLE_2ADDR: { 2379 Binop_12x<HRem>(instruction, Primitive::kPrimDouble, dex_pc); 2380 break; 2381 } 2382 2383 case Instruction::SHL_INT_2ADDR: { 2384 Binop_12x_shift<HShl>(instruction, Primitive::kPrimInt, dex_pc); 2385 break; 2386 } 2387 2388 case Instruction::SHL_LONG_2ADDR: { 2389 Binop_12x_shift<HShl>(instruction, Primitive::kPrimLong, dex_pc); 2390 break; 2391 } 2392 2393 case Instruction::SHR_INT_2ADDR: { 2394 Binop_12x_shift<HShr>(instruction, Primitive::kPrimInt, dex_pc); 2395 break; 2396 } 2397 2398 case Instruction::SHR_LONG_2ADDR: { 2399 Binop_12x_shift<HShr>(instruction, Primitive::kPrimLong, dex_pc); 2400 break; 2401 } 2402 2403 case Instruction::USHR_INT_2ADDR: { 2404 Binop_12x_shift<HUShr>(instruction, Primitive::kPrimInt, dex_pc); 2405 break; 2406 } 2407 2408 case Instruction::USHR_LONG_2ADDR: { 2409 Binop_12x_shift<HUShr>(instruction, Primitive::kPrimLong, dex_pc); 2410 break; 2411 } 2412 2413 case Instruction::DIV_FLOAT_2ADDR: { 2414 Binop_12x<HDiv>(instruction, Primitive::kPrimFloat, dex_pc); 2415 break; 2416 } 2417 2418 case Instruction::DIV_DOUBLE_2ADDR: { 2419 Binop_12x<HDiv>(instruction, Primitive::kPrimDouble, dex_pc); 2420 break; 2421 } 2422 2423 case Instruction::AND_INT_2ADDR: { 2424 Binop_12x<HAnd>(instruction, Primitive::kPrimInt, dex_pc); 2425 break; 2426 } 2427 2428 case Instruction::AND_LONG_2ADDR: { 2429 Binop_12x<HAnd>(instruction, Primitive::kPrimLong, dex_pc); 2430 break; 2431 } 2432 2433 case Instruction::OR_INT_2ADDR: { 2434 Binop_12x<HOr>(instruction, Primitive::kPrimInt, dex_pc); 2435 break; 2436 } 2437 2438 case Instruction::OR_LONG_2ADDR: { 2439 Binop_12x<HOr>(instruction, Primitive::kPrimLong, dex_pc); 2440 break; 2441 } 2442 2443 case Instruction::XOR_INT_2ADDR: { 2444 Binop_12x<HXor>(instruction, Primitive::kPrimInt, dex_pc); 2445 break; 2446 } 2447 2448 case Instruction::XOR_LONG_2ADDR: { 2449 Binop_12x<HXor>(instruction, Primitive::kPrimLong, dex_pc); 2450 break; 2451 } 2452 2453 case Instruction::ADD_INT_LIT16: { 2454 Binop_22s<HAdd>(instruction, false, dex_pc); 2455 break; 2456 } 2457 2458 case Instruction::AND_INT_LIT16: { 2459 Binop_22s<HAnd>(instruction, false, dex_pc); 2460 break; 2461 } 2462 2463 case Instruction::OR_INT_LIT16: { 2464 Binop_22s<HOr>(instruction, false, dex_pc); 2465 break; 2466 } 2467 2468 case Instruction::XOR_INT_LIT16: { 2469 Binop_22s<HXor>(instruction, false, dex_pc); 2470 break; 2471 } 2472 2473 case Instruction::RSUB_INT: { 2474 Binop_22s<HSub>(instruction, true, dex_pc); 2475 break; 2476 } 2477 2478 case Instruction::MUL_INT_LIT16: { 2479 Binop_22s<HMul>(instruction, false, dex_pc); 2480 break; 2481 } 2482 2483 case Instruction::ADD_INT_LIT8: { 2484 Binop_22b<HAdd>(instruction, false, dex_pc); 2485 break; 2486 } 2487 2488 case Instruction::AND_INT_LIT8: { 2489 Binop_22b<HAnd>(instruction, false, dex_pc); 2490 break; 2491 } 2492 2493 case Instruction::OR_INT_LIT8: { 2494 Binop_22b<HOr>(instruction, false, dex_pc); 2495 break; 2496 } 2497 2498 case Instruction::XOR_INT_LIT8: { 2499 Binop_22b<HXor>(instruction, false, dex_pc); 2500 break; 2501 } 2502 2503 case Instruction::RSUB_INT_LIT8: { 2504 Binop_22b<HSub>(instruction, true, dex_pc); 2505 break; 2506 } 2507 2508 case Instruction::MUL_INT_LIT8: { 2509 Binop_22b<HMul>(instruction, false, dex_pc); 2510 break; 2511 } 2512 2513 case Instruction::DIV_INT_LIT16: 2514 case Instruction::DIV_INT_LIT8: { 2515 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(), 2516 dex_pc, Primitive::kPrimInt, true, true); 2517 break; 2518 } 2519 2520 case Instruction::REM_INT_LIT16: 2521 case Instruction::REM_INT_LIT8: { 2522 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(), 2523 dex_pc, Primitive::kPrimInt, true, false); 2524 break; 2525 } 2526 2527 case Instruction::SHL_INT_LIT8: { 2528 Binop_22b<HShl>(instruction, false, dex_pc); 2529 break; 2530 } 2531 2532 case Instruction::SHR_INT_LIT8: { 2533 Binop_22b<HShr>(instruction, false, dex_pc); 2534 break; 2535 } 2536 2537 case Instruction::USHR_INT_LIT8: { 2538 Binop_22b<HUShr>(instruction, false, dex_pc); 2539 break; 2540 } 2541 2542 case Instruction::NEW_INSTANCE: { 2543 uint16_t type_index = instruction.VRegB_21c(); 2544 if (compiler_driver_->IsStringTypeIndex(type_index, dex_file_)) { 2545 int32_t register_index = instruction.VRegA(); 2546 HFakeString* fake_string = new (arena_) HFakeString(dex_pc); 2547 current_block_->AddInstruction(fake_string); 2548 UpdateLocal(register_index, fake_string, dex_pc); 2549 } else { 2550 QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index) 2551 ? kQuickAllocObjectWithAccessCheck 2552 : kQuickAllocObject; 2553 2554 current_block_->AddInstruction(new (arena_) HNewInstance( 2555 graph_->GetCurrentMethod(), 2556 dex_pc, 2557 type_index, 2558 *dex_compilation_unit_->GetDexFile(), 2559 entrypoint)); 2560 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc); 2561 } 2562 break; 2563 } 2564 2565 case Instruction::NEW_ARRAY: { 2566 uint16_t type_index = instruction.VRegC_22c(); 2567 HInstruction* length = LoadLocal(instruction.VRegB_22c(), Primitive::kPrimInt, dex_pc); 2568 QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index) 2569 ? kQuickAllocArrayWithAccessCheck 2570 : kQuickAllocArray; 2571 current_block_->AddInstruction(new (arena_) HNewArray(length, 2572 graph_->GetCurrentMethod(), 2573 dex_pc, 2574 type_index, 2575 *dex_compilation_unit_->GetDexFile(), 2576 entrypoint)); 2577 UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction(), dex_pc); 2578 break; 2579 } 2580 2581 case Instruction::FILLED_NEW_ARRAY: { 2582 uint32_t number_of_vreg_arguments = instruction.VRegA_35c(); 2583 uint32_t type_index = instruction.VRegB_35c(); 2584 uint32_t args[5]; 2585 instruction.GetVarArgs(args); 2586 BuildFilledNewArray(dex_pc, type_index, number_of_vreg_arguments, false, args, 0); 2587 break; 2588 } 2589 2590 case Instruction::FILLED_NEW_ARRAY_RANGE: { 2591 uint32_t number_of_vreg_arguments = instruction.VRegA_3rc(); 2592 uint32_t type_index = instruction.VRegB_3rc(); 2593 uint32_t register_index = instruction.VRegC_3rc(); 2594 BuildFilledNewArray( 2595 dex_pc, type_index, number_of_vreg_arguments, true, nullptr, register_index); 2596 break; 2597 } 2598 2599 case Instruction::FILL_ARRAY_DATA: { 2600 BuildFillArrayData(instruction, dex_pc); 2601 break; 2602 } 2603 2604 case Instruction::MOVE_RESULT: 2605 case Instruction::MOVE_RESULT_WIDE: 2606 case Instruction::MOVE_RESULT_OBJECT: { 2607 if (latest_result_ == nullptr) { 2608 // Only dead code can lead to this situation, where the verifier 2609 // does not reject the method. 2610 } else { 2611 // An Invoke/FilledNewArray and its MoveResult could have landed in 2612 // different blocks if there was a try/catch block boundary between 2613 // them. For Invoke, we insert a StoreLocal after the instruction. For 2614 // FilledNewArray, the local needs to be updated after the array was 2615 // filled, otherwise we might overwrite an input vreg. 2616 HStoreLocal* update_local = 2617 new (arena_) HStoreLocal(GetLocalAt(instruction.VRegA()), latest_result_, dex_pc); 2618 HBasicBlock* block = latest_result_->GetBlock(); 2619 if (block == current_block_) { 2620 // MoveResult and the previous instruction are in the same block. 2621 current_block_->AddInstruction(update_local); 2622 } else { 2623 // The two instructions are in different blocks. Insert the MoveResult 2624 // before the final control-flow instruction of the previous block. 2625 DCHECK(block->EndsWithControlFlowInstruction()); 2626 DCHECK(current_block_->GetInstructions().IsEmpty()); 2627 block->InsertInstructionBefore(update_local, block->GetLastInstruction()); 2628 } 2629 latest_result_ = nullptr; 2630 } 2631 break; 2632 } 2633 2634 case Instruction::CMP_LONG: { 2635 Binop_23x_cmp(instruction, Primitive::kPrimLong, ComparisonBias::kNoBias, dex_pc); 2636 break; 2637 } 2638 2639 case Instruction::CMPG_FLOAT: { 2640 Binop_23x_cmp(instruction, Primitive::kPrimFloat, ComparisonBias::kGtBias, dex_pc); 2641 break; 2642 } 2643 2644 case Instruction::CMPG_DOUBLE: { 2645 Binop_23x_cmp(instruction, Primitive::kPrimDouble, ComparisonBias::kGtBias, dex_pc); 2646 break; 2647 } 2648 2649 case Instruction::CMPL_FLOAT: { 2650 Binop_23x_cmp(instruction, Primitive::kPrimFloat, ComparisonBias::kLtBias, dex_pc); 2651 break; 2652 } 2653 2654 case Instruction::CMPL_DOUBLE: { 2655 Binop_23x_cmp(instruction, Primitive::kPrimDouble, ComparisonBias::kLtBias, dex_pc); 2656 break; 2657 } 2658 2659 case Instruction::NOP: 2660 break; 2661 2662 case Instruction::IGET: 2663 case Instruction::IGET_QUICK: 2664 case Instruction::IGET_WIDE: 2665 case Instruction::IGET_WIDE_QUICK: 2666 case Instruction::IGET_OBJECT: 2667 case Instruction::IGET_OBJECT_QUICK: 2668 case Instruction::IGET_BOOLEAN: 2669 case Instruction::IGET_BOOLEAN_QUICK: 2670 case Instruction::IGET_BYTE: 2671 case Instruction::IGET_BYTE_QUICK: 2672 case Instruction::IGET_CHAR: 2673 case Instruction::IGET_CHAR_QUICK: 2674 case Instruction::IGET_SHORT: 2675 case Instruction::IGET_SHORT_QUICK: { 2676 if (!BuildInstanceFieldAccess(instruction, dex_pc, false)) { 2677 return false; 2678 } 2679 break; 2680 } 2681 2682 case Instruction::IPUT: 2683 case Instruction::IPUT_QUICK: 2684 case Instruction::IPUT_WIDE: 2685 case Instruction::IPUT_WIDE_QUICK: 2686 case Instruction::IPUT_OBJECT: 2687 case Instruction::IPUT_OBJECT_QUICK: 2688 case Instruction::IPUT_BOOLEAN: 2689 case Instruction::IPUT_BOOLEAN_QUICK: 2690 case Instruction::IPUT_BYTE: 2691 case Instruction::IPUT_BYTE_QUICK: 2692 case Instruction::IPUT_CHAR: 2693 case Instruction::IPUT_CHAR_QUICK: 2694 case Instruction::IPUT_SHORT: 2695 case Instruction::IPUT_SHORT_QUICK: { 2696 if (!BuildInstanceFieldAccess(instruction, dex_pc, true)) { 2697 return false; 2698 } 2699 break; 2700 } 2701 2702 case Instruction::SGET: 2703 case Instruction::SGET_WIDE: 2704 case Instruction::SGET_OBJECT: 2705 case Instruction::SGET_BOOLEAN: 2706 case Instruction::SGET_BYTE: 2707 case Instruction::SGET_CHAR: 2708 case Instruction::SGET_SHORT: { 2709 if (!BuildStaticFieldAccess(instruction, dex_pc, false)) { 2710 return false; 2711 } 2712 break; 2713 } 2714 2715 case Instruction::SPUT: 2716 case Instruction::SPUT_WIDE: 2717 case Instruction::SPUT_OBJECT: 2718 case Instruction::SPUT_BOOLEAN: 2719 case Instruction::SPUT_BYTE: 2720 case Instruction::SPUT_CHAR: 2721 case Instruction::SPUT_SHORT: { 2722 if (!BuildStaticFieldAccess(instruction, dex_pc, true)) { 2723 return false; 2724 } 2725 break; 2726 } 2727 2728#define ARRAY_XX(kind, anticipated_type) \ 2729 case Instruction::AGET##kind: { \ 2730 BuildArrayAccess(instruction, dex_pc, false, anticipated_type); \ 2731 break; \ 2732 } \ 2733 case Instruction::APUT##kind: { \ 2734 BuildArrayAccess(instruction, dex_pc, true, anticipated_type); \ 2735 break; \ 2736 } 2737 2738 ARRAY_XX(, Primitive::kPrimInt); 2739 ARRAY_XX(_WIDE, Primitive::kPrimLong); 2740 ARRAY_XX(_OBJECT, Primitive::kPrimNot); 2741 ARRAY_XX(_BOOLEAN, Primitive::kPrimBoolean); 2742 ARRAY_XX(_BYTE, Primitive::kPrimByte); 2743 ARRAY_XX(_CHAR, Primitive::kPrimChar); 2744 ARRAY_XX(_SHORT, Primitive::kPrimShort); 2745 2746 case Instruction::ARRAY_LENGTH: { 2747 HInstruction* object = LoadLocal(instruction.VRegB_12x(), Primitive::kPrimNot, dex_pc); 2748 // No need for a temporary for the null check, it is the only input of the following 2749 // instruction. 2750 object = new (arena_) HNullCheck(object, dex_pc); 2751 current_block_->AddInstruction(object); 2752 current_block_->AddInstruction(new (arena_) HArrayLength(object, dex_pc)); 2753 UpdateLocal(instruction.VRegA_12x(), current_block_->GetLastInstruction(), dex_pc); 2754 break; 2755 } 2756 2757 case Instruction::CONST_STRING: { 2758 current_block_->AddInstruction( 2759 new (arena_) HLoadString(graph_->GetCurrentMethod(), instruction.VRegB_21c(), dex_pc)); 2760 UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction(), dex_pc); 2761 break; 2762 } 2763 2764 case Instruction::CONST_STRING_JUMBO: { 2765 current_block_->AddInstruction( 2766 new (arena_) HLoadString(graph_->GetCurrentMethod(), instruction.VRegB_31c(), dex_pc)); 2767 UpdateLocal(instruction.VRegA_31c(), current_block_->GetLastInstruction(), dex_pc); 2768 break; 2769 } 2770 2771 case Instruction::CONST_CLASS: { 2772 uint16_t type_index = instruction.VRegB_21c(); 2773 bool type_known_final; 2774 bool type_known_abstract; 2775 bool dont_use_is_referrers_class; 2776 // `CanAccessTypeWithoutChecks` will tell whether the method being 2777 // built is trying to access its own class, so that the generated 2778 // code can optimize for this case. However, the optimization does not 2779 // work for inlining, so we use `IsOutermostCompilingClass` instead. 2780 bool can_access = compiler_driver_->CanAccessTypeWithoutChecks( 2781 dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index, 2782 &type_known_final, &type_known_abstract, &dont_use_is_referrers_class); 2783 if (!can_access) { 2784 MaybeRecordStat(MethodCompilationStat::kNotCompiledCantAccesType); 2785 return false; 2786 } 2787 current_block_->AddInstruction(new (arena_) HLoadClass( 2788 graph_->GetCurrentMethod(), 2789 type_index, 2790 *dex_compilation_unit_->GetDexFile(), 2791 IsOutermostCompilingClass(type_index), 2792 dex_pc)); 2793 UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction(), dex_pc); 2794 break; 2795 } 2796 2797 case Instruction::MOVE_EXCEPTION: { 2798 current_block_->AddInstruction(new (arena_) HLoadException(dex_pc)); 2799 UpdateLocal(instruction.VRegA_11x(), current_block_->GetLastInstruction(), dex_pc); 2800 current_block_->AddInstruction(new (arena_) HClearException(dex_pc)); 2801 break; 2802 } 2803 2804 case Instruction::THROW: { 2805 HInstruction* exception = LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot, dex_pc); 2806 current_block_->AddInstruction(new (arena_) HThrow(exception, dex_pc)); 2807 // A throw instruction must branch to the exit block. 2808 current_block_->AddSuccessor(exit_block_); 2809 // We finished building this block. Set the current block to null to avoid 2810 // adding dead instructions to it. 2811 current_block_ = nullptr; 2812 break; 2813 } 2814 2815 case Instruction::INSTANCE_OF: { 2816 uint8_t destination = instruction.VRegA_22c(); 2817 uint8_t reference = instruction.VRegB_22c(); 2818 uint16_t type_index = instruction.VRegC_22c(); 2819 if (!BuildTypeCheck(instruction, destination, reference, type_index, dex_pc)) { 2820 return false; 2821 } 2822 break; 2823 } 2824 2825 case Instruction::CHECK_CAST: { 2826 uint8_t reference = instruction.VRegA_21c(); 2827 uint16_t type_index = instruction.VRegB_21c(); 2828 if (!BuildTypeCheck(instruction, -1, reference, type_index, dex_pc)) { 2829 return false; 2830 } 2831 break; 2832 } 2833 2834 case Instruction::MONITOR_ENTER: { 2835 current_block_->AddInstruction(new (arena_) HMonitorOperation( 2836 LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot, dex_pc), 2837 HMonitorOperation::kEnter, 2838 dex_pc)); 2839 break; 2840 } 2841 2842 case Instruction::MONITOR_EXIT: { 2843 current_block_->AddInstruction(new (arena_) HMonitorOperation( 2844 LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot, dex_pc), 2845 HMonitorOperation::kExit, 2846 dex_pc)); 2847 break; 2848 } 2849 2850 case Instruction::PACKED_SWITCH: { 2851 BuildPackedSwitch(instruction, dex_pc); 2852 break; 2853 } 2854 2855 case Instruction::SPARSE_SWITCH: { 2856 BuildSparseSwitch(instruction, dex_pc); 2857 break; 2858 } 2859 2860 default: 2861 VLOG(compiler) << "Did not compile " 2862 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_) 2863 << " because of unhandled instruction " 2864 << instruction.Name(); 2865 MaybeRecordStat(MethodCompilationStat::kNotCompiledUnhandledInstruction); 2866 return false; 2867 } 2868 return true; 2869} // NOLINT(readability/fn_size) 2870 2871HLocal* HGraphBuilder::GetLocalAt(uint32_t register_index) const { 2872 DCHECK_LT(register_index, locals_.size()); 2873 return locals_[register_index]; 2874} 2875 2876void HGraphBuilder::UpdateLocal(uint32_t register_index, 2877 HInstruction* instruction, 2878 uint32_t dex_pc) const { 2879 HLocal* local = GetLocalAt(register_index); 2880 current_block_->AddInstruction(new (arena_) HStoreLocal(local, instruction, dex_pc)); 2881} 2882 2883HInstruction* HGraphBuilder::LoadLocal(uint32_t register_index, 2884 Primitive::Type type, 2885 uint32_t dex_pc) const { 2886 HLocal* local = GetLocalAt(register_index); 2887 current_block_->AddInstruction(new (arena_) HLoadLocal(local, type, dex_pc)); 2888 return current_block_->GetLastInstruction(); 2889} 2890 2891} // namespace art 2892