| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_REGISTER_ALLOCATOR_H_ | 5 #ifndef V8_REGISTER_ALLOCATOR_H_ |
| 6 #define V8_REGISTER_ALLOCATOR_H_ | 6 #define V8_REGISTER_ALLOCATOR_H_ |
| 7 | 7 |
| 8 #include "src/compiler/instruction.h" | 8 #include "src/compiler/instruction.h" |
| 9 #include "src/zone-containers.h" | 9 #include "src/zone-containers.h" |
| 10 | 10 |
| 11 namespace v8 { | 11 namespace v8 { |
| 12 namespace internal { | 12 namespace internal { |
| 13 namespace compiler { | 13 namespace compiler { |
| 14 | 14 |
| 15 enum RegisterKind { | 15 enum RegisterKind { |
| 16 UNALLOCATED_REGISTERS, | 16 UNALLOCATED_REGISTERS, |
| 17 GENERAL_REGISTERS, | 17 GENERAL_REGISTERS, |
| 18 DOUBLE_REGISTERS | 18 DOUBLE_REGISTERS |
| 19 }; | 19 }; |
| 20 | 20 |
| 21 | 21 |
| 22 // This class represents a single point of a InstructionOperand's lifetime. For | 22 // This class represents a single point of a InstructionOperand's lifetime. For |
| 23 // each instruction there are exactly two lifetime positions: the beginning and | 23 // each instruction there are four lifetime positions: |
| 24 // the end of the instruction. Lifetime positions for different instructions are | 24 // |
| 25 // disjoint. | 25 // [[START, END], [START, END]] |
| 26 // |
| 27 // Where the first half position corresponds to |
| 28 // |
| 29 // [GapPosition::START, GapPosition::END] |
| 30 // |
| 31 // and the second half position corresponds to |
| 32 // |
| 33 // [Lifetime::USED_AT_START, Lifetime::USED_AT_END] |
| 34 // |
| 26 class LifetimePosition FINAL { | 35 class LifetimePosition FINAL { |
| 27 public: | 36 public: |
| 28 // Return the lifetime position that corresponds to the beginning of | 37 // Return the lifetime position that corresponds to the beginning of |
| 38 // the gap with the given index. |
| 39 static LifetimePosition GapFromInstructionIndex(int index) { |
| 40 return LifetimePosition(index * kStep); |
| 41 } |
| 42 // Return the lifetime position that corresponds to the beginning of |
| 29 // the instruction with the given index. | 43 // the instruction with the given index. |
| 30 static LifetimePosition FromInstructionIndex(int index) { | 44 static LifetimePosition InstructionFromInstructionIndex(int index) { |
| 31 return LifetimePosition(index * kStep); | 45 return LifetimePosition(index * kStep + kHalfStep); |
| 32 } | 46 } |
| 33 | 47 |
| 34 // Returns a numeric representation of this lifetime position. | 48 // Returns a numeric representation of this lifetime position. |
| 35 int Value() const { return value_; } | 49 int Value() const { return value_; } |
| 36 | 50 |
| 37 // Returns the index of the instruction to which this lifetime position | 51 // Returns the index of the instruction to which this lifetime position |
| 38 // corresponds. | 52 // corresponds. |
| 39 int InstructionIndex() const { | 53 int ToInstructionIndex() const { |
| 40 DCHECK(IsValid()); | 54 DCHECK(IsValid()); |
| 41 return value_ / kStep; | 55 return value_ / kStep; |
| 42 } | 56 } |
| 43 | 57 |
| 44 // Returns true if this lifetime position corresponds to the instruction | 58 // Returns true if this lifetime position corresponds to a START value |
| 45 // start. | 59 bool IsStart() const { return (value_ & (kHalfStep - 1)) == 0; } |
| 46 bool IsInstructionStart() const { return (value_ & (kStep - 1)) == 0; } | 60 // Returns true if this lifetime position corresponds to a gap START value |
| 61 bool IsFullStart() const { return (value_ & (kStep - 1)) == 0; } |
| 47 | 62 |
| 48 // Returns the lifetime position for the start of the instruction which | 63 bool IsGapPosition() { return (value_ & 0x2) == 0; } |
| 49 // corresponds to this lifetime position. | 64 bool IsInstructionPosition() { return !IsGapPosition(); } |
| 50 LifetimePosition InstructionStart() const { | 65 |
| 66 // Returns the lifetime position for the current START. |
| 67 LifetimePosition Start() const { |
| 68 DCHECK(IsValid()); |
| 69 return LifetimePosition(value_ & ~(kHalfStep - 1)); |
| 70 } |
| 71 |
| 72 // Returns the lifetime position for the current gap START. |
| 73 LifetimePosition FullStart() const { |
| 51 DCHECK(IsValid()); | 74 DCHECK(IsValid()); |
| 52 return LifetimePosition(value_ & ~(kStep - 1)); | 75 return LifetimePosition(value_ & ~(kStep - 1)); |
| 53 } | 76 } |
| 54 | 77 |
| 55 // Returns the lifetime position for the end of the instruction which | 78 // Returns the lifetime position for the current END. |
| 56 // corresponds to this lifetime position. | 79 LifetimePosition End() const { |
| 57 LifetimePosition InstructionEnd() const { | |
| 58 DCHECK(IsValid()); | 80 DCHECK(IsValid()); |
| 59 return LifetimePosition(InstructionStart().Value() + kStep / 2); | 81 return LifetimePosition(Start().Value() + kHalfStep / 2); |
| 60 } | 82 } |
| 61 | 83 |
| 62 // Returns the lifetime position for the beginning of the next instruction. | 84 // Returns the lifetime position for the beginning of the next START. |
| 63 LifetimePosition NextInstruction() const { | 85 LifetimePosition NextStart() const { |
| 64 DCHECK(IsValid()); | 86 DCHECK(IsValid()); |
| 65 return LifetimePosition(InstructionStart().Value() + kStep); | 87 return LifetimePosition(Start().Value() + kHalfStep); |
| 66 } | 88 } |
| 67 | 89 |
| 68 // Returns the lifetime position for the beginning of the previous | 90 // Returns the lifetime position for the beginning of the next gap START. |
| 69 // instruction. | 91 LifetimePosition NextFullStart() const { |
| 70 LifetimePosition PrevInstruction() const { | |
| 71 DCHECK(IsValid()); | 92 DCHECK(IsValid()); |
| 72 DCHECK(value_ > 1); | 93 return LifetimePosition(FullStart().Value() + kStep); |
| 73 return LifetimePosition(InstructionStart().Value() - kStep); | 94 } |
| 95 |
| 96 // Returns the lifetime position for the beginning of the previous START. |
| 97 LifetimePosition PrevStart() const { |
| 98 DCHECK(IsValid()); |
| 99 DCHECK(value_ >= kHalfStep); |
| 100 return LifetimePosition(Start().Value() - kHalfStep); |
| 74 } | 101 } |
| 75 | 102 |
| 76 // Constructs the lifetime position which does not correspond to any | 103 // Constructs the lifetime position which does not correspond to any |
| 77 // instruction. | 104 // instruction. |
| 78 LifetimePosition() : value_(-1) {} | 105 LifetimePosition() : value_(-1) {} |
| 79 | 106 |
| 80 // Returns true if this lifetime positions corrensponds to some | 107 // Returns true if this lifetime positions corrensponds to some |
| 81 // instruction. | 108 // instruction. |
| 82 bool IsValid() const { return value_ != -1; } | 109 bool IsValid() const { return value_ != -1; } |
| 83 | 110 |
| 84 static inline LifetimePosition Invalid() { return LifetimePosition(); } | 111 static inline LifetimePosition Invalid() { return LifetimePosition(); } |
| 85 | 112 |
| 86 static inline LifetimePosition MaxPosition() { | 113 static inline LifetimePosition MaxPosition() { |
| 87 // We have to use this kind of getter instead of static member due to | 114 // We have to use this kind of getter instead of static member due to |
| 88 // crash bug in GDB. | 115 // crash bug in GDB. |
| 89 return LifetimePosition(kMaxInt); | 116 return LifetimePosition(kMaxInt); |
| 90 } | 117 } |
| 91 | 118 |
| 92 private: | 119 private: |
| 93 static const int kStep = 2; | 120 static const int kHalfStep = 2; |
| 121 static const int kStep = 2 * kHalfStep; |
| 94 | 122 |
| 95 // Code relies on kStep being a power of two. | 123 // Code relies on kStep and kHalfStep being a power of two. |
| 96 STATIC_ASSERT(IS_POWER_OF_TWO(kStep)); | 124 STATIC_ASSERT(IS_POWER_OF_TWO(kHalfStep)); |
| 97 | 125 |
| 98 explicit LifetimePosition(int value) : value_(value) {} | 126 explicit LifetimePosition(int value) : value_(value) {} |
| 99 | 127 |
| 100 int value_; | 128 int value_; |
| 101 }; | 129 }; |
| 102 | 130 |
| 103 | 131 |
| 104 // Representation of the non-empty interval [start,end[. | 132 // Representation of the non-empty interval [start,end[. |
| 105 class UseInterval FINAL : public ZoneObject { | 133 class UseInterval FINAL : public ZoneObject { |
| 106 public: | 134 public: |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const; | 516 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const; |
| 489 bool SafePointsAreInOrder() const; | 517 bool SafePointsAreInOrder() const; |
| 490 | 518 |
| 491 // Liveness analysis support. | 519 // Liveness analysis support. |
| 492 BitVector* ComputeLiveOut(const InstructionBlock* block); | 520 BitVector* ComputeLiveOut(const InstructionBlock* block); |
| 493 void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out); | 521 void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out); |
| 494 bool IsOutputRegisterOf(Instruction* instr, int index); | 522 bool IsOutputRegisterOf(Instruction* instr, int index); |
| 495 bool IsOutputDoubleRegisterOf(Instruction* instr, int index); | 523 bool IsOutputDoubleRegisterOf(Instruction* instr, int index); |
| 496 void ProcessInstructions(const InstructionBlock* block, BitVector* live); | 524 void ProcessInstructions(const InstructionBlock* block, BitVector* live); |
| 497 void MeetRegisterConstraints(const InstructionBlock* block); | 525 void MeetRegisterConstraints(const InstructionBlock* block); |
| 498 void MeetConstraintsBetween(Instruction* first, Instruction* second, | 526 void MeetConstraintsBefore(int index); |
| 499 int gap_index); | 527 void MeetConstraintsAfter(int index); |
| 500 void MeetRegisterConstraintsForLastInstructionInBlock( | 528 void MeetRegisterConstraintsForLastInstructionInBlock( |
| 501 const InstructionBlock* block); | 529 const InstructionBlock* block); |
| 502 void ResolvePhis(const InstructionBlock* block); | 530 void ResolvePhis(const InstructionBlock* block); |
| 503 | 531 |
| 504 // Helper methods for building intervals. | 532 // Helper methods for building intervals. |
| 505 InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos, | 533 InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos, |
| 506 bool is_tagged); | 534 bool is_tagged); |
| 507 LiveRange* LiveRangeFor(InstructionOperand* operand); | 535 LiveRange* LiveRangeFor(InstructionOperand* operand); |
| 508 void Define(LifetimePosition position, InstructionOperand* operand, | 536 void Define(LifetimePosition position, InstructionOperand* operand, |
| 509 InstructionOperand* hint); | 537 InstructionOperand* hint); |
| 510 void Use(LifetimePosition block_start, LifetimePosition position, | 538 void Use(LifetimePosition block_start, LifetimePosition position, |
| 511 InstructionOperand* operand, InstructionOperand* hint); | 539 InstructionOperand* operand, InstructionOperand* hint); |
| 512 void AddGapMove(int index, GapInstruction::InnerPosition position, | 540 void AddGapMove(int index, Instruction::GapPosition position, |
| 513 InstructionOperand* from, InstructionOperand* to); | 541 InstructionOperand* from, InstructionOperand* to); |
| 514 | 542 |
| 515 // Helper methods for updating the life range lists. | 543 // Helper methods for updating the life range lists. |
| 516 void AddToActive(LiveRange* range); | 544 void AddToActive(LiveRange* range); |
| 517 void AddToInactive(LiveRange* range); | 545 void AddToInactive(LiveRange* range); |
| 518 void AddToUnhandledSorted(LiveRange* range); | 546 void AddToUnhandledSorted(LiveRange* range); |
| 519 void AddToUnhandledUnsorted(LiveRange* range); | 547 void AddToUnhandledUnsorted(LiveRange* range); |
| 520 void SortUnhandled(); | 548 void SortUnhandled(); |
| 521 bool UnhandledIsSorted(); | 549 bool UnhandledIsSorted(); |
| 522 void ActiveToHandled(LiveRange* range); | 550 void ActiveToHandled(LiveRange* range); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 // Return the block which contains give lifetime position. | 611 // Return the block which contains give lifetime position. |
| 584 const InstructionBlock* GetInstructionBlock(LifetimePosition pos); | 612 const InstructionBlock* GetInstructionBlock(LifetimePosition pos); |
| 585 | 613 |
| 586 // Helper methods for the fixed registers. | 614 // Helper methods for the fixed registers. |
| 587 int RegisterCount() const; | 615 int RegisterCount() const; |
| 588 static int FixedLiveRangeID(int index) { return -index - 1; } | 616 static int FixedLiveRangeID(int index) { return -index - 1; } |
| 589 int FixedDoubleLiveRangeID(int index); | 617 int FixedDoubleLiveRangeID(int index); |
| 590 LiveRange* FixedLiveRangeFor(int index); | 618 LiveRange* FixedLiveRangeFor(int index); |
| 591 LiveRange* FixedDoubleLiveRangeFor(int index); | 619 LiveRange* FixedDoubleLiveRangeFor(int index); |
| 592 LiveRange* LiveRangeFor(int index); | 620 LiveRange* LiveRangeFor(int index); |
| 593 GapInstruction* GetLastGap(const InstructionBlock* block); | 621 Instruction* GetLastInstruction(const InstructionBlock* block); |
| 594 | 622 |
| 595 const char* RegisterName(int allocation_index); | 623 const char* RegisterName(int allocation_index); |
| 596 | 624 |
| 597 Instruction* InstructionAt(int index) { return code()->InstructionAt(index); } | 625 Instruction* InstructionAt(int index) { return code()->InstructionAt(index); } |
| 598 | 626 |
| 599 Frame* frame() const { return frame_; } | 627 Frame* frame() const { return frame_; } |
| 600 const char* debug_name() const { return debug_name_; } | 628 const char* debug_name() const { return debug_name_; } |
| 601 const RegisterConfiguration* config() const { return config_; } | 629 const RegisterConfiguration* config() const { return config_; } |
| 602 InstructionOperandCache* operand_cache() const { return operand_cache_; } | 630 InstructionOperandCache* operand_cache() const { return operand_cache_; } |
| 603 ZoneVector<LiveRange*>& live_ranges() { return live_ranges_; } | 631 ZoneVector<LiveRange*>& live_ranges() { return live_ranges_; } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 #endif | 685 #endif |
| 658 | 686 |
| 659 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator); | 687 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator); |
| 660 }; | 688 }; |
| 661 | 689 |
| 662 } // namespace compiler | 690 } // namespace compiler |
| 663 } // namespace internal | 691 } // namespace internal |
| 664 } // namespace v8 | 692 } // namespace v8 |
| 665 | 693 |
| 666 #endif // V8_REGISTER_ALLOCATOR_H_ | 694 #endif // V8_REGISTER_ALLOCATOR_H_ |
| OLD | NEW |