diff --git a/js/src/jsinterp.c b/js/src/jsinterp.c index 3574c6f2b103..78e2c5a56995 100644 --- a/js/src/jsinterp.c +++ b/js/src/jsinterp.c @@ -581,15 +581,14 @@ js_ComputeThis(JSContext *cx, JSObject *thisp, jsval *argv) static JSBool NoSuchMethod(JSContext *cx, JSStackFrame *fp, jsval *vp, uint32 flags, - uintN *argcp) + uintN argc) { - jsval v, *sp, *newsp; JSObject *thisp, *argsobj; + jsval *sp, roots[3]; + JSTempValueRooter tvr; jsid id; + JSBool ok; jsbytecode *pc; - JSAtom *atom; - uintN argc; - JSArena *a; /* * We must call js_ComputeThis here to censor Call objects. A performance @@ -618,6 +617,11 @@ NoSuchMethod(JSContext *cx, JSStackFrame *fp, jsval *vp, uint32 flags, thisp = js_ComputeThis(cx, thisp, vp + 2); if (!thisp) return JS_FALSE; + vp[1] = OBJECT_TO_JSVAL(thisp); + + /* From here on, control must flow through label out: to return. */ + memset(roots, 0, sizeof roots); + JS_PUSH_TEMP_ROOT(cx, JS_ARRAY_LENGTH(roots), roots, &tvr); id = ATOM_TO_JSID(cx->runtime->atomState.noSuchMethodAtom); #if JS_HAS_XML_SUPPORT @@ -625,18 +629,21 @@ NoSuchMethod(JSContext *cx, JSStackFrame *fp, jsval *vp, uint32 flags, JSXMLObjectOps *ops; ops = (JSXMLObjectOps *) thisp->map->ops; - thisp = ops->getMethod(cx, thisp, id, &v); - if (!thisp) - return JS_FALSE; + thisp = ops->getMethod(cx, thisp, id, &roots[2]); + if (!thisp) { + ok = JS_FALSE; + goto out; + } vp[1] = OBJECT_TO_JSVAL(thisp); } else #endif { - if (!OBJ_GET_PROPERTY(cx, thisp, id, &v)) - return JS_FALSE; + ok = OBJ_GET_PROPERTY(cx, thisp, id, &roots[2]); + if (!ok) + goto out; } - if (JSVAL_IS_PRIMITIVE(v)) - goto bad; + if (JSVAL_IS_PRIMITIVE(roots[2])) + goto not_function; pc = (jsbytecode *) vp[-(intN)fp->script->depth]; switch ((JSOp) *pc) { @@ -645,55 +652,29 @@ NoSuchMethod(JSContext *cx, JSStackFrame *fp, jsval *vp, uint32 flags, #if JS_HAS_XML_SUPPORT case JSOP_CALLPROP: #endif - atom = js_GetAtomFromBytecode(fp->script, pc, 0); - argc = *argcp; + roots[0] = ATOM_KEY(js_GetAtomFromBytecode(fp->script, pc, 0)); argsobj = js_NewArrayObject(cx, argc, vp + 2); - if (!argsobj) - return JS_FALSE; - - sp = vp + 4; - if (argc < 2) { - a = cx->stackPool.current; - if ((jsuword)sp > a->limit) { - /* - * Arguments must be contiguous, and must include argv[-1] - * and argv[-2], so allocate more stack, advance sp, and - * set newsp[1] to thisp (vp[1]). The other argv elements - * will be set below, using negative indexing from sp. - */ - newsp = js_AllocRawStack(cx, 4, NULL); - if (!newsp) - return JS_FALSE; - newsp[1] = OBJECT_TO_JSVAL(thisp); - sp = newsp + 4; - } else if ((jsuword)sp > a->avail) { - /* - * Inline, optimized version of JS_ARENA_ALLOCATE to claim - * the small number of words not already allocated as part - * of the caller's operand stack. - */ - JS_ArenaCountAllocation(&cx->stackPool, - (jsuword)sp - a->avail); - a->avail = (jsuword)sp; - } + if (!argsobj) { + ok = JS_FALSE; + goto out; } - - sp[-4] = v; - JS_ASSERT(sp[-3] == OBJECT_TO_JSVAL(thisp)); - sp[-2] = ATOM_KEY(atom); - sp[-1] = OBJECT_TO_JSVAL(argsobj); - SAVE_SP(fp); - *argcp = 2; + roots[1] = OBJECT_TO_JSVAL(argsobj); + ok = js_InternalInvoke(cx, thisp, roots[2], flags | JSINVOKE_INTERNAL, + 2, roots, &vp[0]); break; default: - goto bad; + goto not_function; } - return JS_TRUE; -bad: + out: + JS_POP_TEMP_ROOT(cx, &tvr); + return ok; + + not_function: js_ReportIsNotFunction(cx, vp, flags & JSINVOKE_FUNFLAGS); - return JS_FALSE; + ok = JS_FALSE; + goto out; } #endif /* JS_HAS_NO_SUCH_METHOD */ @@ -1097,16 +1078,14 @@ js_Invoke(JSContext *cx, uintN argc, uintN flags) */ if (JSVAL_IS_PRIMITIVE(v)) { #if JS_HAS_NO_SUCH_METHOD - if (!fp->script || (flags & JSINVOKE_INTERNAL)) - goto bad; - ok = NoSuchMethod(cx, fp, vp, flags, &argc); - if (!ok) + if (fp->script && !(flags & JSINVOKE_INTERNAL)) { + ok = NoSuchMethod(cx, fp, vp, flags, argc); + if (ok) + frame.rval = *vp; goto out2; - RESTORE_SP(fp); - v = *vp; -#else - goto bad; + } #endif + goto bad; } /* Load thisv after potentially calling NoSuchMethod, which may set it. */ @@ -3847,16 +3826,6 @@ interrupt: vp = sp - (argc + 2); lval = *vp; SAVE_SP_AND_PC(fp); -#if JS_HAS_NO_SUCH_METHOD - if (JSVAL_IS_PRIMITIVE(lval)) { - ok = NoSuchMethod(cx, fp, vp, 0, &argc); - if (!ok) - goto out; - RESTORE_SP(fp); - lval = *vp; - } -#endif - if (VALUE_IS_FUNCTION(cx, lval) && (obj = JSVAL_TO_OBJECT(lval), fun = (JSFunction *) JS_GetPrivate(cx, obj),