Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/lithium-allocator.cc

Issue 527063002: Revert "More aggressive reuse of spill slots in the register allocator." (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/lithium-allocator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/hydrogen.h" 7 #include "src/hydrogen.h"
8 #include "src/lithium-inl.h" 8 #include "src/lithium-inl.h"
9 #include "src/lithium-allocator-inl.h" 9 #include "src/lithium-allocator-inl.h"
10 #include "src/string-stream.h" 10 #include "src/string-stream.h"
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 assigned_register_(kInvalidAssignment), 102 assigned_register_(kInvalidAssignment),
103 last_interval_(NULL), 103 last_interval_(NULL),
104 first_interval_(NULL), 104 first_interval_(NULL),
105 first_pos_(NULL), 105 first_pos_(NULL),
106 parent_(NULL), 106 parent_(NULL),
107 next_(NULL), 107 next_(NULL),
108 current_interval_(NULL), 108 current_interval_(NULL),
109 last_processed_use_(NULL), 109 last_processed_use_(NULL),
110 current_hint_operand_(NULL), 110 current_hint_operand_(NULL),
111 spill_operand_(new (zone) LOperand()), 111 spill_operand_(new (zone) LOperand()),
112 spill_start_index_(kMaxInt), 112 spill_start_index_(kMaxInt) {}
113 spill_range_(NULL) {}
114 113
115 114
116 void LiveRange::set_assigned_register(int reg, Zone* zone) { 115 void LiveRange::set_assigned_register(int reg, Zone* zone) {
117 DCHECK(!HasRegisterAssigned() && !IsSpilled()); 116 DCHECK(!HasRegisterAssigned() && !IsSpilled());
118 assigned_register_ = reg; 117 assigned_register_ = reg;
119 ConvertOperands(zone); 118 ConvertOperands(zone);
120 } 119 }
121 120
122 121
123 void LiveRange::MakeSpilled(Zone* zone) { 122 void LiveRange::MakeSpilled(Zone* zone) {
124 DCHECK(!IsSpilled()); 123 DCHECK(!IsSpilled());
125 DCHECK(TopLevel()->HasAllocatedSpillOperand()); 124 DCHECK(TopLevel()->HasAllocatedSpillOperand());
126 spilled_ = true; 125 spilled_ = true;
127 assigned_register_ = kInvalidAssignment; 126 assigned_register_ = kInvalidAssignment;
128 if (spill_range_ == NULL) { 127 ConvertOperands(zone);
129 ConvertOperands(zone);
130 }
131 } 128 }
132 129
133 130
134 bool LiveRange::HasAllocatedSpillOperand() const { 131 bool LiveRange::HasAllocatedSpillOperand() const {
135 DCHECK(spill_operand_ != NULL); 132 DCHECK(spill_operand_ != NULL);
136 return !spill_operand_->IsIgnored() || spill_range_ != NULL; 133 return !spill_operand_->IsIgnored();
137 } 134 }
138 135
139 136
140 void LiveRange::SetSpillOperand(LOperand* operand) { 137 void LiveRange::SetSpillOperand(LOperand* operand) {
141 DCHECK(!operand->IsUnallocated()); 138 DCHECK(!operand->IsUnallocated());
142 DCHECK(spill_operand_ != NULL); 139 DCHECK(spill_operand_ != NULL);
143 DCHECK(spill_operand_->IsIgnored()); 140 DCHECK(spill_operand_->IsIgnored());
144 spill_operand_->ConvertTo(operand->kind(), operand->index()); 141 spill_operand_->ConvertTo(operand->kind(), operand->index());
145 } 142 }
146 143
147 144
148 void LiveRange::CommitSpillOperand(LOperand* operand) {
149 DCHECK(spill_range_ != NULL);
150 DCHECK(!IsChild());
151 spill_range_ = NULL;
152 SetSpillOperand(operand);
153 for (LiveRange* range = this; range != NULL; range = range->next()) {
154 if (range->IsSpilled()) {
155 range->ConvertUsesToOperand(operand);
156 }
157 }
158 }
159
160
161 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) { 145 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) {
162 UsePosition* use_pos = last_processed_use_; 146 UsePosition* use_pos = last_processed_use_;
163 if (use_pos == NULL) use_pos = first_pos(); 147 if (use_pos == NULL) use_pos = first_pos();
164 while (use_pos != NULL && use_pos->pos().Value() < start.Value()) { 148 while (use_pos != NULL && use_pos->pos().Value() < start.Value()) {
165 use_pos = use_pos->next(); 149 use_pos = use_pos->next();
166 } 150 }
167 last_processed_use_ = use_pos; 151 last_processed_use_ = use_pos;
168 return use_pos; 152 return use_pos;
169 } 153 }
170 154
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 use_pos->next_ = prev->next_; 439 use_pos->next_ = prev->next_;
456 prev->next_ = use_pos; 440 prev->next_ = use_pos;
457 } 441 }
458 442
459 if (prev_hint == NULL && use_pos->HasHint()) { 443 if (prev_hint == NULL && use_pos->HasHint()) {
460 current_hint_operand_ = hint; 444 current_hint_operand_ = hint;
461 } 445 }
462 } 446 }
463 447
464 448
465 void LiveRange::ConvertUsesToOperand(LOperand* op) { 449 void LiveRange::ConvertOperands(Zone* zone) {
450 LOperand* op = CreateAssignedOperand(zone);
466 UsePosition* use_pos = first_pos(); 451 UsePosition* use_pos = first_pos();
467 while (use_pos != NULL) { 452 while (use_pos != NULL) {
468 DCHECK(Start().Value() <= use_pos->pos().Value() && 453 DCHECK(Start().Value() <= use_pos->pos().Value() &&
469 use_pos->pos().Value() <= End().Value()); 454 use_pos->pos().Value() <= End().Value());
470 455
471 if (use_pos->HasOperand()) { 456 if (use_pos->HasOperand()) {
472 DCHECK(op->IsRegister() || op->IsDoubleRegister() || 457 DCHECK(op->IsRegister() || op->IsDoubleRegister() ||
473 !use_pos->RequiresRegister()); 458 !use_pos->RequiresRegister());
474 use_pos->operand()->ConvertTo(op->kind(), op->index()); 459 use_pos->operand()->ConvertTo(op->kind(), op->index());
475 } 460 }
476 use_pos = use_pos->next(); 461 use_pos = use_pos->next();
477 } 462 }
478 } 463 }
479 464
480 465
481 void LiveRange::ConvertOperands(Zone* zone) {
482 LOperand* op = CreateAssignedOperand(zone);
483 ConvertUsesToOperand(op);
484 }
485
486
487 bool LiveRange::CanCover(LifetimePosition position) const { 466 bool LiveRange::CanCover(LifetimePosition position) const {
488 if (IsEmpty()) return false; 467 if (IsEmpty()) return false;
489 return Start().Value() <= position.Value() && 468 return Start().Value() <= position.Value() &&
490 position.Value() < End().Value(); 469 position.Value() < End().Value();
491 } 470 }
492 471
493 472
494 bool LiveRange::Covers(LifetimePosition position) { 473 bool LiveRange::Covers(LifetimePosition position) {
495 if (!CanCover(position)) return false; 474 if (!CanCover(position)) return false;
496 UseInterval* start_search = FirstSearchIntervalForPosition(position); 475 UseInterval* start_search = FirstSearchIntervalForPosition(position);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 : zone_(graph->isolate()), 514 : zone_(graph->isolate()),
536 chunk_(NULL), 515 chunk_(NULL),
537 live_in_sets_(graph->blocks()->length(), zone()), 516 live_in_sets_(graph->blocks()->length(), zone()),
538 live_ranges_(num_values * 2, zone()), 517 live_ranges_(num_values * 2, zone()),
539 fixed_live_ranges_(NULL), 518 fixed_live_ranges_(NULL),
540 fixed_double_live_ranges_(NULL), 519 fixed_double_live_ranges_(NULL),
541 unhandled_live_ranges_(num_values * 2, zone()), 520 unhandled_live_ranges_(num_values * 2, zone()),
542 active_live_ranges_(8, zone()), 521 active_live_ranges_(8, zone()),
543 inactive_live_ranges_(8, zone()), 522 inactive_live_ranges_(8, zone()),
544 reusable_slots_(8, zone()), 523 reusable_slots_(8, zone()),
545 spill_ranges_(8, zone()),
546 next_virtual_register_(num_values), 524 next_virtual_register_(num_values),
547 first_artificial_register_(num_values), 525 first_artificial_register_(num_values),
548 mode_(UNALLOCATED_REGISTERS), 526 mode_(UNALLOCATED_REGISTERS),
549 num_registers_(-1), 527 num_registers_(-1),
550 graph_(graph), 528 graph_(graph),
551 has_osr_entry_(false), 529 has_osr_entry_(false),
552 allocation_ok_(true) {} 530 allocation_ok_(true) {}
553 531
554 532
555 void LAllocator::InitializeLivenessAnalysis() { 533 void LAllocator::InitializeLivenessAnalysis() {
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
1031 index = index - 1; 1009 index = index - 1;
1032 } 1010 }
1033 } 1011 }
1034 1012
1035 1013
1036 void LAllocator::ResolvePhis(HBasicBlock* block) { 1014 void LAllocator::ResolvePhis(HBasicBlock* block) {
1037 const ZoneList<HPhi*>* phis = block->phis(); 1015 const ZoneList<HPhi*>* phis = block->phis();
1038 for (int i = 0; i < phis->length(); ++i) { 1016 for (int i = 0; i < phis->length(); ++i) {
1039 HPhi* phi = phis->at(i); 1017 HPhi* phi = phis->at(i);
1040 LUnallocated* phi_operand = 1018 LUnallocated* phi_operand =
1041 new (chunk()->zone()) LUnallocated(LUnallocated::ANY); 1019 new (chunk()->zone()) LUnallocated(LUnallocated::NONE);
1042 phi_operand->set_virtual_register(phi->id()); 1020 phi_operand->set_virtual_register(phi->id());
1043 for (int j = 0; j < phi->OperandCount(); ++j) { 1021 for (int j = 0; j < phi->OperandCount(); ++j) {
1044 HValue* op = phi->OperandAt(j); 1022 HValue* op = phi->OperandAt(j);
1045 LOperand* operand = NULL; 1023 LOperand* operand = NULL;
1046 if (op->IsConstant() && op->EmitAtUses()) { 1024 if (op->IsConstant() && op->EmitAtUses()) {
1047 HConstant* constant = HConstant::cast(op); 1025 HConstant* constant = HConstant::cast(op);
1048 operand = chunk_->DefineConstantOperand(constant); 1026 operand = chunk_->DefineConstantOperand(constant);
1049 } else { 1027 } else {
1050 DCHECK(!op->EmitAtUses()); 1028 DCHECK(!op->EmitAtUses());
1051 LUnallocated* unalloc = 1029 LUnallocated* unalloc =
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1098 new(chunk->zone()) BitVector(DoubleRegister::NumAllocatableRegisters(), 1076 new(chunk->zone()) BitVector(DoubleRegister::NumAllocatableRegisters(),
1099 chunk->zone()); 1077 chunk->zone());
1100 MeetRegisterConstraints(); 1078 MeetRegisterConstraints();
1101 if (!AllocationOk()) return false; 1079 if (!AllocationOk()) return false;
1102 ResolvePhis(); 1080 ResolvePhis();
1103 BuildLiveRanges(); 1081 BuildLiveRanges();
1104 AllocateGeneralRegisters(); 1082 AllocateGeneralRegisters();
1105 if (!AllocationOk()) return false; 1083 if (!AllocationOk()) return false;
1106 AllocateDoubleRegisters(); 1084 AllocateDoubleRegisters();
1107 if (!AllocationOk()) return false; 1085 if (!AllocationOk()) return false;
1108 ReuseSpillSlots();
1109 PopulatePointerMaps(); 1086 PopulatePointerMaps();
1110 ConnectRanges(); 1087 ConnectRanges();
1111 ResolveControlFlow(); 1088 ResolveControlFlow();
1112 return true; 1089 return true;
1113 } 1090 }
1114 1091
1115 1092
1116 static bool AreUseIntervalsIntersecting(UseInterval* interval1,
1117 UseInterval* interval2) {
1118 while (interval1 != NULL && interval2 != NULL) {
1119 if (interval1->start().Value() < interval2->start().Value()) {
1120 if (interval1->end().Value() > interval2->start().Value()) {
1121 return true;
1122 }
1123 interval1 = interval1->next();
1124 } else {
1125 if (interval2->end().Value() > interval1->start().Value()) {
1126 return true;
1127 }
1128 interval2 = interval2->next();
1129 }
1130 }
1131 return false;
1132 }
1133
1134
1135 SpillRange::SpillRange(LiveRange* range, int id, Zone* zone)
1136 : id_(id), live_ranges_(1, zone), end_position_(range->End()) {
1137 UseInterval* src = range->first_interval();
1138 UseInterval* result = NULL;
1139 UseInterval* node = NULL;
1140 // Copy the nodes
1141 while (src != NULL) {
1142 UseInterval* new_node = new (zone) UseInterval(src->start(), src->end());
1143 if (result == NULL) {
1144 result = new_node;
1145 } else {
1146 node->set_next(new_node);
1147 }
1148 node = new_node;
1149 src = src->next();
1150 }
1151 use_interval_ = result;
1152 live_ranges_.Add(range, zone);
1153 DCHECK(range->GetSpillRange() == NULL);
1154 range->SetSpillRange(this);
1155 }
1156
1157
1158 bool SpillRange::IsIntersectingWith(SpillRange* other) {
1159 if (End().Value() <= other->use_interval_->start().Value() ||
1160 other->End().Value() <= use_interval_->start().Value()) {
1161 return false;
1162 }
1163 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_);
1164 }
1165
1166
1167 bool SpillRange::TryMerge(SpillRange* other, Zone* zone) {
1168 if (Kind() == other->Kind() &&
1169 !AreUseIntervalsIntersecting(use_interval_, other->use_interval_)) {
1170 if (End().Value() < other->End().Value()) {
1171 end_position_ = other->End();
1172 }
1173
1174 MergeDisjointIntervals(other->use_interval_, zone);
1175 other->use_interval_ = NULL;
1176
1177 for (int i = 0; i < other->live_ranges_.length(); i++) {
1178 DCHECK(other->live_ranges_.at(i)->GetSpillRange() == other);
1179 other->live_ranges_.at(i)->SetSpillRange(this);
1180 }
1181
1182 live_ranges_.AddAll(other->live_ranges_, zone);
1183 other->live_ranges_.Clear();
1184
1185 return true;
1186 }
1187 return false;
1188 }
1189
1190
1191 void SpillRange::SetOperand(LOperand* op) {
1192 for (int i = 0; i < live_ranges_.length(); i++) {
1193 DCHECK(live_ranges_.at(i)->GetSpillRange() == this);
1194 live_ranges_.at(i)->CommitSpillOperand(op);
1195 }
1196 }
1197
1198
1199 void SpillRange::MergeDisjointIntervals(UseInterval* other, Zone* zone) {
1200 UseInterval* tail = NULL;
1201 UseInterval* current = use_interval_;
1202 while (other != NULL) {
1203 // Make sure the 'current' list starts first
1204 if (current == NULL || current->start().Value() > other->start().Value()) {
1205 std::swap(current, other);
1206 }
1207
1208 // Check disjointness
1209 DCHECK(other == NULL || current->end().Value() <= other->start().Value());
1210
1211 // Append the 'current' node to the result accumulator and move forward
1212 if (tail == NULL) {
1213 use_interval_ = current;
1214 } else {
1215 tail->set_next(current);
1216 }
1217 tail = current;
1218 current = current->next();
1219 }
1220 // Other list is empty => we are done
1221 }
1222
1223
1224 void LAllocator::ReuseSpillSlots() {
1225 // Merge disjoint spill ranges
1226 for (int i = 0; i < spill_ranges_.length(); i++) {
1227 SpillRange* range = spill_ranges_.at(i);
1228 if (!range->IsEmpty()) {
1229 for (int j = i + 1; j < spill_ranges_.length(); j++) {
1230 SpillRange* other = spill_ranges_.at(j);
1231 if (!other->IsEmpty()) {
1232 range->TryMerge(spill_ranges_.at(j), zone());
1233 }
1234 }
1235 }
1236 }
1237
1238 // Allocate slots for the merged spill ranges.
1239 for (int i = 0; i < spill_ranges_.length(); i++) {
1240 SpillRange* range = spill_ranges_.at(i);
1241 if (!range->IsEmpty()) {
1242 LOperand* op = chunk_->GetNextSpillSlot(range->Kind());
1243 range->SetOperand(op);
1244 }
1245 }
1246 }
1247
1248
1249 void LAllocator::MeetRegisterConstraints() { 1093 void LAllocator::MeetRegisterConstraints() {
1250 LAllocatorPhase phase("L_Register constraints", this); 1094 LAllocatorPhase phase("L_Register constraints", this);
1251 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); 1095 const ZoneList<HBasicBlock*>* blocks = graph_->blocks();
1252 for (int i = 0; i < blocks->length(); ++i) { 1096 for (int i = 0; i < blocks->length(); ++i) {
1253 HBasicBlock* block = blocks->at(i); 1097 HBasicBlock* block = blocks->at(i);
1254 MeetRegisterConstraints(block); 1098 MeetRegisterConstraints(block);
1255 if (!AllocationOk()) return; 1099 if (!AllocationOk()) return;
1256 } 1100 }
1257 } 1101 }
1258 1102
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
1629 1473
1630 1474
1631 void LAllocator::AllocateDoubleRegisters() { 1475 void LAllocator::AllocateDoubleRegisters() {
1632 LAllocatorPhase phase("L_Allocate double registers", this); 1476 LAllocatorPhase phase("L_Allocate double registers", this);
1633 num_registers_ = DoubleRegister::NumAllocatableRegisters(); 1477 num_registers_ = DoubleRegister::NumAllocatableRegisters();
1634 mode_ = DOUBLE_REGISTERS; 1478 mode_ = DOUBLE_REGISTERS;
1635 AllocateRegisters(); 1479 AllocateRegisters();
1636 } 1480 }
1637 1481
1638 1482
1639 bool LAllocator::TryReuseSpillForPhi(LiveRange* range) {
1640 DCHECK(!range->HasAllocatedSpillOperand());
1641 if (range->IsChild()) {
1642 return false;
1643 }
1644 HValue* instr = graph_->LookupValue(range->id());
1645 if (instr == NULL || !instr->IsPhi()) {
1646 return false;
1647 }
1648
1649 // Count the number of spilled operands.
1650 HPhi* phi = HPhi::cast(instr);
1651 int spilled_count = 0;
1652 LiveRange* first_op = NULL;
1653 for (int i = 0; i < phi->OperandCount(); i++) {
1654 HValue* op = phi->OperandAt(i);
1655 LiveRange* op_range = LiveRangeFor(op->id());
1656 if (op_range->GetSpillRange() != NULL) {
1657 HBasicBlock* pred = instr->block()->predecessors()->at(i);
1658 LifetimePosition pred_end = LifetimePosition::FromInstructionIndex(
1659 pred->last_instruction_index());
1660 while (op_range != NULL && !op_range->CanCover(pred_end)) {
1661 op_range = op_range->next();
1662 }
1663 if (op_range != NULL && op_range->IsSpilled()) {
1664 spilled_count++;
1665 if (first_op == NULL) {
1666 first_op = op_range->TopLevel();
1667 }
1668 }
1669 }
1670 }
1671
1672 // Only continue if more than half of the operands are spilled.
1673 if (spilled_count * 2 <= phi->OperandCount()) {
1674 return false;
1675 }
1676
1677 // Try to merge the spilled operands and count the number of merged spilled
1678 // operands.
1679 DCHECK(first_op != NULL);
1680 SpillRange* first_op_spill = first_op->GetSpillRange();
1681 int num_merged = 1;
1682 for (int i = 1; i < phi->OperandCount(); i++) {
1683 HValue* op = phi->OperandAt(i);
1684 LiveRange* op_range = LiveRangeFor(op->id());
1685 SpillRange* op_spill = op_range->GetSpillRange();
1686 if (op_spill != NULL) {
1687 if (op_spill->id() == first_op_spill->id() ||
1688 first_op_spill->TryMerge(op_spill, zone())) {
1689 num_merged++;
1690 }
1691 }
1692 }
1693
1694 // Only continue if enough operands could be merged to the
1695 // same spill slot.
1696 if (num_merged * 2 <= phi->OperandCount() ||
1697 AreUseIntervalsIntersecting(first_op_spill->interval(),
1698 range->first_interval())) {
1699 return false;
1700 }
1701
1702 // If the range does not need register soon, spill it to the merged
1703 // spill range.
1704 LifetimePosition next_pos = range->Start();
1705 if (IsGapAt(next_pos.InstructionIndex())) {
1706 next_pos = next_pos.NextInstruction();
1707 }
1708 UsePosition* pos = range->NextUsePositionRegisterIsBeneficial(next_pos);
1709 if (pos == NULL) {
1710 SpillRange* spill_range = AssignSpillRangeToLiveRange(range->TopLevel());
1711 CHECK(first_op_spill->TryMerge(spill_range, zone()));
1712 Spill(range);
1713 return true;
1714 } else if (pos->pos().Value() > range->Start().NextInstruction().Value()) {
1715 SpillRange* spill_range = AssignSpillRangeToLiveRange(range->TopLevel());
1716 CHECK(first_op_spill->TryMerge(spill_range, zone()));
1717 SpillBetween(range, range->Start(), pos->pos());
1718 if (!AllocationOk()) return false;
1719 DCHECK(UnhandledIsSorted());
1720 return true;
1721 }
1722
1723 return false;
1724 }
1725
1726
1727 SpillRange* LAllocator::AssignSpillRangeToLiveRange(LiveRange* range) {
1728 int spill_id = spill_ranges_.length();
1729 SpillRange* spill_range = new (zone()) SpillRange(range, spill_id, zone());
1730 spill_ranges_.Add(spill_range, zone());
1731 return spill_range;
1732 }
1733
1734
1735 void LAllocator::AllocateRegisters() { 1483 void LAllocator::AllocateRegisters() {
1736 DCHECK(unhandled_live_ranges_.is_empty()); 1484 DCHECK(unhandled_live_ranges_.is_empty());
1737 1485
1738 for (int i = 0; i < live_ranges_.length(); ++i) { 1486 for (int i = 0; i < live_ranges_.length(); ++i) {
1739 if (live_ranges_[i] != NULL) { 1487 if (live_ranges_[i] != NULL) {
1740 if (live_ranges_[i]->Kind() == mode_) { 1488 if (live_ranges_[i]->Kind() == mode_) {
1741 AddToUnhandledUnsorted(live_ranges_[i]); 1489 AddToUnhandledUnsorted(live_ranges_[i]);
1742 } 1490 }
1743 } 1491 }
1744 } 1492 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1794 current->Start().NextInstruction().Value()) { 1542 current->Start().NextInstruction().Value()) {
1795 // Do not spill live range eagerly if use position that can benefit from 1543 // Do not spill live range eagerly if use position that can benefit from
1796 // the register is too close to the start of live range. 1544 // the register is too close to the start of live range.
1797 SpillBetween(current, current->Start(), pos->pos()); 1545 SpillBetween(current, current->Start(), pos->pos());
1798 if (!AllocationOk()) return; 1546 if (!AllocationOk()) return;
1799 DCHECK(UnhandledIsSorted()); 1547 DCHECK(UnhandledIsSorted());
1800 continue; 1548 continue;
1801 } 1549 }
1802 } 1550 }
1803 1551
1804 if (TryReuseSpillForPhi(current)) {
1805 continue;
1806 }
1807 if (!AllocationOk()) return;
1808
1809 for (int i = 0; i < active_live_ranges_.length(); ++i) { 1552 for (int i = 0; i < active_live_ranges_.length(); ++i) {
1810 LiveRange* cur_active = active_live_ranges_.at(i); 1553 LiveRange* cur_active = active_live_ranges_.at(i);
1811 if (cur_active->End().Value() <= position.Value()) { 1554 if (cur_active->End().Value() <= position.Value()) {
1812 ActiveToHandled(cur_active); 1555 ActiveToHandled(cur_active);
1813 --i; // The live range was removed from the list of active live ranges. 1556 --i; // The live range was removed from the list of active live ranges.
1814 } else if (!cur_active->Covers(position)) { 1557 } else if (!cur_active->Covers(position)) {
1815 ActiveToInactive(cur_active); 1558 ActiveToInactive(cur_active);
1816 --i; // The live range was removed from the list of active live ranges. 1559 --i; // The live range was removed from the list of active live ranges.
1817 } 1560 }
1818 } 1561 }
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1949 int len = unhandled_live_ranges_.length(); 1692 int len = unhandled_live_ranges_.length();
1950 for (int i = 1; i < len; i++) { 1693 for (int i = 1; i < len; i++) {
1951 LiveRange* a = unhandled_live_ranges_.at(i - 1); 1694 LiveRange* a = unhandled_live_ranges_.at(i - 1);
1952 LiveRange* b = unhandled_live_ranges_.at(i); 1695 LiveRange* b = unhandled_live_ranges_.at(i);
1953 if (a->Start().Value() < b->Start().Value()) return false; 1696 if (a->Start().Value() < b->Start().Value()) return false;
1954 } 1697 }
1955 return true; 1698 return true;
1956 } 1699 }
1957 1700
1958 1701
1702 void LAllocator::FreeSpillSlot(LiveRange* range) {
1703 // Check that we are the last range.
1704 if (range->next() != NULL) return;
1705
1706 if (!range->TopLevel()->HasAllocatedSpillOperand()) return;
1707
1708 int index = range->TopLevel()->GetSpillOperand()->index();
1709 if (index >= 0) {
1710 reusable_slots_.Add(range, zone());
1711 }
1712 }
1713
1714
1715 LOperand* LAllocator::TryReuseSpillSlot(LiveRange* range) {
1716 if (reusable_slots_.is_empty()) return NULL;
1717 if (reusable_slots_.first()->End().Value() >
1718 range->TopLevel()->Start().Value()) {
1719 return NULL;
1720 }
1721 LOperand* result = reusable_slots_.first()->TopLevel()->GetSpillOperand();
1722 reusable_slots_.Remove(0);
1723 return result;
1724 }
1725
1726
1959 void LAllocator::ActiveToHandled(LiveRange* range) { 1727 void LAllocator::ActiveToHandled(LiveRange* range) {
1960 DCHECK(active_live_ranges_.Contains(range)); 1728 DCHECK(active_live_ranges_.Contains(range));
1961 active_live_ranges_.RemoveElement(range); 1729 active_live_ranges_.RemoveElement(range);
1962 TraceAlloc("Moving live range %d from active to handled\n", range->id()); 1730 TraceAlloc("Moving live range %d from active to handled\n", range->id());
1731 FreeSpillSlot(range);
1963 } 1732 }
1964 1733
1965 1734
1966 void LAllocator::ActiveToInactive(LiveRange* range) { 1735 void LAllocator::ActiveToInactive(LiveRange* range) {
1967 DCHECK(active_live_ranges_.Contains(range)); 1736 DCHECK(active_live_ranges_.Contains(range));
1968 active_live_ranges_.RemoveElement(range); 1737 active_live_ranges_.RemoveElement(range);
1969 inactive_live_ranges_.Add(range, zone()); 1738 inactive_live_ranges_.Add(range, zone());
1970 TraceAlloc("Moving live range %d from active to inactive\n", range->id()); 1739 TraceAlloc("Moving live range %d from active to inactive\n", range->id());
1971 } 1740 }
1972 1741
1973 1742
1974 void LAllocator::InactiveToHandled(LiveRange* range) { 1743 void LAllocator::InactiveToHandled(LiveRange* range) {
1975 DCHECK(inactive_live_ranges_.Contains(range)); 1744 DCHECK(inactive_live_ranges_.Contains(range));
1976 inactive_live_ranges_.RemoveElement(range); 1745 inactive_live_ranges_.RemoveElement(range);
1977 TraceAlloc("Moving live range %d from inactive to handled\n", range->id()); 1746 TraceAlloc("Moving live range %d from inactive to handled\n", range->id());
1747 FreeSpillSlot(range);
1978 } 1748 }
1979 1749
1980 1750
1981 void LAllocator::InactiveToActive(LiveRange* range) { 1751 void LAllocator::InactiveToActive(LiveRange* range) {
1982 DCHECK(inactive_live_ranges_.Contains(range)); 1752 DCHECK(inactive_live_ranges_.Contains(range));
1983 inactive_live_ranges_.RemoveElement(range); 1753 inactive_live_ranges_.RemoveElement(range);
1984 active_live_ranges_.Add(range, zone()); 1754 active_live_ranges_.Add(range, zone());
1985 TraceAlloc("Moving live range %d from inactive to active\n", range->id()); 1755 TraceAlloc("Moving live range %d from inactive to active\n", range->id());
1986 } 1756 }
1987 1757
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
2051 } 1821 }
2052 1822
2053 if (pos.Value() < current->End().Value()) { 1823 if (pos.Value() < current->End().Value()) {
2054 // Register reg is available at the range start but becomes blocked before 1824 // Register reg is available at the range start but becomes blocked before
2055 // the range end. Split current at position where it becomes blocked. 1825 // the range end. Split current at position where it becomes blocked.
2056 LiveRange* tail = SplitRangeAt(current, pos); 1826 LiveRange* tail = SplitRangeAt(current, pos);
2057 if (!AllocationOk()) return false; 1827 if (!AllocationOk()) return false;
2058 AddToUnhandledSorted(tail); 1828 AddToUnhandledSorted(tail);
2059 } 1829 }
2060 1830
1831
2061 // Register reg is available at the range start and is free until 1832 // Register reg is available at the range start and is free until
2062 // the range end. 1833 // the range end.
2063 DCHECK(pos.Value() >= current->End().Value()); 1834 DCHECK(pos.Value() >= current->End().Value());
2064 TraceAlloc("Assigning free reg %s to live range %d\n", 1835 TraceAlloc("Assigning free reg %s to live range %d\n",
2065 RegisterName(reg), 1836 RegisterName(reg),
2066 current->id()); 1837 current->id());
2067 SetLiveRangeAssignedRegister(current, reg); 1838 SetLiveRangeAssignedRegister(current, reg);
2068 1839
2069 return true; 1840 return true;
2070 } 1841 }
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
2358 } 2129 }
2359 } 2130 }
2360 2131
2361 2132
2362 void LAllocator::Spill(LiveRange* range) { 2133 void LAllocator::Spill(LiveRange* range) {
2363 DCHECK(!range->IsSpilled()); 2134 DCHECK(!range->IsSpilled());
2364 TraceAlloc("Spilling live range %d\n", range->id()); 2135 TraceAlloc("Spilling live range %d\n", range->id());
2365 LiveRange* first = range->TopLevel(); 2136 LiveRange* first = range->TopLevel();
2366 2137
2367 if (!first->HasAllocatedSpillOperand()) { 2138 if (!first->HasAllocatedSpillOperand()) {
2368 AssignSpillRangeToLiveRange(first); 2139 LOperand* op = TryReuseSpillSlot(range);
2140 if (op == NULL) op = chunk_->GetNextSpillSlot(range->Kind());
2141 first->SetSpillOperand(op);
2369 } 2142 }
2370 range->MakeSpilled(chunk()->zone()); 2143 range->MakeSpilled(chunk()->zone());
2371 } 2144 }
2372 2145
2373 2146
2374 int LAllocator::RegisterCount() const { 2147 int LAllocator::RegisterCount() const {
2375 return num_registers_; 2148 return num_registers_;
2376 } 2149 }
2377 2150
2378 2151
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2412 isolate()->GetHTracer()->TraceLiveRanges(name(), allocator_); 2185 isolate()->GetHTracer()->TraceLiveRanges(name(), allocator_);
2413 } 2186 }
2414 2187
2415 #ifdef DEBUG 2188 #ifdef DEBUG
2416 if (allocator_ != NULL) allocator_->Verify(); 2189 if (allocator_ != NULL) allocator_->Verify();
2417 #endif 2190 #endif
2418 } 2191 }
2419 2192
2420 2193
2421 } } // namespace v8::internal 2194 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/lithium-allocator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698