diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index ba6774be61b..604f21bc3d4 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -2787,6 +2787,12 @@ BEGIN_CASE(JSOP_FUNAPPLY) InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE; JSScript *newScript = fun->script(); + + if (newScript->compileAndGo && newScript->hasClearedGlobal()) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CLEARED_SCOPE); + goto error; + } + if (!cx->stack.pushInlineFrame(cx, regs, args, *fun, newScript, initial)) goto error; diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index 749ee7566f7..c4da81a16db 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -55,6 +55,10 @@ #include "vm/RegExpObject-inl.h" #include "vm/RegExpStatics-inl.h" +#ifdef JS_METHODJIT +#include "methodjit/Retcon.h" +#endif + using namespace js; JSObject * @@ -360,6 +364,21 @@ GlobalObject::clear(JSContext *cx) * prototypes cached on the global object are immutable. */ cx->compartment->newObjectCache.reset(); + +#ifdef JS_METHODJIT + /* + * Destroy compiled code for any scripts parented to this global. Call ICs + * can directly call scripts which have associated JIT code, and do so + * without checking whether the script's global has been cleared. + */ + for (gc::CellIter i(cx, cx->compartment, gc::FINALIZE_SCRIPT); !i.done(); i.next()) { + JSScript *script = i.get(); + if (script->compileAndGo && script->hasJITCode() && script->hasClearedGlobal()) { + mjit::Recompiler::clearStackReferences(cx, script); + mjit::ReleaseScriptCode(cx, script); + } + } +#endif } bool diff --git a/js/xpconnect/tests/mochitest/test_bug605167.html b/js/xpconnect/tests/mochitest/test_bug605167.html index 29a9044564b..eaa4d2f67ef 100644 --- a/js/xpconnect/tests/mochitest/test_bug605167.html +++ b/js/xpconnect/tests/mochitest/test_bug605167.html @@ -36,7 +36,8 @@ function go() { f().cross_origin_property; ok(false, "should have thrown an exception"); } catch (e) { - ok(/Permission denied/.test(e), "threw the correct exception"); + ok(/Permission denied/.test(e) || /attempt to run compile-and-go script/.test(e), + "threw the correct exception"); } SimpleTest.finish(); break;