Bug 412571 - replace thisp with thisv (r=brendan,mrbkap)

This commit is contained in:
Luke Wagner 2009-09-11 19:07:00 -07:00
parent 7232012b19
commit 854c0294df
10 changed files with 46 additions and 40 deletions

View File

@ -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);
/*

View File

@ -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 *)

View File

@ -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");

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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;
}