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/base/adapters.h" | 5 #include "src/base/adapters.h" |
6 #include "src/compiler/linkage.h" | 6 #include "src/compiler/linkage.h" |
7 #include "src/compiler/register-allocator.h" | 7 #include "src/compiler/register-allocator.h" |
8 #include "src/string-stream.h" | 8 #include "src/string-stream.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 } | 105 } |
106 | 106 |
107 | 107 |
108 void UsePosition::set_type(UsePositionType type, bool register_beneficial) { | 108 void UsePosition::set_type(UsePositionType type, bool register_beneficial) { |
109 DCHECK_IMPLIES(type == UsePositionType::kRequiresSlot, !register_beneficial); | 109 DCHECK_IMPLIES(type == UsePositionType::kRequiresSlot, !register_beneficial); |
110 flags_ = TypeField::encode(type) | | 110 flags_ = TypeField::encode(type) | |
111 RegisterBeneficialField::encode(register_beneficial); | 111 RegisterBeneficialField::encode(register_beneficial); |
112 } | 112 } |
113 | 113 |
114 | 114 |
115 void UseInterval::SplitAt(LifetimePosition pos, Zone* zone) { | 115 UseInterval* UseInterval::SplitAt(LifetimePosition pos, Zone* zone) { |
116 DCHECK(Contains(pos) && pos.Value() != start().Value()); | 116 DCHECK(Contains(pos) && pos.Value() != start().Value()); |
117 auto after = new (zone) UseInterval(pos, end_); | 117 auto after = new (zone) UseInterval(pos, end_); |
118 after->next_ = next_; | 118 after->next_ = next_; |
119 next_ = after; | 119 next_ = nullptr; |
120 end_ = pos; | 120 end_ = pos; |
| 121 return after; |
121 } | 122 } |
122 | 123 |
123 | 124 |
124 struct LiveRange::SpillAtDefinitionList : ZoneObject { | 125 struct LiveRange::SpillAtDefinitionList : ZoneObject { |
125 SpillAtDefinitionList(int gap_index, InstructionOperand* operand, | 126 SpillAtDefinitionList(int gap_index, InstructionOperand* operand, |
126 SpillAtDefinitionList* next) | 127 SpillAtDefinitionList* next) |
127 : gap_index(gap_index), operand(operand), next(next) {} | 128 : gap_index(gap_index), operand(operand), next(next) {} |
128 const int gap_index; | 129 const int gap_index; |
129 InstructionOperand* const operand; | 130 InstructionOperand* const operand; |
130 SpillAtDefinitionList* const next; | 131 SpillAtDefinitionList* const next; |
(...skipping 16 matching lines...) Expand all Loading... |
147 current_interval_(nullptr), | 148 current_interval_(nullptr), |
148 last_processed_use_(nullptr), | 149 last_processed_use_(nullptr), |
149 current_hint_operand_(nullptr), | 150 current_hint_operand_(nullptr), |
150 spill_start_index_(kMaxInt), | 151 spill_start_index_(kMaxInt), |
151 spill_type_(SpillType::kNoSpillType), | 152 spill_type_(SpillType::kNoSpillType), |
152 spill_operand_(nullptr), | 153 spill_operand_(nullptr), |
153 spills_at_definition_(nullptr) {} | 154 spills_at_definition_(nullptr) {} |
154 | 155 |
155 | 156 |
156 void LiveRange::Verify() const { | 157 void LiveRange::Verify() const { |
157 UsePosition* cur = first_pos_; | 158 // Walk the positions, verifying that each is in an interval. |
158 while (cur != nullptr) { | 159 auto interval = first_interval_; |
159 CHECK(Start().Value() <= cur->pos().Value() && | 160 for (auto pos = first_pos_; pos != nullptr; pos = pos->next()) { |
160 cur->pos().Value() <= End().Value()); | 161 CHECK(Start().Value() <= pos->pos().Value()); |
161 cur = cur->next(); | 162 CHECK(pos->pos().Value() <= End().Value()); |
| 163 CHECK(interval != nullptr); |
| 164 while (!interval->Contains(pos->pos()) && |
| 165 interval->end().Value() != pos->pos().Value()) { |
| 166 interval = interval->next(); |
| 167 CHECK(interval != nullptr); |
| 168 } |
162 } | 169 } |
163 } | 170 } |
164 | 171 |
165 | 172 |
166 bool LiveRange::HasOverlap(UseInterval* target) const { | |
167 UseInterval* current_interval = first_interval_; | |
168 while (current_interval != nullptr) { | |
169 // Intervals overlap if the start of one is contained in the other. | |
170 if (current_interval->Contains(target->start()) || | |
171 target->Contains(current_interval->start())) { | |
172 return true; | |
173 } | |
174 current_interval = current_interval->next(); | |
175 } | |
176 return false; | |
177 } | |
178 | |
179 | |
180 void LiveRange::set_assigned_register(int reg) { | 173 void LiveRange::set_assigned_register(int reg) { |
181 DCHECK(!HasRegisterAssigned() && !IsSpilled()); | 174 DCHECK(!HasRegisterAssigned() && !IsSpilled()); |
182 assigned_register_ = reg; | 175 assigned_register_ = reg; |
183 } | 176 } |
184 | 177 |
185 | 178 |
186 void LiveRange::MakeSpilled() { | 179 void LiveRange::MakeSpilled() { |
187 DCHECK(!IsSpilled()); | 180 DCHECK(!IsSpilled()); |
188 DCHECK(!TopLevel()->HasNoSpillType()); | 181 DCHECK(!TopLevel()->HasNoSpillType()); |
189 spilled_ = true; | 182 spilled_ = true; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 | 352 |
360 // If the split position coincides with the beginning of a use interval | 353 // If the split position coincides with the beginning of a use interval |
361 // we need to split use positons in a special way. | 354 // we need to split use positons in a special way. |
362 bool split_at_start = false; | 355 bool split_at_start = false; |
363 | 356 |
364 if (current->start().Value() == position.Value()) { | 357 if (current->start().Value() == position.Value()) { |
365 // When splitting at start we need to locate the previous use interval. | 358 // When splitting at start we need to locate the previous use interval. |
366 current = first_interval_; | 359 current = first_interval_; |
367 } | 360 } |
368 | 361 |
| 362 UseInterval* after = nullptr; |
369 while (current != nullptr) { | 363 while (current != nullptr) { |
370 if (current->Contains(position)) { | 364 if (current->Contains(position)) { |
371 current->SplitAt(position, zone); | 365 after = current->SplitAt(position, zone); |
372 break; | 366 break; |
373 } | 367 } |
374 auto next = current->next(); | 368 auto next = current->next(); |
375 if (next->start().Value() >= position.Value()) { | 369 if (next->start().Value() >= position.Value()) { |
376 split_at_start = (next->start().Value() == position.Value()); | 370 split_at_start = (next->start().Value() == position.Value()); |
377 break; | 371 break; |
378 } | 372 } |
379 current = next; | 373 current = next; |
380 } | 374 } |
381 | 375 |
382 // Partition original use intervals to the two live ranges. | 376 // Partition original use intervals to the two live ranges. |
383 auto before = current; | 377 auto before = current; |
384 auto after = before->next(); | 378 if (after == nullptr) after = before->next(); |
385 result->last_interval_ = | 379 result->last_interval_ = |
386 (last_interval_ == before) | 380 (last_interval_ == before) |
387 ? after // Only interval in the range after split. | 381 ? after // Only interval in the range after split. |
388 : last_interval_; // Last interval of the original range. | 382 : last_interval_; // Last interval of the original range. |
389 result->first_interval_ = after; | 383 result->first_interval_ = after; |
390 last_interval_ = before; | 384 last_interval_ = before; |
391 | 385 |
392 // Find the last use position before the split and the first use | 386 // Find the last use position before the split and the first use |
393 // position after it. | 387 // position after it. |
394 auto use_after = first_pos_; | 388 auto use_after = first_pos_; |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
625 if (interval2->end().Value() > interval1->start().Value()) { | 619 if (interval2->end().Value() > interval1->start().Value()) { |
626 return true; | 620 return true; |
627 } | 621 } |
628 interval2 = interval2->next(); | 622 interval2 = interval2->next(); |
629 } | 623 } |
630 } | 624 } |
631 return false; | 625 return false; |
632 } | 626 } |
633 | 627 |
634 | 628 |
635 SpillRange::SpillRange(LiveRange* range, Zone* zone) : live_ranges_(zone) { | 629 SpillRange::SpillRange(LiveRange* parent, Zone* zone) : live_ranges_(zone) { |
636 auto src = range->first_interval(); | 630 DCHECK(!parent->IsChild()); |
637 UseInterval* result = nullptr; | 631 UseInterval* result = nullptr; |
638 UseInterval* node = nullptr; | 632 UseInterval* node = nullptr; |
639 // Copy the nodes | 633 // Copy the intervals for all ranges. |
640 while (src != nullptr) { | 634 for (auto range = parent; range != nullptr; range = range->next()) { |
641 auto new_node = new (zone) UseInterval(src->start(), src->end()); | 635 auto src = range->first_interval(); |
642 if (result == nullptr) { | 636 while (src != nullptr) { |
643 result = new_node; | 637 auto new_node = new (zone) UseInterval(src->start(), src->end()); |
644 } else { | 638 if (result == nullptr) { |
645 node->set_next(new_node); | 639 result = new_node; |
| 640 } else { |
| 641 node->set_next(new_node); |
| 642 } |
| 643 node = new_node; |
| 644 src = src->next(); |
646 } | 645 } |
647 node = new_node; | |
648 src = src->next(); | |
649 } | 646 } |
650 use_interval_ = result; | 647 use_interval_ = result; |
651 live_ranges().push_back(range); | 648 live_ranges().push_back(parent); |
652 end_position_ = node->end(); | 649 end_position_ = node->end(); |
653 DCHECK(!range->HasSpillRange()); | 650 DCHECK(!parent->HasSpillRange()); |
654 range->SetSpillRange(this); | 651 parent->SetSpillRange(this); |
655 } | 652 } |
656 | 653 |
657 | 654 |
658 bool SpillRange::IsIntersectingWith(SpillRange* other) const { | 655 bool SpillRange::IsIntersectingWith(SpillRange* other) const { |
659 if (this->use_interval_ == nullptr || other->use_interval_ == nullptr || | 656 if (this->use_interval_ == nullptr || other->use_interval_ == nullptr || |
660 this->End().Value() <= other->use_interval_->start().Value() || | 657 this->End().Value() <= other->use_interval_->start().Value() || |
661 other->End().Value() <= this->use_interval_->start().Value()) { | 658 other->End().Value() <= this->use_interval_->start().Value()) { |
662 return false; | 659 return false; |
663 } | 660 } |
664 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_); | 661 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_); |
(...skipping 2199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2864 auto eliminate = moves->PrepareInsertAfter(move); | 2861 auto eliminate = moves->PrepareInsertAfter(move); |
2865 to_insert.push_back(move); | 2862 to_insert.push_back(move); |
2866 if (eliminate != nullptr) to_eliminate.push_back(eliminate); | 2863 if (eliminate != nullptr) to_eliminate.push_back(eliminate); |
2867 } | 2864 } |
2868 } | 2865 } |
2869 | 2866 |
2870 | 2867 |
2871 } // namespace compiler | 2868 } // namespace compiler |
2872 } // namespace internal | 2869 } // namespace internal |
2873 } // namespace v8 | 2870 } // namespace v8 |
OLD | NEW |