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