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 #include "src/compiler/linkage.h" | 5 #include "src/compiler/linkage.h" |
6 #include "src/compiler/register-allocator.h" | 6 #include "src/compiler/register-allocator.h" |
7 #include "src/string-stream.h" | 7 #include "src/string-stream.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 | 60 |
61 void UseInterval::SplitAt(LifetimePosition pos, Zone* zone) { | 61 void UseInterval::SplitAt(LifetimePosition pos, Zone* zone) { |
62 DCHECK(Contains(pos) && pos.Value() != start().Value()); | 62 DCHECK(Contains(pos) && pos.Value() != start().Value()); |
63 UseInterval* after = new (zone) UseInterval(pos, end_); | 63 UseInterval* after = new (zone) UseInterval(pos, end_); |
64 after->next_ = next_; | 64 after->next_ = next_; |
65 next_ = after; | 65 next_ = after; |
66 end_ = pos; | 66 end_ = pos; |
67 } | 67 } |
68 | 68 |
69 | 69 |
| 70 struct LiveRange::SpillAtDefinitionList : ZoneObject { |
| 71 SpillAtDefinitionList(int gap_index, InstructionOperand* operand, |
| 72 SpillAtDefinitionList* next) |
| 73 : gap_index(gap_index), operand(operand), next(next) {} |
| 74 const int gap_index; |
| 75 InstructionOperand* const operand; |
| 76 SpillAtDefinitionList* const next; |
| 77 }; |
| 78 |
| 79 |
70 #ifdef DEBUG | 80 #ifdef DEBUG |
71 | 81 |
72 | 82 |
73 void LiveRange::Verify() const { | 83 void LiveRange::Verify() const { |
74 UsePosition* cur = first_pos_; | 84 UsePosition* cur = first_pos_; |
75 while (cur != NULL) { | 85 while (cur != NULL) { |
76 DCHECK(Start().Value() <= cur->pos().Value() && | 86 DCHECK(Start().Value() <= cur->pos().Value() && |
77 cur->pos().Value() <= End().Value()); | 87 cur->pos().Value() <= End().Value()); |
78 cur = cur->next(); | 88 cur = cur->next(); |
79 } | 89 } |
(...skipping 17 matching lines...) Expand all Loading... |
97 #endif | 107 #endif |
98 | 108 |
99 | 109 |
100 LiveRange::LiveRange(int id, Zone* zone) | 110 LiveRange::LiveRange(int id, Zone* zone) |
101 : id_(id), | 111 : id_(id), |
102 spilled_(false), | 112 spilled_(false), |
103 is_phi_(false), | 113 is_phi_(false), |
104 is_non_loop_phi_(false), | 114 is_non_loop_phi_(false), |
105 kind_(UNALLOCATED_REGISTERS), | 115 kind_(UNALLOCATED_REGISTERS), |
106 assigned_register_(kInvalidAssignment), | 116 assigned_register_(kInvalidAssignment), |
107 last_interval_(NULL), | 117 last_interval_(nullptr), |
108 first_interval_(NULL), | 118 first_interval_(nullptr), |
109 first_pos_(NULL), | 119 first_pos_(nullptr), |
110 parent_(NULL), | 120 parent_(nullptr), |
111 next_(NULL), | 121 next_(nullptr), |
112 current_interval_(NULL), | 122 current_interval_(nullptr), |
113 last_processed_use_(NULL), | 123 last_processed_use_(nullptr), |
114 current_hint_operand_(NULL), | 124 current_hint_operand_(nullptr), |
115 spill_operand_(new (zone) InstructionOperand()), | |
116 spill_start_index_(kMaxInt), | 125 spill_start_index_(kMaxInt), |
117 spill_range_(NULL) {} | 126 spill_type_(SpillType::kNoSpillType), |
| 127 spill_operand_(nullptr), |
| 128 spills_at_definition_(nullptr) {} |
118 | 129 |
119 | 130 |
120 void LiveRange::set_assigned_register(int reg, Zone* zone) { | 131 void LiveRange::set_assigned_register(int reg) { |
121 DCHECK(!HasRegisterAssigned() && !IsSpilled()); | 132 DCHECK(!HasRegisterAssigned() && !IsSpilled()); |
122 assigned_register_ = reg; | 133 assigned_register_ = reg; |
123 if (spill_range_ == nullptr) { | |
124 ConvertOperands(zone); | |
125 } | |
126 } | 134 } |
127 | 135 |
128 | 136 |
129 void LiveRange::MakeSpilled(Zone* zone) { | 137 void LiveRange::MakeSpilled() { |
130 DCHECK(!IsSpilled()); | 138 DCHECK(!IsSpilled()); |
131 DCHECK(TopLevel()->HasAllocatedSpillOperand()); | 139 DCHECK(!TopLevel()->HasNoSpillType()); |
132 spilled_ = true; | 140 spilled_ = true; |
133 assigned_register_ = kInvalidAssignment; | 141 assigned_register_ = kInvalidAssignment; |
134 ConvertOperands(zone); | |
135 } | 142 } |
136 | 143 |
137 | 144 |
138 bool LiveRange::HasAllocatedSpillOperand() const { | 145 void LiveRange::SpillAtDefinition(Zone* zone, int gap_index, |
139 DCHECK(spill_operand_ != NULL); | 146 InstructionOperand* operand) { |
140 return !spill_operand_->IsIgnored() || spill_range_ != NULL; | 147 DCHECK(HasNoSpillType()); |
| 148 spills_at_definition_ = new (zone) |
| 149 SpillAtDefinitionList(gap_index, operand, spills_at_definition_); |
| 150 } |
| 151 |
| 152 |
| 153 void LiveRange::CommitSpillsAtDefinition(InstructionSequence* sequence, |
| 154 InstructionOperand* op) { |
| 155 auto to_spill = TopLevel()->spills_at_definition_; |
| 156 if (to_spill == nullptr) return; |
| 157 Zone* zone = sequence->zone(); |
| 158 for (; to_spill != nullptr; to_spill = to_spill->next) { |
| 159 auto gap = sequence->GapAt(to_spill->gap_index); |
| 160 auto move = gap->GetOrCreateParallelMove(GapInstruction::START, zone); |
| 161 move->AddMove(to_spill->operand, op, zone); |
| 162 } |
| 163 TopLevel()->spills_at_definition_ = nullptr; |
141 } | 164 } |
142 | 165 |
143 | 166 |
144 void LiveRange::SetSpillOperand(InstructionOperand* operand) { | 167 void LiveRange::SetSpillOperand(InstructionOperand* operand) { |
| 168 DCHECK(HasNoSpillType()); |
145 DCHECK(!operand->IsUnallocated()); | 169 DCHECK(!operand->IsUnallocated()); |
146 DCHECK(spill_operand_ != NULL); | 170 spill_type_ = SpillType::kSpillOperand; |
147 DCHECK(spill_operand_->IsIgnored()); | 171 spill_operand_ = operand; |
148 spill_operand_->ConvertTo(operand->kind(), operand->index()); | 172 } |
| 173 |
| 174 |
| 175 void LiveRange::SetSpillRange(SpillRange* spill_range) { |
| 176 DCHECK(HasNoSpillType() || HasSpillRange()); |
| 177 DCHECK_NE(spill_range, nullptr); |
| 178 spill_type_ = SpillType::kSpillRange; |
| 179 spill_range_ = spill_range; |
149 } | 180 } |
150 | 181 |
151 | 182 |
152 void LiveRange::CommitSpillOperand(InstructionOperand* operand) { | 183 void LiveRange::CommitSpillOperand(InstructionOperand* operand) { |
153 DCHECK(spill_range_ != NULL); | 184 DCHECK(HasSpillRange()); |
| 185 DCHECK(!operand->IsUnallocated()); |
154 DCHECK(!IsChild()); | 186 DCHECK(!IsChild()); |
155 spill_range_ = NULL; | 187 spill_type_ = SpillType::kSpillOperand; |
156 SetSpillOperand(operand); | 188 spill_operand_ = operand; |
157 for (LiveRange* range = this; range != NULL; range = range->next()) { | |
158 if (range->IsSpilled()) { | |
159 range->ConvertUsesToOperand(operand); | |
160 } | |
161 } | |
162 } | 189 } |
163 | 190 |
164 | 191 |
165 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) { | 192 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) { |
166 UsePosition* use_pos = last_processed_use_; | 193 UsePosition* use_pos = last_processed_use_; |
167 if (use_pos == NULL) use_pos = first_pos(); | 194 if (use_pos == NULL) use_pos = first_pos(); |
168 while (use_pos != NULL && use_pos->pos().Value() < start.Value()) { | 195 while (use_pos != NULL && use_pos->pos().Value() < start.Value()) { |
169 use_pos = use_pos->next(); | 196 use_pos = use_pos->next(); |
170 } | 197 } |
171 last_processed_use_ = use_pos; | 198 last_processed_use_ = use_pos; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 // We cannot spill a live range that has a use requiring a register | 235 // We cannot spill a live range that has a use requiring a register |
209 // at the current or the immediate next position. | 236 // at the current or the immediate next position. |
210 UsePosition* use_pos = NextRegisterPosition(pos); | 237 UsePosition* use_pos = NextRegisterPosition(pos); |
211 if (use_pos == NULL) return true; | 238 if (use_pos == NULL) return true; |
212 return use_pos->pos().Value() > | 239 return use_pos->pos().Value() > |
213 pos.NextInstruction().InstructionEnd().Value(); | 240 pos.NextInstruction().InstructionEnd().Value(); |
214 } | 241 } |
215 | 242 |
216 | 243 |
217 InstructionOperand* LiveRange::CreateAssignedOperand(Zone* zone) const { | 244 InstructionOperand* LiveRange::CreateAssignedOperand(Zone* zone) const { |
218 InstructionOperand* op = NULL; | 245 InstructionOperand* op = nullptr; |
219 if (HasRegisterAssigned()) { | 246 if (HasRegisterAssigned()) { |
220 DCHECK(!IsSpilled()); | 247 DCHECK(!IsSpilled()); |
221 switch (Kind()) { | 248 switch (Kind()) { |
222 case GENERAL_REGISTERS: | 249 case GENERAL_REGISTERS: |
223 op = RegisterOperand::Create(assigned_register(), zone); | 250 op = RegisterOperand::Create(assigned_register(), zone); |
224 break; | 251 break; |
225 case DOUBLE_REGISTERS: | 252 case DOUBLE_REGISTERS: |
226 op = DoubleRegisterOperand::Create(assigned_register(), zone); | 253 op = DoubleRegisterOperand::Create(assigned_register(), zone); |
227 break; | 254 break; |
228 default: | 255 default: |
229 UNREACHABLE(); | 256 UNREACHABLE(); |
230 } | 257 } |
231 } else if (IsSpilled()) { | 258 } else { |
| 259 DCHECK(IsSpilled()); |
232 DCHECK(!HasRegisterAssigned()); | 260 DCHECK(!HasRegisterAssigned()); |
233 op = TopLevel()->GetSpillOperand(); | 261 op = TopLevel()->GetSpillOperand(); |
234 DCHECK(!op->IsUnallocated()); | 262 DCHECK(!op->IsUnallocated()); |
235 } else { | |
236 UnallocatedOperand* unalloc = | |
237 new (zone) UnallocatedOperand(UnallocatedOperand::NONE); | |
238 unalloc->set_virtual_register(id_); | |
239 op = unalloc; | |
240 } | 263 } |
241 return op; | 264 return op; |
242 } | 265 } |
243 | 266 |
244 | 267 |
245 UseInterval* LiveRange::FirstSearchIntervalForPosition( | 268 UseInterval* LiveRange::FirstSearchIntervalForPosition( |
246 LifetimePosition position) const { | 269 LifetimePosition position) const { |
247 if (current_interval_ == NULL) return first_interval_; | 270 if (current_interval_ == NULL) return first_interval_; |
248 if (current_interval_->start().Value() > position.Value()) { | 271 if (current_interval_->start().Value() > position.Value()) { |
249 current_interval_ = NULL; | 272 current_interval_ = NULL; |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 if (use_pos->HasOperand()) { | 490 if (use_pos->HasOperand()) { |
468 DCHECK(op->IsRegister() || op->IsDoubleRegister() || | 491 DCHECK(op->IsRegister() || op->IsDoubleRegister() || |
469 !use_pos->RequiresRegister()); | 492 !use_pos->RequiresRegister()); |
470 use_pos->operand()->ConvertTo(op->kind(), op->index()); | 493 use_pos->operand()->ConvertTo(op->kind(), op->index()); |
471 } | 494 } |
472 use_pos = use_pos->next(); | 495 use_pos = use_pos->next(); |
473 } | 496 } |
474 } | 497 } |
475 | 498 |
476 | 499 |
477 void LiveRange::ConvertOperands(Zone* zone) { | |
478 ConvertUsesToOperand(CreateAssignedOperand(zone)); | |
479 } | |
480 | |
481 | |
482 bool LiveRange::CanCover(LifetimePosition position) const { | 500 bool LiveRange::CanCover(LifetimePosition position) const { |
483 if (IsEmpty()) return false; | 501 if (IsEmpty()) return false; |
484 return Start().Value() <= position.Value() && | 502 return Start().Value() <= position.Value() && |
485 position.Value() < End().Value(); | 503 position.Value() < End().Value(); |
486 } | 504 } |
487 | 505 |
488 | 506 |
489 bool LiveRange::Covers(LifetimePosition position) { | 507 bool LiveRange::Covers(LifetimePosition position) { |
490 if (!CanCover(position)) return false; | 508 if (!CanCover(position)) return false; |
491 UseInterval* start_search = FirstSearchIntervalForPosition(position); | 509 UseInterval* start_search = FirstSearchIntervalForPosition(position); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 spill_ranges_(8, local_zone()), | 566 spill_ranges_(8, local_zone()), |
549 mode_(UNALLOCATED_REGISTERS), | 567 mode_(UNALLOCATED_REGISTERS), |
550 num_registers_(-1), | 568 num_registers_(-1), |
551 allocation_ok_(true) { | 569 allocation_ok_(true) { |
552 DCHECK(this->config()->num_general_registers() <= | 570 DCHECK(this->config()->num_general_registers() <= |
553 RegisterConfiguration::kMaxGeneralRegisters); | 571 RegisterConfiguration::kMaxGeneralRegisters); |
554 DCHECK(this->config()->num_double_registers() <= | 572 DCHECK(this->config()->num_double_registers() <= |
555 RegisterConfiguration::kMaxDoubleRegisters); | 573 RegisterConfiguration::kMaxDoubleRegisters); |
556 // TryAllocateFreeReg and AllocateBlockedReg assume this | 574 // TryAllocateFreeReg and AllocateBlockedReg assume this |
557 // when allocating local arrays. | 575 // when allocating local arrays. |
558 DCHECK(this->config()->num_double_registers() >= | 576 DCHECK(RegisterConfiguration::kMaxDoubleRegisters >= |
559 this->config()->num_general_registers()); | 577 this->config()->num_general_registers()); |
560 assigned_registers_ = | 578 assigned_registers_ = |
561 new (code_zone()) BitVector(config->num_general_registers(), code_zone()); | 579 new (code_zone()) BitVector(config->num_general_registers(), code_zone()); |
562 assigned_double_registers_ = new (code_zone()) | 580 assigned_double_registers_ = new (code_zone()) |
563 BitVector(config->num_aliased_double_registers(), code_zone()); | 581 BitVector(config->num_aliased_double_registers(), code_zone()); |
564 frame->SetAllocatedRegisters(assigned_registers_); | 582 frame->SetAllocatedRegisters(assigned_registers_); |
565 frame->SetAllocatedDoubleRegisters(assigned_double_registers_); | 583 frame->SetAllocatedDoubleRegisters(assigned_double_registers_); |
566 } | 584 } |
567 | 585 |
568 | 586 |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
769 } | 787 } |
770 } | 788 } |
771 move->AddMove(from, to, code_zone()); | 789 move->AddMove(from, to, code_zone()); |
772 } | 790 } |
773 | 791 |
774 | 792 |
775 static bool AreUseIntervalsIntersecting(UseInterval* interval1, | 793 static bool AreUseIntervalsIntersecting(UseInterval* interval1, |
776 UseInterval* interval2) { | 794 UseInterval* interval2) { |
777 while (interval1 != NULL && interval2 != NULL) { | 795 while (interval1 != NULL && interval2 != NULL) { |
778 if (interval1->start().Value() < interval2->start().Value()) { | 796 if (interval1->start().Value() < interval2->start().Value()) { |
779 if (interval1->end().Value() >= interval2->start().Value()) { | 797 if (interval1->end().Value() > interval2->start().Value()) { |
780 return true; | 798 return true; |
781 } | 799 } |
782 interval1 = interval1->next(); | 800 interval1 = interval1->next(); |
783 } else { | 801 } else { |
784 if (interval2->end().Value() >= interval1->start().Value()) { | 802 if (interval2->end().Value() > interval1->start().Value()) { |
785 return true; | 803 return true; |
786 } | 804 } |
787 interval2 = interval2->next(); | 805 interval2 = interval2->next(); |
788 } | 806 } |
789 } | 807 } |
790 return false; | 808 return false; |
791 } | 809 } |
792 | 810 |
793 | 811 |
794 SpillRange::SpillRange(LiveRange* range, int id, Zone* zone) | 812 SpillRange::SpillRange(LiveRange* range, int id, Zone* zone) |
795 : id_(id), live_ranges_(1, zone), end_position_(range->End()) { | 813 : id_(id), live_ranges_(1, zone), end_position_(range->End()) { |
796 UseInterval* src = range->first_interval(); | 814 UseInterval* src = range->first_interval(); |
797 UseInterval* result = NULL; | 815 UseInterval* result = NULL; |
798 UseInterval* node = NULL; | 816 UseInterval* node = NULL; |
799 // Copy the nodes | 817 // Copy the nodes |
800 while (src != NULL) { | 818 while (src != NULL) { |
801 UseInterval* new_node = new (zone) UseInterval(src->start(), src->end()); | 819 UseInterval* new_node = new (zone) UseInterval(src->start(), src->end()); |
802 if (result == NULL) { | 820 if (result == NULL) { |
803 result = new_node; | 821 result = new_node; |
804 } else { | 822 } else { |
805 node->set_next(new_node); | 823 node->set_next(new_node); |
806 } | 824 } |
807 node = new_node; | 825 node = new_node; |
808 src = src->next(); | 826 src = src->next(); |
809 } | 827 } |
810 use_interval_ = result; | 828 use_interval_ = result; |
811 live_ranges_.Add(range, zone); | 829 live_ranges_.Add(range, zone); |
812 DCHECK(range->GetSpillRange() == NULL); | 830 DCHECK(!range->HasSpillRange()); |
813 range->SetSpillRange(this); | 831 range->SetSpillRange(this); |
814 } | 832 } |
815 | 833 |
816 | 834 |
817 bool SpillRange::IsIntersectingWith(SpillRange* other) { | 835 bool SpillRange::IsIntersectingWith(SpillRange* other) { |
818 if (End().Value() <= other->use_interval_->start().Value() || | 836 if (End().Value() <= other->use_interval_->start().Value() || |
819 other->End().Value() <= use_interval_->start().Value()) { | 837 other->End().Value() <= use_interval_->start().Value()) { |
820 return false; | 838 return false; |
821 } | 839 } |
822 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_); | 840 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
891 SpillRange* other = spill_ranges_.at(j); | 909 SpillRange* other = spill_ranges_.at(j); |
892 if (!other->IsEmpty()) { | 910 if (!other->IsEmpty()) { |
893 range->TryMerge(spill_ranges_.at(j), local_zone()); | 911 range->TryMerge(spill_ranges_.at(j), local_zone()); |
894 } | 912 } |
895 } | 913 } |
896 } | 914 } |
897 } | 915 } |
898 | 916 |
899 // Allocate slots for the merged spill ranges. | 917 // Allocate slots for the merged spill ranges. |
900 for (int i = 0; i < spill_ranges_.length(); i++) { | 918 for (int i = 0; i < spill_ranges_.length(); i++) { |
901 SpillRange* range = spill_ranges_.at(i); | 919 auto range = spill_ranges_.at(i); |
902 if (!range->IsEmpty()) { | 920 if (range->IsEmpty()) continue; |
903 // Allocate a new operand referring to the spill slot. | 921 // Allocate a new operand referring to the spill slot. |
904 RegisterKind kind = range->Kind(); | 922 auto kind = range->Kind(); |
905 int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS); | 923 int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS); |
906 InstructionOperand* op = nullptr; | 924 auto op_kind = kind == DOUBLE_REGISTERS |
907 if (kind == DOUBLE_REGISTERS) { | 925 ? InstructionOperand::DOUBLE_STACK_SLOT |
908 op = DoubleStackSlotOperand::Create(index, local_zone()); | 926 : InstructionOperand::STACK_SLOT; |
909 } else { | 927 auto op = new (code_zone()) InstructionOperand(op_kind, index); |
910 DCHECK(kind == GENERAL_REGISTERS); | 928 range->SetOperand(op); |
911 op = StackSlotOperand::Create(index, local_zone()); | 929 } |
912 } | 930 } |
913 range->SetOperand(op); | 931 |
| 932 |
| 933 void RegisterAllocator::CommitAssignment() { |
| 934 for (auto range : live_ranges()) { |
| 935 if (range == nullptr || range->IsEmpty()) continue; |
| 936 auto assigned = range->CreateAssignedOperand(code_zone()); |
| 937 range->ConvertUsesToOperand(assigned); |
| 938 if (range->IsSpilled()) { |
| 939 range->CommitSpillsAtDefinition(code(), assigned); |
914 } | 940 } |
915 } | 941 } |
916 } | 942 } |
917 | 943 |
918 | 944 |
919 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) { | 945 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) { |
920 DCHECK(FLAG_turbo_reuse_spill_slots); | 946 DCHECK(FLAG_turbo_reuse_spill_slots); |
921 int spill_id = spill_ranges_.length(); | 947 int spill_id = spill_ranges_.length(); |
922 SpillRange* spill_range = | 948 SpillRange* spill_range = |
923 new (local_zone()) SpillRange(range, spill_id, local_zone()); | 949 new (local_zone()) SpillRange(range, spill_id, local_zone()); |
924 spill_ranges_.Add(spill_range, local_zone()); | 950 spill_ranges_.Add(spill_range, local_zone()); |
925 return spill_range; | 951 return spill_range; |
926 } | 952 } |
927 | 953 |
928 | 954 |
929 bool RegisterAllocator::TryReuseSpillForPhi(LiveRange* range) { | 955 bool RegisterAllocator::TryReuseSpillForPhi(LiveRange* range) { |
930 DCHECK(FLAG_turbo_reuse_spill_slots); | 956 DCHECK(FLAG_turbo_reuse_spill_slots); |
931 DCHECK(!range->HasAllocatedSpillOperand()); | 957 DCHECK(range->HasNoSpillType()); |
932 if (range->IsChild() || !range->is_phi()) return false; | 958 if (range->IsChild() || !range->is_phi()) return false; |
933 | 959 |
934 auto lookup = phi_map_.find(range->id()); | 960 auto lookup = phi_map_.find(range->id()); |
935 DCHECK(lookup != phi_map_.end()); | 961 DCHECK(lookup != phi_map_.end()); |
936 auto phi = lookup->second.phi; | 962 auto phi = lookup->second.phi; |
937 auto block = lookup->second.block; | 963 auto block = lookup->second.block; |
938 // Count the number of spilled operands. | 964 // Count the number of spilled operands. |
939 size_t spilled_count = 0; | 965 size_t spilled_count = 0; |
940 LiveRange* first_op = nullptr; | 966 LiveRange* first_op = nullptr; |
941 for (size_t i = 0; i < phi->operands().size(); i++) { | 967 for (size_t i = 0; i < phi->operands().size(); i++) { |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1040 InstructionOperand* output_operand = last_instruction->OutputAt(i); | 1066 InstructionOperand* output_operand = last_instruction->OutputAt(i); |
1041 DCHECK(!output_operand->IsConstant()); | 1067 DCHECK(!output_operand->IsConstant()); |
1042 UnallocatedOperand* output = UnallocatedOperand::cast(output_operand); | 1068 UnallocatedOperand* output = UnallocatedOperand::cast(output_operand); |
1043 int output_vreg = output->virtual_register(); | 1069 int output_vreg = output->virtual_register(); |
1044 LiveRange* range = LiveRangeFor(output_vreg); | 1070 LiveRange* range = LiveRangeFor(output_vreg); |
1045 bool assigned = false; | 1071 bool assigned = false; |
1046 if (output->HasFixedPolicy()) { | 1072 if (output->HasFixedPolicy()) { |
1047 AllocateFixed(output, -1, false); | 1073 AllocateFixed(output, -1, false); |
1048 // This value is produced on the stack, we never need to spill it. | 1074 // This value is produced on the stack, we never need to spill it. |
1049 if (output->IsStackSlot()) { | 1075 if (output->IsStackSlot()) { |
| 1076 DCHECK(output->index() < 0); |
1050 range->SetSpillOperand(output); | 1077 range->SetSpillOperand(output); |
1051 range->SetSpillStartIndex(end); | 1078 range->SetSpillStartIndex(end); |
1052 assigned = true; | 1079 assigned = true; |
1053 } | 1080 } |
1054 | 1081 |
1055 for (auto succ : block->successors()) { | 1082 for (auto succ : block->successors()) { |
1056 const InstructionBlock* successor = code()->InstructionBlockAt(succ); | 1083 const InstructionBlock* successor = code()->InstructionBlockAt(succ); |
1057 DCHECK(successor->PredecessorCount() == 1); | 1084 DCHECK(successor->PredecessorCount() == 1); |
1058 int gap_index = successor->first_instruction_index() + 1; | 1085 int gap_index = successor->first_instruction_index() + 1; |
1059 DCHECK(code()->IsGapAt(gap_index)); | 1086 DCHECK(code()->IsGapAt(gap_index)); |
1060 | 1087 |
1061 // Create an unconstrained operand for the same virtual register | 1088 // Create an unconstrained operand for the same virtual register |
1062 // and insert a gap move from the fixed output to the operand. | 1089 // and insert a gap move from the fixed output to the operand. |
1063 UnallocatedOperand* output_copy = | 1090 UnallocatedOperand* output_copy = |
1064 new (code_zone()) UnallocatedOperand(UnallocatedOperand::ANY); | 1091 new (code_zone()) UnallocatedOperand(UnallocatedOperand::ANY); |
1065 output_copy->set_virtual_register(output_vreg); | 1092 output_copy->set_virtual_register(output_vreg); |
1066 | 1093 |
1067 code()->AddGapMove(gap_index, output, output_copy); | 1094 code()->AddGapMove(gap_index, output, output_copy); |
1068 } | 1095 } |
1069 } | 1096 } |
1070 | 1097 |
1071 if (!assigned) { | 1098 if (!assigned) { |
1072 for (auto succ : block->successors()) { | 1099 for (auto succ : block->successors()) { |
1073 const InstructionBlock* successor = code()->InstructionBlockAt(succ); | 1100 const InstructionBlock* successor = code()->InstructionBlockAt(succ); |
1074 DCHECK(successor->PredecessorCount() == 1); | 1101 DCHECK(successor->PredecessorCount() == 1); |
1075 int gap_index = successor->first_instruction_index() + 1; | 1102 int gap_index = successor->first_instruction_index() + 1; |
| 1103 range->SpillAtDefinition(local_zone(), gap_index, output); |
1076 range->SetSpillStartIndex(gap_index); | 1104 range->SetSpillStartIndex(gap_index); |
1077 | |
1078 // This move to spill operand is not a real use. Liveness analysis | |
1079 // and splitting of live ranges do not account for it. | |
1080 // Thus it should be inserted to a lifetime position corresponding to | |
1081 // the instruction end. | |
1082 GapInstruction* gap = code()->GapAt(gap_index); | |
1083 ParallelMove* move = | |
1084 gap->GetOrCreateParallelMove(GapInstruction::BEFORE, code_zone()); | |
1085 move->AddMove(output, range->GetSpillOperand(), code_zone()); | |
1086 } | 1105 } |
1087 } | 1106 } |
1088 } | 1107 } |
1089 } | 1108 } |
1090 | 1109 |
1091 | 1110 |
1092 void RegisterAllocator::MeetConstraintsBetween(Instruction* first, | 1111 void RegisterAllocator::MeetConstraintsBetween(Instruction* first, |
1093 Instruction* second, | 1112 Instruction* second, |
1094 int gap_index) { | 1113 int gap_index) { |
1095 if (first != NULL) { | 1114 if (first != NULL) { |
(...skipping 18 matching lines...) Expand all Loading... |
1114 LiveRange* range = LiveRangeFor(first_output->virtual_register()); | 1133 LiveRange* range = LiveRangeFor(first_output->virtual_register()); |
1115 bool assigned = false; | 1134 bool assigned = false; |
1116 if (first_output->HasFixedPolicy()) { | 1135 if (first_output->HasFixedPolicy()) { |
1117 UnallocatedOperand* output_copy = | 1136 UnallocatedOperand* output_copy = |
1118 first_output->CopyUnconstrained(code_zone()); | 1137 first_output->CopyUnconstrained(code_zone()); |
1119 bool is_tagged = HasTaggedValue(first_output->virtual_register()); | 1138 bool is_tagged = HasTaggedValue(first_output->virtual_register()); |
1120 AllocateFixed(first_output, gap_index, is_tagged); | 1139 AllocateFixed(first_output, gap_index, is_tagged); |
1121 | 1140 |
1122 // This value is produced on the stack, we never need to spill it. | 1141 // This value is produced on the stack, we never need to spill it. |
1123 if (first_output->IsStackSlot()) { | 1142 if (first_output->IsStackSlot()) { |
| 1143 DCHECK(first_output->index() < 0); |
1124 range->SetSpillOperand(first_output); | 1144 range->SetSpillOperand(first_output); |
1125 range->SetSpillStartIndex(gap_index - 1); | 1145 range->SetSpillStartIndex(gap_index - 1); |
1126 assigned = true; | 1146 assigned = true; |
1127 } | 1147 } |
1128 code()->AddGapMove(gap_index, first_output, output_copy); | 1148 code()->AddGapMove(gap_index, first_output, output_copy); |
1129 } | 1149 } |
1130 | 1150 |
1131 // Make sure we add a gap move for spilling (if we have not done | 1151 // Make sure we add a gap move for spilling (if we have not done |
1132 // so already). | 1152 // so already). |
1133 if (!assigned) { | 1153 if (!assigned) { |
| 1154 range->SpillAtDefinition(local_zone(), gap_index, first_output); |
1134 range->SetSpillStartIndex(gap_index); | 1155 range->SetSpillStartIndex(gap_index); |
1135 | |
1136 // This move to spill operand is not a real use. Liveness analysis | |
1137 // and splitting of live ranges do not account for it. | |
1138 // Thus it should be inserted to a lifetime position corresponding to | |
1139 // the instruction end. | |
1140 GapInstruction* gap = code()->GapAt(gap_index); | |
1141 ParallelMove* move = | |
1142 gap->GetOrCreateParallelMove(GapInstruction::BEFORE, code_zone()); | |
1143 move->AddMove(first_output, range->GetSpillOperand(), code_zone()); | |
1144 } | 1156 } |
1145 } | 1157 } |
1146 } | 1158 } |
1147 } | 1159 } |
1148 | 1160 |
1149 if (second != NULL) { | 1161 if (second != NULL) { |
1150 // Handle fixed input operands of second instruction. | 1162 // Handle fixed input operands of second instruction. |
1151 for (size_t i = 0; i < second->InputCount(); i++) { | 1163 for (size_t i = 0; i < second->InputCount(); i++) { |
1152 InstructionOperand* input = second->InputAt(i); | 1164 InstructionOperand* input = second->InputAt(i); |
1153 if (input->IsImmediate()) continue; // Ignore immediates. | 1165 if (input->IsImmediate()) continue; // Ignore immediates. |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1234 if (instr->IsGapMoves()) { | 1246 if (instr->IsGapMoves()) { |
1235 // Process the moves of the gap instruction, making their sources live. | 1247 // Process the moves of the gap instruction, making their sources live. |
1236 GapInstruction* gap = code()->GapAt(index); | 1248 GapInstruction* gap = code()->GapAt(index); |
1237 | 1249 |
1238 // TODO(titzer): no need to create the parallel move if it doesn't exist. | 1250 // TODO(titzer): no need to create the parallel move if it doesn't exist. |
1239 ParallelMove* move = | 1251 ParallelMove* move = |
1240 gap->GetOrCreateParallelMove(GapInstruction::START, code_zone()); | 1252 gap->GetOrCreateParallelMove(GapInstruction::START, code_zone()); |
1241 const ZoneList<MoveOperands>* move_operands = move->move_operands(); | 1253 const ZoneList<MoveOperands>* move_operands = move->move_operands(); |
1242 for (int i = 0; i < move_operands->length(); ++i) { | 1254 for (int i = 0; i < move_operands->length(); ++i) { |
1243 MoveOperands* cur = &move_operands->at(i); | 1255 MoveOperands* cur = &move_operands->at(i); |
1244 if (cur->IsIgnored()) continue; | |
1245 InstructionOperand* from = cur->source(); | 1256 InstructionOperand* from = cur->source(); |
1246 InstructionOperand* to = cur->destination(); | 1257 InstructionOperand* to = cur->destination(); |
1247 InstructionOperand* hint = to; | 1258 InstructionOperand* hint = to; |
1248 if (to->IsUnallocated()) { | 1259 if (to->IsUnallocated()) { |
1249 int to_vreg = UnallocatedOperand::cast(to)->virtual_register(); | 1260 int to_vreg = UnallocatedOperand::cast(to)->virtual_register(); |
1250 LiveRange* to_range = LiveRangeFor(to_vreg); | 1261 LiveRange* to_range = LiveRangeFor(to_vreg); |
1251 if (to_range->is_phi()) { | 1262 if (to_range->is_phi()) { |
1252 DCHECK(!FLAG_turbo_delay_ssa_decon); | 1263 DCHECK(!FLAG_turbo_delay_ssa_decon); |
1253 if (to_range->is_non_loop_phi()) { | 1264 if (to_range->is_non_loop_phi()) { |
1254 hint = to_range->current_hint_operand(); | 1265 hint = to_range->current_hint_operand(); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1356 code()->InstructionBlockAt(block->predecessors()[i]); | 1367 code()->InstructionBlockAt(block->predecessors()[i]); |
1357 // The gap move must be added without any special processing as in | 1368 // The gap move must be added without any special processing as in |
1358 // the AddConstraintsGapMove. | 1369 // the AddConstraintsGapMove. |
1359 code()->AddGapMove(cur_block->last_instruction_index() - 1, | 1370 code()->AddGapMove(cur_block->last_instruction_index() - 1, |
1360 phi->inputs()[i], output); | 1371 phi->inputs()[i], output); |
1361 DCHECK(!InstructionAt(cur_block->last_instruction_index()) | 1372 DCHECK(!InstructionAt(cur_block->last_instruction_index()) |
1362 ->HasPointerMap()); | 1373 ->HasPointerMap()); |
1363 } | 1374 } |
1364 } | 1375 } |
1365 LiveRange* live_range = LiveRangeFor(phi_vreg); | 1376 LiveRange* live_range = LiveRangeFor(phi_vreg); |
1366 BlockStartInstruction* block_start = | 1377 int gap_index = block->first_instruction_index(); |
1367 code()->GetBlockStart(block->rpo_number()); | 1378 live_range->SpillAtDefinition(local_zone(), gap_index, output); |
1368 block_start->GetOrCreateParallelMove(GapInstruction::BEFORE, code_zone()) | 1379 live_range->SetSpillStartIndex(gap_index); |
1369 ->AddMove(output, live_range->GetSpillOperand(), code_zone()); | |
1370 live_range->SetSpillStartIndex(block->first_instruction_index()); | |
1371 // We use the phi-ness of some nodes in some later heuristics. | 1380 // We use the phi-ness of some nodes in some later heuristics. |
1372 live_range->set_is_phi(true); | 1381 live_range->set_is_phi(true); |
1373 if (!block->IsLoopHeader()) { | 1382 if (!block->IsLoopHeader()) { |
1374 live_range->set_is_non_loop_phi(true); | 1383 live_range->set_is_non_loop_phi(true); |
1375 } | 1384 } |
1376 } | 1385 } |
1377 } | 1386 } |
1378 | 1387 |
1379 | 1388 |
1380 void RegisterAllocator::MeetRegisterConstraints() { | 1389 void RegisterAllocator::MeetRegisterConstraints() { |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1735 | 1744 |
1736 for (size_t i = 0; i < live_ranges_.size(); ++i) { | 1745 for (size_t i = 0; i < live_ranges_.size(); ++i) { |
1737 if (live_ranges_[i] != NULL) { | 1746 if (live_ranges_[i] != NULL) { |
1738 live_ranges_[i]->kind_ = RequiredRegisterKind(live_ranges_[i]->id()); | 1747 live_ranges_[i]->kind_ = RequiredRegisterKind(live_ranges_[i]->id()); |
1739 | 1748 |
1740 // TODO(bmeurer): This is a horrible hack to make sure that for constant | 1749 // TODO(bmeurer): This is a horrible hack to make sure that for constant |
1741 // live ranges, every use requires the constant to be in a register. | 1750 // live ranges, every use requires the constant to be in a register. |
1742 // Without this hack, all uses with "any" policy would get the constant | 1751 // Without this hack, all uses with "any" policy would get the constant |
1743 // operand assigned. | 1752 // operand assigned. |
1744 LiveRange* range = live_ranges_[i]; | 1753 LiveRange* range = live_ranges_[i]; |
1745 if (range->HasAllocatedSpillOperand() && | 1754 if (range->HasSpillOperand() && range->GetSpillOperand()->IsConstant()) { |
1746 range->GetSpillOperand()->IsConstant()) { | |
1747 for (UsePosition* pos = range->first_pos(); pos != NULL; | 1755 for (UsePosition* pos = range->first_pos(); pos != NULL; |
1748 pos = pos->next_) { | 1756 pos = pos->next_) { |
1749 pos->register_beneficial_ = true; | 1757 pos->register_beneficial_ = true; |
1750 // TODO(dcarney): should the else case assert requires_reg_ == false? | 1758 // TODO(dcarney): should the else case assert requires_reg_ == false? |
1751 // Can't mark phis as needing a register. | 1759 // Can't mark phis as needing a register. |
1752 if (!code() | 1760 if (!code() |
1753 ->InstructionAt(pos->pos().InstructionIndex()) | 1761 ->InstructionAt(pos->pos().InstructionIndex()) |
1754 ->IsGapMoves()) { | 1762 ->IsGapMoves()) { |
1755 pos->requires_reg_ = true; | 1763 pos->requires_reg_ = true; |
1756 } | 1764 } |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1848 LifetimePosition safe_point_pos = | 1856 LifetimePosition safe_point_pos = |
1849 LifetimePosition::FromInstructionIndex(safe_point); | 1857 LifetimePosition::FromInstructionIndex(safe_point); |
1850 LiveRange* cur = range; | 1858 LiveRange* cur = range; |
1851 while (cur != NULL && !cur->Covers(safe_point_pos)) { | 1859 while (cur != NULL && !cur->Covers(safe_point_pos)) { |
1852 cur = cur->next(); | 1860 cur = cur->next(); |
1853 } | 1861 } |
1854 if (cur == NULL) continue; | 1862 if (cur == NULL) continue; |
1855 | 1863 |
1856 // Check if the live range is spilled and the safe point is after | 1864 // Check if the live range is spilled and the safe point is after |
1857 // the spill position. | 1865 // the spill position. |
1858 if (range->HasAllocatedSpillOperand() && | 1866 if (range->HasSpillOperand() && |
1859 safe_point >= range->spill_start_index() && | 1867 safe_point >= range->spill_start_index() && |
1860 !range->GetSpillOperand()->IsConstant()) { | 1868 !range->GetSpillOperand()->IsConstant()) { |
1861 TraceAlloc("Pointer for range %d (spilled at %d) at safe point %d\n", | 1869 TraceAlloc("Pointer for range %d (spilled at %d) at safe point %d\n", |
1862 range->id(), range->spill_start_index(), safe_point); | 1870 range->id(), range->spill_start_index(), safe_point); |
1863 map->RecordPointer(range->GetSpillOperand(), code_zone()); | 1871 map->RecordPointer(range->GetSpillOperand(), code_zone()); |
1864 } | 1872 } |
1865 | 1873 |
1866 if (!cur->IsSpilled()) { | 1874 if (!cur->IsSpilled()) { |
1867 TraceAlloc( | 1875 TraceAlloc( |
1868 "Pointer in register for range %d (start at %d) " | 1876 "Pointer in register for range %d (start at %d) " |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1928 DCHECK(UnhandledIsSorted()); | 1936 DCHECK(UnhandledIsSorted()); |
1929 LiveRange* current = unhandled_live_ranges_.RemoveLast(); | 1937 LiveRange* current = unhandled_live_ranges_.RemoveLast(); |
1930 DCHECK(UnhandledIsSorted()); | 1938 DCHECK(UnhandledIsSorted()); |
1931 LifetimePosition position = current->Start(); | 1939 LifetimePosition position = current->Start(); |
1932 #ifdef DEBUG | 1940 #ifdef DEBUG |
1933 allocation_finger_ = position; | 1941 allocation_finger_ = position; |
1934 #endif | 1942 #endif |
1935 TraceAlloc("Processing interval %d start=%d\n", current->id(), | 1943 TraceAlloc("Processing interval %d start=%d\n", current->id(), |
1936 position.Value()); | 1944 position.Value()); |
1937 | 1945 |
1938 if (current->HasAllocatedSpillOperand()) { | 1946 if (!current->HasNoSpillType()) { |
1939 TraceAlloc("Live range %d already has a spill operand\n", current->id()); | 1947 TraceAlloc("Live range %d already has a spill operand\n", current->id()); |
1940 LifetimePosition next_pos = position; | 1948 LifetimePosition next_pos = position; |
1941 if (code()->IsGapAt(next_pos.InstructionIndex())) { | 1949 if (code()->IsGapAt(next_pos.InstructionIndex())) { |
1942 next_pos = next_pos.NextInstruction(); | 1950 next_pos = next_pos.NextInstruction(); |
1943 } | 1951 } |
1944 UsePosition* pos = current->NextUsePositionRegisterIsBeneficial(next_pos); | 1952 UsePosition* pos = current->NextUsePositionRegisterIsBeneficial(next_pos); |
1945 // If the range already has a spill operand and it doesn't need a | 1953 // If the range already has a spill operand and it doesn't need a |
1946 // register immediately, split it and spill the first part of the range. | 1954 // register immediately, split it and spill the first part of the range. |
1947 if (pos == NULL) { | 1955 if (pos == NULL) { |
1948 Spill(current); | 1956 Spill(current); |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2093 } | 2101 } |
2094 return true; | 2102 return true; |
2095 } | 2103 } |
2096 | 2104 |
2097 | 2105 |
2098 void RegisterAllocator::FreeSpillSlot(LiveRange* range) { | 2106 void RegisterAllocator::FreeSpillSlot(LiveRange* range) { |
2099 DCHECK(!FLAG_turbo_reuse_spill_slots); | 2107 DCHECK(!FLAG_turbo_reuse_spill_slots); |
2100 // Check that we are the last range. | 2108 // Check that we are the last range. |
2101 if (range->next() != NULL) return; | 2109 if (range->next() != NULL) return; |
2102 | 2110 |
2103 if (!range->TopLevel()->HasAllocatedSpillOperand()) return; | 2111 if (!range->TopLevel()->HasSpillOperand()) return; |
2104 | 2112 |
2105 InstructionOperand* spill_operand = range->TopLevel()->GetSpillOperand(); | 2113 InstructionOperand* spill_operand = range->TopLevel()->GetSpillOperand(); |
2106 if (spill_operand->IsConstant()) return; | 2114 if (spill_operand->IsConstant()) return; |
2107 if (spill_operand->index() >= 0) { | 2115 if (spill_operand->index() >= 0) { |
2108 reusable_slots_.Add(range, local_zone()); | 2116 reusable_slots_.Add(range, local_zone()); |
2109 } | 2117 } |
2110 } | 2118 } |
2111 | 2119 |
2112 | 2120 |
2113 InstructionOperand* RegisterAllocator::TryReuseSpillSlot(LiveRange* range) { | 2121 InstructionOperand* RegisterAllocator::TryReuseSpillSlot(LiveRange* range) { |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2233 | 2241 |
2234 void RegisterAllocator::AllocateBlockedReg(LiveRange* current) { | 2242 void RegisterAllocator::AllocateBlockedReg(LiveRange* current) { |
2235 UsePosition* register_use = current->NextRegisterPosition(current->Start()); | 2243 UsePosition* register_use = current->NextRegisterPosition(current->Start()); |
2236 if (register_use == NULL) { | 2244 if (register_use == NULL) { |
2237 // There is no use in the current live range that requires a register. | 2245 // There is no use in the current live range that requires a register. |
2238 // We can just spill it. | 2246 // We can just spill it. |
2239 Spill(current); | 2247 Spill(current); |
2240 return; | 2248 return; |
2241 } | 2249 } |
2242 | 2250 |
2243 LifetimePosition use_pos[RegisterConfiguration::kMaxGeneralRegisters]; | 2251 LifetimePosition use_pos[RegisterConfiguration::kMaxDoubleRegisters]; |
2244 LifetimePosition block_pos[RegisterConfiguration::kMaxDoubleRegisters]; | 2252 LifetimePosition block_pos[RegisterConfiguration::kMaxDoubleRegisters]; |
2245 | 2253 |
2246 for (int i = 0; i < num_registers_; i++) { | 2254 for (int i = 0; i < num_registers_; i++) { |
2247 use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition(); | 2255 use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition(); |
2248 } | 2256 } |
2249 | 2257 |
2250 for (int i = 0; i < active_live_ranges_.length(); ++i) { | 2258 for (int i = 0; i < active_live_ranges_.length(); ++i) { |
2251 LiveRange* range = active_live_ranges_[i]; | 2259 LiveRange* range = active_live_ranges_[i]; |
2252 int cur_reg = range->assigned_register(); | 2260 int cur_reg = range->assigned_register(); |
2253 if (range->IsFixed() || !range->CanBeSpilled(current->Start())) { | 2261 if (range->IsFixed() || !range->CanBeSpilled(current->Start())) { |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2520 // Nothing to spill. Just put it to unhandled as whole. | 2528 // Nothing to spill. Just put it to unhandled as whole. |
2521 AddToUnhandledSorted(second_part); | 2529 AddToUnhandledSorted(second_part); |
2522 } | 2530 } |
2523 } | 2531 } |
2524 | 2532 |
2525 | 2533 |
2526 void RegisterAllocator::Spill(LiveRange* range) { | 2534 void RegisterAllocator::Spill(LiveRange* range) { |
2527 DCHECK(!range->IsSpilled()); | 2535 DCHECK(!range->IsSpilled()); |
2528 TraceAlloc("Spilling live range %d\n", range->id()); | 2536 TraceAlloc("Spilling live range %d\n", range->id()); |
2529 LiveRange* first = range->TopLevel(); | 2537 LiveRange* first = range->TopLevel(); |
2530 | 2538 if (first->HasNoSpillType()) { |
2531 if (!first->HasAllocatedSpillOperand()) { | |
2532 if (FLAG_turbo_reuse_spill_slots) { | 2539 if (FLAG_turbo_reuse_spill_slots) { |
2533 AssignSpillRangeToLiveRange(first); | 2540 AssignSpillRangeToLiveRange(first); |
2534 } else { | 2541 } else { |
2535 InstructionOperand* op = TryReuseSpillSlot(range); | 2542 InstructionOperand* op = TryReuseSpillSlot(range); |
2536 if (op == NULL) { | 2543 if (op == NULL) { |
2537 // Allocate a new operand referring to the spill slot. | 2544 // Allocate a new operand referring to the spill slot. |
2538 RegisterKind kind = range->Kind(); | 2545 RegisterKind kind = range->Kind(); |
2539 int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS); | 2546 int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS); |
2540 if (kind == DOUBLE_REGISTERS) { | 2547 auto op_kind = kind == DOUBLE_REGISTERS |
2541 op = DoubleStackSlotOperand::Create(index, local_zone()); | 2548 ? InstructionOperand::DOUBLE_STACK_SLOT |
2542 } else { | 2549 : InstructionOperand::STACK_SLOT; |
2543 DCHECK(kind == GENERAL_REGISTERS); | 2550 op = new (code_zone()) InstructionOperand(op_kind, index); |
2544 op = StackSlotOperand::Create(index, local_zone()); | |
2545 } | |
2546 } | 2551 } |
2547 first->SetSpillOperand(op); | 2552 first->SetSpillOperand(op); |
2548 } | 2553 } |
2549 } | 2554 } |
2550 range->MakeSpilled(code_zone()); | 2555 range->MakeSpilled(); |
2551 } | 2556 } |
2552 | 2557 |
2553 | 2558 |
2554 int RegisterAllocator::RegisterCount() const { return num_registers_; } | 2559 int RegisterAllocator::RegisterCount() const { return num_registers_; } |
2555 | 2560 |
2556 | 2561 |
2557 #ifdef DEBUG | 2562 #ifdef DEBUG |
2558 | 2563 |
2559 | 2564 |
2560 void RegisterAllocator::Verify() const { | 2565 void RegisterAllocator::Verify() const { |
2561 for (auto current : live_ranges()) { | 2566 for (auto current : live_ranges()) { |
2562 if (current != NULL) current->Verify(); | 2567 if (current != NULL) current->Verify(); |
2563 } | 2568 } |
2564 } | 2569 } |
2565 | 2570 |
2566 | 2571 |
2567 #endif | 2572 #endif |
2568 | 2573 |
2569 | 2574 |
2570 void RegisterAllocator::SetLiveRangeAssignedRegister(LiveRange* range, | 2575 void RegisterAllocator::SetLiveRangeAssignedRegister(LiveRange* range, |
2571 int reg) { | 2576 int reg) { |
2572 if (range->Kind() == DOUBLE_REGISTERS) { | 2577 if (range->Kind() == DOUBLE_REGISTERS) { |
2573 assigned_double_registers_->Add(reg); | 2578 assigned_double_registers_->Add(reg); |
2574 } else { | 2579 } else { |
2575 DCHECK(range->Kind() == GENERAL_REGISTERS); | 2580 DCHECK(range->Kind() == GENERAL_REGISTERS); |
2576 assigned_registers_->Add(reg); | 2581 assigned_registers_->Add(reg); |
2577 } | 2582 } |
2578 range->set_assigned_register(reg, code_zone()); | 2583 range->set_assigned_register(reg); |
2579 } | 2584 } |
2580 | 2585 |
2581 } // namespace compiler | 2586 } // namespace compiler |
2582 } // namespace internal | 2587 } // namespace internal |
2583 } // namespace v8 | 2588 } // namespace v8 |
OLD | NEW |