Bug 980585 - Don't delazify lazy scripts whose outer functions couldn't be compiled. (r=bhackett)

This commit is contained in:
Shu-yu Guo 2014-03-13 18:41:46 -07:00
parent cff466f79f
commit 008ce30860
4 changed files with 37 additions and 2 deletions

View File

@ -0,0 +1,10 @@
var g = newGlobal();
var dbg = new Debugger(g);
try {
g.eval("function f() { var array = ['a', 'b']; [1].map(function () {}); return {array}; }");
} catch (e) {
// Ignore the syntax error.
}
dbg.findScripts();

View File

@ -721,8 +721,7 @@ CreateLazyScriptsForCompartment(JSContext *cx)
// Find all live lazy scripts in the compartment, and via them all root
// lazy functions in the compartment: those which have not been compiled
// and which have a source object, indicating that their parent has been
// compiled.
// and which have a source object, indicating that they have a parent.
for (gc::CellIter i(cx->zone(), gc::FINALIZE_LAZY_SCRIPT); !i.done(); i.next()) {
LazyScript *lazy = i.get<LazyScript>();
JSFunction *fun = lazy->functionNonDelazifying();
@ -731,6 +730,13 @@ CreateLazyScriptsForCompartment(JSContext *cx)
{
MOZ_ASSERT(fun->isInterpretedLazy());
MOZ_ASSERT(lazy == fun->lazyScriptOrNull());
// Only compile lazy scripts that in fact escaped to script. We
// are iterating GC things here, so we might see lazy scripts
// whose enclosing scripts were not successfully compiled.
if (lazy->hasUncompiledEnclosingScript())
continue;
if (!lazyFunctions.append(fun))
return false;
}

View File

@ -3673,6 +3673,24 @@ LazyScript::initRuntimeFields(uint64_t packedFields)
p_.treatAsRunOnce = p.treatAsRunOnce;
}
bool
LazyScript::hasUncompiledEnclosingScript() const
{
// It can happen that we created lazy scripts while compiling an enclosing
// script, but we errored out while compiling that script. When we iterate
// over lazy script in a compartment, we might see lazy scripts that never
// escaped to script and should be ignored.
//
// If the enclosing scope is a function with a null script or has a script
// without code, it was not successfully compiled.
if (!enclosingScope() || !enclosingScope()->is<JSFunction>())
return false;
JSFunction &fun = enclosingScope()->as<JSFunction>();
return fun.isInterpreted() && (!fun.mutableScript() || !fun.nonLazyScript()->code());
}
uint32_t
LazyScript::staticLevel(JSContext *cx) const
{

View File

@ -1825,6 +1825,7 @@ class LazyScript : public gc::BarrieredCell<LazyScript>
return column_;
}
bool hasUncompiledEnclosingScript() const;
uint32_t staticLevel(JSContext *cx) const;
void markChildren(JSTracer *trc);