diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 265abb41d0f..577f377d78d 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4457,7 +4457,7 @@ js_generic_native_method_dispatcher(JSContext *cx, JSObject *obj, */ if (!js_ComputeThis(cx, JS_TRUE, argv)) return JS_FALSE; - js_GetTopStackFrame(cx)->thisp = JSVAL_TO_OBJECT(argv[-1]); + js_GetTopStackFrame(cx)->thisv = argv[-1]; JS_ASSERT(cx->fp->argv == argv); /* diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 5fbeadce4f9..a4f1e142c3b 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -1126,7 +1126,7 @@ JS_GetFrameThis(JSContext *cx, JSStackFrame *fp) JSStackFrame *afp; if (fp->flags & JSFRAME_COMPUTED_THIS) - return fp->thisp; + return JSVAL_TO_OBJECT(fp->thisv); /* JSVAL_COMPUTED_THIS invariant */ /* js_ComputeThis gets confused if fp != cx->fp, so set it aside. */ if (js_GetTopStackFrame(cx) != fp) { @@ -1140,8 +1140,8 @@ JS_GetFrameThis(JSContext *cx, JSStackFrame *fp) afp = NULL; } - if (!fp->thisp && fp->argv) - fp->thisp = js_ComputeThis(cx, JS_TRUE, fp->argv); + if (JSVAL_IS_NULL(fp->thisv) && fp->argv) + fp->thisv = OBJECT_TO_JSVAL(js_ComputeThis(cx, JS_TRUE, fp->argv)); if (afp) { cx->fp = afp; @@ -1149,7 +1149,7 @@ JS_GetFrameThis(JSContext *cx, JSStackFrame *fp) afp->dormantNext = NULL; } - return fp->thisp; + return JSVAL_TO_OBJECT(fp->thisv); } JS_PUBLIC_API(JSFunction *) diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 61920479c39..a3230969ce8 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -2861,9 +2861,7 @@ js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp) } /* Allow for primitive this parameter due to JSFUN_THISP_* flags. */ - JS_ASSERT(JSVAL_IS_OBJECT((jsval)fp->thisp) || - (fp->fun && JSFUN_THISP_FLAGS(fp->fun->flags))); - JS_CALL_VALUE_TRACER(trc, (jsval)fp->thisp, "this"); + JS_CALL_VALUE_TRACER(trc, fp->thisv, "this"); if (fp->argv) { JS_CALL_VALUE_TRACER(trc, fp->argv[-2], "callee"); diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 67b7bba057a..eb0134af2fd 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -1298,12 +1298,8 @@ have_fun: /* * Initialize the frame. - * - * To set thisp we use an explicit cast and not JSVAL_TO_OBJECT, as vp[1] - * can be a primitive value here for those native functions specified with - * JSFUN_THISP_(NUMBER|STRING|BOOLEAN) flags. */ - frame.thisp = (JSObject *)vp[1]; + frame.thisv = vp[1]; frame.varobj = NULL; frame.callobj = NULL; frame.argsobj = NULL; @@ -1376,8 +1372,9 @@ have_fun: #ifdef DEBUG_NOT_THROWING JSBool alreadyThrowing = cx->throwing; #endif - - ok = native(cx, frame.thisp, argc, frame.argv, &frame.rval); + /* Primitive |this| should not be passed to slow natives. */ + JSObject *thisp = JSVAL_TO_OBJECT(frame.thisv); + ok = native(cx, thisp, argc, frame.argv, &frame.rval); JS_RUNTIME_METER(cx->runtime, nativeCalls); #ifdef DEBUG_NOT_THROWING if (ok && !alreadyThrowing) @@ -1533,7 +1530,7 @@ js_Execute(JSContext *cx, JSObject *chain, JSScript *script, frame.argsobj = down->argsobj; frame.varobj = down->varobj; frame.fun = down->fun; - frame.thisp = down->thisp; + frame.thisv = down->thisv; if (down->flags & JSFRAME_COMPUTED_THIS) flags |= JSFRAME_COMPUTED_THIS; frame.argc = down->argc; @@ -1549,7 +1546,7 @@ js_Execute(JSContext *cx, JSObject *chain, JSScript *script, } frame.varobj = obj; frame.fun = NULL; - frame.thisp = chain; + frame.thisv = OBJECT_TO_JSVAL(chain); frame.argc = 0; frame.argv = NULL; frame.annotation = NULL; @@ -1626,11 +1623,12 @@ js_Execute(JSContext *cx, JSObject *chain, JSScript *script, return JS_FALSE; frame.scopeChain = chain; - frame.thisp = frame.thisp->thisObject(cx); - if (!frame.thisp) { + JSObject *thisp = JSVAL_TO_OBJECT(frame.thisv)->thisObject(cx); + if (!thisp) { ok = JS_FALSE; goto out2; } + frame.thisv = OBJECT_TO_JSVAL(thisp); frame.flags |= JSFRAME_COMPUTED_THIS; } diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index 135fcea8cc7..cad8f97d592 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -76,7 +76,7 @@ struct JSStackFrame { JSObject *varobj; /* variables object, where vars go */ JSScript *script; /* script being interpreted */ JSFunction *fun; /* function being called or null */ - JSObject *thisp; /* "this" pointer if in method */ + jsval thisv; /* "this" pointer if in method */ uintN argc; /* actual argument count */ jsval *argv; /* base of argument stack slots */ jsval rval; /* function return value */ @@ -190,7 +190,8 @@ typedef struct JSInlineFrame { /* JS stack frame flags. */ #define JSFRAME_CONSTRUCTING 0x01 /* frame is for a constructor invocation */ -#define JSFRAME_COMPUTED_THIS 0x02 /* frame.thisp was computed already */ +#define JSFRAME_COMPUTED_THIS 0x02 /* frame.thisv was computed already and + JSVAL_IS_OBJECT(thisv) */ #define JSFRAME_ASSIGNING 0x04 /* a complex (not simplex JOF_ASSIGNING) op is currently assigning to a property */ #define JSFRAME_DEBUGGER 0x08 /* frame for JS_EvaluateInStackFrame */ @@ -474,11 +475,11 @@ static JS_INLINE JSObject * js_ComputeThisForFrame(JSContext *cx, JSStackFrame *fp) { if (fp->flags & JSFRAME_COMPUTED_THIS) - return fp->thisp; + return JSVAL_TO_OBJECT(fp->thisv); /* JSVAL_COMPUTED_THIS invariant */ JSObject* obj = js_ComputeThis(cx, JS_TRUE, fp->argv); if (!obj) return NULL; - fp->thisp = obj; + fp->thisv = OBJECT_TO_JSVAL(obj); fp->flags |= JSFRAME_COMPUTED_THIS; return obj; } diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index a24dd594309..0d93b5c64a7 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -731,7 +731,7 @@ js_NewGenerator(JSContext *cx, JSStackFrame *fp) /* These two references can be shared with fp until it goes away. */ gen->frame.varobj = fp->varobj; - gen->frame.thisp = fp->thisp; + gen->frame.thisv = fp->thisv; /* Copy call-invariant script and function references. */ gen->frame.script = fp->script; diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 6fab18f738c..ae7bc9b4553 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -6274,6 +6274,16 @@ MaybeDumpObject(const char *name, JSObject *obj) } } +static void +MaybeDumpValue(const char *name, jsval v) +{ + if (!JSVAL_IS_NULL(v)) { + fprintf(stderr, " %s: ", name); + dumpValue(v); + fputc('\n', stderr); + } +} + JS_FRIEND_API(void) js_DumpStackFrame(JSStackFrame *fp) { @@ -6328,7 +6338,7 @@ js_DumpStackFrame(JSStackFrame *fp) MaybeDumpObject("callobj", fp->callobj); MaybeDumpObject("argsobj", JSVAL_TO_OBJECT(fp->argsobj)); MaybeDumpObject("varobj", fp->varobj); - MaybeDumpObject("this", fp->thisp); + MaybeDumpValue("this", fp->thisv); fprintf(stderr, " rval: "); dumpValue(fp->rval); fputc('\n', stderr); diff --git a/js/src/jsops.cpp b/js/src/jsops.cpp index 6148703031f..0ce57f2cca1 100644 --- a/js/src/jsops.cpp +++ b/js/src/jsops.cpp @@ -222,7 +222,7 @@ js_ValueToPrintableString(cx, rval)); goto error; } - fp->rval = OBJECT_TO_JSVAL(fp->thisp); + fp->rval = fp->thisv; } ok = JS_TRUE; if (inlineCallCount) @@ -284,7 +284,7 @@ */ if (fp->flags & JSFRAME_CONSTRUCTING) { if (JSVAL_IS_PRIMITIVE(fp->rval)) - fp->rval = OBJECT_TO_JSVAL(fp->thisp); + fp->rval = fp->thisv; JS_RUNTIME_METER(cx->runtime, constructs); } @@ -2145,8 +2145,7 @@ /* Compute the 'this' parameter now that argv is set. */ JS_ASSERT(!JSFUN_BOUND_METHOD_TEST(fun->flags)); - JS_ASSERT(JSVAL_IS_OBJECT(vp[1])); - newifp->frame.thisp = (JSObject *)vp[1]; + newifp->frame.thisv = vp[1]; newifp->frame.regs = NULL; newifp->frame.imacpc = NULL; diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 29a39d69406..0c2d8eb1ffb 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -331,7 +331,7 @@ script_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, * Emulate eval() by using caller's this, var object, sharp array, etc., * all propagated by js_Execute via a non-null fourth (down) argument to * js_Execute. If there is no scripted caller, js_Execute uses its second - * (chain) argument to set the exec frame's varobj, thisp, and scopeChain. + * (chain) argument to set the exec frame's varobj, thisv, and scopeChain. * * Unlike eval, which the compiler detects, Script.prototype.exec may be * called from a lightweight function, or even from native code (in which diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index f8f195d5aeb..510ff45e178 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -2705,7 +2705,7 @@ FlushNativeStackFrame(JSContext* cx, unsigned callDepth, JSTraceType* mp, double FlushNativeStackFrameVisitor visitor(cx, mp, np, stopAt); VisitStackSlots(visitor, cx, callDepth); - // Restore thisp from the now-restored argv[-1] in each pending frame. + // Restore thisv from the now-restored argv[-1] in each pending frame. // Keep in mind that we didn't restore frames at stopFrame and above! // Scope to keep |fp| from leaking into the macros we're using. { @@ -2768,7 +2768,7 @@ FlushNativeStackFrame(JSContext* cx, unsigned callDepth, JSTraceType* mp, double ((JSInlineFrame*)fp)->hookData = hookData; } } - fp->thisp = JSVAL_TO_OBJECT(fp->argv[-1]); + fp->thisv = fp->argv[-1]; if (fp->flags & JSFRAME_CONSTRUCTING) // constructors always compute 'this' fp->flags |= JSFRAME_COMPUTED_THIS; } @@ -4806,7 +4806,7 @@ SynthesizeFrame(JSContext* cx, const FrameInfo& fi, JSObject* callee) newifp->frame.dormantNext = NULL; newifp->frame.blockChain = NULL; newifp->mark = newmark; - newifp->frame.thisp = NULL; // will be updated in FlushNativeStackFrame + newifp->frame.thisv = JSVAL_NULL; // will be updated in FlushNativeStackFrame newifp->frame.regs = fp->regs; newifp->frame.regs->pc = script->code; @@ -4874,8 +4874,7 @@ SynthesizeSlowNativeFrame(InterpState& state, JSContext *cx, VMSideExit *exit) fp->argsobj = NULL; fp->varobj = cx->fp->varobj; fp->script = NULL; - // fp->thisp is really a jsval, so reinterpret_cast here, not JSVAL_TO_OBJECT. - fp->thisp = (JSObject *) state.nativeVp[1]; + fp->thisv = state.nativeVp[1]; fp->argc = state.nativeVpLen - 2; fp->argv = state.nativeVp + 2; fp->fun = GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(fp->argv[-2])); @@ -8773,7 +8772,7 @@ TraceRecorder::record_JSOP_RETURN() jsval& rval = stackval(-1); JSStackFrame *fp = cx->fp; if ((cx->fp->flags & JSFRAME_CONSTRUCTING) && JSVAL_IS_PRIMITIVE(rval)) { - JS_ASSERT(OBJECT_TO_JSVAL(fp->thisp) == fp->argv[-1]); + JS_ASSERT(fp->thisv == fp->argv[-1]); rval_ins = get(&fp->argv[-1]); } else { rval_ins = get(&rval); @@ -12902,7 +12901,7 @@ TraceRecorder::record_JSOP_STOP() * of the last expression-statement, debugger API calls). */ if (fp->flags & JSFRAME_CONSTRUCTING) { - JS_ASSERT(OBJECT_TO_JSVAL(fp->thisp) == fp->argv[-1]); + JS_ASSERT(fp->thisv == fp->argv[-1]); rval_ins = get(&fp->argv[-1]); } else { rval_ins = INS_CONST(JSVAL_TO_SPECIAL(JSVAL_VOID)); @@ -13014,10 +13013,11 @@ TraceRecorder::record_JSOP_GETTHISPROP() CHECK_STATUS(getThis(this_ins)); /* - * It's safe to just use cx->fp->thisp here because getThis() returns - * JSRS_STOP if thisp is not available. + * It's safe to just use cx->fp->thisv here because getThis() returns + * JSRS_STOP if thisv is not available. */ - CHECK_STATUS(getProp(cx->fp->thisp, this_ins)); + JS_ASSERT(cx->fp->flags & JSFRAME_COMPUTED_THIS); + CHECK_STATUS(getProp(JSVAL_TO_OBJECT(cx->fp->thisv), this_ins)); return JSRS_CONTINUE; }