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 |