Index: src/lithium-allocator.cc |
diff --git a/src/lithium-allocator.cc b/src/lithium-allocator.cc |
index fa2aa248245c94b7556216a38a280fde26ec0abe..7bddef7f99b940cfaa6c02bf8dfdd3378f34915e 100644 |
--- a/src/lithium-allocator.cc |
+++ b/src/lithium-allocator.cc |
@@ -1546,6 +1546,9 @@ void LAllocator::AllocateRegisters() { |
LiveRange* current = unhandled_live_ranges_.RemoveLast(); |
ASSERT(UnhandledIsSorted()); |
LifetimePosition position = current->Start(); |
+#ifdef DEBUG |
+ allocation_finger_ = position; |
+#endif |
TraceAlloc("Processing interval %d start=%d\n", |
current->id(), |
position.Value()); |
@@ -1670,6 +1673,7 @@ void LAllocator::AddToInactive(LiveRange* range) { |
void LAllocator::AddToUnhandledSorted(LiveRange* range) { |
if (range == NULL || range->IsEmpty()) return; |
ASSERT(!range->HasRegisterAssigned() && !range->IsSpilled()); |
+ ASSERT(allocation_finger_.Value() <= range->Start().Value()); |
for (int i = unhandled_live_ranges_.length() - 1; i >= 0; --i) { |
LiveRange* cur_range = unhandled_live_ranges_.at(i); |
if (range->ShouldBeAllocatedBefore(cur_range)) { |
@@ -2000,7 +2004,15 @@ void LAllocator::SplitAndSpillIntersecting(LiveRange* current) { |
if (next_pos == NULL) { |
SpillAfter(range, spill_pos); |
} else { |
- SpillBetween(range, spill_pos, next_pos->pos()); |
+ // When spilling between spill_pos and next_pos ensure that the range |
+ // remains spilled at least until the start of the current live range. |
+ // This guarantees that we will not introduce new unhandled ranges that |
+ // start before the current range as this violates allocation invariant |
+ // and will lead to an inconsistent state of active and inactive |
+ // live-ranges: ranges are allocated in order of their start positions, |
+ // ranges are retired from active/inactive when the start of the |
+ // current live-range is larger than their end. |
+ SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos()); |
} |
if (!AllocationOk()) return; |
ActiveToHandled(range); |
@@ -2114,6 +2126,14 @@ void LAllocator::SpillAfter(LiveRange* range, LifetimePosition pos) { |
void LAllocator::SpillBetween(LiveRange* range, |
LifetimePosition start, |
LifetimePosition end) { |
+ SpillBetweenUntil(range, start, start, end); |
+} |
+ |
+ |
+void LAllocator::SpillBetweenUntil(LiveRange* range, |
+ LifetimePosition start, |
+ LifetimePosition until, |
+ LifetimePosition end) { |
CHECK(start.Value() < end.Value()); |
LiveRange* second_part = SplitRangeAt(range, start); |
if (!AllocationOk()) return; |
@@ -2124,7 +2144,7 @@ void LAllocator::SpillBetween(LiveRange* range, |
// and put the rest to unhandled. |
LiveRange* third_part = SplitBetween( |
second_part, |
- second_part->Start().InstructionEnd(), |
+ Max(second_part->Start().InstructionEnd(), until), |
end.PrevInstruction().InstructionEnd()); |
if (!AllocationOk()) return; |