зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1186006 - Add a copy of the successor resume point to the split-edge blocks. r=bhackett
This commit is contained in:
Родитель
5f15eed746
Коммит
3a24c0c1be
|
@ -421,27 +421,11 @@ SplitCriticalEdgesForBlock(MIRGraph& graph, MBasicBlock* block)
|
|||
if (target->numPredecessors() < 2)
|
||||
continue;
|
||||
|
||||
// Create a new block inheriting from the predecessor.
|
||||
MBasicBlock* split = MBasicBlock::NewSplitEdge(graph, block->info(), block);
|
||||
// Create a simple new block which contains a goto and which split the
|
||||
// edge between block and target.
|
||||
MBasicBlock* split = MBasicBlock::NewSplitEdge(graph, block->info(), block, i, target);
|
||||
if (!split)
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -4682,6 +4682,7 @@ LIRGenerator::updateResumeState(MInstruction* ins)
|
|||
void
|
||||
LIRGenerator::updateResumeState(MBasicBlock* block)
|
||||
{
|
||||
MOZ_ASSERT_IF(!mir()->compilingAsmJS(), block->entryResumePoint());
|
||||
lastResumePoint_ = block->entryResumePoint();
|
||||
if (JitSpewEnabled(JitSpew_IonSnapshots) && lastResumePoint_)
|
||||
SpewResumePoint(block, nullptr, lastResumePoint_);
|
||||
|
@ -4726,27 +4727,6 @@ LIRGenerator::visitBlock(MBasicBlock* block)
|
|||
if (!visitInstruction(block->lastIns()))
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -333,13 +333,76 @@ MBasicBlock::NewPendingLoopHeader(MIRGraph& graph, const CompileInfo& info,
|
|||
}
|
||||
|
||||
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::New(graph, nullptr, info, pred,
|
||||
new(graph.alloc()) BytecodeSite(pred->trackedTree(), pred->pc()),
|
||||
SPLIT_EDGE)
|
||||
: MBasicBlock::NewAsmJS(graph, info, pred, SPLIT_EDGE);
|
||||
MBasicBlock* split = nullptr;
|
||||
if (!pred->pc()) {
|
||||
// The predecessor does not have a PC, this is an AsmJS compilation.
|
||||
split = 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*
|
||||
|
|
|
@ -116,7 +116,9 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
|
|||
static MBasicBlock* NewPendingLoopHeader(MIRGraph& graph, const CompileInfo& info,
|
||||
MBasicBlock* pred, BytecodeSite* site,
|
||||
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,
|
||||
MBasicBlock* pred, Kind kind);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче