Bug 1042729 part 2 - Ensure that a resume point belongs to one instruction. r=h4writer

This commit is contained in:
Nicolas B. Pierron 2014-08-05 04:29:12 -07:00
parent 4ded2e7b05
commit 7edba63c04
7 changed files with 55 additions and 33 deletions

View File

@ -1744,10 +1744,15 @@ jit::AssertBasicGraphCoherency(MIRGraph &graph)
for (size_t i = 0; i < block->numPredecessors(); i++)
JS_ASSERT(CheckPredecessorImpliesSuccessor(*block, block->getPredecessor(i)));
MOZ_ASSERT_IF(block->entryResumePoint(), !block->entryResumePoint()->instruction());
for (MResumePointIterator iter(block->resumePointsBegin()); iter != block->resumePointsEnd(); iter++) {
// We cannot yet assert that is there is no instruction then this is
// the entry resume point because we are still storing resume points
// in the InlinePropertyTable.
MOZ_ASSERT_IF(iter->instruction(), iter->instruction()->block() == *block);
for (uint32_t i = 0, e = iter->numOperands(); i < e; i++) {
if (iter->getUseFor(i)->hasProducer())
JS_ASSERT(CheckOperandImpliesUse(*iter, iter->getOperand(i)));
MOZ_ASSERT(iter->getUseFor(i)->hasProducer());
MOZ_ASSERT(CheckOperandImpliesUse(*iter, iter->getOperand(i)));
}
}
for (MPhiIterator phi(block->phisBegin()); phi != block->phisEnd(); phi++) {
@ -1765,11 +1770,8 @@ jit::AssertBasicGraphCoherency(MIRGraph &graph)
if (iter->isInstruction()) {
if (MResumePoint *resume = iter->toInstruction()->resumePoint()) {
if (MInstruction *ins = resume->instruction())
JS_ASSERT(ins->block() == iter->block());
for (uint32_t i = 0, e = resume->numOperands(); i < e; i++)
MOZ_ASSERT(resume->getUseFor(i)->hasProducer());
MOZ_ASSERT(resume->instruction() == *iter);
MOZ_ASSERT(resume->block() == *block);
}
}

View File

@ -6051,7 +6051,6 @@ IonBuilder::resume(MInstruction *ins, jsbytecode *pc, MResumePoint::Mode mode)
if (!resumePoint)
return false;
ins->setResumePoint(resumePoint);
resumePoint->setInstruction(ins);
return true;
}

View File

@ -231,6 +231,23 @@ MDefinition::analyzeEdgeCasesBackward()
{
}
void
MInstruction::setResumePoint(MResumePoint *resumePoint)
{
JS_ASSERT(!resumePoint_);
resumePoint_ = resumePoint;
resumePoint_->setInstruction(this);
}
void
MInstruction::stealResumePoint(MInstruction *ins)
{
MOZ_ASSERT(ins->resumePoint_->instruction() == ins);
resumePoint_ = ins->resumePoint_;
ins->resumePoint_ = nullptr;
resumePoint_->replaceInstruction(this);
}
static bool
MaybeEmulatesUndefined(MDefinition *op)
{

View File

@ -779,15 +779,9 @@ class MInstruction
: resumePoint_(nullptr)
{ }
void setResumePoint(MResumePoint *resumePoint) {
JS_ASSERT(!resumePoint_);
resumePoint_ = resumePoint;
}
void setResumePoint(MResumePoint *resumePoint);
// Used to transfer the resume point to the rewritten instruction.
void stealResumePoint(MInstruction *ins) {
resumePoint_ = ins->resumePoint_;
ins->resumePoint_ = nullptr;
}
void stealResumePoint(MInstruction *ins);
MResumePoint *resumePoint() const {
return resumePoint_;
}
@ -10302,6 +10296,12 @@ class MResumePoint MOZ_FINAL : public MNode, public InlineForwardListNode<MResum
return instruction_;
}
void setInstruction(MInstruction *ins) {
MOZ_ASSERT(!instruction_);
instruction_ = ins;
}
// Only to be used by stealResumePoint.
void replaceInstruction(MInstruction *ins) {
MOZ_ASSERT(instruction_);
instruction_ = ins;
}
Mode mode() const {

View File

@ -448,6 +448,9 @@ MBasicBlock::inheritSlots(MBasicBlock *parent)
bool
MBasicBlock::initEntrySlots(TempAllocator &alloc)
{
// Remove the previous resume point.
discardResumePoint(entryResumePoint_);
// Create a resume point using our initial stack state.
entryResumePoint_ = MResumePoint::New(alloc, this, pc(), callerResumePoint(),
MResumePoint::ResumeAt);
@ -716,6 +719,19 @@ AssertSafelyDiscardable(MDefinition *def)
#endif
}
void
MBasicBlock::discardResumePoint(MResumePoint *rp)
{
rp->discardUses();
MResumePointIterator iter = resumePointsBegin();
while (*iter != rp) {
// We should reach it before reaching the end.
MOZ_ASSERT(iter != resumePointsEnd());
iter++;
}
resumePoints_.removeAt(iter);
}
void
MBasicBlock::prepareForDiscard(MInstruction *ins, ReferencesType refType /* = RefType_Default */)
{
@ -724,19 +740,8 @@ MBasicBlock::prepareForDiscard(MInstruction *ins, ReferencesType refType /* = Re
MOZ_ASSERT(ins->block() == this);
MResumePoint *rp = ins->resumePoint();
if (refType & RefType_DiscardResumePoint && rp) {
rp->discardUses();
// Resume point are using a forward list only, so we need to iterate
// to the location of the resume point in order to remove it.
MResumePointIterator iter = resumePointsBegin();
while (*iter != rp) {
// If the instruction has a resume point, then it should be part
// of the basic block list of resume points.
MOZ_ASSERT(iter != resumePointsEnd());
iter++;
}
resumePoints_.removeAt(iter);
}
if (refType & RefType_DiscardResumePoint && rp)
discardResumePoint(rp);
// We need to assert that instructions have no uses after removing the their
// resume points operands as they could be captured by their own resume

View File

@ -61,6 +61,8 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
// as needed.
void setVariable(uint32_t slot);
void discardResumePoint(MResumePoint *rp);
enum ReferencesType {
RefType_AssertNoUses = 1 << 0,
RefType_DiscardOperands = 1 << 1,

View File

@ -337,11 +337,8 @@ static void
TransplantResumePoint(MInstruction *oldInstruction, MInstruction *replacementInstruction)
{
MOZ_ASSERT(!oldInstruction->isDiscarded());
if (MResumePoint *rp = oldInstruction->resumePoint()) {
if (oldInstruction->resumePoint())
replacementInstruction->stealResumePoint(oldInstruction);
if (rp->instruction() == oldInstruction)
rp->setInstruction(replacementInstruction);
}
}
bool