| 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 |