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());
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)) {
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);
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;
// 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;
// Spill the given life range after position pos.
void SpillAfter(LiveRange* range, LifetimePosition pos);
- // Spill the given life range after position start and up to position end.
+ // Spill the given life range after position [start] and up to position [end].
void SpillBetween(LiveRange* range,
LifetimePosition start,
LifetimePosition end);
+ // Spill the given life range after position [start] and up to position [end].
+ // Range is guaranteed to be spilled at least until position [until].
+ void SpillBetweenUntil(LiveRange* range,
+ LifetimePosition start,
+ LifetimePosition until,
+ LifetimePosition end);
+
void SplitAndSpillIntersecting(LiveRange* range);
// If we are trying to spill a range inside the loop try to
// Indicates success or failure during register allocation.
bool allocation_ok_;
+#ifdef DEBUG
+ LifetimePosition allocation_finger_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(LAllocator);
};