diff --git a/js/src/jit-test/tests/basic/testBug663789-2.js b/js/src/jit-test/tests/basic/testBug663789-2.js index 463116488428..d7ee30599867 100644 --- a/js/src/jit-test/tests/basic/testBug663789-2.js +++ b/js/src/jit-test/tests/basic/testBug663789-2.js @@ -1,11 +1,6 @@ // |jit-test| debug;mjit -/* - * NOTE: this evalInFrame is explicitly exposing an optimization artifact that - * InvokeSessionGuard leaves the callee frame on the stack between invocations. - * If this ever gets fixed or InvokeSessionGuard gets removed, this test will - * fail and it can be removed. - */ -o = { toString:function() { return evalInFrame(1, "arguments; x") } } +o = { toString:function() { return evalInFrame(1, "x") } } +var x = 'C'; var s = "aaaaaaaaaa".replace(/a/g, function() { var x = 'B'; return o }); -assertEq(s, "BBBBBBBBBB"); +assertEq(s, "CCCCCCCCCC"); diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index face66854803..fdef86e682a8 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -709,6 +709,9 @@ InvokeSessionGuard::start(JSContext *cx, const Value &calleev, const Value &this savedCallee_ = args_.calleev() = calleev; savedThis_ = args_.thisv() = thisv; + /* If anyone (through jsdbgapi) finds this frame, make it safe. */ + MakeRangeGCSafe(args_.argv(), args_.argc()); + do { /* Hoist dynamic checks from scripted Invoke. */ if (!calleev.isObject()) diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index def187658b52..24d14ee99224 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -963,6 +963,12 @@ StackIter::settleOnNewState() continue; } + /* Censor pushed-but-not-active frames from InvokeSessionGuard. */ + if (containsCall && !calls_->active() && calls_->argv() == fp_->actualArgs()) { + popFrame(); + continue; + } + /* * As an optimization, there is no CallArgsList element pushed for * natives called directly by a script (compiled or interpreted).