Bug 1149811. When XDR-decoding a non-lazy function that can be lazified, we need to set up a backpointer from its LazyScript to its JSScript. r=luke

This commit is contained in:
Boris Zbarsky 2015-04-01 12:05:28 -04:00
Родитель 91e4501840
Коммит ab081583b6
4 изменённых файлов: 50 добавлений и 15 удалений

Просмотреть файл

@ -0,0 +1,19 @@
load(libdir + 'bytecode-cache.js');
// Ensure that if a function is encoded when non-lazy but relazifiable, then
// decoded, the resulting LazyScript is marked as being non-lazy so that when
// the debugger tries to delazify things it doesn't get all confused. We just
// use findScripts() to trigger debugger delazification; we don't really care
// about the scripts themselves.
function checkAfter(ctx) {
var dbg = new Debugger(ctx.global);
var allScripts = dbg.findScripts();
assertEq(allScripts.length == 0, false);
}
test = `
function f() { return true; };
f();
`
evalWithCache(test, { assertEqBytecode: true, assertEqResult: true,
checkAfter: checkAfter });

Просмотреть файл

@ -1407,7 +1407,8 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext* cx, HandleFuncti
// chain of their inner functions, or in the case of eval, possibly
// eval'd inner functions. This prohibits re-lazification as
// StaticScopeIter queries isHeavyweight of those functions, which
// requires a non-lazy script.
// requires a non-lazy script. Note that if this ever changes,
// XDRRelazificationInfo will have to be fixed.
bool canRelazify = !lazy->numInnerFunctions() && !lazy->hasDirectEval();
if (script) {

Просмотреть файл

@ -504,21 +504,24 @@ XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun, HandleScript scri
MOZ_ASSERT(end == lazy->end());
MOZ_ASSERT(lineno == lazy->lineno());
MOZ_ASSERT(column == lazy->column());
// We can assert we have no inner functions because we don't
// relazify scripts with inner functions. See
// JSFunction::createScriptForLazilyInterpretedFunction.
MOZ_ASSERT(lazy->numInnerFunctions() == 0);
}
if (!xdr->codeUint64(&packedFields))
return false;
if (mode == XDR_DECODE) {
lazy.set(LazyScript::Create(cx, fun, packedFields, begin, end, lineno, column));
lazy.set(LazyScript::Create(cx, fun, script, enclosingScope,
&script->scriptSourceUnwrap(),
packedFields, begin, end, lineno, column));
// As opposed to XDRLazyScript, we need to restore the runtime bits
// of the script, as we are trying to match the fact this function
// has already been parsed and that it would need to be re-lazified.
lazy->initRuntimeFields(packedFields);
MOZ_ASSERT(!lazy->sourceObject());
lazy->setParent(enclosingScope, &script->scriptSourceUnwrap());
}
}
@ -526,6 +529,9 @@ XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun, HandleScript scri
if (!XDRLazyFreeVariables(xdr, lazy))
return false;
// No need to do anything with inner functions, since we asserted we don't
// have any.
return true;
}
@ -1143,7 +1149,9 @@ js::XDRLazyScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript
}
if (mode == XDR_DECODE)
lazy.set(LazyScript::Create(cx, fun, packedFields, begin, end, lineno, column));
lazy.set(LazyScript::Create(cx, fun, NullPtr(), enclosingScope,
&enclosingScript->scriptSourceUnwrap(),
packedFields, begin, end, lineno, column));
}
// Code free variables.
@ -1167,15 +1175,6 @@ js::XDRLazyScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript
}
}
if (mode == XDR_DECODE) {
MOZ_ASSERT(!lazy->sourceObject());
ScriptSourceObject* sourceObject = &enclosingScript->scriptSourceUnwrap();
// Set the enclosing scope of the lazy function, this would later be
// used to define the environment when the function would be used.
lazy->setParent(enclosingScope, sourceObject);
}
return true;
}
@ -3826,6 +3825,8 @@ LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun,
/* static */ LazyScript*
LazyScript::Create(ExclusiveContext* cx, HandleFunction fun,
HandleScript script, HandleObject enclosingScope,
ScriptSourceObject* sourceObject,
uint64_t packedFields, uint32_t begin, uint32_t end,
uint32_t lineno, uint32_t column)
{
@ -3851,6 +3852,15 @@ LazyScript::Create(ExclusiveContext* cx, HandleFunction fun,
for (i = 0, num = res->numInnerFunctions(); i < num; i++)
functions[i].init(dummyFun);
// Set the enclosing scope of the lazy function, this would later be
// used to define the environment when the function would be used.
MOZ_ASSERT(!res->sourceObject());
res->setParent(enclosingScope, sourceObject);
MOZ_ASSERT(!res->maybeScript());
if (script)
res->initScript(script);
return res;
}

Просмотреть файл

@ -1914,7 +1914,12 @@ class LazyScript : public gc::TenuredCell
// Create a LazyScript and initialize the freeVariables and the
// innerFunctions with dummy values to be replaced in a later initialization
// phase.
//
// The "script" argument to this function can be null. If it's non-null,
// then this LazyScript should be associated with the given JSScript.
static LazyScript* Create(ExclusiveContext* cx, HandleFunction fun,
HandleScript script, HandleObject enclosingScope,
ScriptSourceObject* sourceObject,
uint64_t packedData, uint32_t begin, uint32_t end,
uint32_t lineno, uint32_t column);