LSnapshot *
LIRGeneratorShared::buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKind kind)
{
    LSnapshot *snapshot = LSnapshot::New(gen, rp, kind);
    if (!snapshot)
        return NULL;

    FlattenedMResumePointIter iter(rp);
    if (!iter.init())
        return NULL;

    size_t i = 0;
    for (MResumePoint **it = iter.begin(), **end = iter.end(); it != end; ++it) {
        MResumePoint *mir = *it;
        for (size_t j = 0; j < mir->numOperands(); ++i, ++j) {
            MDefinition *def = mir->getOperand(j);

            if (def->isPassArg())
                def = def->toPassArg()->getArgument();

            LAllocation *a = snapshot->getEntry(i);

            if (def->isUnused()) {
                *a = LConstantIndex::Bogus();
                continue;
            }

            *a = useKeepaliveOrConstant(def);
        }
    }

    return snapshot;
}
LSnapshot *
LIRGeneratorShared::buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKind kind)
{
    LRecoverInfo *recoverInfo = getRecoverInfo(rp);
    if (!recoverInfo)
        return nullptr;

    LSnapshot *snapshot = LSnapshot::New(gen, recoverInfo, kind);
    if (!snapshot)
        return nullptr;

    size_t index = 0;
    LRecoverInfo::OperandIter it(recoverInfo->begin());
    LRecoverInfo::OperandIter end(recoverInfo->end());
    for (; it != end; ++it) {
        // Check that optimized out operands are in eliminable slots.
        MOZ_ASSERT(it.canOptimizeOutIfUnused());

        MDefinition *def = *it;

        if (def->isRecoveredOnBailout())
            continue;

        if (def->isBox())
            def = def->toBox()->getOperand(0);

        // Guards should never be eliminated.
        MOZ_ASSERT_IF(def->isUnused(), !def->isGuard());

        // Snapshot operands other than constants should never be
        // emitted-at-uses. Try-catch support depends on there being no
        // code between an instruction and the LOsiPoint that follows it.
        MOZ_ASSERT_IF(!def->isConstant(), !def->isEmittedAtUses());

        LAllocation *a = snapshot->getEntry(index++);

        if (def->isUnused()) {
            *a = LConstantIndex::Bogus();
            continue;
        }

        *a = useKeepaliveOrConstant(def);
    }

    return snapshot;
}
LSnapshot *
LIRGeneratorShared::buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKind kind)
{
    LSnapshot *snapshot = LSnapshot::New(gen, rp, kind);
    if (!snapshot)
        return NULL;

    FlattenedMResumePointIter iter(rp);
    if (!iter.init())
        return NULL;

    size_t i = 0;
    for (MResumePoint **it = iter.begin(), **end = iter.end(); it != end; ++it) {
        MResumePoint *mir = *it;
        for (size_t j = 0, e = mir->numOperands(); j < e; ++i, ++j) {
            MDefinition *def = mir->getOperand(j);

            if (def->isPassArg())
                def = def->toPassArg()->getArgument();
            JS_ASSERT(!def->isPassArg());

            if (def->isBox())
                def = def->toBox()->getOperand(0);

            // Guards should never be eliminated.
            JS_ASSERT_IF(def->isUnused(), !def->isGuard());

            // Snapshot operands other than constants should never be
            // emitted-at-uses. Try-catch support depends on there being no
            // code between an instruction and the LOsiPoint that follows it.
            JS_ASSERT_IF(!def->isConstant(), !def->isEmittedAtUses());

            LAllocation *a = snapshot->getEntry(i);

            if (def->isUnused()) {
                *a = LConstantIndex::Bogus();
                continue;
            }

            *a = useKeepaliveOrConstant(def);
        }
    }

    return snapshot;
}
void
GreedyAllocator::informSnapshot(LInstruction *ins)
{
    LSnapshot *snapshot = ins->snapshot();
    for (size_t i = 0; i < snapshot->numEntries(); i++) {
        LAllocation *a = snapshot->getEntry(i);
        if (!a->isUse())
            continue;

        // Every definition in a snapshot gets a stack slot. This
        // simplification means we can treat normal snapshots and LOsiPoint
        // snapshots (which follow calls) the same, without adding a special
        // exception to note that registers are spilled at the LOsiPoint.
        VirtualRegister *vr = getVirtualRegister(a->toUse());
        allocateStack(vr);
        *a = vr->backingStack();
    }
}