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