From 90da0401dc42f8528eaaffe4f3600430049b06a5 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Fri, 21 Sep 2012 16:41:23 -0700 Subject: [PATCH] Invalidate scripts when forbidding compilation (bug 792552, r=jandem). --- js/src/ion/Ion.cpp | 30 +++++++++++++++++------------- js/src/ion/Ion.h | 2 +- js/src/ion/VMFunctions.cpp | 7 +++---- js/src/jsfun.cpp | 2 +- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/js/src/ion/Ion.cpp b/js/src/ion/Ion.cpp index 2de39e9630f..a8964c12ebf 100644 --- a/js/src/ion/Ion.cpp +++ b/js/src/ion/Ion.cpp @@ -1047,7 +1047,7 @@ TestIonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osr { if (!IonCompile(cx, script, fun, osrPc, constructing)) { if (!cx->isExceptionPending()) - ForbidCompilation(script); + ForbidCompilation(cx, script); return false; } return true; @@ -1202,7 +1202,7 @@ ion::CanEnterAtBranch(JSContext *cx, HandleScript script, StackFrame *fp, jsbyte // Mark as forbidden if frame can't be handled. if (!CheckFrame(fp)) { - ForbidCompilation(script); + ForbidCompilation(cx, script); return Method_CantCompile; } @@ -1211,7 +1211,7 @@ ion::CanEnterAtBranch(JSContext *cx, HandleScript script, StackFrame *fp, jsbyte MethodStatus status = Compile(cx, script, fun, pc, false); if (status != Method_Compiled) { if (status == Method_CantCompile) - ForbidCompilation(script); + ForbidCompilation(cx, script); return status; } @@ -1258,7 +1258,7 @@ ion::CanEnter(JSContext *cx, HandleScript script, StackFrame *fp, bool newType) // Mark as forbidden if frame can't be handled. if (!CheckFrame(fp)) { - ForbidCompilation(script); + ForbidCompilation(cx, script); return Method_CantCompile; } @@ -1267,7 +1267,7 @@ ion::CanEnter(JSContext *cx, HandleScript script, StackFrame *fp, bool newType) MethodStatus status = Compile(cx, script, fun, NULL, fp->isConstructing()); if (status != Method_Compiled) { if (status == Method_CantCompile) - ForbidCompilation(script); + ForbidCompilation(cx, script); return status; } @@ -1634,7 +1634,9 @@ ion::Invalidate(JSContext *cx, JSScript *script, bool resetUses) JS_ASSERT(script->hasIonScript()); Vector scripts(cx); - scripts.append(script->ionScript()->recompileInfo()); + if (!scripts.append(script->ionScript()->recompileInfo())) + return false; + Invalidate(cx, scripts, resetUses); return true; } @@ -1667,17 +1669,19 @@ ion::MarkFromIon(JSCompartment *comp, Value *vp) } void -ion::ForbidCompilation(JSScript *script) +ion::ForbidCompilation(JSContext *cx, JSScript *script) { IonSpew(IonSpew_Abort, "Disabling Ion compilation of script %s:%d", script->filename, script->lineno); - if (script->hasIonScript() && script->compartment()->needsBarrier()) { - // We're about to remove edges from the JSScript to gcthings - // embedded in the IonScript. Perform one final trace of the - // IonScript for the incremental GC, as it must know about - // those edges. - IonScript::Trace(script->compartment()->barrierTracer(), script->ion); + if (script->hasIonScript()) { + // It is only safe to modify script->ion if the script is not currently + // running, because IonFrameIterator needs to tell what ionScript to + // use (either the one on the JSScript, or the one hidden in the + // breadcrumbs Invalidation() leaves). Therefore, if invalidation + // fails, we cannot disable the script. + if (!Invalidate(cx, script, false)) + return; } script->ion = ION_DISABLED_SCRIPT; diff --git a/js/src/ion/Ion.h b/js/src/ion/Ion.h index 5d9e93d19e7..7ad116ef7f3 100644 --- a/js/src/ion/Ion.h +++ b/js/src/ion/Ion.h @@ -252,7 +252,7 @@ static inline bool IsEnabled(JSContext *cx) return cx->hasRunOption(JSOPTION_ION) && cx->typeInferenceEnabled(); } -void ForbidCompilation(JSScript *script); +void ForbidCompilation(JSContext *cx, JSScript *script); uint32_t UsesBeforeIonRecompile(JSScript *script, jsbytecode *pc); } // namespace ion diff --git a/js/src/ion/VMFunctions.cpp b/js/src/ion/VMFunctions.cpp index 71143fb8fa8..278a2a9fba6 100644 --- a/js/src/ion/VMFunctions.cpp +++ b/js/src/ion/VMFunctions.cpp @@ -39,14 +39,13 @@ InvokeFunction(JSContext *cx, JSFunction *fun, uint32 argc, Value *argv, Value * JSScript *script = GetTopIonJSScript(cx); if (script->hasIonScript() && ++script->ion->slowCallCount >= js_IonOptions.slowCallLimit) { AutoFlushCache afc("InvokeFunction"); - Invalidate(cx, script, false); - // Finally, poison the script so we don't try to run it again - ForbidCompilation(script); + // Poison the script so we don't try to run it again. This will + // trigger invalidation. + ForbidCompilation(cx, script); } } - // TI will return false for monitorReturnTypes, meaning there is no // TypeBarrier or Monitor instruction following this. However, we need to // explicitly monitor if the callee has not been analyzed yet. We special diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 4955e96f407..c1c54f26741 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -131,7 +131,7 @@ fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValu // detecting its use early. JSScript *script = iter.script(); if (!script->hasIonScript()) - ion::ForbidCompilation(script); + ion::ForbidCompilation(cx, script); #endif vp.setObject(*argsobj);