Bug 825447 - Populate safepoints directly in backtracking register allocator, r=jandem.

This commit is contained in:
Brian Hackett 2013-01-04 07:53:20 -07:00
parent d045dbdfe2
commit 8545f79247
7 changed files with 137 additions and 55 deletions

View File

@ -140,7 +140,7 @@ BacktrackingAllocator::go()
if (IonSpewEnabled(IonSpew_RegAlloc))
dumpAllocations();
return resolveControlFlow() && reifyAllocations();
return resolveControlFlow() && reifyAllocations() && populateSafepoints();
}
static bool
@ -1021,6 +1021,8 @@ BacktrackingAllocator::reifyAllocations()
}
}
}
addLiveRegistersForInterval(reg, interval);
}
}
@ -1028,6 +1030,79 @@ BacktrackingAllocator::reifyAllocations()
return true;
}
bool
BacktrackingAllocator::populateSafepoints()
{
size_t firstSafepoint = 0;
for (uint32_t i = 0; i < vregs.numVirtualRegisters(); i++) {
BacktrackingVirtualRegister *reg = &vregs[i];
if (!reg->def() || (!IsTraceable(reg) && !IsNunbox(reg)))
continue;
firstSafepoint = findFirstSafepoint(reg->getInterval(0), firstSafepoint);
if (firstSafepoint >= graph.numSafepoints())
break;
// Find the furthest endpoint.
CodePosition end = reg->getInterval(0)->end();
for (size_t j = 1; j < reg->numIntervals(); j++)
end = Max(end, reg->getInterval(j)->end());
for (size_t j = firstSafepoint; j < graph.numSafepoints(); j++) {
LInstruction *ins = graph.getSafepoint(j);
// Stop processing safepoints if we know we're out of this virtual
// register's range.
if (end < inputOf(ins))
break;
// Include temps but not instruction outputs. Also make sure MUST_REUSE_INPUT
// is not used with gcthings or nunboxes, or we would have to add the input reg
// to this safepoint.
if (ins == reg->ins() && !reg->isTemp()) {
DebugOnly<LDefinition*> def = reg->def();
JS_ASSERT_IF(def->policy() == LDefinition::MUST_REUSE_INPUT,
def->type() == LDefinition::GENERAL || def->type() == LDefinition::DOUBLE);
continue;
}
LSafepoint *safepoint = ins->safepoint();
LiveInterval *interval = reg->intervalFor(inputOf(ins));
if (!interval)
continue;
LAllocation *a = interval->getAllocation();
if (a->isGeneralReg() && ins->isCall())
continue;
switch (reg->type()) {
case LDefinition::OBJECT:
safepoint->addGcPointer(*a);
break;
#ifdef JS_NUNBOX32
case LDefinition::TYPE:
safepoint->addNunboxType(i, *a);
break;
case LDefinition::PAYLOAD:
safepoint->addNunboxPayload(i, *a);
break;
#else
case LDefinition::BOX:
safepoint->addBoxedValue(*a);
break;
#endif
default:
JS_NOT_REACHED("Bad register type");
}
}
}
return true;
}
void
BacktrackingAllocator::dumpRegisterGroups()
{

View File

@ -201,6 +201,7 @@ class BacktrackingAllocator : public LiveRangeAllocator<BacktrackingVirtualRegis
bool resolveControlFlow();
bool reifyAllocations();
bool populateSafepoints();
void dumpRegisterGroups();
void dumpLiveness();

View File

@ -1001,13 +1001,17 @@ CompileBackEnd(MIRGenerator *mir)
}
case RegisterAllocator_Backtracking: {
#ifdef DEBUG
integrity.record();
#endif
BacktrackingAllocator regalloc(mir, &lirgen, *lir);
if (!regalloc.go())
return NULL;
if (!integrity.check(true))
return NULL;
#ifdef DEBUG
integrity.check(false);
#endif
IonSpewPass("Allocate Registers [Backtracking]");
break;

View File

@ -422,31 +422,7 @@ LinearScanAllocator::reifyAllocations()
}
}
// Fill in the live register sets for all non-call safepoints.
LAllocation *a = interval->getAllocation();
if (a->isRegister()) {
// Don't add output registers to the safepoint.
CodePosition start = interval->start();
if (interval->index() == 0 && !reg->isTemp())
start = start.next();
size_t i = findFirstNonCallSafepoint(start);
for (; i < graph.numNonCallSafepoints(); i++) {
LInstruction *ins = graph.getNonCallSafepoint(i);
CodePosition pos = inputOf(ins);
// Safepoints are sorted, so we can shortcut out of this loop
// if we go out of range.
if (interval->end() < pos)
break;
if (!interval->covers(pos))
continue;
LSafepoint *safepoint = ins->safepoint();
safepoint->addLiveRegister(a->toRegister());
}
}
addLiveRegistersForInterval(reg, interval);
}} // Iteration over virtual register intervals.
// Set the graph overall stack height
@ -455,31 +431,6 @@ LinearScanAllocator::reifyAllocations()
return true;
}
// Finds the first safepoint that is within range of an interval.
size_t
LinearScanAllocator::findFirstSafepoint(LiveInterval *interval, size_t startFrom)
{
size_t i = startFrom;
for (; i < graph.numSafepoints(); i++) {
LInstruction *ins = graph.getSafepoint(i);
if (interval->start() <= inputOf(ins))
break;
}
return i;
}
size_t
LinearScanAllocator::findFirstNonCallSafepoint(CodePosition from)
{
size_t i = 0;
for (; i < graph.numNonCallSafepoints(); i++) {
LInstruction *ins = graph.getNonCallSafepoint(i);
if (from <= inputOf(ins))
break;
}
return i;
}
inline bool
LinearScanAllocator::isSpilledAt(LiveInterval *interval, CodePosition pos)
{

View File

@ -110,8 +110,6 @@ class LinearScanAllocator : public LiveRangeAllocator<LinearScanVirtualRegister>
bool canCoexist(LiveInterval *a, LiveInterval *b);
bool moveInputAlloc(CodePosition pos, LAllocation *from, LAllocation *to);
void setIntervalRequirement(LiveInterval *interval);
size_t findFirstSafepoint(LiveInterval *interval, size_t firstSafepoint);
size_t findFirstNonCallSafepoint(CodePosition from);
bool isSpilledAt(LiveInterval *interval, CodePosition pos);
#ifdef DEBUG

View File

@ -603,6 +603,48 @@ class LiveRangeAllocator : public RegisterAllocator
LMoveGroup *moves = getMoveGroupAfter(pos);
return addMove(moves, from, to);
}
void addLiveRegistersForInterval(VirtualRegister *reg, LiveInterval *interval)
{
// Fill in the live register sets for all non-call safepoints.
LAllocation *a = interval->getAllocation();
if (!a->isRegister())
return;
// Don't add output registers to the safepoint.
CodePosition start = interval->start();
if (interval->index() == 0 && !reg->isTemp())
start = start.next();
size_t i = findFirstNonCallSafepoint(start);
for (; i < graph.numNonCallSafepoints(); i++) {
LInstruction *ins = graph.getNonCallSafepoint(i);
CodePosition pos = inputOf(ins);
// Safepoints are sorted, so we can shortcut out of this loop
// if we go out of range.
if (interval->end() < pos)
break;
if (!interval->covers(pos))
continue;
LSafepoint *safepoint = ins->safepoint();
safepoint->addLiveRegister(a->toRegister());
}
}
// Finds the first safepoint that is within range of an interval.
size_t findFirstSafepoint(LiveInterval *interval, size_t startFrom)
{
size_t i = startFrom;
for (; i < graph.numSafepoints(); i++) {
LInstruction *ins = graph.getSafepoint(i);
if (interval->start() <= inputOf(ins))
break;
}
return i;
}
};
} // namespace ion

View File

@ -336,6 +336,17 @@ class RegisterAllocator
LMoveGroup *getMoveGroupAfter(CodePosition pos) {
return getMoveGroupAfter(pos.ins());
}
size_t findFirstNonCallSafepoint(CodePosition from)
{
size_t i = 0;
for (; i < graph.numNonCallSafepoints(); i++) {
LInstruction *ins = graph.getNonCallSafepoint(i);
if (from <= inputOf(ins))
break;
}
return i;
}
};
} // namespace ion