зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1027897 - IonMonkey: Refactor split position bookkeeping into helper classes. r=bhackett
This commit is contained in:
Родитель
a4c98e274e
Коммит
ea7231030a
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче