diff --git a/js/src/jit/BacktrackingAllocator.cpp b/js/src/jit/BacktrackingAllocator.cpp index 81f51666052..3498c0083a6 100644 --- a/js/src/jit/BacktrackingAllocator.cpp +++ b/js/src/jit/BacktrackingAllocator.cpp @@ -12,52 +12,6 @@ using namespace js::jit; using mozilla::DebugOnly; -bool -SplitPositions::append(CodePosition pos) -{ - MOZ_ASSERT(empty() || positions_.back() < pos, - "split positions must be sorted"); - return positions_.append(pos); -} - -bool -SplitPositions::empty() const -{ - return positions_.empty(); -} - -SplitPositionsIterator::SplitPositionsIterator(const SplitPositions &splitPositions) - : splitPositions_(splitPositions), - current_(splitPositions_.positions_.begin()) -{ - JS_ASSERT(!splitPositions_.empty()); -} - -// Proceed to the next split after |pos|. -void -SplitPositionsIterator::advancePast(CodePosition pos) -{ - JS_ASSERT(!splitPositions_.empty()); - while (current_ < splitPositions_.positions_.end() && *current_ <= pos) - ++current_; -} - -// Test whether |pos| is at or beyond the next split. -bool -SplitPositionsIterator::isBeyondNextSplit(CodePosition pos) const -{ - JS_ASSERT(!splitPositions_.empty()); - return current_ < splitPositions_.positions_.end() && pos >= *current_; -} - -// Test whether |pos| is beyond the next split. -bool -SplitPositionsIterator::isEndBeyondNextSplit(CodePosition pos) const -{ - JS_ASSERT(!splitPositions_.empty()); - return current_ < splitPositions_.positions_.end() && pos > *current_; -} - bool BacktrackingAllocator::init() { @@ -1567,7 +1521,7 @@ BacktrackingAllocator::trySplitAcrossHotcode(LiveInterval *interval, bool *succe JitSpew(JitSpew_RegAlloc, " split across hot range %s", hotRange->toString()); - SplitPositions splitPositions; + SplitPositionVector splitPositions; if (!splitPositions.append(hotRange->from) || !splitPositions.append(hotRange->to)) return false; *success = true; @@ -1625,7 +1579,7 @@ BacktrackingAllocator::trySplitAfterLastRegisterUse(LiveInterval *interval, Live JitSpew(JitSpew_RegAlloc, " split after last register use at %u", lastRegisterTo.bits()); - SplitPositions splitPositions; + SplitPositionVector splitPositions; if (!splitPositions.append(lastRegisterTo)) return false; *success = true; @@ -1674,7 +1628,7 @@ BacktrackingAllocator::trySplitBeforeFirstRegisterUse(LiveInterval *interval, Li JitSpew(JitSpew_RegAlloc, " split before first register use at %u", firstRegisterFrom.bits()); - SplitPositions splitPositions; + SplitPositionVector splitPositions; if (!splitPositions.append(firstRegisterFrom)) return false; *success = true; @@ -1756,13 +1710,41 @@ BacktrackingAllocator::splitAtAllRegisterUses(LiveInterval *interval) return split(interval, newIntervals) && requeueIntervals(newIntervals); } +// Find the next split position after the current position. +static size_t NextSplitPosition(size_t activeSplitPosition, + const SplitPositionVector &splitPositions, + CodePosition currentPos) +{ + while (activeSplitPosition < splitPositions.length() && + splitPositions[activeSplitPosition] <= currentPos) + { + ++activeSplitPosition; + } + return activeSplitPosition; +} + +// Test whether the current position has just crossed a split point. +static bool SplitHere(size_t activeSplitPosition, + const SplitPositionVector &splitPositions, + CodePosition currentPos) +{ + return activeSplitPosition < splitPositions.length() && + currentPos >= splitPositions[activeSplitPosition]; +} + bool -BacktrackingAllocator::splitAt(LiveInterval *interval, const SplitPositions &splitPositions) +BacktrackingAllocator::splitAt(LiveInterval *interval, + const SplitPositionVector &splitPositions) { // Split the interval at the given split points. Unlike splitAtAllRegisterUses, // consolidate any register uses which have no intervening split points into the // same resulting interval. + // splitPositions should be non-empty and sorted. + JS_ASSERT(!splitPositions.empty()); + for (size_t i = 1; i < splitPositions.length(); ++i) + JS_ASSERT(splitPositions[i-1] < splitPositions[i]); + // Don't spill the interval until after the end of its definition. CodePosition spillStart = interval->start(); if (isRegisterDefinition(interval)) @@ -1798,17 +1780,15 @@ BacktrackingAllocator::splitAt(LiveInterval *interval, const SplitPositions &spl lastRegisterUse = interval->start(); } - SplitPositionsIterator splitIter(splitPositions); - splitIter.advancePast(interval->start()); - + size_t activeSplitPosition = NextSplitPosition(0, splitPositions, interval->start()); for (UsePositionIterator iter(interval->usesBegin()); iter != interval->usesEnd(); iter++) { LInstruction *ins = insData[iter->pos].ins(); if (iter->pos < spillStart) { newIntervals.back()->addUseAtEnd(new(alloc()) UsePosition(iter->use, iter->pos)); - splitIter.advancePast(iter->pos); + activeSplitPosition = NextSplitPosition(activeSplitPosition, splitPositions, iter->pos); } else if (isRegisterUse(iter->use, ins)) { if (lastRegisterUse.bits() == 0 || - splitIter.isBeyondNextSplit(iter->pos)) + SplitHere(activeSplitPosition, splitPositions, iter->pos)) { // Place this register use into a different interval from the // last one if there are any split points between the two uses. @@ -1816,7 +1796,9 @@ BacktrackingAllocator::splitAt(LiveInterval *interval, const SplitPositions &spl newInterval->setSpillInterval(spillInterval); if (!newIntervals.append(newInterval)) return false; - splitIter.advancePast(iter->pos); + activeSplitPosition = NextSplitPosition(activeSplitPosition, + splitPositions, + iter->pos); } newIntervals.back()->addUseAtEnd(new(alloc()) UsePosition(iter->use, iter->pos)); lastRegisterUse = iter->pos; @@ -1871,19 +1853,23 @@ BacktrackingAllocator::splitAcrossCalls(LiveInterval *interval) // are introduced by buildLivenessInfo only for calls when allocating for // the backtracking allocator. fixedIntervalsUnion is sorted backwards, so // iterate through it backwards. - SplitPositions callPositions; - JitSpewStart(JitSpew_RegAlloc, " split across calls at "); + SplitPositionVector callPositions; for (size_t i = fixedIntervalsUnion->numRanges(); i > 0; i--) { const LiveInterval::Range *range = fixedIntervalsUnion->getRange(i - 1); if (interval->covers(range->from) && interval->covers(range->from.previous())) { - if (!callPositions.empty()) - JitSpewCont(JitSpew_RegAlloc, ", "); - JitSpewCont(JitSpew_RegAlloc, "%u", range->from); if (!callPositions.append(range->from)) return false; } } + JS_ASSERT(callPositions.length()); + +#ifdef DEBUG + JitSpewStart(JitSpew_RegAlloc, " split across calls at "); + for (size_t i = 0; i < callPositions.length(); ++i) { + JitSpewCont(JitSpew_RegAlloc, "%s%u", i != 0 ? ", " : "", callPositions[i].bits()); + } JitSpewFin(JitSpew_RegAlloc); +#endif return splitAt(interval, callPositions); } diff --git a/js/src/jit/BacktrackingAllocator.h b/js/src/jit/BacktrackingAllocator.h index 595e7382186..a95c47c8f59 100644 --- a/js/src/jit/BacktrackingAllocator.h +++ b/js/src/jit/BacktrackingAllocator.h @@ -104,32 +104,9 @@ class BacktrackingVirtualRegister : public VirtualRegister } }; -class SplitPositionsIterator; - // A sequence of code positions, for tellings BacktrackingAllocator::splitAt // where to split. -class SplitPositions { - friend class SplitPositionsIterator; - - js::Vector positions_; - - public: - bool append(CodePosition pos); - bool empty() const; -}; - -// An iterator over the positions in a SplitPositions object. -class SplitPositionsIterator { - const SplitPositions &splitPositions_; - const CodePosition *current_; - - public: - explicit SplitPositionsIterator(const SplitPositions &splitPositions); - - void advancePast(CodePosition pos); - bool isBeyondNextSplit(CodePosition pos) const; - bool isEndBeyondNextSplit(CodePosition pos) const; -}; +typedef js::Vector SplitPositionVector; class BacktrackingAllocator : private LiveRangeAllocator @@ -261,7 +238,8 @@ class BacktrackingAllocator bool chooseIntervalSplit(LiveInterval *interval, LiveInterval *conflict); - bool splitAt(LiveInterval *interval, const SplitPositions &splitPositions); + bool splitAt(LiveInterval *interval, + const SplitPositionVector &splitPositions); bool trySplitAcrossHotcode(LiveInterval *interval, bool *success); bool trySplitAfterLastRegisterUse(LiveInterval *interval, LiveInterval *conflict, bool *success); bool trySplitBeforeFirstRegisterUse(LiveInterval *interval, LiveInterval *conflict, bool *success);