diff --git a/js/src/jit-test/tests/ion/bug732853.js b/js/src/jit-test/tests/ion/bug732853.js deleted file mode 100644 index 24f5229ec7c..00000000000 --- a/js/src/jit-test/tests/ion/bug732853.js +++ /dev/null @@ -1,25 +0,0 @@ -/* Check that f.caller is not null in inlined frames */ -function foo1() { - return foo1.caller.p; -} - -function bar1() { - foo1(0, 1); -} - -bar1(); -bar1(); - -/* Check that we recover overflow args after a bailout - * and that we can still iterate on the stack. */ -function foo2() { - [][0]; // cause a bailout. - dumpStack(); -} - -function bar2() { - foo2(0, 1); -} - -bar2(); -bar2(); diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 76b5686ef46..2cbbbc1d25f 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -227,22 +227,36 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) vp->setNull(); /* Find fun's top-most activation record. */ - StackIter iter(cx); - for (; !iter.done(); ++iter) { - if (!iter.isFunctionFrame() || iter.isEvalFrame()) + StackFrame *fp = js_GetTopStackFrame(cx, FRAME_EXPAND_NONE); + for (; fp; fp = fp->prev()) { + if (!fp->isFunctionFrame() || fp->isEvalFrame()) continue; - Value callee = iter.calleev(); - if (callee.isNull()) + Value callee; + if (!fp->getValidCalleeObject(cx, &callee)) return false; if (&callee.toObject() == fun) break; } - if (iter.done()) + if (!fp) return true; - StackFrame *fp = NULL; - if (iter.isScript()) - fp = iter.fp(); +#ifdef JS_METHODJIT + if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom) && fp && fp->prev()) { + /* + * If the frame was called from within an inlined frame, mark the + * innermost function as uninlineable to expand its frame and allow us + * to recover its callee object. + */ + JSInlinedSite *inlined; + jsbytecode *prevpc = fp->prev()->pcQuadratic(cx->stack, fp, &inlined); + if (inlined) { + mjit::JITChunk *chunk = fp->prev()->jit()->chunk(prevpc); + JSFunction *fun = chunk->inlineFrames()[inlined->inlineIndex].fun; + fun->script()->uninlineable = true; + MarkTypeObjectFlags(cx, fun, OBJECT_FLAG_UNINLINEABLE); + } + } +#endif if (JSID_IS_ATOM(id, cx->runtime->atomState.argumentsAtom)) { /* Warn if strict about f.arguments or equivalent unqualified uses. */ @@ -251,19 +265,7 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) return false; } - ArgumentsObject *argsobj; - if (!fp) { - JSObject &f = iter.callee(); - if (!&f) - return false; - // Currently we don't have a way to recover the number of actual - // arguments from an Ion Frame. This should be modified later with - // the implementation of JSOP_ARGUMENTS (Bug 735406). - argsobj = ArgumentsObject::createPoison(cx, f.toFunction()->nargs, f); - } else { - argsobj = ArgumentsObject::createUnexpected(cx, fp); - } - + ArgumentsObject *argsobj = ArgumentsObject::createUnexpected(cx, fp); if (!argsobj) return false; @@ -271,38 +273,16 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) return true; } - StackIter prev(iter); - ++prev; - -#ifdef JS_METHODJIT - StackFrame *fpPrev = NULL; - if (!prev.done() && prev.isScript()) - fpPrev = prev.fp(); - - if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom) && fp && fpPrev) { - /* - * If the frame was called from within an inlined frame, mark the - * innermost function as uninlineable to expand its frame and allow us - * to recover its callee object. - */ - JSInlinedSite *inlined; - jsbytecode *prevpc = fpPrev->pcQuadratic(cx->stack, fp, &inlined); - if (inlined) { - mjit::JITChunk *chunk = fpPrev->jit()->chunk(prevpc); - JSFunction *fun = chunk->inlineFrames()[inlined->inlineIndex].fun; - fun->script()->uninlineable = true; - MarkTypeObjectFlags(cx, fun, OBJECT_FLAG_UNINLINEABLE); - } - } -#endif - if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom)) { - if (prev.done()) + if (!fp->prev()) return true; - if (!prev.isFunctionFrame()) + StackFrame *frame = fp->prev(); + while (frame && frame->isDummyFrame()) + frame = frame->prev(); + + if (frame && !frame->getValidCalleeObject(cx, vp)) return false; - *vp = prev.calleev(); if (!vp->isObject()) { JS_ASSERT(vp->isNull()); diff --git a/js/src/vm/ArgumentsObject.cpp b/js/src/vm/ArgumentsObject.cpp index dbceb1c3917..d649a8e041b 100644 --- a/js/src/vm/ArgumentsObject.cpp +++ b/js/src/vm/ArgumentsObject.cpp @@ -178,12 +178,6 @@ ArgumentsObject::createUnexpected(JSContext *cx, StackFrame *fp) return argsobj; } -ArgumentsObject * -ArgumentsObject::createPoison(JSContext *cx, uint32_t argc, JSObject &callee) -{ - return ArgumentsObject::create(cx, argc, callee); -} - static JSBool args_delProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) { diff --git a/js/src/vm/ArgumentsObject.h b/js/src/vm/ArgumentsObject.h index 1cc5239ed15..00f0b219840 100644 --- a/js/src/vm/ArgumentsObject.h +++ b/js/src/vm/ArgumentsObject.h @@ -155,12 +155,6 @@ class ArgumentsObject : public JSObject */ static ArgumentsObject *createUnexpected(JSContext *cx, StackFrame *fp); - /* - * Cannot recover any fields of the arguments object, and replace it by - * the poison value. - */ - static ArgumentsObject *createPoison(JSContext *cx, uint32_t argc, JSObject &callee); - /* * Return the initial length of the arguments. This may differ from the * current value of arguments.length! diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index abf1587b2ec..e3558920b3a 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -1392,27 +1392,6 @@ StackIter::isNonEvalFunctionFrame() const return false; } -JSObject & -StackIter::callee() const -{ - JS_ASSERT(isFunctionFrame()); - switch (state_) { - case ION: - return *ionInlineFrames_.callee(); - case SCRIPTED: - { - Value v; - if (!fp()->getValidCalleeObject(cx_, &v)) - return *(JSObject *) NULL; - return v.toObject(); - } - default: - return nativeArgs().callee(); - } - JS_NOT_REACHED("Unreachable"); - return *(JSObject *) NULL; -} - Value StackIter::calleev() const { diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index 1d344fadb4f..990be4f3f80 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -1901,7 +1901,6 @@ class StackIter Value *sp() const { JS_ASSERT(!done() && isScript()); return sp_; } jsbytecode *pc() const { JS_ASSERT(!done() && isScripted()); return pc_; } JSScript *script() const { JS_ASSERT(!done() && isScripted()); return script_; } - JSObject &callee() const; Value calleev() const; bool isNativeCall() const { JS_ASSERT(!done()); return state_ != SCRIPTED; }