Bug 619565 - Fix activation object handling by InvokeSessionGuard (r=waldo,a=shaver)

--HG--
extra : rebase_source : 24e4d6ecf1cb9696fda7468eb631f13d92d7ab7a
This commit is contained in:
Luke Wagner 2011-02-24 12:34:33 -08:00
Родитель 52b61d8acb
Коммит bfdc0faf9f
5 изменённых файлов: 40 добавлений и 19 удалений

Просмотреть файл

@ -0,0 +1,8 @@
// |jit-test| mjitalways;debug
[1,2,3,4,5,6,7,8].forEach(
function(x) {
// evalInFrame means lightweight gets call obj
assertEq(evalInFrame(0, "x"), x);
}
);

Просмотреть файл

@ -0,0 +1,12 @@
otherGlobal = newGlobal("same-compartment");
otherGlobal.poison = Proxy.create({});
callee = new otherGlobal.Function("return this.poison;");
var caught = false;
try {
[1,2,3,4,5,6,7,8].sort(callee);
} catch(e) {
assertEq(e instanceof Error, true);
caught = true;
}
assertEq(caught, true);

Просмотреть файл

@ -461,6 +461,7 @@ class InvokeFrameGuard
InvokeFrameGuard() : cx_(NULL) {}
~InvokeFrameGuard() { if (pushed()) pop(); }
bool pushed() const { return cx_ != NULL; }
JSContext *pushedFrameContext() const { JS_ASSERT(pushed()); return cx_; }
void pop();
JSStackFrame *fp() const { return regs_.fp; }
};

Просмотреть файл

@ -775,7 +775,14 @@ InvokeSessionGuard::start(JSContext *cx, const Value &calleev, const Value &this
if (fun->isNative())
break;
script_ = fun->script();
if (fun->isHeavyweight() || script_->isEmpty() || cx->compartment->debugMode)
if (fun->isHeavyweight() || script_->isEmpty())
break;
/*
* The frame will remain pushed even when the callee isn't active which
* will affect the observable current global, so avoid any change.
*/
if (callee.getGlobal() != GetGlobalForScopeChain(cx))
break;
/* Push the stack frame once for the session. */

Просмотреть файл

@ -102,14 +102,9 @@ JSStackFrame::resetInvokeCallFrame()
{
/* Undo changes to frame made during execution; see initCallFrame */
if (hasArgsObj())
args.nactual = argsObj().getArgsInitialLength();
JS_ASSERT(!(flags_ & ~(JSFRAME_FUNCTION |
JSFRAME_OVERFLOW_ARGS |
JSFRAME_UNDERFLOW_ARGS |
JSFRAME_HAS_CALL_OBJ |
JSFRAME_HAS_ARGS_OBJ |
JSFRAME_OVERRIDE_ARGS |
JSFRAME_HAS_PREVPC |
JSFRAME_HAS_RVAL |
@ -121,16 +116,8 @@ JSStackFrame::resetInvokeCallFrame()
JSFRAME_HAS_PREVPC |
JSFRAME_UNDERFLOW_ARGS;
JS_ASSERT_IF(!hasCallObj(), scopeChain_ == calleeValue().toObject().getParent());
JS_ASSERT_IF(hasCallObj(), scopeChain_ == callObj().getParent());
if (hasCallObj())
scopeChain_ = callObj().getParent();
JS_ASSERT(exec.fun == calleeValue().toObject().getFunctionPrivate());
JS_ASSERT(!hasImacropc());
JS_ASSERT(!hasHookData());
JS_ASSERT(annotation() == NULL);
JS_ASSERT(!hasCallObj());
JS_ASSERT(exec.fun == callee().getFunctionPrivate());
scopeChain_ = callee().getParent();
}
inline void
@ -566,7 +553,7 @@ class InvokeSessionGuard
public:
InvokeSessionGuard() : args_(), frame_() {}
~InvokeSessionGuard() {}
inline ~InvokeSessionGuard();
bool start(JSContext *cx, const Value &callee, const Value &thisv, uintN argc);
bool invoke(JSContext *cx) const;
@ -592,6 +579,13 @@ class InvokeSessionGuard
}
};
inline
InvokeSessionGuard::~InvokeSessionGuard()
{
if (frame_.pushed())
PutActivationObjects(frame_.pushedFrameContext(), frame_.fp());
}
inline bool
InvokeSessionGuard::invoke(JSContext *cx) const
{
@ -612,6 +606,7 @@ InvokeSessionGuard::invoke(JSContext *cx) const
/* Clear any garbage left from the last Invoke. */
JSStackFrame *fp = frame_.fp();
fp->clearMissingArgs();
PutActivationObjects(cx, frame_.fp());
fp->resetInvokeCallFrame();
SetValueRangeToUndefined(fp->slots(), script_->nfixed);
@ -630,8 +625,6 @@ InvokeSessionGuard::invoke(JSContext *cx) const
Probes::exitJSFun(cx, fp->fun(), script_);
}
PutActivationObjects(cx, fp);
/* Don't clobber callee with rval; rval gets read from fp->rval. */
return ok;
}