зеркало из 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)
|
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);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче