SnapshotIterator::SnapshotIterator(const IonBailoutIterator &iter) : snapshot_(iter.ionScript()->snapshots(), iter.snapshotOffset(), iter.ionScript()->snapshotsRVATableSize(), iter.ionScript()->snapshotsListSize()), recover_(snapshot_, iter.ionScript()->recovers(), iter.ionScript()->recoversSize()), fp_(iter.jsFrame()), machine_(iter.machineState()), ionScript_(iter.ionScript()) { }
SnapshotIterator::SnapshotIterator(const IonBailoutIterator &iter) : SnapshotReader(iter.ionScript()->snapshots() + iter.snapshotOffset(), iter.ionScript()->snapshots() + iter.ionScript()->snapshotsSize()), fp_(iter.jsFrame()), machine_(iter.machineState()), ionScript_(iter.ionScript()) { }
static uint32 ConvertFrames(JSContext *cx, IonActivation *activation, IonBailoutIterator &it) { AssertCanGC(); IonSpew(IonSpew_Bailouts, "Bailing out %s:%u, IonScript %p", it.script()->filename, it.script()->lineno, (void *) it.ionScript()); IonSpew(IonSpew_Bailouts, " reading from snapshot offset %u size %u", it.snapshotOffset(), it.ionScript()->snapshotsSize()); #ifdef DEBUG // Use count is reset after invalidation. Log use count on bailouts to // determine if we have a critical sequence of bailout. if (it.script()->ion == it.ionScript()) { IonSpew(IonSpew_Bailouts, " Current script use count is %u", it.script()->getUseCount()); } #endif SnapshotIterator iter(it); // Set a flag to avoid bailing out on every iteration or function call. Ion can // compile and run the script again after an invalidation. it.ionScript()->setBailoutExpected(); // We use OffTheBooks instead of cx because at this time we cannot iterate // on the stack safely and the reported error attempts to walk the IonMonkey // frames. We cannot iterate on the stack because we have no exit frame to // start Ion frames iteratons. BailoutClosure *br = js_new<BailoutClosure>(); if (!br) return BAILOUT_RETURN_FATAL_ERROR; activation->setBailout(br); StackFrame *fp; if (it.isEntryJSFrame() && cx->fp()->runningInIon() && activation->entryfp()) { // Avoid creating duplicate interpreter frames. This is necessary to // avoid blowing out the interpreter stack, and must be used in // conjunction with inline-OSR from within bailouts (since each Ion // activation must be tied to a unique JSStackFrame for StackIter to // work). // // Note: If the entry frame is a placeholder (a stub frame pushed for // JM -> Ion calls), then we cannot re-use it as it does not have // enough slots. JS_ASSERT(cx->fp() == activation->entryfp()); fp = cx->fp(); cx->regs().sp = fp->base(); } else { br->constructFrame(); if (!cx->stack.pushBailoutArgs(cx, it, br->argsGuard())) return BAILOUT_RETURN_FATAL_ERROR; fp = cx->stack.pushBailoutFrame(cx, it, *br->argsGuard(), br->frameGuard()); } if (!fp) return BAILOUT_RETURN_OVERRECURSED; br->setEntryFrame(fp); JSFunction *callee = it.maybeCallee(); if (callee) fp->formals()[-2].setObject(*callee); if (it.isConstructing()) fp->setConstructing(); while (true) { IonSpew(IonSpew_Bailouts, " restoring frame"); fp->initFromBailout(cx, iter); if (!iter.moreFrames()) break; iter.nextFrame(); fp = PushInlinedFrame(cx, fp); if (!fp) return BAILOUT_RETURN_OVERRECURSED; } jsbytecode *bailoutPc = fp->script()->code + iter.pcOffset(); br->setBailoutPc(bailoutPc); switch (iter.bailoutKind()) { case Bailout_Normal: return BAILOUT_RETURN_OK; case Bailout_TypeBarrier: return BAILOUT_RETURN_TYPE_BARRIER; case Bailout_Monitor: return BAILOUT_RETURN_MONITOR; case Bailout_RecompileCheck: return BAILOUT_RETURN_RECOMPILE_CHECK; case Bailout_BoundsCheck: return BAILOUT_RETURN_BOUNDS_CHECK; case Bailout_Invalidate: return BAILOUT_RETURN_INVALIDATE; case Bailout_CachedShapeGuard: return BAILOUT_RETURN_CACHED_SHAPE_GUARD; // When bailing out from an argument check, none of the code of the // function has run yet. When profiling, this means that the function // hasn't flagged its entry just yet. It has been "entered," however, so // we flag it here manually that the entry has happened. case Bailout_ArgumentCheck: fp->unsetPushedSPSFrame(); Probes::enterScript(cx, fp->script().unsafeGet(), fp->script()->function(), fp); return BAILOUT_RETURN_ARGUMENT_CHECK; } JS_NOT_REACHED("bad bailout kind"); return BAILOUT_RETURN_FATAL_ERROR; }