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 #ifndef ART_COMPILER_OPTIMIZING_NODES_H_ 18 #define ART_COMPILER_OPTIMIZING_NODES_H_ 19 20 #include "base/arena_containers.h" 21 #include "base/arena_object.h" 22 #include "dex/compiler_enums.h" 23 #include "entrypoints/quick/quick_entrypoints_enum.h" 24 #include "handle.h" 25 #include "handle_scope.h" 26 #include "invoke_type.h" 27 #include "locations.h" 28 #include "mirror/class.h" 29 #include "offsets.h" 30 #include "primitive.h" 31 #include "utils/arena_bit_vector.h" 32 #include "utils/growable_array.h" 33 34 namespace art { 35 36 class GraphChecker; 37 class HBasicBlock; 38 class HDoubleConstant; 39 class HEnvironment; 40 class HFloatConstant; 41 class HGraphVisitor; 42 class HInstruction; 43 class HIntConstant; 44 class HInvoke; 45 class HLongConstant; 46 class HNullConstant; 47 class HPhi; 48 class HSuspendCheck; 49 class LiveInterval; 50 class LocationSummary; 51 class SlowPathCode; 52 class SsaBuilder; 53 54 static const int kDefaultNumberOfBlocks = 8; 55 static const int kDefaultNumberOfSuccessors = 2; 56 static const int kDefaultNumberOfPredecessors = 2; 57 static const int kDefaultNumberOfDominatedBlocks = 1; 58 static const int kDefaultNumberOfBackEdges = 1; 59 60 static constexpr uint32_t kMaxIntShiftValue = 0x1f; 61 static constexpr uint64_t kMaxLongShiftValue = 0x3f; 62 63 enum IfCondition { 64 kCondEQ, 65 kCondNE, 66 kCondLT, 67 kCondLE, 68 kCondGT, 69 kCondGE, 70 }; 71 72 class HInstructionList { 73 public: 74 HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {} 75 76 void AddInstruction(HInstruction* instruction); 77 void RemoveInstruction(HInstruction* instruction); 78 79 // Insert `instruction` before/after an existing instruction `cursor`. 80 void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor); 81 void InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor); 82 83 // Return true if this list contains `instruction`. 84 bool Contains(HInstruction* instruction) const; 85 86 // Return true if `instruction1` is found before `instruction2` in 87 // this instruction list and false otherwise. Abort if none 88 // of these instructions is found. 89 bool FoundBefore(const HInstruction* instruction1, 90 const HInstruction* instruction2) const; 91 92 bool IsEmpty() const { return first_instruction_ == nullptr; } 93 void Clear() { first_instruction_ = last_instruction_ = nullptr; } 94 95 // Update the block of all instructions to be `block`. 96 void SetBlockOfInstructions(HBasicBlock* block) const; 97 98 void AddAfter(HInstruction* cursor, const HInstructionList& instruction_list); 99 void Add(const HInstructionList& instruction_list); 100 101 // Return the number of instructions in the list. This is an expensive operation. 102 size_t CountSize() const; 103 104 private: 105 HInstruction* first_instruction_; 106 HInstruction* last_instruction_; 107 108 friend class HBasicBlock; 109 friend class HGraph; 110 friend class HInstruction; 111 friend class HInstructionIterator; 112 friend class HBackwardInstructionIterator; 113 114 DISALLOW_COPY_AND_ASSIGN(HInstructionList); 115 }; 116 117 // Control-flow graph of a method. Contains a list of basic blocks. 118 class HGraph : public ArenaObject<kArenaAllocMisc> { 119 public: 120 HGraph(ArenaAllocator* arena, 121 const DexFile& dex_file, 122 uint32_t method_idx, 123 InstructionSet instruction_set, 124 bool debuggable = false, 125 int start_instruction_id = 0) 126 : arena_(arena), 127 blocks_(arena, kDefaultNumberOfBlocks), 128 reverse_post_order_(arena, kDefaultNumberOfBlocks), 129 linear_order_(arena, kDefaultNumberOfBlocks), 130 entry_block_(nullptr), 131 exit_block_(nullptr), 132 maximum_number_of_out_vregs_(0), 133 number_of_vregs_(0), 134 number_of_in_vregs_(0), 135 temporaries_vreg_slots_(0), 136 has_bounds_checks_(false), 137 debuggable_(debuggable), 138 current_instruction_id_(start_instruction_id), 139 dex_file_(dex_file), 140 method_idx_(method_idx), 141 instruction_set_(instruction_set), 142 cached_null_constant_(nullptr), 143 cached_int_constants_(std::less<int32_t>(), arena->Adapter()), 144 cached_float_constants_(std::less<int32_t>(), arena->Adapter()), 145 cached_long_constants_(std::less<int64_t>(), arena->Adapter()), 146 cached_double_constants_(std::less<int64_t>(), arena->Adapter()) {} 147 148 ArenaAllocator* GetArena() const { return arena_; } 149 const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; } 150 HBasicBlock* GetBlock(size_t id) const { return blocks_.Get(id); } 151 152 HBasicBlock* GetEntryBlock() const { return entry_block_; } 153 HBasicBlock* GetExitBlock() const { return exit_block_; } 154 155 void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; } 156 void SetExitBlock(HBasicBlock* block) { exit_block_ = block; } 157 158 void AddBlock(HBasicBlock* block); 159 160 // Try building the SSA form of this graph, with dominance computation and loop 161 // recognition. Returns whether it was successful in doing all these steps. 162 bool TryBuildingSsa() { 163 BuildDominatorTree(); 164 // The SSA builder requires loops to all be natural. Specifically, the dead phi 165 // elimination phase checks the consistency of the graph when doing a post-order 166 // visit for eliminating dead phis: a dead phi can only have loop header phi 167 // users remaining when being visited. 168 if (!AnalyzeNaturalLoops()) return false; 169 TransformToSsa(); 170 return true; 171 } 172 173 void ComputeDominanceInformation(); 174 void ClearDominanceInformation(); 175 176 void BuildDominatorTree(); 177 void TransformToSsa(); 178 void SimplifyCFG(); 179 180 // Analyze all natural loops in this graph. Returns false if one 181 // loop is not natural, that is the header does not dominate the 182 // back edge. 183 bool AnalyzeNaturalLoops() const; 184 185 // Inline this graph in `outer_graph`, replacing the given `invoke` instruction. 186 void InlineInto(HGraph* outer_graph, HInvoke* invoke); 187 188 // Need to add a couple of blocks to test if the loop body is entered and 189 // put deoptimization instructions, etc. 190 void TransformLoopHeaderForBCE(HBasicBlock* header); 191 192 // Removes `block` from the graph. 193 void DeleteDeadBlock(HBasicBlock* block); 194 195 void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor); 196 void SimplifyLoop(HBasicBlock* header); 197 198 int32_t GetNextInstructionId() { 199 DCHECK_NE(current_instruction_id_, INT32_MAX); 200 return current_instruction_id_++; 201 } 202 203 int32_t GetCurrentInstructionId() const { 204 return current_instruction_id_; 205 } 206 207 void SetCurrentInstructionId(int32_t id) { 208 current_instruction_id_ = id; 209 } 210 211 uint16_t GetMaximumNumberOfOutVRegs() const { 212 return maximum_number_of_out_vregs_; 213 } 214 215 void SetMaximumNumberOfOutVRegs(uint16_t new_value) { 216 maximum_number_of_out_vregs_ = new_value; 217 } 218 219 void UpdateTemporariesVRegSlots(size_t slots) { 220 temporaries_vreg_slots_ = std::max(slots, temporaries_vreg_slots_); 221 } 222 223 size_t GetTemporariesVRegSlots() const { 224 return temporaries_vreg_slots_; 225 } 226 227 void SetNumberOfVRegs(uint16_t number_of_vregs) { 228 number_of_vregs_ = number_of_vregs; 229 } 230 231 uint16_t GetNumberOfVRegs() const { 232 return number_of_vregs_; 233 } 234 235 void SetNumberOfInVRegs(uint16_t value) { 236 number_of_in_vregs_ = value; 237 } 238 239 uint16_t GetNumberOfLocalVRegs() const { 240 return number_of_vregs_ - number_of_in_vregs_; 241 } 242 243 const GrowableArray<HBasicBlock*>& GetReversePostOrder() const { 244 return reverse_post_order_; 245 } 246 247 const GrowableArray<HBasicBlock*>& GetLinearOrder() const { 248 return linear_order_; 249 } 250 251 bool HasBoundsChecks() const { 252 return has_bounds_checks_; 253 } 254 255 void SetHasBoundsChecks(bool value) { 256 has_bounds_checks_ = value; 257 } 258 259 bool IsDebuggable() const { return debuggable_; } 260 261 // Returns a constant of the given type and value. If it does not exist 262 // already, it is created and inserted into the graph. This method is only for 263 // integral types. 264 HConstant* GetConstant(Primitive::Type type, int64_t value); 265 HNullConstant* GetNullConstant(); 266 HIntConstant* GetIntConstant(int32_t value) { 267 return CreateConstant(value, &cached_int_constants_); 268 } 269 HLongConstant* GetLongConstant(int64_t value) { 270 return CreateConstant(value, &cached_long_constants_); 271 } 272 HFloatConstant* GetFloatConstant(float value) { 273 return CreateConstant(bit_cast<int32_t, float>(value), &cached_float_constants_); 274 } 275 HDoubleConstant* GetDoubleConstant(double value) { 276 return CreateConstant(bit_cast<int64_t, double>(value), &cached_double_constants_); 277 } 278 279 HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const; 280 281 const DexFile& GetDexFile() const { 282 return dex_file_; 283 } 284 285 uint32_t GetMethodIdx() const { 286 return method_idx_; 287 } 288 289 private: 290 void VisitBlockForDominatorTree(HBasicBlock* block, 291 HBasicBlock* predecessor, 292 GrowableArray<size_t>* visits); 293 void FindBackEdges(ArenaBitVector* visited); 294 void VisitBlockForBackEdges(HBasicBlock* block, 295 ArenaBitVector* visited, 296 ArenaBitVector* visiting); 297 void RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const; 298 void RemoveDeadBlocks(const ArenaBitVector& visited); 299 300 template <class InstructionType, typename ValueType> 301 InstructionType* CreateConstant(ValueType value, 302 ArenaSafeMap<ValueType, InstructionType*>* cache) { 303 // Try to find an existing constant of the given value. 304 InstructionType* constant = nullptr; 305 auto cached_constant = cache->find(value); 306 if (cached_constant != cache->end()) { 307 constant = cached_constant->second; 308 } 309 310 // If not found or previously deleted, create and cache a new instruction. 311 if (constant == nullptr || constant->GetBlock() == nullptr) { 312 constant = new (arena_) InstructionType(value); 313 cache->Overwrite(value, constant); 314 InsertConstant(constant); 315 } 316 return constant; 317 } 318 319 void InsertConstant(HConstant* instruction); 320 321 // Cache a float constant into the graph. This method should only be 322 // called by the SsaBuilder when creating "equivalent" instructions. 323 void CacheFloatConstant(HFloatConstant* constant); 324 325 // See CacheFloatConstant comment. 326 void CacheDoubleConstant(HDoubleConstant* constant); 327 328 ArenaAllocator* const arena_; 329 330 // List of blocks in insertion order. 331 GrowableArray<HBasicBlock*> blocks_; 332 333 // List of blocks to perform a reverse post order tree traversal. 334 GrowableArray<HBasicBlock*> reverse_post_order_; 335 336 // List of blocks to perform a linear order tree traversal. 337 GrowableArray<HBasicBlock*> linear_order_; 338 339 HBasicBlock* entry_block_; 340 HBasicBlock* exit_block_; 341 342 // The maximum number of virtual registers arguments passed to a HInvoke in this graph. 343 uint16_t maximum_number_of_out_vregs_; 344 345 // The number of virtual registers in this method. Contains the parameters. 346 uint16_t number_of_vregs_; 347 348 // The number of virtual registers used by parameters of this method. 349 uint16_t number_of_in_vregs_; 350 351 // Number of vreg size slots that the temporaries use (used in baseline compiler). 352 size_t temporaries_vreg_slots_; 353 354 // Has bounds checks. We can totally skip BCE if it's false. 355 bool has_bounds_checks_; 356 357 // Indicates whether the graph should be compiled in a way that 358 // ensures full debuggability. If false, we can apply more 359 // aggressive optimizations that may limit the level of debugging. 360 const bool debuggable_; 361 362 // The current id to assign to a newly added instruction. See HInstruction.id_. 363 int32_t current_instruction_id_; 364 365 // The dex file from which the method is from. 366 const DexFile& dex_file_; 367 368 // The method index in the dex file. 369 const uint32_t method_idx_; 370 371 const InstructionSet instruction_set_; 372 373 // Cached constants. 374 HNullConstant* cached_null_constant_; 375 ArenaSafeMap<int32_t, HIntConstant*> cached_int_constants_; 376 ArenaSafeMap<int32_t, HFloatConstant*> cached_float_constants_; 377 ArenaSafeMap<int64_t, HLongConstant*> cached_long_constants_; 378 ArenaSafeMap<int64_t, HDoubleConstant*> cached_double_constants_; 379 380 friend class SsaBuilder; // For caching constants. 381 friend class SsaLivenessAnalysis; // For the linear order. 382 ART_FRIEND_TEST(GraphTest, IfSuccessorSimpleJoinBlock1); 383 DISALLOW_COPY_AND_ASSIGN(HGraph); 384 }; 385 386 class HLoopInformation : public ArenaObject<kArenaAllocMisc> { 387 public: 388 HLoopInformation(HBasicBlock* header, HGraph* graph) 389 : header_(header), 390 suspend_check_(nullptr), 391 back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges), 392 // Make bit vector growable, as the number of blocks may change. 393 blocks_(graph->GetArena(), graph->GetBlocks().Size(), true) {} 394 395 HBasicBlock* GetHeader() const { 396 return header_; 397 } 398 399 void SetHeader(HBasicBlock* block) { 400 header_ = block; 401 } 402 403 HSuspendCheck* GetSuspendCheck() const { return suspend_check_; } 404 void SetSuspendCheck(HSuspendCheck* check) { suspend_check_ = check; } 405 bool HasSuspendCheck() const { return suspend_check_ != nullptr; } 406 407 void AddBackEdge(HBasicBlock* back_edge) { 408 back_edges_.Add(back_edge); 409 } 410 411 void RemoveBackEdge(HBasicBlock* back_edge) { 412 back_edges_.Delete(back_edge); 413 } 414 415 bool IsBackEdge(const HBasicBlock& block) const { 416 for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) { 417 if (back_edges_.Get(i) == &block) return true; 418 } 419 return false; 420 } 421 422 size_t NumberOfBackEdges() const { 423 return back_edges_.Size(); 424 } 425 426 HBasicBlock* GetPreHeader() const; 427 428 const GrowableArray<HBasicBlock*>& GetBackEdges() const { 429 return back_edges_; 430 } 431 432 // Returns the lifetime position of the back edge that has the 433 // greatest lifetime position. 434 size_t GetLifetimeEnd() const; 435 436 void ReplaceBackEdge(HBasicBlock* existing, HBasicBlock* new_back_edge) { 437 for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) { 438 if (back_edges_.Get(i) == existing) { 439 back_edges_.Put(i, new_back_edge); 440 return; 441 } 442 } 443 UNREACHABLE(); 444 } 445 446 // Finds blocks that are part of this loop. Returns whether the loop is a natural loop, 447 // that is the header dominates the back edge. 448 bool Populate(); 449 450 // Reanalyzes the loop by removing loop info from its blocks and re-running 451 // Populate(). If there are no back edges left, the loop info is completely 452 // removed as well as its SuspendCheck instruction. It must be run on nested 453 // inner loops first. 454 void Update(); 455 456 // Returns whether this loop information contains `block`. 457 // Note that this loop information *must* be populated before entering this function. 458 bool Contains(const HBasicBlock& block) const; 459 460 // Returns whether this loop information is an inner loop of `other`. 461 // Note that `other` *must* be populated before entering this function. 462 bool IsIn(const HLoopInformation& other) const; 463 464 const ArenaBitVector& GetBlocks() const { return blocks_; } 465 466 void Add(HBasicBlock* block); 467 void Remove(HBasicBlock* block); 468 469 private: 470 // Internal recursive implementation of `Populate`. 471 void PopulateRecursive(HBasicBlock* block); 472 473 HBasicBlock* header_; 474 HSuspendCheck* suspend_check_; 475 GrowableArray<HBasicBlock*> back_edges_; 476 ArenaBitVector blocks_; 477 478 DISALLOW_COPY_AND_ASSIGN(HLoopInformation); 479 }; 480 481 static constexpr size_t kNoLifetime = -1; 482 static constexpr uint32_t kNoDexPc = -1; 483 484 // A block in a method. Contains the list of instructions represented 485 // as a double linked list. Each block knows its predecessors and 486 // successors. 487 488 class HBasicBlock : public ArenaObject<kArenaAllocMisc> { 489 public: 490 explicit HBasicBlock(HGraph* graph, uint32_t dex_pc = kNoDexPc) 491 : graph_(graph), 492 predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors), 493 successors_(graph->GetArena(), kDefaultNumberOfSuccessors), 494 loop_information_(nullptr), 495 dominator_(nullptr), 496 dominated_blocks_(graph->GetArena(), kDefaultNumberOfDominatedBlocks), 497 block_id_(-1), 498 dex_pc_(dex_pc), 499 lifetime_start_(kNoLifetime), 500 lifetime_end_(kNoLifetime), 501 is_catch_block_(false) {} 502 503 const GrowableArray<HBasicBlock*>& GetPredecessors() const { 504 return predecessors_; 505 } 506 507 const GrowableArray<HBasicBlock*>& GetSuccessors() const { 508 return successors_; 509 } 510 511 const GrowableArray<HBasicBlock*>& GetDominatedBlocks() const { 512 return dominated_blocks_; 513 } 514 515 bool IsEntryBlock() const { 516 return graph_->GetEntryBlock() == this; 517 } 518 519 bool IsExitBlock() const { 520 return graph_->GetExitBlock() == this; 521 } 522 523 bool IsSingleGoto() const; 524 525 void AddBackEdge(HBasicBlock* back_edge) { 526 if (loop_information_ == nullptr) { 527 loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_); 528 } 529 DCHECK_EQ(loop_information_->GetHeader(), this); 530 loop_information_->AddBackEdge(back_edge); 531 } 532 533 HGraph* GetGraph() const { return graph_; } 534 void SetGraph(HGraph* graph) { graph_ = graph; } 535 536 int GetBlockId() const { return block_id_; } 537 void SetBlockId(int id) { block_id_ = id; } 538 539 HBasicBlock* GetDominator() const { return dominator_; } 540 void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; } 541 void AddDominatedBlock(HBasicBlock* block) { dominated_blocks_.Add(block); } 542 void RemoveDominatedBlock(HBasicBlock* block) { dominated_blocks_.Delete(block); } 543 void ReplaceDominatedBlock(HBasicBlock* existing, HBasicBlock* new_block) { 544 for (size_t i = 0, e = dominated_blocks_.Size(); i < e; ++i) { 545 if (dominated_blocks_.Get(i) == existing) { 546 dominated_blocks_.Put(i, new_block); 547 return; 548 } 549 } 550 LOG(FATAL) << "Unreachable"; 551 UNREACHABLE(); 552 } 553 void ClearDominanceInformation(); 554 555 int NumberOfBackEdges() const { 556 return IsLoopHeader() ? loop_information_->NumberOfBackEdges() : 0; 557 } 558 559 HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; } 560 HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; } 561 const HInstructionList& GetInstructions() const { return instructions_; } 562 HInstruction* GetFirstPhi() const { return phis_.first_instruction_; } 563 HInstruction* GetLastPhi() const { return phis_.last_instruction_; } 564 const HInstructionList& GetPhis() const { return phis_; } 565 566 void AddSuccessor(HBasicBlock* block) { 567 successors_.Add(block); 568 block->predecessors_.Add(this); 569 } 570 571 void ReplaceSuccessor(HBasicBlock* existing, HBasicBlock* new_block) { 572 size_t successor_index = GetSuccessorIndexOf(existing); 573 DCHECK_NE(successor_index, static_cast<size_t>(-1)); 574 existing->RemovePredecessor(this); 575 new_block->predecessors_.Add(this); 576 successors_.Put(successor_index, new_block); 577 } 578 579 void ReplacePredecessor(HBasicBlock* existing, HBasicBlock* new_block) { 580 size_t predecessor_index = GetPredecessorIndexOf(existing); 581 DCHECK_NE(predecessor_index, static_cast<size_t>(-1)); 582 existing->RemoveSuccessor(this); 583 new_block->successors_.Add(this); 584 predecessors_.Put(predecessor_index, new_block); 585 } 586 587 // Insert `this` between `predecessor` and `successor. This method 588 // preserves the indicies, and will update the first edge found between 589 // `predecessor` and `successor`. 590 void InsertBetween(HBasicBlock* predecessor, HBasicBlock* successor) { 591 size_t predecessor_index = successor->GetPredecessorIndexOf(predecessor); 592 DCHECK_NE(predecessor_index, static_cast<size_t>(-1)); 593 size_t successor_index = predecessor->GetSuccessorIndexOf(successor); 594 DCHECK_NE(successor_index, static_cast<size_t>(-1)); 595 successor->predecessors_.Put(predecessor_index, this); 596 predecessor->successors_.Put(successor_index, this); 597 successors_.Add(successor); 598 predecessors_.Add(predecessor); 599 } 600 601 void RemovePredecessor(HBasicBlock* block) { 602 predecessors_.Delete(block); 603 } 604 605 void RemoveSuccessor(HBasicBlock* block) { 606 successors_.Delete(block); 607 } 608 609 void ClearAllPredecessors() { 610 predecessors_.Reset(); 611 } 612 613 void AddPredecessor(HBasicBlock* block) { 614 predecessors_.Add(block); 615 block->successors_.Add(this); 616 } 617 618 void SwapPredecessors() { 619 DCHECK_EQ(predecessors_.Size(), 2u); 620 HBasicBlock* temp = predecessors_.Get(0); 621 predecessors_.Put(0, predecessors_.Get(1)); 622 predecessors_.Put(1, temp); 623 } 624 625 void SwapSuccessors() { 626 DCHECK_EQ(successors_.Size(), 2u); 627 HBasicBlock* temp = successors_.Get(0); 628 successors_.Put(0, successors_.Get(1)); 629 successors_.Put(1, temp); 630 } 631 632 size_t GetPredecessorIndexOf(HBasicBlock* predecessor) { 633 for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) { 634 if (predecessors_.Get(i) == predecessor) { 635 return i; 636 } 637 } 638 return -1; 639 } 640 641 size_t GetSuccessorIndexOf(HBasicBlock* successor) { 642 for (size_t i = 0, e = successors_.Size(); i < e; ++i) { 643 if (successors_.Get(i) == successor) { 644 return i; 645 } 646 } 647 return -1; 648 } 649 650 // Split the block into two blocks just after `cursor`. Returns the newly 651 // created block. Note that this method just updates raw block information, 652 // like predecessors, successors, dominators, and instruction list. It does not 653 // update the graph, reverse post order, loop information, nor make sure the 654 // blocks are consistent (for example ending with a control flow instruction). 655 HBasicBlock* SplitAfter(HInstruction* cursor); 656 657 // Merge `other` at the end of `this`. Successors and dominated blocks of 658 // `other` are changed to be successors and dominated blocks of `this`. Note 659 // that this method does not update the graph, reverse post order, loop 660 // information, nor make sure the blocks are consistent (for example ending 661 // with a control flow instruction). 662 void MergeWithInlined(HBasicBlock* other); 663 664 // Replace `this` with `other`. Predecessors, successors, and dominated blocks 665 // of `this` are moved to `other`. 666 // Note that this method does not update the graph, reverse post order, loop 667 // information, nor make sure the blocks are consistent (for example ending 668 // with a control flow instruction). 669 void ReplaceWith(HBasicBlock* other); 670 671 // Merge `other` at the end of `this`. This method updates loops, reverse post 672 // order, links to predecessors, successors, dominators and deletes the block 673 // from the graph. The two blocks must be successive, i.e. `this` the only 674 // predecessor of `other` and vice versa. 675 void MergeWith(HBasicBlock* other); 676 677 // Disconnects `this` from all its predecessors, successors and dominator, 678 // removes it from all loops it is included in and eventually from the graph. 679 // The block must not dominate any other block. Predecessors and successors 680 // are safely updated. 681 void DisconnectAndDelete(); 682 683 void AddInstruction(HInstruction* instruction); 684 // Insert `instruction` before/after an existing instruction `cursor`. 685 void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor); 686 void InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor); 687 // Replace instruction `initial` with `replacement` within this block. 688 void ReplaceAndRemoveInstructionWith(HInstruction* initial, 689 HInstruction* replacement); 690 void AddPhi(HPhi* phi); 691 void InsertPhiAfter(HPhi* instruction, HPhi* cursor); 692 // RemoveInstruction and RemovePhi delete a given instruction from the respective 693 // instruction list. With 'ensure_safety' set to true, it verifies that the 694 // instruction is not in use and removes it from the use lists of its inputs. 695 void RemoveInstruction(HInstruction* instruction, bool ensure_safety = true); 696 void RemovePhi(HPhi* phi, bool ensure_safety = true); 697 void RemoveInstructionOrPhi(HInstruction* instruction, bool ensure_safety = true); 698 699 bool IsLoopHeader() const { 700 return IsInLoop() && (loop_information_->GetHeader() == this); 701 } 702 703 bool IsLoopPreHeaderFirstPredecessor() const { 704 DCHECK(IsLoopHeader()); 705 DCHECK(!GetPredecessors().IsEmpty()); 706 return GetPredecessors().Get(0) == GetLoopInformation()->GetPreHeader(); 707 } 708 709 HLoopInformation* GetLoopInformation() const { 710 return loop_information_; 711 } 712 713 // Set the loop_information_ on this block. Overrides the current 714 // loop_information if it is an outer loop of the passed loop information. 715 // Note that this method is called while creating the loop information. 716 void SetInLoop(HLoopInformation* info) { 717 if (IsLoopHeader()) { 718 // Nothing to do. This just means `info` is an outer loop. 719 } else if (!IsInLoop()) { 720 loop_information_ = info; 721 } else if (loop_information_->Contains(*info->GetHeader())) { 722 // Block is currently part of an outer loop. Make it part of this inner loop. 723 // Note that a non loop header having a loop information means this loop information 724 // has already been populated 725 loop_information_ = info; 726 } else { 727 // Block is part of an inner loop. Do not update the loop information. 728 // Note that we cannot do the check `info->Contains(loop_information_)->GetHeader()` 729 // at this point, because this method is being called while populating `info`. 730 } 731 } 732 733 // Raw update of the loop information. 734 void SetLoopInformation(HLoopInformation* info) { 735 loop_information_ = info; 736 } 737 738 bool IsInLoop() const { return loop_information_ != nullptr; } 739 740 // Returns whether this block dominates the blocked passed as parameter. 741 bool Dominates(HBasicBlock* block) const; 742 743 size_t GetLifetimeStart() const { return lifetime_start_; } 744 size_t GetLifetimeEnd() const { return lifetime_end_; } 745 746 void SetLifetimeStart(size_t start) { lifetime_start_ = start; } 747 void SetLifetimeEnd(size_t end) { lifetime_end_ = end; } 748 749 uint32_t GetDexPc() const { return dex_pc_; } 750 751 bool IsCatchBlock() const { return is_catch_block_; } 752 void SetIsCatchBlock() { is_catch_block_ = true; } 753 754 bool EndsWithControlFlowInstruction() const; 755 bool EndsWithIf() const; 756 bool HasSinglePhi() const; 757 758 private: 759 HGraph* graph_; 760 GrowableArray<HBasicBlock*> predecessors_; 761 GrowableArray<HBasicBlock*> successors_; 762 HInstructionList instructions_; 763 HInstructionList phis_; 764 HLoopInformation* loop_information_; 765 HBasicBlock* dominator_; 766 GrowableArray<HBasicBlock*> dominated_blocks_; 767 int block_id_; 768 // The dex program counter of the first instruction of this block. 769 const uint32_t dex_pc_; 770 size_t lifetime_start_; 771 size_t lifetime_end_; 772 bool is_catch_block_; 773 774 friend class HGraph; 775 friend class HInstruction; 776 777 DISALLOW_COPY_AND_ASSIGN(HBasicBlock); 778 }; 779 780 // Iterates over the LoopInformation of all loops which contain 'block' 781 // from the innermost to the outermost. 782 class HLoopInformationOutwardIterator : public ValueObject { 783 public: 784 explicit HLoopInformationOutwardIterator(const HBasicBlock& block) 785 : current_(block.GetLoopInformation()) {} 786 787 bool Done() const { return current_ == nullptr; } 788 789 void Advance() { 790 DCHECK(!Done()); 791 current_ = current_->GetPreHeader()->GetLoopInformation(); 792 } 793 794 HLoopInformation* Current() const { 795 DCHECK(!Done()); 796 return current_; 797 } 798 799 private: 800 HLoopInformation* current_; 801 802 DISALLOW_COPY_AND_ASSIGN(HLoopInformationOutwardIterator); 803 }; 804 805 #define FOR_EACH_CONCRETE_INSTRUCTION(M) \ 806 M(Add, BinaryOperation) \ 807 M(And, BinaryOperation) \ 808 M(ArrayGet, Instruction) \ 809 M(ArrayLength, Instruction) \ 810 M(ArraySet, Instruction) \ 811 M(BooleanNot, UnaryOperation) \ 812 M(BoundsCheck, Instruction) \ 813 M(BoundType, Instruction) \ 814 M(CheckCast, Instruction) \ 815 M(ClinitCheck, Instruction) \ 816 M(Compare, BinaryOperation) \ 817 M(Condition, BinaryOperation) \ 818 M(Deoptimize, Instruction) \ 819 M(Div, BinaryOperation) \ 820 M(DivZeroCheck, Instruction) \ 821 M(DoubleConstant, Constant) \ 822 M(Equal, Condition) \ 823 M(Exit, Instruction) \ 824 M(FloatConstant, Constant) \ 825 M(Goto, Instruction) \ 826 M(GreaterThan, Condition) \ 827 M(GreaterThanOrEqual, Condition) \ 828 M(If, Instruction) \ 829 M(InstanceFieldGet, Instruction) \ 830 M(InstanceFieldSet, Instruction) \ 831 M(InstanceOf, Instruction) \ 832 M(IntConstant, Constant) \ 833 M(InvokeInterface, Invoke) \ 834 M(InvokeStaticOrDirect, Invoke) \ 835 M(InvokeVirtual, Invoke) \ 836 M(LessThan, Condition) \ 837 M(LessThanOrEqual, Condition) \ 838 M(LoadClass, Instruction) \ 839 M(LoadException, Instruction) \ 840 M(LoadLocal, Instruction) \ 841 M(LoadString, Instruction) \ 842 M(Local, Instruction) \ 843 M(LongConstant, Constant) \ 844 M(MemoryBarrier, Instruction) \ 845 M(MonitorOperation, Instruction) \ 846 M(Mul, BinaryOperation) \ 847 M(Neg, UnaryOperation) \ 848 M(NewArray, Instruction) \ 849 M(NewInstance, Instruction) \ 850 M(Not, UnaryOperation) \ 851 M(NotEqual, Condition) \ 852 M(NullConstant, Instruction) \ 853 M(NullCheck, Instruction) \ 854 M(Or, BinaryOperation) \ 855 M(ParallelMove, Instruction) \ 856 M(ParameterValue, Instruction) \ 857 M(Phi, Instruction) \ 858 M(Rem, BinaryOperation) \ 859 M(Return, Instruction) \ 860 M(ReturnVoid, Instruction) \ 861 M(Shl, BinaryOperation) \ 862 M(Shr, BinaryOperation) \ 863 M(StaticFieldGet, Instruction) \ 864 M(StaticFieldSet, Instruction) \ 865 M(StoreLocal, Instruction) \ 866 M(Sub, BinaryOperation) \ 867 M(SuspendCheck, Instruction) \ 868 M(Temporary, Instruction) \ 869 M(Throw, Instruction) \ 870 M(TypeConversion, Instruction) \ 871 M(UShr, BinaryOperation) \ 872 M(Xor, BinaryOperation) \ 873 874 #define FOR_EACH_INSTRUCTION(M) \ 875 FOR_EACH_CONCRETE_INSTRUCTION(M) \ 876 M(Constant, Instruction) \ 877 M(UnaryOperation, Instruction) \ 878 M(BinaryOperation, Instruction) \ 879 M(Invoke, Instruction) 880 881 #define FORWARD_DECLARATION(type, super) class H##type; 882 FOR_EACH_INSTRUCTION(FORWARD_DECLARATION) 883 #undef FORWARD_DECLARATION 884 885 #define DECLARE_INSTRUCTION(type) \ 886 InstructionKind GetKind() const OVERRIDE { return k##type; } \ 887 const char* DebugName() const OVERRIDE { return #type; } \ 888 const H##type* As##type() const OVERRIDE { return this; } \ 889 H##type* As##type() OVERRIDE { return this; } \ 890 bool InstructionTypeEquals(HInstruction* other) const OVERRIDE { \ 891 return other->Is##type(); \ 892 } \ 893 void Accept(HGraphVisitor* visitor) OVERRIDE 894 895 template <typename T> class HUseList; 896 897 template <typename T> 898 class HUseListNode : public ArenaObject<kArenaAllocMisc> { 899 public: 900 HUseListNode* GetPrevious() const { return prev_; } 901 HUseListNode* GetNext() const { return next_; } 902 T GetUser() const { return user_; } 903 size_t GetIndex() const { return index_; } 904 void SetIndex(size_t index) { index_ = index; } 905 906 private: 907 HUseListNode(T user, size_t index) 908 : user_(user), index_(index), prev_(nullptr), next_(nullptr) {} 909 910 T const user_; 911 size_t index_; 912 HUseListNode<T>* prev_; 913 HUseListNode<T>* next_; 914 915 friend class HUseList<T>; 916 917 DISALLOW_COPY_AND_ASSIGN(HUseListNode); 918 }; 919 920 template <typename T> 921 class HUseList : public ValueObject { 922 public: 923 HUseList() : first_(nullptr) {} 924 925 void Clear() { 926 first_ = nullptr; 927 } 928 929 // Adds a new entry at the beginning of the use list and returns 930 // the newly created node. 931 HUseListNode<T>* AddUse(T user, size_t index, ArenaAllocator* arena) { 932 HUseListNode<T>* new_node = new (arena) HUseListNode<T>(user, index); 933 if (IsEmpty()) { 934 first_ = new_node; 935 } else { 936 first_->prev_ = new_node; 937 new_node->next_ = first_; 938 first_ = new_node; 939 } 940 return new_node; 941 } 942 943 HUseListNode<T>* GetFirst() const { 944 return first_; 945 } 946 947 void Remove(HUseListNode<T>* node) { 948 DCHECK(node != nullptr); 949 DCHECK(Contains(node)); 950 951 if (node->prev_ != nullptr) { 952 node->prev_->next_ = node->next_; 953 } 954 if (node->next_ != nullptr) { 955 node->next_->prev_ = node->prev_; 956 } 957 if (node == first_) { 958 first_ = node->next_; 959 } 960 } 961 962 bool Contains(const HUseListNode<T>* node) const { 963 if (node == nullptr) { 964 return false; 965 } 966 for (HUseListNode<T>* current = first_; current != nullptr; current = current->GetNext()) { 967 if (current == node) { 968 return true; 969 } 970 } 971 return false; 972 } 973 974 bool IsEmpty() const { 975 return first_ == nullptr; 976 } 977 978 bool HasOnlyOneUse() const { 979 return first_ != nullptr && first_->next_ == nullptr; 980 } 981 982 size_t SizeSlow() const { 983 size_t count = 0; 984 for (HUseListNode<T>* current = first_; current != nullptr; current = current->GetNext()) { 985 ++count; 986 } 987 return count; 988 } 989 990 private: 991 HUseListNode<T>* first_; 992 }; 993 994 template<typename T> 995 class HUseIterator : public ValueObject { 996 public: 997 explicit HUseIterator(const HUseList<T>& uses) : current_(uses.GetFirst()) {} 998 999 bool Done() const { return current_ == nullptr; } 1000 1001 void Advance() { 1002 DCHECK(!Done()); 1003 current_ = current_->GetNext(); 1004 } 1005 1006 HUseListNode<T>* Current() const { 1007 DCHECK(!Done()); 1008 return current_; 1009 } 1010 1011 private: 1012 HUseListNode<T>* current_; 1013 1014 friend class HValue; 1015 }; 1016 1017 // This class is used by HEnvironment and HInstruction classes to record the 1018 // instructions they use and pointers to the corresponding HUseListNodes kept 1019 // by the used instructions. 1020 template <typename T> 1021 class HUserRecord : public ValueObject { 1022 public: 1023 HUserRecord() : instruction_(nullptr), use_node_(nullptr) {} 1024 explicit HUserRecord(HInstruction* instruction) : instruction_(instruction), use_node_(nullptr) {} 1025 1026 HUserRecord(const HUserRecord<T>& old_record, HUseListNode<T>* use_node) 1027 : instruction_(old_record.instruction_), use_node_(use_node) { 1028 DCHECK(instruction_ != nullptr); 1029 DCHECK(use_node_ != nullptr); 1030 DCHECK(old_record.use_node_ == nullptr); 1031 } 1032 1033 HInstruction* GetInstruction() const { return instruction_; } 1034 HUseListNode<T>* GetUseNode() const { return use_node_; } 1035 1036 private: 1037 // Instruction used by the user. 1038 HInstruction* instruction_; 1039 1040 // Corresponding entry in the use list kept by 'instruction_'. 1041 HUseListNode<T>* use_node_; 1042 }; 1043 1044 // TODO: Add better documentation to this class and maybe refactor with more suggestive names. 1045 // - Has(All)SideEffects suggests that all the side effects are present but only ChangesSomething 1046 // flag is consider. 1047 // - DependsOn suggests that there is a real dependency between side effects but it only 1048 // checks DependendsOnSomething flag. 1049 // 1050 // Represents the side effects an instruction may have. 1051 class SideEffects : public ValueObject { 1052 public: 1053 SideEffects() : flags_(0) {} 1054 1055 static SideEffects None() { 1056 return SideEffects(0); 1057 } 1058 1059 static SideEffects All() { 1060 return SideEffects(ChangesSomething().flags_ | DependsOnSomething().flags_); 1061 } 1062 1063 static SideEffects ChangesSomething() { 1064 return SideEffects((1 << kFlagChangesCount) - 1); 1065 } 1066 1067 static SideEffects DependsOnSomething() { 1068 int count = kFlagDependsOnCount - kFlagChangesCount; 1069 return SideEffects(((1 << count) - 1) << kFlagChangesCount); 1070 } 1071 1072 SideEffects Union(SideEffects other) const { 1073 return SideEffects(flags_ | other.flags_); 1074 } 1075 1076 bool HasSideEffects() const { 1077 size_t all_bits_set = (1 << kFlagChangesCount) - 1; 1078 return (flags_ & all_bits_set) != 0; 1079 } 1080 1081 bool HasAllSideEffects() const { 1082 size_t all_bits_set = (1 << kFlagChangesCount) - 1; 1083 return all_bits_set == (flags_ & all_bits_set); 1084 } 1085 1086 bool DependsOn(SideEffects other) const { 1087 size_t depends_flags = other.ComputeDependsFlags(); 1088 return (flags_ & depends_flags) != 0; 1089 } 1090 1091 bool HasDependencies() const { 1092 int count = kFlagDependsOnCount - kFlagChangesCount; 1093 size_t all_bits_set = (1 << count) - 1; 1094 return ((flags_ >> kFlagChangesCount) & all_bits_set) != 0; 1095 } 1096 1097 private: 1098 static constexpr int kFlagChangesSomething = 0; 1099 static constexpr int kFlagChangesCount = kFlagChangesSomething + 1; 1100 1101 static constexpr int kFlagDependsOnSomething = kFlagChangesCount; 1102 static constexpr int kFlagDependsOnCount = kFlagDependsOnSomething + 1; 1103 1104 explicit SideEffects(size_t flags) : flags_(flags) {} 1105 1106 size_t ComputeDependsFlags() const { 1107 return flags_ << kFlagChangesCount; 1108 } 1109 1110 size_t flags_; 1111 }; 1112 1113 // A HEnvironment object contains the values of virtual registers at a given location. 1114 class HEnvironment : public ArenaObject<kArenaAllocMisc> { 1115 public: 1116 HEnvironment(ArenaAllocator* arena, 1117 size_t number_of_vregs, 1118 const DexFile& dex_file, 1119 uint32_t method_idx, 1120 uint32_t dex_pc) 1121 : vregs_(arena, number_of_vregs), 1122 locations_(arena, number_of_vregs), 1123 parent_(nullptr), 1124 dex_file_(dex_file), 1125 method_idx_(method_idx), 1126 dex_pc_(dex_pc) { 1127 vregs_.SetSize(number_of_vregs); 1128 for (size_t i = 0; i < number_of_vregs; i++) { 1129 vregs_.Put(i, HUserRecord<HEnvironment*>()); 1130 } 1131 1132 locations_.SetSize(number_of_vregs); 1133 for (size_t i = 0; i < number_of_vregs; ++i) { 1134 locations_.Put(i, Location()); 1135 } 1136 } 1137 1138 void SetAndCopyParentChain(ArenaAllocator* allocator, HEnvironment* parent) { 1139 parent_ = new (allocator) HEnvironment(allocator, 1140 parent->Size(), 1141 parent->GetDexFile(), 1142 parent->GetMethodIdx(), 1143 parent->GetDexPc()); 1144 if (parent->GetParent() != nullptr) { 1145 parent_->SetAndCopyParentChain(allocator, parent->GetParent()); 1146 } 1147 parent_->CopyFrom(parent); 1148 } 1149 1150 void CopyFrom(const GrowableArray<HInstruction*>& locals); 1151 void CopyFrom(HEnvironment* environment); 1152 1153 // Copy from `env`. If it's a loop phi for `loop_header`, copy the first 1154 // input to the loop phi instead. This is for inserting instructions that 1155 // require an environment (like HDeoptimization) in the loop pre-header. 1156 void CopyFromWithLoopPhiAdjustment(HEnvironment* env, HBasicBlock* loop_header); 1157 1158 void SetRawEnvAt(size_t index, HInstruction* instruction) { 1159 vregs_.Put(index, HUserRecord<HEnvironment*>(instruction)); 1160 } 1161 1162 HInstruction* GetInstructionAt(size_t index) const { 1163 return vregs_.Get(index).GetInstruction(); 1164 } 1165 1166 void RemoveAsUserOfInput(size_t index) const; 1167 1168 size_t Size() const { return vregs_.Size(); } 1169 1170 HEnvironment* GetParent() const { return parent_; } 1171 1172 void SetLocationAt(size_t index, Location location) { 1173 locations_.Put(index, location); 1174 } 1175 1176 Location GetLocationAt(size_t index) const { 1177 return locations_.Get(index); 1178 } 1179 1180 uint32_t GetDexPc() const { 1181 return dex_pc_; 1182 } 1183 1184 uint32_t GetMethodIdx() const { 1185 return method_idx_; 1186 } 1187 1188 const DexFile& GetDexFile() const { 1189 return dex_file_; 1190 } 1191 1192 private: 1193 // Record instructions' use entries of this environment for constant-time removal. 1194 // It should only be called by HInstruction when a new environment use is added. 1195 void RecordEnvUse(HUseListNode<HEnvironment*>* env_use) { 1196 DCHECK(env_use->GetUser() == this); 1197 size_t index = env_use->GetIndex(); 1198 vregs_.Put(index, HUserRecord<HEnvironment*>(vregs_.Get(index), env_use)); 1199 } 1200 1201 GrowableArray<HUserRecord<HEnvironment*> > vregs_; 1202 GrowableArray<Location> locations_; 1203 HEnvironment* parent_; 1204 const DexFile& dex_file_; 1205 const uint32_t method_idx_; 1206 const uint32_t dex_pc_; 1207 1208 friend class HInstruction; 1209 1210 DISALLOW_COPY_AND_ASSIGN(HEnvironment); 1211 }; 1212 1213 class ReferenceTypeInfo : ValueObject { 1214 public: 1215 typedef Handle<mirror::Class> TypeHandle; 1216 1217 static ReferenceTypeInfo Create(TypeHandle type_handle, bool is_exact) 1218 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 1219 if (type_handle->IsObjectClass()) { 1220 // Override the type handle to be consistent with the case when we get to 1221 // Top but don't have the Object class available. It avoids having to guess 1222 // what value the type_handle has when it's Top. 1223 return ReferenceTypeInfo(TypeHandle(), is_exact, true); 1224 } else { 1225 return ReferenceTypeInfo(type_handle, is_exact, false); 1226 } 1227 } 1228 1229 static ReferenceTypeInfo CreateTop(bool is_exact) { 1230 return ReferenceTypeInfo(TypeHandle(), is_exact, true); 1231 } 1232 1233 bool IsExact() const { return is_exact_; } 1234 bool IsTop() const { return is_top_; } 1235 1236 Handle<mirror::Class> GetTypeHandle() const { return type_handle_; } 1237 1238 bool IsSupertypeOf(ReferenceTypeInfo rti) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 1239 if (IsTop()) { 1240 // Top (equivalent for java.lang.Object) is supertype of anything. 1241 return true; 1242 } 1243 if (rti.IsTop()) { 1244 // If we get here `this` is not Top() so it can't be a supertype. 1245 return false; 1246 } 1247 return GetTypeHandle()->IsAssignableFrom(rti.GetTypeHandle().Get()); 1248 } 1249 1250 // Returns true if the type information provide the same amount of details. 1251 // Note that it does not mean that the instructions have the same actual type 1252 // (e.g. tops are equal but they can be the result of a merge). 1253 bool IsEqual(ReferenceTypeInfo rti) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 1254 if (IsExact() != rti.IsExact()) { 1255 return false; 1256 } 1257 if (IsTop() && rti.IsTop()) { 1258 // `Top` means java.lang.Object, so the types are equivalent. 1259 return true; 1260 } 1261 if (IsTop() || rti.IsTop()) { 1262 // If only one is top or object than they are not equivalent. 1263 // NB: We need this extra check because the type_handle of `Top` is invalid 1264 // and we cannot inspect its reference. 1265 return false; 1266 } 1267 1268 // Finally check the types. 1269 return GetTypeHandle().Get() == rti.GetTypeHandle().Get(); 1270 } 1271 1272 private: 1273 ReferenceTypeInfo() : ReferenceTypeInfo(TypeHandle(), false, true) {} 1274 ReferenceTypeInfo(TypeHandle type_handle, bool is_exact, bool is_top) 1275 : type_handle_(type_handle), is_exact_(is_exact), is_top_(is_top) {} 1276 1277 // The class of the object. 1278 TypeHandle type_handle_; 1279 // Whether or not the type is exact or a superclass of the actual type. 1280 // Whether or not we have any information about this type. 1281 bool is_exact_; 1282 // A true value here means that the object type should be java.lang.Object. 1283 // We don't have access to the corresponding mirror object every time so this 1284 // flag acts as a substitute. When true, the TypeHandle refers to a null 1285 // pointer and should not be used. 1286 bool is_top_; 1287 }; 1288 1289 std::ostream& operator<<(std::ostream& os, const ReferenceTypeInfo& rhs); 1290 1291 class HInstruction : public ArenaObject<kArenaAllocMisc> { 1292 public: 1293 explicit HInstruction(SideEffects side_effects) 1294 : previous_(nullptr), 1295 next_(nullptr), 1296 block_(nullptr), 1297 id_(-1), 1298 ssa_index_(-1), 1299 environment_(nullptr), 1300 locations_(nullptr), 1301 live_interval_(nullptr), 1302 lifetime_position_(kNoLifetime), 1303 side_effects_(side_effects), 1304 reference_type_info_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {} 1305 1306 virtual ~HInstruction() {} 1307 1308 #define DECLARE_KIND(type, super) k##type, 1309 enum InstructionKind { 1310 FOR_EACH_INSTRUCTION(DECLARE_KIND) 1311 }; 1312 #undef DECLARE_KIND 1313 1314 HInstruction* GetNext() const { return next_; } 1315 HInstruction* GetPrevious() const { return previous_; } 1316 1317 HInstruction* GetNextDisregardingMoves() const; 1318 HInstruction* GetPreviousDisregardingMoves() const; 1319 1320 HBasicBlock* GetBlock() const { return block_; } 1321 void SetBlock(HBasicBlock* block) { block_ = block; } 1322 bool IsInBlock() const { return block_ != nullptr; } 1323 bool IsInLoop() const { return block_->IsInLoop(); } 1324 bool IsLoopHeaderPhi() { return IsPhi() && block_->IsLoopHeader(); } 1325 1326 virtual size_t InputCount() const = 0; 1327 HInstruction* InputAt(size_t i) const { return InputRecordAt(i).GetInstruction(); } 1328 1329 virtual void Accept(HGraphVisitor* visitor) = 0; 1330 virtual const char* DebugName() const = 0; 1331 1332 virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; } 1333 void SetRawInputAt(size_t index, HInstruction* input) { 1334 SetRawInputRecordAt(index, HUserRecord<HInstruction*>(input)); 1335 } 1336 1337 virtual bool NeedsEnvironment() const { return false; } 1338 virtual uint32_t GetDexPc() const { 1339 LOG(FATAL) << "GetDexPc() cannot be called on an instruction that" 1340 " does not need an environment"; 1341 UNREACHABLE(); 1342 } 1343 virtual bool IsControlFlow() const { return false; } 1344 virtual bool CanThrow() const { return false; } 1345 bool HasSideEffects() const { return side_effects_.HasSideEffects(); } 1346 1347 // Does not apply for all instructions, but having this at top level greatly 1348 // simplifies the null check elimination. 1349 virtual bool CanBeNull() const { 1350 DCHECK_EQ(GetType(), Primitive::kPrimNot) << "CanBeNull only applies to reference types"; 1351 return true; 1352 } 1353 1354 virtual bool CanDoImplicitNullCheckOn(HInstruction* obj) const { 1355 UNUSED(obj); 1356 return false; 1357 } 1358 1359 void SetReferenceTypeInfo(ReferenceTypeInfo reference_type_info) { 1360 DCHECK_EQ(GetType(), Primitive::kPrimNot); 1361 reference_type_info_ = reference_type_info; 1362 } 1363 1364 ReferenceTypeInfo GetReferenceTypeInfo() const { 1365 DCHECK_EQ(GetType(), Primitive::kPrimNot); 1366 return reference_type_info_; 1367 } 1368 1369 void AddUseAt(HInstruction* user, size_t index) { 1370 DCHECK(user != nullptr); 1371 HUseListNode<HInstruction*>* use = 1372 uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena()); 1373 user->SetRawInputRecordAt(index, HUserRecord<HInstruction*>(user->InputRecordAt(index), use)); 1374 } 1375 1376 void AddEnvUseAt(HEnvironment* user, size_t index) { 1377 DCHECK(user != nullptr); 1378 HUseListNode<HEnvironment*>* env_use = 1379 env_uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena()); 1380 user->RecordEnvUse(env_use); 1381 } 1382 1383 void RemoveAsUserOfInput(size_t input) { 1384 HUserRecord<HInstruction*> input_use = InputRecordAt(input); 1385 input_use.GetInstruction()->uses_.Remove(input_use.GetUseNode()); 1386 } 1387 1388 const HUseList<HInstruction*>& GetUses() const { return uses_; } 1389 const HUseList<HEnvironment*>& GetEnvUses() const { return env_uses_; } 1390 1391 bool HasUses() const { return !uses_.IsEmpty() || !env_uses_.IsEmpty(); } 1392 bool HasEnvironmentUses() const { return !env_uses_.IsEmpty(); } 1393 bool HasNonEnvironmentUses() const { return !uses_.IsEmpty(); } 1394 bool HasOnlyOneNonEnvironmentUse() const { 1395 return !HasEnvironmentUses() && GetUses().HasOnlyOneUse(); 1396 } 1397 1398 // Does this instruction strictly dominate `other_instruction`? 1399 // Returns false if this instruction and `other_instruction` are the same. 1400 // Aborts if this instruction and `other_instruction` are both phis. 1401 bool StrictlyDominates(HInstruction* other_instruction) const; 1402 1403 int GetId() const { return id_; } 1404 void SetId(int id) { id_ = id; } 1405 1406 int GetSsaIndex() const { return ssa_index_; } 1407 void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; } 1408 bool HasSsaIndex() const { return ssa_index_ != -1; } 1409 1410 bool HasEnvironment() const { return environment_ != nullptr; } 1411 HEnvironment* GetEnvironment() const { return environment_; } 1412 // Set the `environment_` field. Raw because this method does not 1413 // update the uses lists. 1414 void SetRawEnvironment(HEnvironment* environment) { environment_ = environment; } 1415 1416 // Set the environment of this instruction, copying it from `environment`. While 1417 // copying, the uses lists are being updated. 1418 void CopyEnvironmentFrom(HEnvironment* environment) { 1419 ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena(); 1420 environment_ = new (allocator) HEnvironment( 1421 allocator, 1422 environment->Size(), 1423 environment->GetDexFile(), 1424 environment->GetMethodIdx(), 1425 environment->GetDexPc()); 1426 environment_->CopyFrom(environment); 1427 if (environment->GetParent() != nullptr) { 1428 environment_->SetAndCopyParentChain(allocator, environment->GetParent()); 1429 } 1430 } 1431 1432 void CopyEnvironmentFromWithLoopPhiAdjustment(HEnvironment* environment, 1433 HBasicBlock* block) { 1434 ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena(); 1435 environment_ = new (allocator) HEnvironment( 1436 allocator, 1437 environment->Size(), 1438 environment->GetDexFile(), 1439 environment->GetMethodIdx(), 1440 environment->GetDexPc()); 1441 if (environment->GetParent() != nullptr) { 1442 environment_->SetAndCopyParentChain(allocator, environment->GetParent()); 1443 } 1444 environment_->CopyFromWithLoopPhiAdjustment(environment, block); 1445 } 1446 1447 // Returns the number of entries in the environment. Typically, that is the 1448 // number of dex registers in a method. It could be more in case of inlining. 1449 size_t EnvironmentSize() const; 1450 1451 LocationSummary* GetLocations() const { return locations_; } 1452 void SetLocations(LocationSummary* locations) { locations_ = locations; } 1453 1454 void ReplaceWith(HInstruction* instruction); 1455 void ReplaceInput(HInstruction* replacement, size_t index); 1456 1457 // This is almost the same as doing `ReplaceWith()`. But in this helper, the 1458 // uses of this instruction by `other` are *not* updated. 1459 void ReplaceWithExceptInReplacementAtIndex(HInstruction* other, size_t use_index) { 1460 ReplaceWith(other); 1461 other->ReplaceInput(this, use_index); 1462 } 1463 1464 // Move `this` instruction before `cursor`. 1465 void MoveBefore(HInstruction* cursor); 1466 1467 #define INSTRUCTION_TYPE_CHECK(type, super) \ 1468 bool Is##type() const { return (As##type() != nullptr); } \ 1469 virtual const H##type* As##type() const { return nullptr; } \ 1470 virtual H##type* As##type() { return nullptr; } 1471 1472 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK) 1473 #undef INSTRUCTION_TYPE_CHECK 1474 1475 // Returns whether the instruction can be moved within the graph. 1476 virtual bool CanBeMoved() const { return false; } 1477 1478 // Returns whether the two instructions are of the same kind. 1479 virtual bool InstructionTypeEquals(HInstruction* other) const { 1480 UNUSED(other); 1481 return false; 1482 } 1483 1484 // Returns whether any data encoded in the two instructions is equal. 1485 // This method does not look at the inputs. Both instructions must be 1486 // of the same type, otherwise the method has undefined behavior. 1487 virtual bool InstructionDataEquals(HInstruction* other) const { 1488 UNUSED(other); 1489 return false; 1490 } 1491 1492 // Returns whether two instructions are equal, that is: 1493 // 1) They have the same type and contain the same data (InstructionDataEquals). 1494 // 2) Their inputs are identical. 1495 bool Equals(HInstruction* other) const; 1496 1497 virtual InstructionKind GetKind() const = 0; 1498 1499 virtual size_t ComputeHashCode() const { 1500 size_t result = GetKind(); 1501 for (size_t i = 0, e = InputCount(); i < e; ++i) { 1502 result = (result * 31) + InputAt(i)->GetId(); 1503 } 1504 return result; 1505 } 1506 1507 SideEffects GetSideEffects() const { return side_effects_; } 1508 1509 size_t GetLifetimePosition() const { return lifetime_position_; } 1510 void SetLifetimePosition(size_t position) { lifetime_position_ = position; } 1511 LiveInterval* GetLiveInterval() const { return live_interval_; } 1512 void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; } 1513 bool HasLiveInterval() const { return live_interval_ != nullptr; } 1514 1515 bool IsSuspendCheckEntry() const { return IsSuspendCheck() && GetBlock()->IsEntryBlock(); } 1516 1517 // Returns whether the code generation of the instruction will require to have access 1518 // to the current method. Such instructions are: 1519 // (1): Instructions that require an environment, as calling the runtime requires 1520 // to walk the stack and have the current method stored at a specific stack address. 1521 // (2): Object literals like classes and strings, that are loaded from the dex cache 1522 // fields of the current method. 1523 bool NeedsCurrentMethod() const { 1524 return NeedsEnvironment() || IsLoadClass() || IsLoadString(); 1525 } 1526 1527 virtual bool NeedsDexCache() const { return false; } 1528 1529 protected: 1530 virtual const HUserRecord<HInstruction*> InputRecordAt(size_t i) const = 0; 1531 virtual void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) = 0; 1532 1533 private: 1534 void RemoveEnvironmentUser(HUseListNode<HEnvironment*>* use_node) { env_uses_.Remove(use_node); } 1535 1536 HInstruction* previous_; 1537 HInstruction* next_; 1538 HBasicBlock* block_; 1539 1540 // An instruction gets an id when it is added to the graph. 1541 // It reflects creation order. A negative id means the instruction 1542 // has not been added to the graph. 1543 int id_; 1544 1545 // When doing liveness analysis, instructions that have uses get an SSA index. 1546 int ssa_index_; 1547 1548 // List of instructions that have this instruction as input. 1549 HUseList<HInstruction*> uses_; 1550 1551 // List of environments that contain this instruction. 1552 HUseList<HEnvironment*> env_uses_; 1553 1554 // The environment associated with this instruction. Not null if the instruction 1555 // might jump out of the method. 1556 HEnvironment* environment_; 1557 1558 // Set by the code generator. 1559 LocationSummary* locations_; 1560 1561 // Set by the liveness analysis. 1562 LiveInterval* live_interval_; 1563 1564 // Set by the liveness analysis, this is the position in a linear 1565 // order of blocks where this instruction's live interval start. 1566 size_t lifetime_position_; 1567 1568 const SideEffects side_effects_; 1569 1570 // TODO: for primitive types this should be marked as invalid. 1571 ReferenceTypeInfo reference_type_info_; 1572 1573 friend class GraphChecker; 1574 friend class HBasicBlock; 1575 friend class HEnvironment; 1576 friend class HGraph; 1577 friend class HInstructionList; 1578 1579 DISALLOW_COPY_AND_ASSIGN(HInstruction); 1580 }; 1581 std::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind& rhs); 1582 1583 class HInputIterator : public ValueObject { 1584 public: 1585 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) {} 1586 1587 bool Done() const { return index_ == instruction_->InputCount(); } 1588 HInstruction* Current() const { return instruction_->InputAt(index_); } 1589 void Advance() { index_++; } 1590 1591 private: 1592 HInstruction* instruction_; 1593 size_t index_; 1594 1595 DISALLOW_COPY_AND_ASSIGN(HInputIterator); 1596 }; 1597 1598 class HInstructionIterator : public ValueObject { 1599 public: 1600 explicit HInstructionIterator(const HInstructionList& instructions) 1601 : instruction_(instructions.first_instruction_) { 1602 next_ = Done() ? nullptr : instruction_->GetNext(); 1603 } 1604 1605 bool Done() const { return instruction_ == nullptr; } 1606 HInstruction* Current() const { return instruction_; } 1607 void Advance() { 1608 instruction_ = next_; 1609 next_ = Done() ? nullptr : instruction_->GetNext(); 1610 } 1611 1612 private: 1613 HInstruction* instruction_; 1614 HInstruction* next_; 1615 1616 DISALLOW_COPY_AND_ASSIGN(HInstructionIterator); 1617 }; 1618 1619 class HBackwardInstructionIterator : public ValueObject { 1620 public: 1621 explicit HBackwardInstructionIterator(const HInstructionList& instructions) 1622 : instruction_(instructions.last_instruction_) { 1623 next_ = Done() ? nullptr : instruction_->GetPrevious(); 1624 } 1625 1626 bool Done() const { return instruction_ == nullptr; } 1627 HInstruction* Current() const { return instruction_; } 1628 void Advance() { 1629 instruction_ = next_; 1630 next_ = Done() ? nullptr : instruction_->GetPrevious(); 1631 } 1632 1633 private: 1634 HInstruction* instruction_; 1635 HInstruction* next_; 1636 1637 DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator); 1638 }; 1639 1640 // An embedded container with N elements of type T. Used (with partial 1641 // specialization for N=0) because embedded arrays cannot have size 0. 1642 template<typename T, intptr_t N> 1643 class EmbeddedArray { 1644 public: 1645 EmbeddedArray() : elements_() {} 1646 1647 intptr_t GetLength() const { return N; } 1648 1649 const T& operator[](intptr_t i) const { 1650 DCHECK_LT(i, GetLength()); 1651 return elements_[i]; 1652 } 1653 1654 T& operator[](intptr_t i) { 1655 DCHECK_LT(i, GetLength()); 1656 return elements_[i]; 1657 } 1658 1659 const T& At(intptr_t i) const { 1660 return (*this)[i]; 1661 } 1662 1663 void SetAt(intptr_t i, const T& val) { 1664 (*this)[i] = val; 1665 } 1666 1667 private: 1668 T elements_[N]; 1669 }; 1670 1671 template<typename T> 1672 class EmbeddedArray<T, 0> { 1673 public: 1674 intptr_t length() const { return 0; } 1675 const T& operator[](intptr_t i) const { 1676 UNUSED(i); 1677 LOG(FATAL) << "Unreachable"; 1678 UNREACHABLE(); 1679 } 1680 T& operator[](intptr_t i) { 1681 UNUSED(i); 1682 LOG(FATAL) << "Unreachable"; 1683 UNREACHABLE(); 1684 } 1685 }; 1686 1687 template<intptr_t N> 1688 class HTemplateInstruction: public HInstruction { 1689 public: 1690 HTemplateInstruction<N>(SideEffects side_effects) 1691 : HInstruction(side_effects), inputs_() {} 1692 virtual ~HTemplateInstruction() {} 1693 1694 size_t InputCount() const OVERRIDE { return N; } 1695 1696 protected: 1697 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_[i]; } 1698 1699 void SetRawInputRecordAt(size_t i, const HUserRecord<HInstruction*>& input) OVERRIDE { 1700 inputs_[i] = input; 1701 } 1702 1703 private: 1704 EmbeddedArray<HUserRecord<HInstruction*>, N> inputs_; 1705 1706 friend class SsaBuilder; 1707 }; 1708 1709 template<intptr_t N> 1710 class HExpression : public HTemplateInstruction<N> { 1711 public: 1712 HExpression<N>(Primitive::Type type, SideEffects side_effects) 1713 : HTemplateInstruction<N>(side_effects), type_(type) {} 1714 virtual ~HExpression() {} 1715 1716 Primitive::Type GetType() const OVERRIDE { return type_; } 1717 1718 protected: 1719 Primitive::Type type_; 1720 }; 1721 1722 // Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow 1723 // instruction that branches to the exit block. 1724 class HReturnVoid : public HTemplateInstruction<0> { 1725 public: 1726 HReturnVoid() : HTemplateInstruction(SideEffects::None()) {} 1727 1728 bool IsControlFlow() const OVERRIDE { return true; } 1729 1730 DECLARE_INSTRUCTION(ReturnVoid); 1731 1732 private: 1733 DISALLOW_COPY_AND_ASSIGN(HReturnVoid); 1734 }; 1735 1736 // Represents dex's RETURN opcodes. A HReturn is a control flow 1737 // instruction that branches to the exit block. 1738 class HReturn : public HTemplateInstruction<1> { 1739 public: 1740 explicit HReturn(HInstruction* value) : HTemplateInstruction(SideEffects::None()) { 1741 SetRawInputAt(0, value); 1742 } 1743 1744 bool IsControlFlow() const OVERRIDE { return true; } 1745 1746 DECLARE_INSTRUCTION(Return); 1747 1748 private: 1749 DISALLOW_COPY_AND_ASSIGN(HReturn); 1750 }; 1751 1752 // The exit instruction is the only instruction of the exit block. 1753 // Instructions aborting the method (HThrow and HReturn) must branch to the 1754 // exit block. 1755 class HExit : public HTemplateInstruction<0> { 1756 public: 1757 HExit() : HTemplateInstruction(SideEffects::None()) {} 1758 1759 bool IsControlFlow() const OVERRIDE { return true; } 1760 1761 DECLARE_INSTRUCTION(Exit); 1762 1763 private: 1764 DISALLOW_COPY_AND_ASSIGN(HExit); 1765 }; 1766 1767 // Jumps from one block to another. 1768 class HGoto : public HTemplateInstruction<0> { 1769 public: 1770 HGoto() : HTemplateInstruction(SideEffects::None()) {} 1771 1772 bool IsControlFlow() const OVERRIDE { return true; } 1773 1774 HBasicBlock* GetSuccessor() const { 1775 return GetBlock()->GetSuccessors().Get(0); 1776 } 1777 1778 DECLARE_INSTRUCTION(Goto); 1779 1780 private: 1781 DISALLOW_COPY_AND_ASSIGN(HGoto); 1782 }; 1783 1784 1785 // Conditional branch. A block ending with an HIf instruction must have 1786 // two successors. 1787 class HIf : public HTemplateInstruction<1> { 1788 public: 1789 explicit HIf(HInstruction* input) : HTemplateInstruction(SideEffects::None()) { 1790 SetRawInputAt(0, input); 1791 } 1792 1793 bool IsControlFlow() const OVERRIDE { return true; } 1794 1795 HBasicBlock* IfTrueSuccessor() const { 1796 return GetBlock()->GetSuccessors().Get(0); 1797 } 1798 1799 HBasicBlock* IfFalseSuccessor() const { 1800 return GetBlock()->GetSuccessors().Get(1); 1801 } 1802 1803 DECLARE_INSTRUCTION(If); 1804 1805 private: 1806 DISALLOW_COPY_AND_ASSIGN(HIf); 1807 }; 1808 1809 // Deoptimize to interpreter, upon checking a condition. 1810 class HDeoptimize : public HTemplateInstruction<1> { 1811 public: 1812 HDeoptimize(HInstruction* cond, uint32_t dex_pc) 1813 : HTemplateInstruction(SideEffects::None()), 1814 dex_pc_(dex_pc) { 1815 SetRawInputAt(0, cond); 1816 } 1817 1818 bool NeedsEnvironment() const OVERRIDE { return true; } 1819 bool CanThrow() const OVERRIDE { return true; } 1820 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 1821 1822 DECLARE_INSTRUCTION(Deoptimize); 1823 1824 private: 1825 uint32_t dex_pc_; 1826 1827 DISALLOW_COPY_AND_ASSIGN(HDeoptimize); 1828 }; 1829 1830 class HUnaryOperation : public HExpression<1> { 1831 public: 1832 HUnaryOperation(Primitive::Type result_type, HInstruction* input) 1833 : HExpression(result_type, SideEffects::None()) { 1834 SetRawInputAt(0, input); 1835 } 1836 1837 HInstruction* GetInput() const { return InputAt(0); } 1838 Primitive::Type GetResultType() const { return GetType(); } 1839 1840 bool CanBeMoved() const OVERRIDE { return true; } 1841 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 1842 UNUSED(other); 1843 return true; 1844 } 1845 1846 // Try to statically evaluate `operation` and return a HConstant 1847 // containing the result of this evaluation. If `operation` cannot 1848 // be evaluated as a constant, return null. 1849 HConstant* TryStaticEvaluation() const; 1850 1851 // Apply this operation to `x`. 1852 virtual int32_t Evaluate(int32_t x) const = 0; 1853 virtual int64_t Evaluate(int64_t x) const = 0; 1854 1855 DECLARE_INSTRUCTION(UnaryOperation); 1856 1857 private: 1858 DISALLOW_COPY_AND_ASSIGN(HUnaryOperation); 1859 }; 1860 1861 class HBinaryOperation : public HExpression<2> { 1862 public: 1863 HBinaryOperation(Primitive::Type result_type, 1864 HInstruction* left, 1865 HInstruction* right) : HExpression(result_type, SideEffects::None()) { 1866 SetRawInputAt(0, left); 1867 SetRawInputAt(1, right); 1868 } 1869 1870 HInstruction* GetLeft() const { return InputAt(0); } 1871 HInstruction* GetRight() const { return InputAt(1); } 1872 Primitive::Type GetResultType() const { return GetType(); } 1873 1874 virtual bool IsCommutative() const { return false; } 1875 1876 // Put constant on the right. 1877 // Returns whether order is changed. 1878 bool OrderInputsWithConstantOnTheRight() { 1879 HInstruction* left = InputAt(0); 1880 HInstruction* right = InputAt(1); 1881 if (left->IsConstant() && !right->IsConstant()) { 1882 ReplaceInput(right, 0); 1883 ReplaceInput(left, 1); 1884 return true; 1885 } 1886 return false; 1887 } 1888 1889 // Order inputs by instruction id, but favor constant on the right side. 1890 // This helps GVN for commutative ops. 1891 void OrderInputs() { 1892 DCHECK(IsCommutative()); 1893 HInstruction* left = InputAt(0); 1894 HInstruction* right = InputAt(1); 1895 if (left == right || (!left->IsConstant() && right->IsConstant())) { 1896 return; 1897 } 1898 if (OrderInputsWithConstantOnTheRight()) { 1899 return; 1900 } 1901 // Order according to instruction id. 1902 if (left->GetId() > right->GetId()) { 1903 ReplaceInput(right, 0); 1904 ReplaceInput(left, 1); 1905 } 1906 } 1907 1908 bool CanBeMoved() const OVERRIDE { return true; } 1909 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 1910 UNUSED(other); 1911 return true; 1912 } 1913 1914 // Try to statically evaluate `operation` and return a HConstant 1915 // containing the result of this evaluation. If `operation` cannot 1916 // be evaluated as a constant, return null. 1917 HConstant* TryStaticEvaluation() const; 1918 1919 // Apply this operation to `x` and `y`. 1920 virtual int32_t Evaluate(int32_t x, int32_t y) const = 0; 1921 virtual int64_t Evaluate(int64_t x, int64_t y) const = 0; 1922 1923 // Returns an input that can legally be used as the right input and is 1924 // constant, or null. 1925 HConstant* GetConstantRight() const; 1926 1927 // If `GetConstantRight()` returns one of the input, this returns the other 1928 // one. Otherwise it returns null. 1929 HInstruction* GetLeastConstantLeft() const; 1930 1931 DECLARE_INSTRUCTION(BinaryOperation); 1932 1933 private: 1934 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation); 1935 }; 1936 1937 class HCondition : public HBinaryOperation { 1938 public: 1939 HCondition(HInstruction* first, HInstruction* second) 1940 : HBinaryOperation(Primitive::kPrimBoolean, first, second), 1941 needs_materialization_(true) {} 1942 1943 bool NeedsMaterialization() const { return needs_materialization_; } 1944 void ClearNeedsMaterialization() { needs_materialization_ = false; } 1945 1946 // For code generation purposes, returns whether this instruction is just before 1947 // `instruction`, and disregard moves in between. 1948 bool IsBeforeWhenDisregardMoves(HInstruction* instruction) const; 1949 1950 DECLARE_INSTRUCTION(Condition); 1951 1952 virtual IfCondition GetCondition() const = 0; 1953 1954 private: 1955 // For register allocation purposes, returns whether this instruction needs to be 1956 // materialized (that is, not just be in the processor flags). 1957 bool needs_materialization_; 1958 1959 DISALLOW_COPY_AND_ASSIGN(HCondition); 1960 }; 1961 1962 // Instruction to check if two inputs are equal to each other. 1963 class HEqual : public HCondition { 1964 public: 1965 HEqual(HInstruction* first, HInstruction* second) 1966 : HCondition(first, second) {} 1967 1968 bool IsCommutative() const OVERRIDE { return true; } 1969 1970 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 1971 return x == y ? 1 : 0; 1972 } 1973 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 1974 return x == y ? 1 : 0; 1975 } 1976 1977 DECLARE_INSTRUCTION(Equal); 1978 1979 IfCondition GetCondition() const OVERRIDE { 1980 return kCondEQ; 1981 } 1982 1983 private: 1984 DISALLOW_COPY_AND_ASSIGN(HEqual); 1985 }; 1986 1987 class HNotEqual : public HCondition { 1988 public: 1989 HNotEqual(HInstruction* first, HInstruction* second) 1990 : HCondition(first, second) {} 1991 1992 bool IsCommutative() const OVERRIDE { return true; } 1993 1994 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 1995 return x != y ? 1 : 0; 1996 } 1997 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 1998 return x != y ? 1 : 0; 1999 } 2000 2001 DECLARE_INSTRUCTION(NotEqual); 2002 2003 IfCondition GetCondition() const OVERRIDE { 2004 return kCondNE; 2005 } 2006 2007 private: 2008 DISALLOW_COPY_AND_ASSIGN(HNotEqual); 2009 }; 2010 2011 class HLessThan : public HCondition { 2012 public: 2013 HLessThan(HInstruction* first, HInstruction* second) 2014 : HCondition(first, second) {} 2015 2016 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 2017 return x < y ? 1 : 0; 2018 } 2019 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 2020 return x < y ? 1 : 0; 2021 } 2022 2023 DECLARE_INSTRUCTION(LessThan); 2024 2025 IfCondition GetCondition() const OVERRIDE { 2026 return kCondLT; 2027 } 2028 2029 private: 2030 DISALLOW_COPY_AND_ASSIGN(HLessThan); 2031 }; 2032 2033 class HLessThanOrEqual : public HCondition { 2034 public: 2035 HLessThanOrEqual(HInstruction* first, HInstruction* second) 2036 : HCondition(first, second) {} 2037 2038 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 2039 return x <= y ? 1 : 0; 2040 } 2041 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 2042 return x <= y ? 1 : 0; 2043 } 2044 2045 DECLARE_INSTRUCTION(LessThanOrEqual); 2046 2047 IfCondition GetCondition() const OVERRIDE { 2048 return kCondLE; 2049 } 2050 2051 private: 2052 DISALLOW_COPY_AND_ASSIGN(HLessThanOrEqual); 2053 }; 2054 2055 class HGreaterThan : public HCondition { 2056 public: 2057 HGreaterThan(HInstruction* first, HInstruction* second) 2058 : HCondition(first, second) {} 2059 2060 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 2061 return x > y ? 1 : 0; 2062 } 2063 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 2064 return x > y ? 1 : 0; 2065 } 2066 2067 DECLARE_INSTRUCTION(GreaterThan); 2068 2069 IfCondition GetCondition() const OVERRIDE { 2070 return kCondGT; 2071 } 2072 2073 private: 2074 DISALLOW_COPY_AND_ASSIGN(HGreaterThan); 2075 }; 2076 2077 class HGreaterThanOrEqual : public HCondition { 2078 public: 2079 HGreaterThanOrEqual(HInstruction* first, HInstruction* second) 2080 : HCondition(first, second) {} 2081 2082 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 2083 return x >= y ? 1 : 0; 2084 } 2085 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 2086 return x >= y ? 1 : 0; 2087 } 2088 2089 DECLARE_INSTRUCTION(GreaterThanOrEqual); 2090 2091 IfCondition GetCondition() const OVERRIDE { 2092 return kCondGE; 2093 } 2094 2095 private: 2096 DISALLOW_COPY_AND_ASSIGN(HGreaterThanOrEqual); 2097 }; 2098 2099 2100 // Instruction to check how two inputs compare to each other. 2101 // Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1. 2102 class HCompare : public HBinaryOperation { 2103 public: 2104 // The bias applies for floating point operations and indicates how NaN 2105 // comparisons are treated: 2106 enum Bias { 2107 kNoBias, // bias is not applicable (i.e. for long operation) 2108 kGtBias, // return 1 for NaN comparisons 2109 kLtBias, // return -1 for NaN comparisons 2110 }; 2111 2112 HCompare(Primitive::Type type, 2113 HInstruction* first, 2114 HInstruction* second, 2115 Bias bias, 2116 uint32_t dex_pc) 2117 : HBinaryOperation(Primitive::kPrimInt, first, second), bias_(bias), dex_pc_(dex_pc) { 2118 DCHECK_EQ(type, first->GetType()); 2119 DCHECK_EQ(type, second->GetType()); 2120 } 2121 2122 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 2123 return 2124 x == y ? 0 : 2125 x > y ? 1 : 2126 -1; 2127 } 2128 2129 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 2130 return 2131 x == y ? 0 : 2132 x > y ? 1 : 2133 -1; 2134 } 2135 2136 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 2137 return bias_ == other->AsCompare()->bias_; 2138 } 2139 2140 bool IsGtBias() { return bias_ == kGtBias; } 2141 2142 uint32_t GetDexPc() const { return dex_pc_; } 2143 2144 DECLARE_INSTRUCTION(Compare); 2145 2146 private: 2147 const Bias bias_; 2148 const uint32_t dex_pc_; 2149 2150 DISALLOW_COPY_AND_ASSIGN(HCompare); 2151 }; 2152 2153 // A local in the graph. Corresponds to a Dex register. 2154 class HLocal : public HTemplateInstruction<0> { 2155 public: 2156 explicit HLocal(uint16_t reg_number) 2157 : HTemplateInstruction(SideEffects::None()), reg_number_(reg_number) {} 2158 2159 DECLARE_INSTRUCTION(Local); 2160 2161 uint16_t GetRegNumber() const { return reg_number_; } 2162 2163 private: 2164 // The Dex register number. 2165 const uint16_t reg_number_; 2166 2167 DISALLOW_COPY_AND_ASSIGN(HLocal); 2168 }; 2169 2170 // Load a given local. The local is an input of this instruction. 2171 class HLoadLocal : public HExpression<1> { 2172 public: 2173 HLoadLocal(HLocal* local, Primitive::Type type) 2174 : HExpression(type, SideEffects::None()) { 2175 SetRawInputAt(0, local); 2176 } 2177 2178 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); } 2179 2180 DECLARE_INSTRUCTION(LoadLocal); 2181 2182 private: 2183 DISALLOW_COPY_AND_ASSIGN(HLoadLocal); 2184 }; 2185 2186 // Store a value in a given local. This instruction has two inputs: the value 2187 // and the local. 2188 class HStoreLocal : public HTemplateInstruction<2> { 2189 public: 2190 HStoreLocal(HLocal* local, HInstruction* value) : HTemplateInstruction(SideEffects::None()) { 2191 SetRawInputAt(0, local); 2192 SetRawInputAt(1, value); 2193 } 2194 2195 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); } 2196 2197 DECLARE_INSTRUCTION(StoreLocal); 2198 2199 private: 2200 DISALLOW_COPY_AND_ASSIGN(HStoreLocal); 2201 }; 2202 2203 class HConstant : public HExpression<0> { 2204 public: 2205 explicit HConstant(Primitive::Type type) : HExpression(type, SideEffects::None()) {} 2206 2207 bool CanBeMoved() const OVERRIDE { return true; } 2208 2209 virtual bool IsMinusOne() const { return false; } 2210 virtual bool IsZero() const { return false; } 2211 virtual bool IsOne() const { return false; } 2212 2213 DECLARE_INSTRUCTION(Constant); 2214 2215 private: 2216 DISALLOW_COPY_AND_ASSIGN(HConstant); 2217 }; 2218 2219 class HFloatConstant : public HConstant { 2220 public: 2221 float GetValue() const { return value_; } 2222 2223 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 2224 return bit_cast<uint32_t, float>(other->AsFloatConstant()->value_) == 2225 bit_cast<uint32_t, float>(value_); 2226 } 2227 2228 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); } 2229 2230 bool IsMinusOne() const OVERRIDE { 2231 return bit_cast<uint32_t, float>(AsFloatConstant()->GetValue()) == 2232 bit_cast<uint32_t, float>((-1.0f)); 2233 } 2234 bool IsZero() const OVERRIDE { 2235 return AsFloatConstant()->GetValue() == 0.0f; 2236 } 2237 bool IsOne() const OVERRIDE { 2238 return bit_cast<uint32_t, float>(AsFloatConstant()->GetValue()) == 2239 bit_cast<uint32_t, float>(1.0f); 2240 } 2241 2242 DECLARE_INSTRUCTION(FloatConstant); 2243 2244 private: 2245 explicit HFloatConstant(float value) : HConstant(Primitive::kPrimFloat), value_(value) {} 2246 explicit HFloatConstant(int32_t value) 2247 : HConstant(Primitive::kPrimFloat), value_(bit_cast<float, int32_t>(value)) {} 2248 2249 const float value_; 2250 2251 // Only the SsaBuilder and HGraph can create floating-point constants. 2252 friend class SsaBuilder; 2253 friend class HGraph; 2254 DISALLOW_COPY_AND_ASSIGN(HFloatConstant); 2255 }; 2256 2257 class HDoubleConstant : public HConstant { 2258 public: 2259 double GetValue() const { return value_; } 2260 2261 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 2262 return bit_cast<uint64_t, double>(other->AsDoubleConstant()->value_) == 2263 bit_cast<uint64_t, double>(value_); 2264 } 2265 2266 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); } 2267 2268 bool IsMinusOne() const OVERRIDE { 2269 return bit_cast<uint64_t, double>(AsDoubleConstant()->GetValue()) == 2270 bit_cast<uint64_t, double>((-1.0)); 2271 } 2272 bool IsZero() const OVERRIDE { 2273 return AsDoubleConstant()->GetValue() == 0.0; 2274 } 2275 bool IsOne() const OVERRIDE { 2276 return bit_cast<uint64_t, double>(AsDoubleConstant()->GetValue()) == 2277 bit_cast<uint64_t, double>(1.0); 2278 } 2279 2280 DECLARE_INSTRUCTION(DoubleConstant); 2281 2282 private: 2283 explicit HDoubleConstant(double value) : HConstant(Primitive::kPrimDouble), value_(value) {} 2284 explicit HDoubleConstant(int64_t value) 2285 : HConstant(Primitive::kPrimDouble), value_(bit_cast<double, int64_t>(value)) {} 2286 2287 const double value_; 2288 2289 // Only the SsaBuilder and HGraph can create floating-point constants. 2290 friend class SsaBuilder; 2291 friend class HGraph; 2292 DISALLOW_COPY_AND_ASSIGN(HDoubleConstant); 2293 }; 2294 2295 class HNullConstant : public HConstant { 2296 public: 2297 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { 2298 return true; 2299 } 2300 2301 size_t ComputeHashCode() const OVERRIDE { return 0; } 2302 2303 DECLARE_INSTRUCTION(NullConstant); 2304 2305 private: 2306 HNullConstant() : HConstant(Primitive::kPrimNot) {} 2307 2308 friend class HGraph; 2309 DISALLOW_COPY_AND_ASSIGN(HNullConstant); 2310 }; 2311 2312 // Constants of the type int. Those can be from Dex instructions, or 2313 // synthesized (for example with the if-eqz instruction). 2314 class HIntConstant : public HConstant { 2315 public: 2316 int32_t GetValue() const { return value_; } 2317 2318 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 2319 return other->AsIntConstant()->value_ == value_; 2320 } 2321 2322 size_t ComputeHashCode() const OVERRIDE { return GetValue(); } 2323 2324 bool IsMinusOne() const OVERRIDE { return GetValue() == -1; } 2325 bool IsZero() const OVERRIDE { return GetValue() == 0; } 2326 bool IsOne() const OVERRIDE { return GetValue() == 1; } 2327 2328 DECLARE_INSTRUCTION(IntConstant); 2329 2330 private: 2331 explicit HIntConstant(int32_t value) : HConstant(Primitive::kPrimInt), value_(value) {} 2332 2333 const int32_t value_; 2334 2335 friend class HGraph; 2336 ART_FRIEND_TEST(GraphTest, InsertInstructionBefore); 2337 ART_FRIEND_TYPED_TEST(ParallelMoveTest, ConstantLast); 2338 DISALLOW_COPY_AND_ASSIGN(HIntConstant); 2339 }; 2340 2341 class HLongConstant : public HConstant { 2342 public: 2343 int64_t GetValue() const { return value_; } 2344 2345 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 2346 return other->AsLongConstant()->value_ == value_; 2347 } 2348 2349 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); } 2350 2351 bool IsMinusOne() const OVERRIDE { return GetValue() == -1; } 2352 bool IsZero() const OVERRIDE { return GetValue() == 0; } 2353 bool IsOne() const OVERRIDE { return GetValue() == 1; } 2354 2355 DECLARE_INSTRUCTION(LongConstant); 2356 2357 private: 2358 explicit HLongConstant(int64_t value) : HConstant(Primitive::kPrimLong), value_(value) {} 2359 2360 const int64_t value_; 2361 2362 friend class HGraph; 2363 DISALLOW_COPY_AND_ASSIGN(HLongConstant); 2364 }; 2365 2366 enum class Intrinsics { 2367 #define OPTIMIZING_INTRINSICS(Name, IsStatic) k ## Name, 2368 #include "intrinsics_list.h" 2369 kNone, 2370 INTRINSICS_LIST(OPTIMIZING_INTRINSICS) 2371 #undef INTRINSICS_LIST 2372 #undef OPTIMIZING_INTRINSICS 2373 }; 2374 std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic); 2375 2376 class HInvoke : public HInstruction { 2377 public: 2378 size_t InputCount() const OVERRIDE { return inputs_.Size(); } 2379 2380 // Runtime needs to walk the stack, so Dex -> Dex calls need to 2381 // know their environment. 2382 bool NeedsEnvironment() const OVERRIDE { return true; } 2383 2384 void SetArgumentAt(size_t index, HInstruction* argument) { 2385 SetRawInputAt(index, argument); 2386 } 2387 2388 // Return the number of arguments. This number can be lower than 2389 // the number of inputs returned by InputCount(), as some invoke 2390 // instructions (e.g. HInvokeStaticOrDirect) can have non-argument 2391 // inputs at the end of their list of inputs. 2392 uint32_t GetNumberOfArguments() const { return number_of_arguments_; } 2393 2394 Primitive::Type GetType() const OVERRIDE { return return_type_; } 2395 2396 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 2397 2398 uint32_t GetDexMethodIndex() const { return dex_method_index_; } 2399 2400 Intrinsics GetIntrinsic() const { 2401 return intrinsic_; 2402 } 2403 2404 void SetIntrinsic(Intrinsics intrinsic) { 2405 intrinsic_ = intrinsic; 2406 } 2407 2408 DECLARE_INSTRUCTION(Invoke); 2409 2410 protected: 2411 HInvoke(ArenaAllocator* arena, 2412 uint32_t number_of_arguments, 2413 uint32_t number_of_other_inputs, 2414 Primitive::Type return_type, 2415 uint32_t dex_pc, 2416 uint32_t dex_method_index) 2417 : HInstruction(SideEffects::All()), 2418 number_of_arguments_(number_of_arguments), 2419 inputs_(arena, number_of_arguments), 2420 return_type_(return_type), 2421 dex_pc_(dex_pc), 2422 dex_method_index_(dex_method_index), 2423 intrinsic_(Intrinsics::kNone) { 2424 uint32_t number_of_inputs = number_of_arguments + number_of_other_inputs; 2425 inputs_.SetSize(number_of_inputs); 2426 } 2427 2428 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_.Get(i); } 2429 void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) OVERRIDE { 2430 inputs_.Put(index, input); 2431 } 2432 2433 uint32_t number_of_arguments_; 2434 GrowableArray<HUserRecord<HInstruction*> > inputs_; 2435 const Primitive::Type return_type_; 2436 const uint32_t dex_pc_; 2437 const uint32_t dex_method_index_; 2438 Intrinsics intrinsic_; 2439 2440 private: 2441 DISALLOW_COPY_AND_ASSIGN(HInvoke); 2442 }; 2443 2444 class HInvokeStaticOrDirect : public HInvoke { 2445 public: 2446 // Requirements of this method call regarding the class 2447 // initialization (clinit) check of its declaring class. 2448 enum class ClinitCheckRequirement { 2449 kNone, // Class already initialized. 2450 kExplicit, // Static call having explicit clinit check as last input. 2451 kImplicit, // Static call implicitly requiring a clinit check. 2452 }; 2453 2454 HInvokeStaticOrDirect(ArenaAllocator* arena, 2455 uint32_t number_of_arguments, 2456 Primitive::Type return_type, 2457 uint32_t dex_pc, 2458 uint32_t dex_method_index, 2459 bool is_recursive, 2460 int32_t string_init_offset, 2461 InvokeType original_invoke_type, 2462 InvokeType invoke_type, 2463 ClinitCheckRequirement clinit_check_requirement) 2464 : HInvoke(arena, 2465 number_of_arguments, 2466 clinit_check_requirement == ClinitCheckRequirement::kExplicit ? 1u : 0u, 2467 return_type, 2468 dex_pc, 2469 dex_method_index), 2470 original_invoke_type_(original_invoke_type), 2471 invoke_type_(invoke_type), 2472 is_recursive_(is_recursive), 2473 clinit_check_requirement_(clinit_check_requirement), 2474 string_init_offset_(string_init_offset) {} 2475 2476 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE { 2477 UNUSED(obj); 2478 // We access the method via the dex cache so we can't do an implicit null check. 2479 // TODO: for intrinsics we can generate implicit null checks. 2480 return false; 2481 } 2482 2483 InvokeType GetOriginalInvokeType() const { return original_invoke_type_; } 2484 InvokeType GetInvokeType() const { return invoke_type_; } 2485 bool IsRecursive() const { return is_recursive_; } 2486 bool NeedsDexCache() const OVERRIDE { return !IsRecursive(); } 2487 bool IsStringInit() const { return string_init_offset_ != 0; } 2488 int32_t GetStringInitOffset() const { return string_init_offset_; } 2489 2490 // Is this instruction a call to a static method? 2491 bool IsStatic() const { 2492 return GetInvokeType() == kStatic; 2493 } 2494 2495 // Remove the art::HLoadClass instruction set as last input by 2496 // art::PrepareForRegisterAllocation::VisitClinitCheck in lieu of 2497 // the initial art::HClinitCheck instruction (only relevant for 2498 // static calls with explicit clinit check). 2499 void RemoveLoadClassAsLastInput() { 2500 DCHECK(IsStaticWithExplicitClinitCheck()); 2501 size_t last_input_index = InputCount() - 1; 2502 HInstruction* last_input = InputAt(last_input_index); 2503 DCHECK(last_input != nullptr); 2504 DCHECK(last_input->IsLoadClass()) << last_input->DebugName(); 2505 RemoveAsUserOfInput(last_input_index); 2506 inputs_.DeleteAt(last_input_index); 2507 clinit_check_requirement_ = ClinitCheckRequirement::kImplicit; 2508 DCHECK(IsStaticWithImplicitClinitCheck()); 2509 } 2510 2511 // Is this a call to a static method whose declaring class has an 2512 // explicit intialization check in the graph? 2513 bool IsStaticWithExplicitClinitCheck() const { 2514 return IsStatic() && (clinit_check_requirement_ == ClinitCheckRequirement::kExplicit); 2515 } 2516 2517 // Is this a call to a static method whose declaring class has an 2518 // implicit intialization check requirement? 2519 bool IsStaticWithImplicitClinitCheck() const { 2520 return IsStatic() && (clinit_check_requirement_ == ClinitCheckRequirement::kImplicit); 2521 } 2522 2523 DECLARE_INSTRUCTION(InvokeStaticOrDirect); 2524 2525 protected: 2526 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { 2527 const HUserRecord<HInstruction*> input_record = HInvoke::InputRecordAt(i); 2528 if (kIsDebugBuild && IsStaticWithExplicitClinitCheck() && (i == InputCount() - 1)) { 2529 HInstruction* input = input_record.GetInstruction(); 2530 // `input` is the last input of a static invoke marked as having 2531 // an explicit clinit check. It must either be: 2532 // - an art::HClinitCheck instruction, set by art::HGraphBuilder; or 2533 // - an art::HLoadClass instruction, set by art::PrepareForRegisterAllocation. 2534 DCHECK(input != nullptr); 2535 DCHECK(input->IsClinitCheck() || input->IsLoadClass()) << input->DebugName(); 2536 } 2537 return input_record; 2538 } 2539 2540 private: 2541 const InvokeType original_invoke_type_; 2542 const InvokeType invoke_type_; 2543 const bool is_recursive_; 2544 ClinitCheckRequirement clinit_check_requirement_; 2545 // Thread entrypoint offset for string init method if this is a string init invoke. 2546 // Note that there are multiple string init methods, each having its own offset. 2547 int32_t string_init_offset_; 2548 2549 DISALLOW_COPY_AND_ASSIGN(HInvokeStaticOrDirect); 2550 }; 2551 2552 class HInvokeVirtual : public HInvoke { 2553 public: 2554 HInvokeVirtual(ArenaAllocator* arena, 2555 uint32_t number_of_arguments, 2556 Primitive::Type return_type, 2557 uint32_t dex_pc, 2558 uint32_t dex_method_index, 2559 uint32_t vtable_index) 2560 : HInvoke(arena, number_of_arguments, 0u, return_type, dex_pc, dex_method_index), 2561 vtable_index_(vtable_index) {} 2562 2563 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE { 2564 // TODO: Add implicit null checks in intrinsics. 2565 return (obj == InputAt(0)) && !GetLocations()->Intrinsified(); 2566 } 2567 2568 uint32_t GetVTableIndex() const { return vtable_index_; } 2569 2570 DECLARE_INSTRUCTION(InvokeVirtual); 2571 2572 private: 2573 const uint32_t vtable_index_; 2574 2575 DISALLOW_COPY_AND_ASSIGN(HInvokeVirtual); 2576 }; 2577 2578 class HInvokeInterface : public HInvoke { 2579 public: 2580 HInvokeInterface(ArenaAllocator* arena, 2581 uint32_t number_of_arguments, 2582 Primitive::Type return_type, 2583 uint32_t dex_pc, 2584 uint32_t dex_method_index, 2585 uint32_t imt_index) 2586 : HInvoke(arena, number_of_arguments, 0u, return_type, dex_pc, dex_method_index), 2587 imt_index_(imt_index) {} 2588 2589 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE { 2590 // TODO: Add implicit null checks in intrinsics. 2591 return (obj == InputAt(0)) && !GetLocations()->Intrinsified(); 2592 } 2593 2594 uint32_t GetImtIndex() const { return imt_index_; } 2595 uint32_t GetDexMethodIndex() const { return dex_method_index_; } 2596 2597 DECLARE_INSTRUCTION(InvokeInterface); 2598 2599 private: 2600 const uint32_t imt_index_; 2601 2602 DISALLOW_COPY_AND_ASSIGN(HInvokeInterface); 2603 }; 2604 2605 class HNewInstance : public HExpression<0> { 2606 public: 2607 HNewInstance(uint32_t dex_pc, uint16_t type_index, QuickEntrypointEnum entrypoint) 2608 : HExpression(Primitive::kPrimNot, SideEffects::None()), 2609 dex_pc_(dex_pc), 2610 type_index_(type_index), 2611 entrypoint_(entrypoint) {} 2612 2613 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 2614 uint16_t GetTypeIndex() const { return type_index_; } 2615 2616 // Calls runtime so needs an environment. 2617 bool NeedsEnvironment() const OVERRIDE { return true; } 2618 // It may throw when called on: 2619 // - interfaces 2620 // - abstract/innaccessible/unknown classes 2621 // TODO: optimize when possible. 2622 bool CanThrow() const OVERRIDE { return true; } 2623 2624 bool CanBeNull() const OVERRIDE { return false; } 2625 2626 QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; } 2627 2628 DECLARE_INSTRUCTION(NewInstance); 2629 2630 private: 2631 const uint32_t dex_pc_; 2632 const uint16_t type_index_; 2633 const QuickEntrypointEnum entrypoint_; 2634 2635 DISALLOW_COPY_AND_ASSIGN(HNewInstance); 2636 }; 2637 2638 class HNeg : public HUnaryOperation { 2639 public: 2640 explicit HNeg(Primitive::Type result_type, HInstruction* input) 2641 : HUnaryOperation(result_type, input) {} 2642 2643 int32_t Evaluate(int32_t x) const OVERRIDE { return -x; } 2644 int64_t Evaluate(int64_t x) const OVERRIDE { return -x; } 2645 2646 DECLARE_INSTRUCTION(Neg); 2647 2648 private: 2649 DISALLOW_COPY_AND_ASSIGN(HNeg); 2650 }; 2651 2652 class HNewArray : public HExpression<1> { 2653 public: 2654 HNewArray(HInstruction* length, 2655 uint32_t dex_pc, 2656 uint16_t type_index, 2657 QuickEntrypointEnum entrypoint) 2658 : HExpression(Primitive::kPrimNot, SideEffects::None()), 2659 dex_pc_(dex_pc), 2660 type_index_(type_index), 2661 entrypoint_(entrypoint) { 2662 SetRawInputAt(0, length); 2663 } 2664 2665 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 2666 uint16_t GetTypeIndex() const { return type_index_; } 2667 2668 // Calls runtime so needs an environment. 2669 bool NeedsEnvironment() const OVERRIDE { return true; } 2670 2671 // May throw NegativeArraySizeException, OutOfMemoryError, etc. 2672 bool CanThrow() const OVERRIDE { return true; } 2673 2674 bool CanBeNull() const OVERRIDE { return false; } 2675 2676 QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; } 2677 2678 DECLARE_INSTRUCTION(NewArray); 2679 2680 private: 2681 const uint32_t dex_pc_; 2682 const uint16_t type_index_; 2683 const QuickEntrypointEnum entrypoint_; 2684 2685 DISALLOW_COPY_AND_ASSIGN(HNewArray); 2686 }; 2687 2688 class HAdd : public HBinaryOperation { 2689 public: 2690 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2691 : HBinaryOperation(result_type, left, right) {} 2692 2693 bool IsCommutative() const OVERRIDE { return true; } 2694 2695 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 2696 return x + y; 2697 } 2698 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 2699 return x + y; 2700 } 2701 2702 DECLARE_INSTRUCTION(Add); 2703 2704 private: 2705 DISALLOW_COPY_AND_ASSIGN(HAdd); 2706 }; 2707 2708 class HSub : public HBinaryOperation { 2709 public: 2710 HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2711 : HBinaryOperation(result_type, left, right) {} 2712 2713 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 2714 return x - y; 2715 } 2716 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 2717 return x - y; 2718 } 2719 2720 DECLARE_INSTRUCTION(Sub); 2721 2722 private: 2723 DISALLOW_COPY_AND_ASSIGN(HSub); 2724 }; 2725 2726 class HMul : public HBinaryOperation { 2727 public: 2728 HMul(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2729 : HBinaryOperation(result_type, left, right) {} 2730 2731 bool IsCommutative() const OVERRIDE { return true; } 2732 2733 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x * y; } 2734 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x * y; } 2735 2736 DECLARE_INSTRUCTION(Mul); 2737 2738 private: 2739 DISALLOW_COPY_AND_ASSIGN(HMul); 2740 }; 2741 2742 class HDiv : public HBinaryOperation { 2743 public: 2744 HDiv(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc) 2745 : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {} 2746 2747 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 2748 // Our graph structure ensures we never have 0 for `y` during constant folding. 2749 DCHECK_NE(y, 0); 2750 // Special case -1 to avoid getting a SIGFPE on x86(_64). 2751 return (y == -1) ? -x : x / y; 2752 } 2753 2754 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 2755 DCHECK_NE(y, 0); 2756 // Special case -1 to avoid getting a SIGFPE on x86(_64). 2757 return (y == -1) ? -x : x / y; 2758 } 2759 2760 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 2761 2762 DECLARE_INSTRUCTION(Div); 2763 2764 private: 2765 const uint32_t dex_pc_; 2766 2767 DISALLOW_COPY_AND_ASSIGN(HDiv); 2768 }; 2769 2770 class HRem : public HBinaryOperation { 2771 public: 2772 HRem(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc) 2773 : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {} 2774 2775 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 2776 DCHECK_NE(y, 0); 2777 // Special case -1 to avoid getting a SIGFPE on x86(_64). 2778 return (y == -1) ? 0 : x % y; 2779 } 2780 2781 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 2782 DCHECK_NE(y, 0); 2783 // Special case -1 to avoid getting a SIGFPE on x86(_64). 2784 return (y == -1) ? 0 : x % y; 2785 } 2786 2787 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 2788 2789 DECLARE_INSTRUCTION(Rem); 2790 2791 private: 2792 const uint32_t dex_pc_; 2793 2794 DISALLOW_COPY_AND_ASSIGN(HRem); 2795 }; 2796 2797 class HDivZeroCheck : public HExpression<1> { 2798 public: 2799 HDivZeroCheck(HInstruction* value, uint32_t dex_pc) 2800 : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) { 2801 SetRawInputAt(0, value); 2802 } 2803 2804 bool CanBeMoved() const OVERRIDE { return true; } 2805 2806 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 2807 UNUSED(other); 2808 return true; 2809 } 2810 2811 bool NeedsEnvironment() const OVERRIDE { return true; } 2812 bool CanThrow() const OVERRIDE { return true; } 2813 2814 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 2815 2816 DECLARE_INSTRUCTION(DivZeroCheck); 2817 2818 private: 2819 const uint32_t dex_pc_; 2820 2821 DISALLOW_COPY_AND_ASSIGN(HDivZeroCheck); 2822 }; 2823 2824 class HShl : public HBinaryOperation { 2825 public: 2826 HShl(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2827 : HBinaryOperation(result_type, left, right) {} 2828 2829 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x << (y & kMaxIntShiftValue); } 2830 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x << (y & kMaxLongShiftValue); } 2831 2832 DECLARE_INSTRUCTION(Shl); 2833 2834 private: 2835 DISALLOW_COPY_AND_ASSIGN(HShl); 2836 }; 2837 2838 class HShr : public HBinaryOperation { 2839 public: 2840 HShr(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2841 : HBinaryOperation(result_type, left, right) {} 2842 2843 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x >> (y & kMaxIntShiftValue); } 2844 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x >> (y & kMaxLongShiftValue); } 2845 2846 DECLARE_INSTRUCTION(Shr); 2847 2848 private: 2849 DISALLOW_COPY_AND_ASSIGN(HShr); 2850 }; 2851 2852 class HUShr : public HBinaryOperation { 2853 public: 2854 HUShr(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2855 : HBinaryOperation(result_type, left, right) {} 2856 2857 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 2858 uint32_t ux = static_cast<uint32_t>(x); 2859 uint32_t uy = static_cast<uint32_t>(y) & kMaxIntShiftValue; 2860 return static_cast<int32_t>(ux >> uy); 2861 } 2862 2863 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 2864 uint64_t ux = static_cast<uint64_t>(x); 2865 uint64_t uy = static_cast<uint64_t>(y) & kMaxLongShiftValue; 2866 return static_cast<int64_t>(ux >> uy); 2867 } 2868 2869 DECLARE_INSTRUCTION(UShr); 2870 2871 private: 2872 DISALLOW_COPY_AND_ASSIGN(HUShr); 2873 }; 2874 2875 class HAnd : public HBinaryOperation { 2876 public: 2877 HAnd(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2878 : HBinaryOperation(result_type, left, right) {} 2879 2880 bool IsCommutative() const OVERRIDE { return true; } 2881 2882 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x & y; } 2883 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x & y; } 2884 2885 DECLARE_INSTRUCTION(And); 2886 2887 private: 2888 DISALLOW_COPY_AND_ASSIGN(HAnd); 2889 }; 2890 2891 class HOr : public HBinaryOperation { 2892 public: 2893 HOr(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2894 : HBinaryOperation(result_type, left, right) {} 2895 2896 bool IsCommutative() const OVERRIDE { return true; } 2897 2898 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x | y; } 2899 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x | y; } 2900 2901 DECLARE_INSTRUCTION(Or); 2902 2903 private: 2904 DISALLOW_COPY_AND_ASSIGN(HOr); 2905 }; 2906 2907 class HXor : public HBinaryOperation { 2908 public: 2909 HXor(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2910 : HBinaryOperation(result_type, left, right) {} 2911 2912 bool IsCommutative() const OVERRIDE { return true; } 2913 2914 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x ^ y; } 2915 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x ^ y; } 2916 2917 DECLARE_INSTRUCTION(Xor); 2918 2919 private: 2920 DISALLOW_COPY_AND_ASSIGN(HXor); 2921 }; 2922 2923 // The value of a parameter in this method. Its location depends on 2924 // the calling convention. 2925 class HParameterValue : public HExpression<0> { 2926 public: 2927 HParameterValue(uint8_t index, Primitive::Type parameter_type, bool is_this = false) 2928 : HExpression(parameter_type, SideEffects::None()), index_(index), is_this_(is_this) {} 2929 2930 uint8_t GetIndex() const { return index_; } 2931 2932 bool CanBeNull() const OVERRIDE { return !is_this_; } 2933 2934 DECLARE_INSTRUCTION(ParameterValue); 2935 2936 private: 2937 // The index of this parameter in the parameters list. Must be less 2938 // than HGraph::number_of_in_vregs_. 2939 const uint8_t index_; 2940 2941 // Whether or not the parameter value corresponds to 'this' argument. 2942 const bool is_this_; 2943 2944 DISALLOW_COPY_AND_ASSIGN(HParameterValue); 2945 }; 2946 2947 class HNot : public HUnaryOperation { 2948 public: 2949 explicit HNot(Primitive::Type result_type, HInstruction* input) 2950 : HUnaryOperation(result_type, input) {} 2951 2952 bool CanBeMoved() const OVERRIDE { return true; } 2953 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 2954 UNUSED(other); 2955 return true; 2956 } 2957 2958 int32_t Evaluate(int32_t x) const OVERRIDE { return ~x; } 2959 int64_t Evaluate(int64_t x) const OVERRIDE { return ~x; } 2960 2961 DECLARE_INSTRUCTION(Not); 2962 2963 private: 2964 DISALLOW_COPY_AND_ASSIGN(HNot); 2965 }; 2966 2967 class HBooleanNot : public HUnaryOperation { 2968 public: 2969 explicit HBooleanNot(HInstruction* input) 2970 : HUnaryOperation(Primitive::Type::kPrimBoolean, input) {} 2971 2972 bool CanBeMoved() const OVERRIDE { return true; } 2973 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 2974 UNUSED(other); 2975 return true; 2976 } 2977 2978 int32_t Evaluate(int32_t x) const OVERRIDE { 2979 DCHECK(IsUint<1>(x)); 2980 return !x; 2981 } 2982 2983 int64_t Evaluate(int64_t x ATTRIBUTE_UNUSED) const OVERRIDE { 2984 LOG(FATAL) << DebugName() << " cannot be used with 64-bit values"; 2985 UNREACHABLE(); 2986 } 2987 2988 DECLARE_INSTRUCTION(BooleanNot); 2989 2990 private: 2991 DISALLOW_COPY_AND_ASSIGN(HBooleanNot); 2992 }; 2993 2994 class HTypeConversion : public HExpression<1> { 2995 public: 2996 // Instantiate a type conversion of `input` to `result_type`. 2997 HTypeConversion(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc) 2998 : HExpression(result_type, SideEffects::None()), dex_pc_(dex_pc) { 2999 SetRawInputAt(0, input); 3000 DCHECK_NE(input->GetType(), result_type); 3001 } 3002 3003 HInstruction* GetInput() const { return InputAt(0); } 3004 Primitive::Type GetInputType() const { return GetInput()->GetType(); } 3005 Primitive::Type GetResultType() const { return GetType(); } 3006 3007 // Required by the x86 and ARM code generators when producing calls 3008 // to the runtime. 3009 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 3010 3011 bool CanBeMoved() const OVERRIDE { return true; } 3012 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { return true; } 3013 3014 DECLARE_INSTRUCTION(TypeConversion); 3015 3016 private: 3017 const uint32_t dex_pc_; 3018 3019 DISALLOW_COPY_AND_ASSIGN(HTypeConversion); 3020 }; 3021 3022 static constexpr uint32_t kNoRegNumber = -1; 3023 3024 class HPhi : public HInstruction { 3025 public: 3026 HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type) 3027 : HInstruction(SideEffects::None()), 3028 inputs_(arena, number_of_inputs), 3029 reg_number_(reg_number), 3030 type_(type), 3031 is_live_(false), 3032 can_be_null_(true) { 3033 inputs_.SetSize(number_of_inputs); 3034 } 3035 3036 // Returns a type equivalent to the given `type`, but that a `HPhi` can hold. 3037 static Primitive::Type ToPhiType(Primitive::Type type) { 3038 switch (type) { 3039 case Primitive::kPrimBoolean: 3040 case Primitive::kPrimByte: 3041 case Primitive::kPrimShort: 3042 case Primitive::kPrimChar: 3043 return Primitive::kPrimInt; 3044 default: 3045 return type; 3046 } 3047 } 3048 3049 size_t InputCount() const OVERRIDE { return inputs_.Size(); } 3050 3051 void AddInput(HInstruction* input); 3052 void RemoveInputAt(size_t index); 3053 3054 Primitive::Type GetType() const OVERRIDE { return type_; } 3055 void SetType(Primitive::Type type) { type_ = type; } 3056 3057 bool CanBeNull() const OVERRIDE { return can_be_null_; } 3058 void SetCanBeNull(bool can_be_null) { can_be_null_ = can_be_null; } 3059 3060 uint32_t GetRegNumber() const { return reg_number_; } 3061 3062 void SetDead() { is_live_ = false; } 3063 void SetLive() { is_live_ = true; } 3064 bool IsDead() const { return !is_live_; } 3065 bool IsLive() const { return is_live_; } 3066 3067 // Returns the next equivalent phi (starting from the current one) or null if there is none. 3068 // An equivalent phi is a phi having the same dex register and type. 3069 // It assumes that phis with the same dex register are adjacent. 3070 HPhi* GetNextEquivalentPhiWithSameType() { 3071 HInstruction* next = GetNext(); 3072 while (next != nullptr && next->AsPhi()->GetRegNumber() == reg_number_) { 3073 if (next->GetType() == GetType()) { 3074 return next->AsPhi(); 3075 } 3076 next = next->GetNext(); 3077 } 3078 return nullptr; 3079 } 3080 3081 DECLARE_INSTRUCTION(Phi); 3082 3083 protected: 3084 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_.Get(i); } 3085 3086 void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) OVERRIDE { 3087 inputs_.Put(index, input); 3088 } 3089 3090 private: 3091 GrowableArray<HUserRecord<HInstruction*> > inputs_; 3092 const uint32_t reg_number_; 3093 Primitive::Type type_; 3094 bool is_live_; 3095 bool can_be_null_; 3096 3097 DISALLOW_COPY_AND_ASSIGN(HPhi); 3098 }; 3099 3100 class HNullCheck : public HExpression<1> { 3101 public: 3102 HNullCheck(HInstruction* value, uint32_t dex_pc) 3103 : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) { 3104 SetRawInputAt(0, value); 3105 } 3106 3107 bool CanBeMoved() const OVERRIDE { return true; } 3108 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 3109 UNUSED(other); 3110 return true; 3111 } 3112 3113 bool NeedsEnvironment() const OVERRIDE { return true; } 3114 3115 bool CanThrow() const OVERRIDE { return true; } 3116 3117 bool CanBeNull() const OVERRIDE { return false; } 3118 3119 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 3120 3121 DECLARE_INSTRUCTION(NullCheck); 3122 3123 private: 3124 const uint32_t dex_pc_; 3125 3126 DISALLOW_COPY_AND_ASSIGN(HNullCheck); 3127 }; 3128 3129 class FieldInfo : public ValueObject { 3130 public: 3131 FieldInfo(MemberOffset field_offset, Primitive::Type field_type, bool is_volatile) 3132 : field_offset_(field_offset), field_type_(field_type), is_volatile_(is_volatile) {} 3133 3134 MemberOffset GetFieldOffset() const { return field_offset_; } 3135 Primitive::Type GetFieldType() const { return field_type_; } 3136 bool IsVolatile() const { return is_volatile_; } 3137 3138 private: 3139 const MemberOffset field_offset_; 3140 const Primitive::Type field_type_; 3141 const bool is_volatile_; 3142 }; 3143 3144 class HInstanceFieldGet : public HExpression<1> { 3145 public: 3146 HInstanceFieldGet(HInstruction* value, 3147 Primitive::Type field_type, 3148 MemberOffset field_offset, 3149 bool is_volatile) 3150 : HExpression(field_type, SideEffects::DependsOnSomething()), 3151 field_info_(field_offset, field_type, is_volatile) { 3152 SetRawInputAt(0, value); 3153 } 3154 3155 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); } 3156 3157 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 3158 HInstanceFieldGet* other_get = other->AsInstanceFieldGet(); 3159 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue(); 3160 } 3161 3162 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE { 3163 return (obj == InputAt(0)) && GetFieldOffset().Uint32Value() < kPageSize; 3164 } 3165 3166 size_t ComputeHashCode() const OVERRIDE { 3167 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue(); 3168 } 3169 3170 const FieldInfo& GetFieldInfo() const { return field_info_; } 3171 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } 3172 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } 3173 bool IsVolatile() const { return field_info_.IsVolatile(); } 3174 3175 DECLARE_INSTRUCTION(InstanceFieldGet); 3176 3177 private: 3178 const FieldInfo field_info_; 3179 3180 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldGet); 3181 }; 3182 3183 class HInstanceFieldSet : public HTemplateInstruction<2> { 3184 public: 3185 HInstanceFieldSet(HInstruction* object, 3186 HInstruction* value, 3187 Primitive::Type field_type, 3188 MemberOffset field_offset, 3189 bool is_volatile) 3190 : HTemplateInstruction(SideEffects::ChangesSomething()), 3191 field_info_(field_offset, field_type, is_volatile) { 3192 SetRawInputAt(0, object); 3193 SetRawInputAt(1, value); 3194 } 3195 3196 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE { 3197 return (obj == InputAt(0)) && GetFieldOffset().Uint32Value() < kPageSize; 3198 } 3199 3200 const FieldInfo& GetFieldInfo() const { return field_info_; } 3201 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } 3202 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } 3203 bool IsVolatile() const { return field_info_.IsVolatile(); } 3204 HInstruction* GetValue() const { return InputAt(1); } 3205 3206 DECLARE_INSTRUCTION(InstanceFieldSet); 3207 3208 private: 3209 const FieldInfo field_info_; 3210 3211 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldSet); 3212 }; 3213 3214 class HArrayGet : public HExpression<2> { 3215 public: 3216 HArrayGet(HInstruction* array, HInstruction* index, Primitive::Type type) 3217 : HExpression(type, SideEffects::DependsOnSomething()) { 3218 SetRawInputAt(0, array); 3219 SetRawInputAt(1, index); 3220 } 3221 3222 bool CanBeMoved() const OVERRIDE { return true; } 3223 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 3224 UNUSED(other); 3225 return true; 3226 } 3227 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE { 3228 UNUSED(obj); 3229 // TODO: We can be smarter here. 3230 // Currently, the array access is always preceded by an ArrayLength or a NullCheck 3231 // which generates the implicit null check. There are cases when these can be removed 3232 // to produce better code. If we ever add optimizations to do so we should allow an 3233 // implicit check here (as long as the address falls in the first page). 3234 return false; 3235 } 3236 3237 void SetType(Primitive::Type type) { type_ = type; } 3238 3239 HInstruction* GetArray() const { return InputAt(0); } 3240 HInstruction* GetIndex() const { return InputAt(1); } 3241 3242 DECLARE_INSTRUCTION(ArrayGet); 3243 3244 private: 3245 DISALLOW_COPY_AND_ASSIGN(HArrayGet); 3246 }; 3247 3248 class HArraySet : public HTemplateInstruction<3> { 3249 public: 3250 HArraySet(HInstruction* array, 3251 HInstruction* index, 3252 HInstruction* value, 3253 Primitive::Type expected_component_type, 3254 uint32_t dex_pc) 3255 : HTemplateInstruction(SideEffects::ChangesSomething()), 3256 dex_pc_(dex_pc), 3257 expected_component_type_(expected_component_type), 3258 needs_type_check_(value->GetType() == Primitive::kPrimNot) { 3259 SetRawInputAt(0, array); 3260 SetRawInputAt(1, index); 3261 SetRawInputAt(2, value); 3262 } 3263 3264 bool NeedsEnvironment() const OVERRIDE { 3265 // We currently always call a runtime method to catch array store 3266 // exceptions. 3267 return needs_type_check_; 3268 } 3269 3270 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE { 3271 UNUSED(obj); 3272 // TODO: Same as for ArrayGet. 3273 return false; 3274 } 3275 3276 void ClearNeedsTypeCheck() { 3277 needs_type_check_ = false; 3278 } 3279 3280 bool NeedsTypeCheck() const { return needs_type_check_; } 3281 3282 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 3283 3284 HInstruction* GetArray() const { return InputAt(0); } 3285 HInstruction* GetIndex() const { return InputAt(1); } 3286 HInstruction* GetValue() const { return InputAt(2); } 3287 3288 Primitive::Type GetComponentType() const { 3289 // The Dex format does not type floating point index operations. Since the 3290 // `expected_component_type_` is set during building and can therefore not 3291 // be correct, we also check what is the value type. If it is a floating 3292 // point type, we must use that type. 3293 Primitive::Type value_type = GetValue()->GetType(); 3294 return ((value_type == Primitive::kPrimFloat) || (value_type == Primitive::kPrimDouble)) 3295 ? value_type 3296 : expected_component_type_; 3297 } 3298 3299 DECLARE_INSTRUCTION(ArraySet); 3300 3301 private: 3302 const uint32_t dex_pc_; 3303 const Primitive::Type expected_component_type_; 3304 bool needs_type_check_; 3305 3306 DISALLOW_COPY_AND_ASSIGN(HArraySet); 3307 }; 3308 3309 class HArrayLength : public HExpression<1> { 3310 public: 3311 explicit HArrayLength(HInstruction* array) 3312 : HExpression(Primitive::kPrimInt, SideEffects::None()) { 3313 // Note that arrays do not change length, so the instruction does not 3314 // depend on any write. 3315 SetRawInputAt(0, array); 3316 } 3317 3318 bool CanBeMoved() const OVERRIDE { return true; } 3319 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 3320 UNUSED(other); 3321 return true; 3322 } 3323 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE { 3324 return obj == InputAt(0); 3325 } 3326 3327 DECLARE_INSTRUCTION(ArrayLength); 3328 3329 private: 3330 DISALLOW_COPY_AND_ASSIGN(HArrayLength); 3331 }; 3332 3333 class HBoundsCheck : public HExpression<2> { 3334 public: 3335 HBoundsCheck(HInstruction* index, HInstruction* length, uint32_t dex_pc) 3336 : HExpression(index->GetType(), SideEffects::None()), dex_pc_(dex_pc) { 3337 DCHECK(index->GetType() == Primitive::kPrimInt); 3338 SetRawInputAt(0, index); 3339 SetRawInputAt(1, length); 3340 } 3341 3342 bool CanBeMoved() const OVERRIDE { return true; } 3343 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 3344 UNUSED(other); 3345 return true; 3346 } 3347 3348 bool NeedsEnvironment() const OVERRIDE { return true; } 3349 3350 bool CanThrow() const OVERRIDE { return true; } 3351 3352 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 3353 3354 DECLARE_INSTRUCTION(BoundsCheck); 3355 3356 private: 3357 const uint32_t dex_pc_; 3358 3359 DISALLOW_COPY_AND_ASSIGN(HBoundsCheck); 3360 }; 3361 3362 /** 3363 * Some DEX instructions are folded into multiple HInstructions that need 3364 * to stay live until the last HInstruction. This class 3365 * is used as a marker for the baseline compiler to ensure its preceding 3366 * HInstruction stays live. `index` represents the stack location index of the 3367 * instruction (the actual offset is computed as index * vreg_size). 3368 */ 3369 class HTemporary : public HTemplateInstruction<0> { 3370 public: 3371 explicit HTemporary(size_t index) : HTemplateInstruction(SideEffects::None()), index_(index) {} 3372 3373 size_t GetIndex() const { return index_; } 3374 3375 Primitive::Type GetType() const OVERRIDE { 3376 // The previous instruction is the one that will be stored in the temporary location. 3377 DCHECK(GetPrevious() != nullptr); 3378 return GetPrevious()->GetType(); 3379 } 3380 3381 DECLARE_INSTRUCTION(Temporary); 3382 3383 private: 3384 const size_t index_; 3385 3386 DISALLOW_COPY_AND_ASSIGN(HTemporary); 3387 }; 3388 3389 class HSuspendCheck : public HTemplateInstruction<0> { 3390 public: 3391 explicit HSuspendCheck(uint32_t dex_pc) 3392 : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc), slow_path_(nullptr) {} 3393 3394 bool NeedsEnvironment() const OVERRIDE { 3395 return true; 3396 } 3397 3398 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 3399 void SetSlowPath(SlowPathCode* slow_path) { slow_path_ = slow_path; } 3400 SlowPathCode* GetSlowPath() const { return slow_path_; } 3401 3402 DECLARE_INSTRUCTION(SuspendCheck); 3403 3404 private: 3405 const uint32_t dex_pc_; 3406 3407 // Only used for code generation, in order to share the same slow path between back edges 3408 // of a same loop. 3409 SlowPathCode* slow_path_; 3410 3411 DISALLOW_COPY_AND_ASSIGN(HSuspendCheck); 3412 }; 3413 3414 /** 3415 * Instruction to load a Class object. 3416 */ 3417 class HLoadClass : public HExpression<0> { 3418 public: 3419 HLoadClass(uint16_t type_index, 3420 bool is_referrers_class, 3421 uint32_t dex_pc) 3422 : HExpression(Primitive::kPrimNot, SideEffects::None()), 3423 type_index_(type_index), 3424 is_referrers_class_(is_referrers_class), 3425 dex_pc_(dex_pc), 3426 generate_clinit_check_(false), 3427 loaded_class_rti_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {} 3428 3429 bool CanBeMoved() const OVERRIDE { return true; } 3430 3431 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 3432 return other->AsLoadClass()->type_index_ == type_index_; 3433 } 3434 3435 size_t ComputeHashCode() const OVERRIDE { return type_index_; } 3436 3437 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 3438 uint16_t GetTypeIndex() const { return type_index_; } 3439 bool IsReferrersClass() const { return is_referrers_class_; } 3440 bool CanBeNull() const OVERRIDE { return false; } 3441 3442 bool NeedsEnvironment() const OVERRIDE { 3443 // Will call runtime and load the class if the class is not loaded yet. 3444 // TODO: finer grain decision. 3445 return !is_referrers_class_; 3446 } 3447 3448 bool MustGenerateClinitCheck() const { 3449 return generate_clinit_check_; 3450 } 3451 3452 void SetMustGenerateClinitCheck() { 3453 generate_clinit_check_ = true; 3454 } 3455 3456 bool CanCallRuntime() const { 3457 return MustGenerateClinitCheck() || !is_referrers_class_; 3458 } 3459 3460 bool CanThrow() const OVERRIDE { 3461 // May call runtime and and therefore can throw. 3462 // TODO: finer grain decision. 3463 return !is_referrers_class_; 3464 } 3465 3466 ReferenceTypeInfo GetLoadedClassRTI() { 3467 return loaded_class_rti_; 3468 } 3469 3470 void SetLoadedClassRTI(ReferenceTypeInfo rti) { 3471 // Make sure we only set exact types (the loaded class should never be merged). 3472 DCHECK(rti.IsExact()); 3473 loaded_class_rti_ = rti; 3474 } 3475 3476 bool IsResolved() { 3477 return loaded_class_rti_.IsExact(); 3478 } 3479 3480 bool NeedsDexCache() const OVERRIDE { return !is_referrers_class_; } 3481 3482 DECLARE_INSTRUCTION(LoadClass); 3483 3484 private: 3485 const uint16_t type_index_; 3486 const bool is_referrers_class_; 3487 const uint32_t dex_pc_; 3488 // Whether this instruction must generate the initialization check. 3489 // Used for code generation. 3490 bool generate_clinit_check_; 3491 3492 ReferenceTypeInfo loaded_class_rti_; 3493 3494 DISALLOW_COPY_AND_ASSIGN(HLoadClass); 3495 }; 3496 3497 class HLoadString : public HExpression<0> { 3498 public: 3499 HLoadString(uint32_t string_index, uint32_t dex_pc) 3500 : HExpression(Primitive::kPrimNot, SideEffects::None()), 3501 string_index_(string_index), 3502 dex_pc_(dex_pc) {} 3503 3504 bool CanBeMoved() const OVERRIDE { return true; } 3505 3506 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 3507 return other->AsLoadString()->string_index_ == string_index_; 3508 } 3509 3510 size_t ComputeHashCode() const OVERRIDE { return string_index_; } 3511 3512 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 3513 uint32_t GetStringIndex() const { return string_index_; } 3514 3515 // TODO: Can we deopt or debug when we resolve a string? 3516 bool NeedsEnvironment() const OVERRIDE { return false; } 3517 bool NeedsDexCache() const OVERRIDE { return true; } 3518 3519 DECLARE_INSTRUCTION(LoadString); 3520 3521 private: 3522 const uint32_t string_index_; 3523 const uint32_t dex_pc_; 3524 3525 DISALLOW_COPY_AND_ASSIGN(HLoadString); 3526 }; 3527 3528 /** 3529 * Performs an initialization check on its Class object input. 3530 */ 3531 class HClinitCheck : public HExpression<1> { 3532 public: 3533 explicit HClinitCheck(HLoadClass* constant, uint32_t dex_pc) 3534 : HExpression(Primitive::kPrimNot, SideEffects::ChangesSomething()), 3535 dex_pc_(dex_pc) { 3536 SetRawInputAt(0, constant); 3537 } 3538 3539 bool CanBeMoved() const OVERRIDE { return true; } 3540 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 3541 UNUSED(other); 3542 return true; 3543 } 3544 3545 bool NeedsEnvironment() const OVERRIDE { 3546 // May call runtime to initialize the class. 3547 return true; 3548 } 3549 3550 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 3551 3552 HLoadClass* GetLoadClass() const { return InputAt(0)->AsLoadClass(); } 3553 3554 DECLARE_INSTRUCTION(ClinitCheck); 3555 3556 private: 3557 const uint32_t dex_pc_; 3558 3559 DISALLOW_COPY_AND_ASSIGN(HClinitCheck); 3560 }; 3561 3562 class HStaticFieldGet : public HExpression<1> { 3563 public: 3564 HStaticFieldGet(HInstruction* cls, 3565 Primitive::Type field_type, 3566 MemberOffset field_offset, 3567 bool is_volatile) 3568 : HExpression(field_type, SideEffects::DependsOnSomething()), 3569 field_info_(field_offset, field_type, is_volatile) { 3570 SetRawInputAt(0, cls); 3571 } 3572 3573 3574 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); } 3575 3576 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 3577 HStaticFieldGet* other_get = other->AsStaticFieldGet(); 3578 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue(); 3579 } 3580 3581 size_t ComputeHashCode() const OVERRIDE { 3582 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue(); 3583 } 3584 3585 const FieldInfo& GetFieldInfo() const { return field_info_; } 3586 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } 3587 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } 3588 bool IsVolatile() const { return field_info_.IsVolatile(); } 3589 3590 DECLARE_INSTRUCTION(StaticFieldGet); 3591 3592 private: 3593 const FieldInfo field_info_; 3594 3595 DISALLOW_COPY_AND_ASSIGN(HStaticFieldGet); 3596 }; 3597 3598 class HStaticFieldSet : public HTemplateInstruction<2> { 3599 public: 3600 HStaticFieldSet(HInstruction* cls, 3601 HInstruction* value, 3602 Primitive::Type field_type, 3603 MemberOffset field_offset, 3604 bool is_volatile) 3605 : HTemplateInstruction(SideEffects::ChangesSomething()), 3606 field_info_(field_offset, field_type, is_volatile) { 3607 SetRawInputAt(0, cls); 3608 SetRawInputAt(1, value); 3609 } 3610 3611 const FieldInfo& GetFieldInfo() const { return field_info_; } 3612 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } 3613 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } 3614 bool IsVolatile() const { return field_info_.IsVolatile(); } 3615 3616 HInstruction* GetValue() const { return InputAt(1); } 3617 3618 DECLARE_INSTRUCTION(StaticFieldSet); 3619 3620 private: 3621 const FieldInfo field_info_; 3622 3623 DISALLOW_COPY_AND_ASSIGN(HStaticFieldSet); 3624 }; 3625 3626 // Implement the move-exception DEX instruction. 3627 class HLoadException : public HExpression<0> { 3628 public: 3629 HLoadException() : HExpression(Primitive::kPrimNot, SideEffects::None()) {} 3630 3631 DECLARE_INSTRUCTION(LoadException); 3632 3633 private: 3634 DISALLOW_COPY_AND_ASSIGN(HLoadException); 3635 }; 3636 3637 class HThrow : public HTemplateInstruction<1> { 3638 public: 3639 HThrow(HInstruction* exception, uint32_t dex_pc) 3640 : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc) { 3641 SetRawInputAt(0, exception); 3642 } 3643 3644 bool IsControlFlow() const OVERRIDE { return true; } 3645 3646 bool NeedsEnvironment() const OVERRIDE { return true; } 3647 3648 bool CanThrow() const OVERRIDE { return true; } 3649 3650 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 3651 3652 DECLARE_INSTRUCTION(Throw); 3653 3654 private: 3655 const uint32_t dex_pc_; 3656 3657 DISALLOW_COPY_AND_ASSIGN(HThrow); 3658 }; 3659 3660 class HInstanceOf : public HExpression<2> { 3661 public: 3662 HInstanceOf(HInstruction* object, 3663 HLoadClass* constant, 3664 bool class_is_final, 3665 uint32_t dex_pc) 3666 : HExpression(Primitive::kPrimBoolean, SideEffects::None()), 3667 class_is_final_(class_is_final), 3668 must_do_null_check_(true), 3669 dex_pc_(dex_pc) { 3670 SetRawInputAt(0, object); 3671 SetRawInputAt(1, constant); 3672 } 3673 3674 bool CanBeMoved() const OVERRIDE { return true; } 3675 3676 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { 3677 return true; 3678 } 3679 3680 bool NeedsEnvironment() const OVERRIDE { 3681 return false; 3682 } 3683 3684 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 3685 3686 bool IsClassFinal() const { return class_is_final_; } 3687 3688 // Used only in code generation. 3689 bool MustDoNullCheck() const { return must_do_null_check_; } 3690 void ClearMustDoNullCheck() { must_do_null_check_ = false; } 3691 3692 DECLARE_INSTRUCTION(InstanceOf); 3693 3694 private: 3695 const bool class_is_final_; 3696 bool must_do_null_check_; 3697 const uint32_t dex_pc_; 3698 3699 DISALLOW_COPY_AND_ASSIGN(HInstanceOf); 3700 }; 3701 3702 class HBoundType : public HExpression<1> { 3703 public: 3704 HBoundType(HInstruction* input, ReferenceTypeInfo bound_type) 3705 : HExpression(Primitive::kPrimNot, SideEffects::None()), 3706 bound_type_(bound_type) { 3707 DCHECK_EQ(input->GetType(), Primitive::kPrimNot); 3708 SetRawInputAt(0, input); 3709 } 3710 3711 const ReferenceTypeInfo& GetBoundType() const { return bound_type_; } 3712 3713 bool CanBeNull() const OVERRIDE { 3714 // `null instanceof ClassX` always return false so we can't be null. 3715 return false; 3716 } 3717 3718 DECLARE_INSTRUCTION(BoundType); 3719 3720 private: 3721 // Encodes the most upper class that this instruction can have. In other words 3722 // it is always the case that GetBoundType().IsSupertypeOf(GetReferenceType()). 3723 // It is used to bound the type in cases like `if (x instanceof ClassX) {}` 3724 const ReferenceTypeInfo bound_type_; 3725 3726 DISALLOW_COPY_AND_ASSIGN(HBoundType); 3727 }; 3728 3729 class HCheckCast : public HTemplateInstruction<2> { 3730 public: 3731 HCheckCast(HInstruction* object, 3732 HLoadClass* constant, 3733 bool class_is_final, 3734 uint32_t dex_pc) 3735 : HTemplateInstruction(SideEffects::None()), 3736 class_is_final_(class_is_final), 3737 must_do_null_check_(true), 3738 dex_pc_(dex_pc) { 3739 SetRawInputAt(0, object); 3740 SetRawInputAt(1, constant); 3741 } 3742 3743 bool CanBeMoved() const OVERRIDE { return true; } 3744 3745 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { 3746 return true; 3747 } 3748 3749 bool NeedsEnvironment() const OVERRIDE { 3750 // Instruction may throw a CheckCastError. 3751 return true; 3752 } 3753 3754 bool CanThrow() const OVERRIDE { return true; } 3755 3756 bool MustDoNullCheck() const { return must_do_null_check_; } 3757 void ClearMustDoNullCheck() { must_do_null_check_ = false; } 3758 3759 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 3760 3761 bool IsClassFinal() const { return class_is_final_; } 3762 3763 DECLARE_INSTRUCTION(CheckCast); 3764 3765 private: 3766 const bool class_is_final_; 3767 bool must_do_null_check_; 3768 const uint32_t dex_pc_; 3769 3770 DISALLOW_COPY_AND_ASSIGN(HCheckCast); 3771 }; 3772 3773 class HMemoryBarrier : public HTemplateInstruction<0> { 3774 public: 3775 explicit HMemoryBarrier(MemBarrierKind barrier_kind) 3776 : HTemplateInstruction(SideEffects::None()), 3777 barrier_kind_(barrier_kind) {} 3778 3779 MemBarrierKind GetBarrierKind() { return barrier_kind_; } 3780 3781 DECLARE_INSTRUCTION(MemoryBarrier); 3782 3783 private: 3784 const MemBarrierKind barrier_kind_; 3785 3786 DISALLOW_COPY_AND_ASSIGN(HMemoryBarrier); 3787 }; 3788 3789 class HMonitorOperation : public HTemplateInstruction<1> { 3790 public: 3791 enum OperationKind { 3792 kEnter, 3793 kExit, 3794 }; 3795 3796 HMonitorOperation(HInstruction* object, OperationKind kind, uint32_t dex_pc) 3797 : HTemplateInstruction(SideEffects::None()), kind_(kind), dex_pc_(dex_pc) { 3798 SetRawInputAt(0, object); 3799 } 3800 3801 // Instruction may throw a Java exception, so we need an environment. 3802 bool NeedsEnvironment() const OVERRIDE { return true; } 3803 bool CanThrow() const OVERRIDE { return true; } 3804 3805 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } 3806 3807 bool IsEnter() const { return kind_ == kEnter; } 3808 3809 DECLARE_INSTRUCTION(MonitorOperation); 3810 3811 private: 3812 const OperationKind kind_; 3813 const uint32_t dex_pc_; 3814 3815 private: 3816 DISALLOW_COPY_AND_ASSIGN(HMonitorOperation); 3817 }; 3818 3819 class MoveOperands : public ArenaObject<kArenaAllocMisc> { 3820 public: 3821 MoveOperands(Location source, 3822 Location destination, 3823 Primitive::Type type, 3824 HInstruction* instruction) 3825 : source_(source), destination_(destination), type_(type), instruction_(instruction) {} 3826 3827 Location GetSource() const { return source_; } 3828 Location GetDestination() const { return destination_; } 3829 3830 void SetSource(Location value) { source_ = value; } 3831 void SetDestination(Location value) { destination_ = value; } 3832 3833 // The parallel move resolver marks moves as "in-progress" by clearing the 3834 // destination (but not the source). 3835 Location MarkPending() { 3836 DCHECK(!IsPending()); 3837 Location dest = destination_; 3838 destination_ = Location::NoLocation(); 3839 return dest; 3840 } 3841 3842 void ClearPending(Location dest) { 3843 DCHECK(IsPending()); 3844 destination_ = dest; 3845 } 3846 3847 bool IsPending() const { 3848 DCHECK(!source_.IsInvalid() || destination_.IsInvalid()); 3849 return destination_.IsInvalid() && !source_.IsInvalid(); 3850 } 3851 3852 // True if this blocks a move from the given location. 3853 bool Blocks(Location loc) const { 3854 return !IsEliminated() && source_.OverlapsWith(loc); 3855 } 3856 3857 // A move is redundant if it's been eliminated, if its source and 3858 // destination are the same, or if its destination is unneeded. 3859 bool IsRedundant() const { 3860 return IsEliminated() || destination_.IsInvalid() || source_.Equals(destination_); 3861 } 3862 3863 // We clear both operands to indicate move that's been eliminated. 3864 void Eliminate() { 3865 source_ = destination_ = Location::NoLocation(); 3866 } 3867 3868 bool IsEliminated() const { 3869 DCHECK(!source_.IsInvalid() || destination_.IsInvalid()); 3870 return source_.IsInvalid(); 3871 } 3872 3873 Primitive::Type GetType() const { return type_; } 3874 3875 bool Is64BitMove() const { 3876 return Primitive::Is64BitType(type_); 3877 } 3878 3879 HInstruction* GetInstruction() const { return instruction_; } 3880 3881 private: 3882 Location source_; 3883 Location destination_; 3884 // The type this move is for. 3885 Primitive::Type type_; 3886 // The instruction this move is assocatied with. Null when this move is 3887 // for moving an input in the expected locations of user (including a phi user). 3888 // This is only used in debug mode, to ensure we do not connect interval siblings 3889 // in the same parallel move. 3890 HInstruction* instruction_; 3891 }; 3892 3893 static constexpr size_t kDefaultNumberOfMoves = 4; 3894 3895 class HParallelMove : public HTemplateInstruction<0> { 3896 public: 3897 explicit HParallelMove(ArenaAllocator* arena) 3898 : HTemplateInstruction(SideEffects::None()), moves_(arena, kDefaultNumberOfMoves) {} 3899 3900 void AddMove(Location source, 3901 Location destination, 3902 Primitive::Type type, 3903 HInstruction* instruction) { 3904 DCHECK(source.IsValid()); 3905 DCHECK(destination.IsValid()); 3906 if (kIsDebugBuild) { 3907 if (instruction != nullptr) { 3908 for (size_t i = 0, e = moves_.Size(); i < e; ++i) { 3909 if (moves_.Get(i).GetInstruction() == instruction) { 3910 // Special case the situation where the move is for the spill slot 3911 // of the instruction. 3912 if ((GetPrevious() == instruction) 3913 || ((GetPrevious() == nullptr) 3914 && instruction->IsPhi() 3915 && instruction->GetBlock() == GetBlock())) { 3916 DCHECK_NE(destination.GetKind(), moves_.Get(i).GetDestination().GetKind()) 3917 << "Doing parallel moves for the same instruction."; 3918 } else { 3919 DCHECK(false) << "Doing parallel moves for the same instruction."; 3920 } 3921 } 3922 } 3923 } 3924 for (size_t i = 0, e = moves_.Size(); i < e; ++i) { 3925 DCHECK(!destination.OverlapsWith(moves_.Get(i).GetDestination())) 3926 << "Overlapped destination for two moves in a parallel move."; 3927 } 3928 } 3929 moves_.Add(MoveOperands(source, destination, type, instruction)); 3930 } 3931 3932 MoveOperands* MoveOperandsAt(size_t index) const { 3933 return moves_.GetRawStorage() + index; 3934 } 3935 3936 size_t NumMoves() const { return moves_.Size(); } 3937 3938 DECLARE_INSTRUCTION(ParallelMove); 3939 3940 private: 3941 GrowableArray<MoveOperands> moves_; 3942 3943 DISALLOW_COPY_AND_ASSIGN(HParallelMove); 3944 }; 3945 3946 class HGraphVisitor : public ValueObject { 3947 public: 3948 explicit HGraphVisitor(HGraph* graph) : graph_(graph) {} 3949 virtual ~HGraphVisitor() {} 3950 3951 virtual void VisitInstruction(HInstruction* instruction) { UNUSED(instruction); } 3952 virtual void VisitBasicBlock(HBasicBlock* block); 3953 3954 // Visit the graph following basic block insertion order. 3955 void VisitInsertionOrder(); 3956 3957 // Visit the graph following dominator tree reverse post-order. 3958 void VisitReversePostOrder(); 3959 3960 HGraph* GetGraph() const { return graph_; } 3961 3962 // Visit functions for instruction classes. 3963 #define DECLARE_VISIT_INSTRUCTION(name, super) \ 3964 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); } 3965 3966 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) 3967 3968 #undef DECLARE_VISIT_INSTRUCTION 3969 3970 private: 3971 HGraph* const graph_; 3972 3973 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor); 3974 }; 3975 3976 class HGraphDelegateVisitor : public HGraphVisitor { 3977 public: 3978 explicit HGraphDelegateVisitor(HGraph* graph) : HGraphVisitor(graph) {} 3979 virtual ~HGraphDelegateVisitor() {} 3980 3981 // Visit functions that delegate to to super class. 3982 #define DECLARE_VISIT_INSTRUCTION(name, super) \ 3983 void Visit##name(H##name* instr) OVERRIDE { Visit##super(instr); } 3984 3985 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) 3986 3987 #undef DECLARE_VISIT_INSTRUCTION 3988 3989 private: 3990 DISALLOW_COPY_AND_ASSIGN(HGraphDelegateVisitor); 3991 }; 3992 3993 class HInsertionOrderIterator : public ValueObject { 3994 public: 3995 explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {} 3996 3997 bool Done() const { return index_ == graph_.GetBlocks().Size(); } 3998 HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); } 3999 void Advance() { ++index_; } 4000 4001 private: 4002 const HGraph& graph_; 4003 size_t index_; 4004 4005 DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator); 4006 }; 4007 4008 class HReversePostOrderIterator : public ValueObject { 4009 public: 4010 explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) { 4011 // Check that reverse post order of the graph has been built. 4012 DCHECK(!graph.GetReversePostOrder().IsEmpty()); 4013 } 4014 4015 bool Done() const { return index_ == graph_.GetReversePostOrder().Size(); } 4016 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_); } 4017 void Advance() { ++index_; } 4018 4019 private: 4020 const HGraph& graph_; 4021 size_t index_; 4022 4023 DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator); 4024 }; 4025 4026 class HPostOrderIterator : public ValueObject { 4027 public: 4028 explicit HPostOrderIterator(const HGraph& graph) 4029 : graph_(graph), index_(graph_.GetReversePostOrder().Size()) { 4030 // Check that reverse post order of the graph has been built. 4031 DCHECK(!graph.GetReversePostOrder().IsEmpty()); 4032 } 4033 4034 bool Done() const { return index_ == 0; } 4035 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_ - 1); } 4036 void Advance() { --index_; } 4037 4038 private: 4039 const HGraph& graph_; 4040 size_t index_; 4041 4042 DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator); 4043 }; 4044 4045 class HLinearPostOrderIterator : public ValueObject { 4046 public: 4047 explicit HLinearPostOrderIterator(const HGraph& graph) 4048 : order_(graph.GetLinearOrder()), index_(graph.GetLinearOrder().Size()) {} 4049 4050 bool Done() const { return index_ == 0; } 4051 4052 HBasicBlock* Current() const { return order_.Get(index_ -1); } 4053 4054 void Advance() { 4055 --index_; 4056 DCHECK_GE(index_, 0U); 4057 } 4058 4059 private: 4060 const GrowableArray<HBasicBlock*>& order_; 4061 size_t index_; 4062 4063 DISALLOW_COPY_AND_ASSIGN(HLinearPostOrderIterator); 4064 }; 4065 4066 class HLinearOrderIterator : public ValueObject { 4067 public: 4068 explicit HLinearOrderIterator(const HGraph& graph) 4069 : order_(graph.GetLinearOrder()), index_(0) {} 4070 4071 bool Done() const { return index_ == order_.Size(); } 4072 HBasicBlock* Current() const { return order_.Get(index_); } 4073 void Advance() { ++index_; } 4074 4075 private: 4076 const GrowableArray<HBasicBlock*>& order_; 4077 size_t index_; 4078 4079 DISALLOW_COPY_AND_ASSIGN(HLinearOrderIterator); 4080 }; 4081 4082 // Iterator over the blocks that art part of the loop. Includes blocks part 4083 // of an inner loop. The order in which the blocks are iterated is on their 4084 // block id. 4085 class HBlocksInLoopIterator : public ValueObject { 4086 public: 4087 explicit HBlocksInLoopIterator(const HLoopInformation& info) 4088 : blocks_in_loop_(info.GetBlocks()), 4089 blocks_(info.GetHeader()->GetGraph()->GetBlocks()), 4090 index_(0) { 4091 if (!blocks_in_loop_.IsBitSet(index_)) { 4092 Advance(); 4093 } 4094 } 4095 4096 bool Done() const { return index_ == blocks_.Size(); } 4097 HBasicBlock* Current() const { return blocks_.Get(index_); } 4098 void Advance() { 4099 ++index_; 4100 for (size_t e = blocks_.Size(); index_ < e; ++index_) { 4101 if (blocks_in_loop_.IsBitSet(index_)) { 4102 break; 4103 } 4104 } 4105 } 4106 4107 private: 4108 const BitVector& blocks_in_loop_; 4109 const GrowableArray<HBasicBlock*>& blocks_; 4110 size_t index_; 4111 4112 DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopIterator); 4113 }; 4114 4115 // Iterator over the blocks that art part of the loop. Includes blocks part 4116 // of an inner loop. The order in which the blocks are iterated is reverse 4117 // post order. 4118 class HBlocksInLoopReversePostOrderIterator : public ValueObject { 4119 public: 4120 explicit HBlocksInLoopReversePostOrderIterator(const HLoopInformation& info) 4121 : blocks_in_loop_(info.GetBlocks()), 4122 blocks_(info.GetHeader()->GetGraph()->GetReversePostOrder()), 4123 index_(0) { 4124 if (!blocks_in_loop_.IsBitSet(blocks_.Get(index_)->GetBlockId())) { 4125 Advance(); 4126 } 4127 } 4128 4129 bool Done() const { return index_ == blocks_.Size(); } 4130 HBasicBlock* Current() const { return blocks_.Get(index_); } 4131 void Advance() { 4132 ++index_; 4133 for (size_t e = blocks_.Size(); index_ < e; ++index_) { 4134 if (blocks_in_loop_.IsBitSet(blocks_.Get(index_)->GetBlockId())) { 4135 break; 4136 } 4137 } 4138 } 4139 4140 private: 4141 const BitVector& blocks_in_loop_; 4142 const GrowableArray<HBasicBlock*>& blocks_; 4143 size_t index_; 4144 4145 DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopReversePostOrderIterator); 4146 }; 4147 4148 inline int64_t Int64FromConstant(HConstant* constant) { 4149 DCHECK(constant->IsIntConstant() || constant->IsLongConstant()); 4150 return constant->IsIntConstant() ? constant->AsIntConstant()->GetValue() 4151 : constant->AsLongConstant()->GetValue(); 4152 } 4153 4154 } // namespace art 4155 4156 #endif // ART_COMPILER_OPTIMIZING_NODES_H_ 4157