Bug 1027897 - IonMonkey: Refactor split position bookkeeping into helper classes. r=bhackett

This commit is contained in:
Dan Gohman 2014-06-23 13:42:07 -07:00
Родитель a4c98e274e
Коммит ea7231030a
2 изменённых файлов: 85 добавлений и 49 удалений

Просмотреть файл

@ -12,6 +12,52 @@ 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()
{
@ -1493,7 +1539,7 @@ BacktrackingAllocator::trySplitAcrossHotcode(LiveInterval *interval, bool *succe
IonSpew(IonSpew_RegAlloc, " split across hot range %s", hotRange->toString());
SplitPositionVector splitPositions;
SplitPositions splitPositions;
if (!splitPositions.append(hotRange->from) || !splitPositions.append(hotRange->to))
return false;
*success = true;
@ -1541,7 +1587,7 @@ BacktrackingAllocator::trySplitAfterLastRegisterUse(LiveInterval *interval, Live
IonSpew(IonSpew_RegAlloc, " split after last register use at %u",
lastRegisterTo.pos());
SplitPositionVector splitPositions;
SplitPositions splitPositions;
if (!splitPositions.append(lastRegisterTo))
return false;
*success = true;
@ -1623,41 +1669,13 @@ 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 SplitPositionVector &splitPositions)
BacktrackingAllocator::splitAt(LiveInterval *interval, const SplitPositions &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))
@ -1693,15 +1711,17 @@ BacktrackingAllocator::splitAt(LiveInterval *interval,
lastRegisterUse = interval->start();
}
size_t activeSplitPosition = NextSplitPosition(0, splitPositions, interval->start());
SplitPositionsIterator splitIter(splitPositions);
splitIter.advancePast(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));
activeSplitPosition = NextSplitPosition(activeSplitPosition, splitPositions, iter->pos);
splitIter.advancePast(iter->pos);
} else if (isRegisterUse(iter->use, ins)) {
if (lastRegisterUse.pos() == 0 ||
SplitHere(activeSplitPosition, splitPositions, iter->pos))
splitIter.isBeyondNextSplit(iter->pos))
{
// Place this register use into a different interval from the
// last one if there are any split points between the two uses.
@ -1709,9 +1729,7 @@ BacktrackingAllocator::splitAt(LiveInterval *interval,
newInterval->setSpillInterval(spillInterval);
if (!newIntervals.append(newInterval))
return false;
activeSplitPosition = NextSplitPosition(activeSplitPosition,
splitPositions,
iter->pos);
splitIter.advancePast(iter->pos);
}
newIntervals.back()->addUseAtEnd(new(alloc()) UsePosition(iter->use, iter->pos));
lastRegisterUse = iter->pos;
@ -1766,23 +1784,19 @@ 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.
SplitPositionVector callPositions;
SplitPositions callPositions;
IonSpewStart(IonSpew_RegAlloc, " split across calls at ");
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())
IonSpewCont(IonSpew_RegAlloc, ", ");
IonSpewCont(IonSpew_RegAlloc, "%u", range->from);
if (!callPositions.append(range->from))
return false;
}
}
JS_ASSERT(callPositions.length());
#ifdef DEBUG
IonSpewStart(IonSpew_RegAlloc, " split across calls at ");
for (size_t i = 0; i < callPositions.length(); ++i) {
IonSpewCont(IonSpew_RegAlloc, "%s%u", i != 0 ? ", " : "", callPositions[i].pos());
}
IonSpewFin(IonSpew_RegAlloc);
#endif
return splitAt(interval, callPositions);
}

Просмотреть файл

@ -104,9 +104,32 @@ class BacktrackingVirtualRegister : public VirtualRegister
}
};
class SplitPositionsIterator;
// A sequence of code positions, for tellings BacktrackingAllocator::splitAt
// where to split.
typedef js::Vector<CodePosition, 4, SystemAllocPolicy> SplitPositionVector;
class SplitPositions {
friend class SplitPositionsIterator;
js::Vector<CodePosition, 4, SystemAllocPolicy> 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;
};
class BacktrackingAllocator
: private LiveRangeAllocator<BacktrackingVirtualRegister, /* forLSRA = */ false>
@ -238,8 +261,7 @@ class BacktrackingAllocator
bool chooseIntervalSplit(LiveInterval *interval, LiveInterval *conflict);
bool splitAt(LiveInterval *interval,
const SplitPositionVector &splitPositions);
bool splitAt(LiveInterval *interval, const SplitPositions &splitPositions);
bool trySplitAcrossHotcode(LiveInterval *interval, bool *success);
bool trySplitAfterLastRegisterUse(LiveInterval *interval, LiveInterval *conflict, bool *success);
bool splitAtAllRegisterUses(LiveInterval *interval);