Invalidate scripts when forbidding compilation (bug 792552, r=jandem).

This commit is contained in:
David Anderson 2012-09-21 16:41:23 -07:00
parent 6d1937793a
commit 90da0401dc
4 changed files with 22 additions and 19 deletions

View File

@ -1047,7 +1047,7 @@ TestIonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osr
{ {
if (!IonCompile<TestCompiler>(cx, script, fun, osrPc, constructing)) { if (!IonCompile<TestCompiler>(cx, script, fun, osrPc, constructing)) {
if (!cx->isExceptionPending()) if (!cx->isExceptionPending())
ForbidCompilation(script); ForbidCompilation(cx, script);
return false; return false;
} }
return true; return true;
@ -1202,7 +1202,7 @@ ion::CanEnterAtBranch(JSContext *cx, HandleScript script, StackFrame *fp, jsbyte
// Mark as forbidden if frame can't be handled. // Mark as forbidden if frame can't be handled.
if (!CheckFrame(fp)) { if (!CheckFrame(fp)) {
ForbidCompilation(script); ForbidCompilation(cx, script);
return Method_CantCompile; return Method_CantCompile;
} }
@ -1211,7 +1211,7 @@ ion::CanEnterAtBranch(JSContext *cx, HandleScript script, StackFrame *fp, jsbyte
MethodStatus status = Compile<TestCompiler>(cx, script, fun, pc, false); MethodStatus status = Compile<TestCompiler>(cx, script, fun, pc, false);
if (status != Method_Compiled) { if (status != Method_Compiled) {
if (status == Method_CantCompile) if (status == Method_CantCompile)
ForbidCompilation(script); ForbidCompilation(cx, script);
return status; 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. // Mark as forbidden if frame can't be handled.
if (!CheckFrame(fp)) { if (!CheckFrame(fp)) {
ForbidCompilation(script); ForbidCompilation(cx, script);
return Method_CantCompile; return Method_CantCompile;
} }
@ -1267,7 +1267,7 @@ ion::CanEnter(JSContext *cx, HandleScript script, StackFrame *fp, bool newType)
MethodStatus status = Compile<TestCompiler>(cx, script, fun, NULL, fp->isConstructing()); MethodStatus status = Compile<TestCompiler>(cx, script, fun, NULL, fp->isConstructing());
if (status != Method_Compiled) { if (status != Method_Compiled) {
if (status == Method_CantCompile) if (status == Method_CantCompile)
ForbidCompilation(script); ForbidCompilation(cx, script);
return status; return status;
} }
@ -1634,7 +1634,9 @@ ion::Invalidate(JSContext *cx, JSScript *script, bool resetUses)
JS_ASSERT(script->hasIonScript()); JS_ASSERT(script->hasIonScript());
Vector<types::RecompileInfo> scripts(cx); Vector<types::RecompileInfo> scripts(cx);
scripts.append(script->ionScript()->recompileInfo()); if (!scripts.append(script->ionScript()->recompileInfo()))
return false;
Invalidate(cx, scripts, resetUses); Invalidate(cx, scripts, resetUses);
return true; return true;
} }
@ -1667,17 +1669,19 @@ ion::MarkFromIon(JSCompartment *comp, Value *vp)
} }
void void
ion::ForbidCompilation(JSScript *script) ion::ForbidCompilation(JSContext *cx, JSScript *script)
{ {
IonSpew(IonSpew_Abort, "Disabling Ion compilation of script %s:%d", IonSpew(IonSpew_Abort, "Disabling Ion compilation of script %s:%d",
script->filename, script->lineno); script->filename, script->lineno);
if (script->hasIonScript() && script->compartment()->needsBarrier()) { if (script->hasIonScript()) {
// We're about to remove edges from the JSScript to gcthings // It is only safe to modify script->ion if the script is not currently
// embedded in the IonScript. Perform one final trace of the // running, because IonFrameIterator needs to tell what ionScript to
// IonScript for the incremental GC, as it must know about // use (either the one on the JSScript, or the one hidden in the
// those edges. // breadcrumbs Invalidation() leaves). Therefore, if invalidation
IonScript::Trace(script->compartment()->barrierTracer(), script->ion); // fails, we cannot disable the script.
if (!Invalidate(cx, script, false))
return;
} }
script->ion = ION_DISABLED_SCRIPT; script->ion = ION_DISABLED_SCRIPT;

View File

@ -252,7 +252,7 @@ static inline bool IsEnabled(JSContext *cx)
return cx->hasRunOption(JSOPTION_ION) && cx->typeInferenceEnabled(); return cx->hasRunOption(JSOPTION_ION) && cx->typeInferenceEnabled();
} }
void ForbidCompilation(JSScript *script); void ForbidCompilation(JSContext *cx, JSScript *script);
uint32_t UsesBeforeIonRecompile(JSScript *script, jsbytecode *pc); uint32_t UsesBeforeIonRecompile(JSScript *script, jsbytecode *pc);
} // namespace ion } // namespace ion

View File

@ -39,14 +39,13 @@ InvokeFunction(JSContext *cx, JSFunction *fun, uint32 argc, Value *argv, Value *
JSScript *script = GetTopIonJSScript(cx); JSScript *script = GetTopIonJSScript(cx);
if (script->hasIonScript() && ++script->ion->slowCallCount >= js_IonOptions.slowCallLimit) { if (script->hasIonScript() && ++script->ion->slowCallCount >= js_IonOptions.slowCallLimit) {
AutoFlushCache afc("InvokeFunction"); AutoFlushCache afc("InvokeFunction");
Invalidate(cx, script, false);
// Finally, poison the script so we don't try to run it again // Poison the script so we don't try to run it again. This will
ForbidCompilation(script); // trigger invalidation.
ForbidCompilation(cx, script);
} }
} }
// TI will return false for monitorReturnTypes, meaning there is no // TI will return false for monitorReturnTypes, meaning there is no
// TypeBarrier or Monitor instruction following this. However, we need to // TypeBarrier or Monitor instruction following this. However, we need to
// explicitly monitor if the callee has not been analyzed yet. We special // explicitly monitor if the callee has not been analyzed yet. We special

View File

@ -131,7 +131,7 @@ fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValu
// detecting its use early. // detecting its use early.
JSScript *script = iter.script(); JSScript *script = iter.script();
if (!script->hasIonScript()) if (!script->hasIonScript())
ion::ForbidCompilation(script); ion::ForbidCompilation(cx, script);
#endif #endif
vp.setObject(*argsobj); vp.setObject(*argsobj);