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 *ins = *it; if (ins->isRecoveredOnBailout()) continue; LAllocation *type = snapshot->typeOfSlot(index); LAllocation *payload = snapshot->payloadOfSlot(index); ++index; if (ins->isBox()) ins = ins->toBox()->getOperand(0); // Guards should never be eliminated. MOZ_ASSERT_IF(ins->isUnused(), !ins->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(!ins->isConstant(), !ins->isEmittedAtUses()); // The register allocation will fill these fields in with actual // register/stack assignments. During code generation, we can restore // interpreter state with the given information. Note that for // constants, including known types, we record a dummy placeholder, // since we can recover the same information, much cleaner, from MIR. if (ins->isConstant() || ins->isUnused()) { *type = LConstantIndex::Bogus(); *payload = LConstantIndex::Bogus(); } else if (ins->type() != MIRType_Value) { *type = LConstantIndex::Bogus(); *payload = use(ins, LUse(LUse::KEEPALIVE)); } else { *type = useType(ins, LUse::KEEPALIVE); *payload = usePayload(ins, LUse::KEEPALIVE); } } 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 *ins = mir->getOperand(j); LAllocation *type = snapshot->typeOfSlot(i); LAllocation *payload = snapshot->payloadOfSlot(i); if (ins->isPassArg()) ins = ins->toPassArg()->getArgument(); JS_ASSERT(!ins->isPassArg()); if (ins->isBox()) ins = ins->toBox()->getOperand(0); // Guards should never be eliminated. JS_ASSERT_IF(ins->isUnused(), !ins->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(!ins->isConstant(), !ins->isEmittedAtUses()); // The register allocation will fill these fields in with actual // register/stack assignments. During code generation, we can restore // interpreter state with the given information. Note that for // constants, including known types, we record a dummy placeholder, // since we can recover the same information, much cleaner, from MIR. if (ins->isConstant() || ins->isUnused()) { *type = LConstantIndex::Bogus(); *payload = LConstantIndex::Bogus(); } else if (ins->type() != MIRType_Value) { *type = LConstantIndex::Bogus(); *payload = use(ins, LUse::KEEPALIVE); } else { *type = useType(ins, LUse::KEEPALIVE); *payload = usePayload(ins, LUse::KEEPALIVE); } } } return snapshot; }