Chromium Code Reviews| Index: src/compiler/register-allocator.cc |
| diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc |
| index 59d80c6f7c6fbfadda50fde5fac33da698b22892..040972dc4076282af563fd64e06c1daef925fbf7 100644 |
| --- a/src/compiler/register-allocator.cc |
| +++ b/src/compiler/register-allocator.cc |
| @@ -545,7 +545,8 @@ RegisterAllocator::RegisterAllocator(const RegisterConfiguration* config, |
| spill_ranges_(8, local_zone()), |
| mode_(UNALLOCATED_REGISTERS), |
| num_registers_(-1), |
| - allocation_ok_(true) { |
| + allocation_ok_(true), |
| + use_spill_ranges_(FLAG_turbo_reuse_spill_slots) { |
|
Jarin
2014/11/21 10:55:39
Why is there this extra indirection? Can't we use
dcarney
2014/11/21 11:03:55
ok
|
| DCHECK(this->config()->num_general_registers() <= |
| RegisterConfiguration::kMaxGeneralRegisters); |
| DCHECK(this->config()->num_double_registers() <= |
| @@ -881,6 +882,8 @@ void SpillRange::MergeDisjointIntervals(UseInterval* other, Zone* zone) { |
| void RegisterAllocator::ReuseSpillSlots() { |
| + DCHECK(use_spill_ranges_); |
| + |
| // Merge disjoint spill ranges |
| for (int i = 0; i < spill_ranges_.length(); i++) { |
| SpillRange* range = spill_ranges_.at(i); |
| @@ -915,6 +918,7 @@ void RegisterAllocator::ReuseSpillSlots() { |
| SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) { |
| + DCHECK(use_spill_ranges_); |
| int spill_id = spill_ranges_.length(); |
| SpillRange* spill_range = |
| new (local_zone()) SpillRange(range, spill_id, local_zone()); |
| @@ -1932,10 +1936,40 @@ bool RegisterAllocator::UnhandledIsSorted() { |
| } |
| +void RegisterAllocator::FreeSpillSlot(LiveRange* range) { |
| + DCHECK(!use_spill_ranges_); |
| + // Check that we are the last range. |
| + if (range->next() != NULL) return; |
| + |
| + if (!range->TopLevel()->HasAllocatedSpillOperand()) return; |
| + |
| + InstructionOperand* spill_operand = range->TopLevel()->GetSpillOperand(); |
| + if (spill_operand->IsConstant()) return; |
| + if (spill_operand->index() >= 0) { |
| + reusable_slots_.Add(range, local_zone()); |
| + } |
| +} |
| + |
| + |
| +InstructionOperand* RegisterAllocator::TryReuseSpillSlot(LiveRange* range) { |
| + DCHECK(!use_spill_ranges_); |
| + if (reusable_slots_.is_empty()) return NULL; |
| + if (reusable_slots_.first()->End().Value() > |
| + range->TopLevel()->Start().Value()) { |
| + return NULL; |
| + } |
| + InstructionOperand* result = |
| + reusable_slots_.first()->TopLevel()->GetSpillOperand(); |
| + reusable_slots_.Remove(0); |
| + return result; |
| +} |
| + |
| + |
| void RegisterAllocator::ActiveToHandled(LiveRange* range) { |
| DCHECK(active_live_ranges_.Contains(range)); |
| active_live_ranges_.RemoveElement(range); |
| TraceAlloc("Moving live range %d from active to handled\n", range->id()); |
| + if (!use_spill_ranges_) FreeSpillSlot(range); |
| } |
| @@ -1951,6 +1985,7 @@ void RegisterAllocator::InactiveToHandled(LiveRange* range) { |
| DCHECK(inactive_live_ranges_.Contains(range)); |
| inactive_live_ranges_.RemoveElement(range); |
| TraceAlloc("Moving live range %d from inactive to handled\n", range->id()); |
| + if (!use_spill_ranges_) FreeSpillSlot(range); |
| } |
| @@ -2335,7 +2370,23 @@ void RegisterAllocator::Spill(LiveRange* range) { |
| LiveRange* first = range->TopLevel(); |
| if (!first->HasAllocatedSpillOperand()) { |
| - AssignSpillRangeToLiveRange(first); |
| + if (use_spill_ranges_) { |
| + AssignSpillRangeToLiveRange(first); |
| + } else { |
| + InstructionOperand* op = TryReuseSpillSlot(range); |
| + if (op == NULL) { |
| + // Allocate a new operand referring to the spill slot. |
| + RegisterKind kind = range->Kind(); |
| + int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS); |
| + if (kind == DOUBLE_REGISTERS) { |
| + op = DoubleStackSlotOperand::Create(index, local_zone()); |
| + } else { |
| + DCHECK(kind == GENERAL_REGISTERS); |
| + op = StackSlotOperand::Create(index, local_zone()); |
| + } |
| + } |
| + first->SetSpillOperand(op); |
| + } |
| } |
| range->MakeSpilled(code_zone()); |
| } |