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