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(); } }