From 0767e097c87b9ee922c4b5a648286fd51289b002 Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Sat, 19 Apr 2014 13:45:59 +0200 Subject: [PATCH] Bug 976536 - Fix JSFunction::existingScript returning NULL in some cases. r=till --- js/src/jit/BaselineBailouts.cpp | 6 +++--- js/src/jit/IonFrames.cpp | 2 +- js/src/jsfun.h | 20 +++++++++++++------- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/js/src/jit/BaselineBailouts.cpp b/js/src/jit/BaselineBailouts.cpp index bd4ad26e4558..9bffcb9d968d 100644 --- a/js/src/jit/BaselineBailouts.cpp +++ b/js/src/jit/BaselineBailouts.cpp @@ -1339,9 +1339,10 @@ jit::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, IonBailoutIt SnapshotIterator snapIter(iter); RootedFunction callee(cx, iter.maybeCallee()); + RootedScript scr(cx, iter.script()); if (callee) { IonSpew(IonSpew_BaselineBailouts, " Callee function (%s:%u)", - callee->existingScript()->filename(), callee->existingScript()->lineno()); + scr->filename(), scr->lineno()); } else { IonSpew(IonSpew_BaselineBailouts, " No callee!"); } @@ -1358,7 +1359,6 @@ jit::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, IonBailoutIt RootedScript caller(cx); jsbytecode *callerPC = nullptr; RootedFunction fun(cx, callee); - RootedScript scr(cx, iter.script()); AutoValueVector startFrameFormals(cx); RootedScript topCaller(cx); @@ -1400,7 +1400,7 @@ jit::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, IonBailoutIt caller = scr; callerPC = callPC; fun = nextCallee; - scr = fun->existingScript(); + scr = fun->existingScriptForInlinedFunction(); // Save top caller info for adjusting SPS frames later. if (!topCaller) { diff --git a/js/src/jit/IonFrames.cpp b/js/src/jit/IonFrames.cpp index 9225cde51cf6..12bb0fbd64e3 100644 --- a/js/src/jit/IonFrames.cpp +++ b/js/src/jit/IonFrames.cpp @@ -1652,7 +1652,7 @@ InlineFrameIteratorMaybeGC::findNextFrame() // Inlined functions may be clones that still point to the lazy script // for the executed script, if they are clones. The actual script // exists though, just make sure the function points to it. - script_ = callee_->existingScript(); + script_ = callee_->existingScriptForInlinedFunction(); MOZ_ASSERT(script_->hasBaselineScript()); pc_ = script_->offsetToPC(si_.pcOffset()); diff --git a/js/src/jsfun.h b/js/src/jsfun.h index d11f1ac52f73..1c15c2af3653 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -268,9 +268,9 @@ class JSFunction : public JSObject // JSScript, delazifying the function if necessary. This is the safest to // use, but has extra checks, requires a cx and may trigger a GC. // - // - For functions which may have a LazyScript but whose JSScript is known - // to exist, existingScript() will get the script and delazify the - // function if necessary. + // - For inlined functions which may have a LazyScript but whose JSScript + // is known to exist, existingScriptForInlinedFunction() will get the + // script and delazify the function if necessary. // // - For functions known to have a JSScript, nonLazyScript() will get it. @@ -286,12 +286,18 @@ class JSFunction : public JSObject return nonLazyScript(); } - JSScript *existingScript() { - JS_ASSERT(isInterpreted()); + JSScript *existingScriptForInlinedFunction() { + MOZ_ASSERT(isInterpreted()); if (isInterpretedLazy()) { + // Get the script from the canonical function. Ion used the + // canonical function to inline the script and because it has + // Baseline code it has not been relazified. Note that we can't + // use lazyScript->script_ here as it may be null in some cases, + // see bug 976536. js::LazyScript *lazy = lazyScript(); - JSScript *script = lazy->maybeScript(); - JS_ASSERT(script); + JSFunction *fun = lazy->functionNonDelazifying(); + MOZ_ASSERT(fun); + JSScript *script = fun->nonLazyScript(); if (shadowZone()->needsBarrier()) js::LazyScript::writeBarrierPre(lazy);