author | David Anderson <danderson@mozilla.com> |
Fri, 21 Sep 2012 16:41:23 -0700 | |
changeset 107785 | c914225fc39adfa6e9865fea3002a67eca84e211 |
parent 107784 | 6fd36867bac751417fce03468cbe2c771810f24c |
child 107786 | d3319e868a9275aba607378ab8df1399eee9d9a0 |
push id | 23509 |
push user | ryanvm@gmail.com |
push date | Sat, 22 Sep 2012 12:28:38 +0000 |
treeherder | mozilla-central@b461a7cd250e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jandem |
bugs | 792552 |
milestone | 18.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
js/src/ion/Ion.cpp | file | annotate | diff | comparison | revisions | |
js/src/ion/Ion.h | file | annotate | diff | comparison | revisions | |
js/src/ion/VMFunctions.cpp | file | annotate | diff | comparison | revisions | |
js/src/jsfun.cpp | file | annotate | diff | comparison | revisions |
--- a/js/src/ion/Ion.cpp +++ b/js/src/ion/Ion.cpp @@ -1042,17 +1042,17 @@ IonCompile(JSContext *cx, JSScript *scri return true; } bool TestIonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing) { if (!IonCompile<TestCompiler>(cx, script, fun, osrPc, constructing)) { if (!cx->isExceptionPending()) - ForbidCompilation(script); + ForbidCompilation(cx, script); return false; } return true; } static bool CheckFrame(StackFrame *fp) { @@ -1197,26 +1197,26 @@ ion::CanEnterAtBranch(JSContext *cx, Han return Method_Skipped; // Optionally ignore on user request. if (!js_IonOptions.osr) return Method_Skipped; // Mark as forbidden if frame can't be handled. if (!CheckFrame(fp)) { - ForbidCompilation(script); + ForbidCompilation(cx, script); return Method_CantCompile; } // Attempt compilation. Returns Method_Compiled if already compiled. JSFunction *fun = fp->isFunctionFrame() ? fp->fun() : NULL; MethodStatus status = Compile<TestCompiler>(cx, script, fun, pc, false); if (status != Method_Compiled) { if (status == Method_CantCompile) - ForbidCompilation(script); + ForbidCompilation(cx, script); return status; } if (script->ion->osrPc() != pc) return Method_Skipped; // This can GC, so afterward, script->ion is not guaranteed to be valid. if (!cx->compartment->ionCompartment()->enterJIT(cx)) @@ -1253,26 +1253,26 @@ ion::CanEnter(JSContext *cx, HandleScrip RootedObject obj(cx, js_CreateThisForFunction(cx, callee, newType)); if (!obj) return Method_Skipped; fp->functionThis().setObject(*obj); } // Mark as forbidden if frame can't be handled. if (!CheckFrame(fp)) { - ForbidCompilation(script); + ForbidCompilation(cx, script); return Method_CantCompile; } // Attempt compilation. Returns Method_Compiled if already compiled. JSFunction *fun = fp->isFunctionFrame() ? fp->fun() : NULL; MethodStatus status = Compile<TestCompiler>(cx, script, fun, NULL, fp->isConstructing()); if (status != Method_Compiled) { if (status == Method_CantCompile) - ForbidCompilation(script); + ForbidCompilation(cx, script); return status; } // This can GC, so afterward, script->ion is not guaranteed to be valid. if (!cx->compartment->ionCompartment()->enterJIT(cx)) return Method_Error; if (!script->ion) @@ -1629,17 +1629,19 @@ ion::Invalidate(JSContext *cx, const Vec } bool ion::Invalidate(JSContext *cx, JSScript *script, bool resetUses) { JS_ASSERT(script->hasIonScript()); Vector<types::RecompileInfo> scripts(cx); - scripts.append(script->ionScript()->recompileInfo()); + if (!scripts.append(script->ionScript()->recompileInfo())) + return false; + Invalidate(cx, scripts, resetUses); return true; } void ion::FinishInvalidation(FreeOp *fop, JSScript *script) { if (!script->hasIonScript()) @@ -1662,27 +1664,29 @@ ion::FinishInvalidation(FreeOp *fop, JSS void ion::MarkFromIon(JSCompartment *comp, Value *vp) { gc::MarkValueUnbarriered(comp->barrierTracer(), vp, "write barrier"); } 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; } uint32_t ion::UsesBeforeIonRecompile(JSScript *script, jsbytecode *pc) {
--- a/js/src/ion/Ion.h +++ b/js/src/ion/Ion.h @@ -247,16 +247,16 @@ void AttachFinishedCompilations(JSContex void FinishOffThreadBuilder(IonBuilder *builder); bool TestIonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing); 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 } // namespace js #endif // jsion_ion_h__
--- a/js/src/ion/VMFunctions.cpp +++ b/js/src/ion/VMFunctions.cpp @@ -34,24 +34,23 @@ InvokeFunction(JSContext *cx, JSFunction // In order to prevent massive bouncing between Ion and JM, see if we keep // hitting functions that are uncompilable. if (fun->isInterpreted() && !fun->script()->canIonCompile()) { 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 // case this to avoid the cost of ion::GetPcScript if we must take this // path frequently. bool needsMonitor = ShouldMonitorReturnType(fun); // Data in the argument vector is arranged for a JIT -> JIT call.
--- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -126,17 +126,17 @@ fun_getProperty(JSContext *cx, HandleObj #ifdef JS_ION // If this script hasn't been compiled yet, make sure it will never // be compiled. IonMonkey does not guarantee |f.arguments| can be // fully recovered, so we try to mitigate observing this behavior by // detecting its use early. JSScript *script = iter.script(); if (!script->hasIonScript()) - ion::ForbidCompilation(script); + ion::ForbidCompilation(cx, script); #endif vp.setObject(*argsobj); return true; } #ifdef JS_METHODJIT if (iter.isScript() && iter.isIon())