Bug 1186006 - Add a copy of the successor resume point to the split-edge blocks. r=bhackett

This commit is contained in:
Nicolas B. Pierron 2016-03-15 16:55:42 +00:00
Родитель 5f15eed746
Коммит 3a24c0c1be
4 изменённых файлов: 76 добавлений и 47 удалений

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

@ -421,27 +421,11 @@ SplitCriticalEdgesForBlock(MIRGraph& graph, MBasicBlock* block)
if (target->numPredecessors() < 2) if (target->numPredecessors() < 2)
continue; continue;
// Create a new block inheriting from the predecessor. // Create a simple new block which contains a goto and which split the
MBasicBlock* split = MBasicBlock::NewSplitEdge(graph, block->info(), block); // edge between block and target.
MBasicBlock* split = MBasicBlock::NewSplitEdge(graph, block->info(), block, i, target);
if (!split) if (!split)
return false; return false;
split->setLoopDepth(block->loopDepth());
graph.insertBlockAfter(block, split);
split->end(MGoto::New(graph.alloc(), target));
// The entry resume point won't properly reflect state at the start of
// the split edge, so remove it. Split edges start out empty, but might
// have fallible code moved into them later. Rather than immediately
// figure out a valid resume point and pc we can use for the split edge,
// we wait until lowering (see LIRGenerator::visitBlock), where this
// will be easier.
if (MResumePoint* rp = split->entryResumePoint()) {
rp->releaseUses();
split->clearEntryResumePoint();
}
block->replaceSuccessor(i, split);
target->replacePredecessor(block, split);
} }
return true; return true;
} }

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

@ -4682,6 +4682,7 @@ LIRGenerator::updateResumeState(MInstruction* ins)
void void
LIRGenerator::updateResumeState(MBasicBlock* block) LIRGenerator::updateResumeState(MBasicBlock* block)
{ {
MOZ_ASSERT_IF(!mir()->compilingAsmJS(), block->entryResumePoint());
lastResumePoint_ = block->entryResumePoint(); lastResumePoint_ = block->entryResumePoint();
if (JitSpewEnabled(JitSpew_IonSnapshots) && lastResumePoint_) if (JitSpewEnabled(JitSpew_IonSnapshots) && lastResumePoint_)
SpewResumePoint(block, nullptr, lastResumePoint_); SpewResumePoint(block, nullptr, lastResumePoint_);
@ -4726,27 +4727,6 @@ LIRGenerator::visitBlock(MBasicBlock* block)
if (!visitInstruction(block->lastIns())) if (!visitInstruction(block->lastIns()))
return false; return false;
// If we have a resume point check that all the following blocks have one,
// otherwise reuse the last resume point as the entry resume point of the
// basic block. This is used to handle fallible code which is moved/added
// into split edge blocks, which do not have resume points. See
// SplitCriticalEdgesForBlock.
//
// When folding conditions, we might create split-edge blocks which have
// multiple predecessors, in such case it is invalid to have any instruction
// in these blocks, as these blocks have no associated pc, thus we cannot
// safely bailout from such block.
if (lastResumePoint_) {
for (size_t s = 0; s < block->numSuccessors(); s++) {
MBasicBlock* succ = block->getSuccessor(s);
if (!succ->entryResumePoint() && succ->numPredecessors() == 1) {
MOZ_ASSERT(succ->isSplitEdge());
MOZ_ASSERT(succ->phisBegin() == succ->phisEnd());
succ->setEntryResumePoint(lastResumePoint_);
}
}
}
return true; return true;
} }

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

@ -333,13 +333,76 @@ MBasicBlock::NewPendingLoopHeader(MIRGraph& graph, const CompileInfo& info,
} }
MBasicBlock* MBasicBlock*
MBasicBlock::NewSplitEdge(MIRGraph& graph, const CompileInfo& info, MBasicBlock* pred) MBasicBlock::NewSplitEdge(MIRGraph& graph, const CompileInfo& info, MBasicBlock* pred, size_t predEdgeIdx, MBasicBlock* succ)
{ {
return pred->pc() MBasicBlock* split = nullptr;
? MBasicBlock::New(graph, nullptr, info, pred, if (!pred->pc()) {
new(graph.alloc()) BytecodeSite(pred->trackedTree(), pred->pc()), // The predecessor does not have a PC, this is an AsmJS compilation.
SPLIT_EDGE) split = MBasicBlock::NewAsmJS(graph, info, pred, SPLIT_EDGE);
: MBasicBlock::NewAsmJS(graph, info, pred, SPLIT_EDGE); if (!split)
return nullptr;
} else {
// The predecessor has a PC, this is an IonBuilder compilation.
MResumePoint* succEntry = succ->entryResumePoint();
BytecodeSite* site = new(graph.alloc()) BytecodeSite(succ->trackedTree(), succEntry->pc());
split = new(graph.alloc()) MBasicBlock(graph, info, site, SPLIT_EDGE);
if (!split->init())
return nullptr;
// A split edge is used to simplify the graph to avoid having a
// predecessor with multiple successors as well as a successor with
// multiple predecessors. As instructions can be moved in this
// split-edge block, we need to give this block a resume point. To do
// so, we copy the entry resume points of the successor and filter the
// phis to keep inputs from the current edge.
// Propagate the caller resume point from the inherited block.
split->callerResumePoint_ = succ->callerResumePoint();
// Split-edge are created after the interpreter stack emulation. Thus,
// there is no need for creating slots.
split->stackPosition_ = succEntry->stackDepth();
// Create a resume point using our initial stack position.
MResumePoint* splitEntry = new(graph.alloc()) MResumePoint(split, succEntry->pc(),
MResumePoint::ResumeAt);
if (!splitEntry->init(graph.alloc()))
return nullptr;
split->entryResumePoint_ = splitEntry;
// The target entry resume point might have phi operands, keep the
// operands of the phi coming from our edge.
size_t succEdgeIdx = succ->indexForPredecessor(pred);
for (size_t i = 0, e = splitEntry->numOperands(); i < e; i++) {
MDefinition* def = succEntry->getOperand(i);
// This early in the pipeline, we have no recover instructions in
// any entry resume point.
MOZ_ASSERT_IF(def->block() == succ, def->isPhi());
if (def->block() == succ)
def = def->toPhi()->getOperand(succEdgeIdx);
splitEntry->initOperand(i, def);
}
// This is done in the NewAsmJS, so we cannot keep this line below,
// where the rest of the graph is modified.
if (!split->predecessors_.append(pred))
return nullptr;
}
split->setLoopDepth(succ->loopDepth());
// Insert the split edge block in-between.
split->end(MGoto::New(graph.alloc(), succ));
graph.insertBlockAfter(pred, split);
pred->replaceSuccessor(predEdgeIdx, split);
succ->replacePredecessor(pred, split);
return split;
} }
MBasicBlock* MBasicBlock*

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

@ -116,7 +116,9 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
static MBasicBlock* NewPendingLoopHeader(MIRGraph& graph, const CompileInfo& info, static MBasicBlock* NewPendingLoopHeader(MIRGraph& graph, const CompileInfo& info,
MBasicBlock* pred, BytecodeSite* site, MBasicBlock* pred, BytecodeSite* site,
unsigned loopStateSlots); unsigned loopStateSlots);
static MBasicBlock* NewSplitEdge(MIRGraph& graph, const CompileInfo& info, MBasicBlock* pred); static MBasicBlock* NewSplitEdge(MIRGraph& graph, const CompileInfo& info,
MBasicBlock* pred, size_t predEdgeIdx,
MBasicBlock* succ);
static MBasicBlock* NewAsmJS(MIRGraph& graph, const CompileInfo& info, static MBasicBlock* NewAsmJS(MIRGraph& graph, const CompileInfo& info,
MBasicBlock* pred, Kind kind); MBasicBlock* pred, Kind kind);