Bug 883630 - Watch for lazy functions when iterating inline Ion frames, clean up methods for accessing function scripts.

This commit is contained in:
Brian Hackett 2013-06-16 10:24:45 -06:00
parent aebd81764e
commit 9a5791cb47
6 changed files with 73 additions and 34 deletions

View File

@ -5316,7 +5316,10 @@ GenerateEntries(ModuleCompiler &m)
static inline bool
TryEnablingIon(JSContext *cx, AsmJSModule::ExitDatum *exitDatum, int32_t argc, Value *argv)
{
JSScript *script = exitDatum->fun->maybeNonLazyScript();
if (!exitDatum->fun->hasScript())
return true;
JSScript *script = exitDatum->fun->nonLazyScript();
if (!script)
return true;

View File

@ -1267,7 +1267,12 @@ InlineFrameIteratorMaybeGC<allowGC>::findNextFrame()
si_.nextFrame();
callee_ = funval.toObject().toFunction();
script_ = callee_->nonLazyScript();
// 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_->getExistingScript();
pc_ = script_->code + si_.pcOffset();
}

View File

@ -634,8 +634,8 @@ CreateLazyScriptsForCompartment(JSContext *cx)
if (obj->compartment() == cx->compartment() && obj->isFunction()) {
JSFunction *fun = obj->toFunction();
if (fun->isInterpretedLazy()) {
LazyScript *lazy = fun->lazyScript();
if (lazy->sourceObject() && !lazy->maybeScript()) {
LazyScript *lazy = fun->lazyScriptOrNull();
if (lazy && lazy->sourceObject() && !lazy->maybeScript()) {
if (!lazyFunctions.append(fun))
return false;
}
@ -666,8 +666,11 @@ CreateLazyScriptsForCompartment(JSContext *cx)
JSObject *obj = i.get<JSObject>();
if (obj->compartment() == cx->compartment() && obj->isFunction()) {
JSFunction *fun = obj->toFunction();
if (fun->isInterpretedLazy() && fun->lazyScript()->maybeScript())
JS_ALWAYS_TRUE(fun->getOrCreateScript(cx));
if (fun->isInterpretedLazy()) {
LazyScript *lazy = fun->lazyScriptOrNull();
if (lazy && lazy->maybeScript())
fun->getExistingScript();
}
}
}

View File

@ -208,6 +208,27 @@ class JSFunction : public JSObject
static bool createScriptForLazilyInterpretedFunction(JSContext *cx, js::HandleFunction fun);
// Function Scripts
//
// Interpreted functions may either have an explicit JSScript (hasScript())
// or be lazy with sufficient information to construct the JSScript if
// necessary (isInterpretedLazy()).
//
// A lazy function will have a LazyScript if the function came from parsed
// source, or NULL if the function is a clone of a self hosted function.
//
// There are several methods to get the script of an interpreted function:
//
// - For all interpreted functions, getOrCreateScript() will get the
// 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, getExistingScript() will get the script and delazify the
// function if necessary.
//
// - For functions known to have a JSScript, nonLazyScript() will get it.
JSScript *getOrCreateScript(JSContext *cx) {
JS_ASSERT(isInterpreted());
JS_ASSERT(cx);
@ -222,35 +243,18 @@ class JSFunction : public JSObject
return u.i.s.script_;
}
static bool maybeGetOrCreateScript(JSContext *cx, js::HandleFunction fun,
js::MutableHandle<JSScript*> script)
{
if (fun->isNative()) {
script.set(NULL);
return true;
}
script.set(fun->getOrCreateScript(cx));
return fun->hasScript();
}
inline JSScript *getExistingScript();
JSScript *nonLazyScript() const {
JS_ASSERT(hasScript());
return JS::HandleScript::fromMarkedLocation(&u.i.s.script_);
}
JSScript *maybeNonLazyScript() const {
return hasScript() ? nonLazyScript() : NULL;
}
js::HeapPtrScript &mutableScript() {
JS_ASSERT(isInterpreted());
return *(js::HeapPtrScript *)&u.i.s.script_;
}
// A lazily interpreted function will have an associated LazyScript if the
// script has not yet been parsed. For functions whose scripts are lazily
// cloned from self hosted code, there is no LazyScript.
js::LazyScript *lazyScript() const {
JS_ASSERT(isInterpretedLazy() && u.i.s.lazy_);
return u.i.s.lazy_;

View File

@ -223,6 +223,25 @@ CloneFunctionObjectIfNotSingleton(JSContext *cx, HandleFunction fun, HandleObjec
} /* namespace js */
inline JSScript *
JSFunction::getExistingScript()
{
JS_ASSERT(isInterpreted());
if (isInterpretedLazy()) {
js::LazyScript *lazy = lazyScript();
JS_ASSERT(lazy->maybeScript());
if (zone()->needsBarrier())
js::LazyScript::writeBarrierPre(lazy);
flags &= ~INTERPRETED_LAZY;
flags |= INTERPRETED;
initScript(lazy->maybeScript());
}
JS_ASSERT(hasScript());
return u.i.s.script_;
}
inline void
JSFunction::setScript(JSScript *script_)
{

View File

@ -1444,11 +1444,15 @@ ValueToScript(JSContext *cx, jsval v, JSFunction **funp = NULL)
else
break;
}
RootedScript script(cx);
JSFunction::maybeGetOrCreateScript(cx, fun, &script);
if (!script)
if (!fun->isInterpreted()) {
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_SCRIPTS_ONLY);
return NULL;
}
JSScript *script = fun->getOrCreateScript(cx);
if (!script)
return NULL;
if (fun && funp)
*funp = fun;
@ -1891,13 +1895,14 @@ DisassembleScript(JSContext *cx, HandleScript script, HandleFunction fun, bool l
JSObject *obj = objects->vector[i];
if (obj->isFunction()) {
Sprint(sp, "\n");
RootedFunction f(cx, obj->toFunction());
RootedScript script(cx);
JSFunction::maybeGetOrCreateScript(cx, f, &script);
if (!script)
RootedFunction fun(cx, obj->toFunction());
if (fun->isInterpreted()) {
RootedScript script(cx, fun->getOrCreateScript(cx));
if (!script || !DisassembleScript(cx, script, fun, lines, recursive, sp))
return false;
} else {
Sprint(sp, "[native code]\n");
else if (!DisassembleScript(cx, script, fun, lines, recursive, sp))
return false;
}
}
}
}