diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 31a076c8303b..ca3f78e8e20b 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -1146,138 +1146,102 @@ js_PutCallObjectOnTrace(JSContext *cx, JSObject *callobj, uint32 nargs, Value *a JS_DEFINE_CALLINFO_6(extern, BOOL, js_PutCallObjectOnTrace, CONTEXT, OBJECT, UINT32, VALUEPTR, UINT32, VALUEPTR, 0, nanojit::ACCSET_STORE_ANY) -enum JSCallPropertyKind { - JSCPK_ARGUMENTS, - JSCPK_ARG, - JSCPK_VAR, - JSCPK_UPVAR -}; - -static JSBool -CallPropertyOp(JSContext *cx, JSObject *obj, jsid id, Value *vp, - JSCallPropertyKind kind, JSBool setter = false) -{ - JS_ASSERT(obj->isCall()); - - uintN i = 0; - if (kind != JSCPK_ARGUMENTS) { - JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id)); - i = (uint16) JSID_TO_INT(id); - } - - Value *array; - if (kind == JSCPK_UPVAR) { - JSObject &callee = obj->getCallObjCallee(); - -#ifdef DEBUG - JSFunction *calleeFun = callee.getFunctionPrivate(); - JS_ASSERT(calleeFun->isFlatClosure()); - JS_ASSERT(calleeFun->script()->bindings.countUpvars() == calleeFun->script()->upvars()->length); - JS_ASSERT(i < calleeFun->script()->bindings.countUpvars()); -#endif - - array = callee.getFlatClosureUpvars(); - } else { - JSFunction *fun = obj->getCallObjCalleeFunction(); - JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs()); - JS_ASSERT_IF(kind == JSCPK_ARG, i < fun->nargs); - JS_ASSERT_IF(kind == JSCPK_VAR, i < fun->script()->bindings.countVars()); - - JSStackFrame *fp = (JSStackFrame *) obj->getPrivate(); - - if (kind == JSCPK_ARGUMENTS) { - if (setter) { - if (fp) - fp->setOverriddenArgs(); - obj->setCallObjArguments(*vp); - } else { - if (fp && !fp->hasOverriddenArgs()) { - JSObject *argsobj; - - argsobj = js_GetArgsObject(cx, fp); - if (!argsobj) - return false; - vp->setObject(*argsobj); - } else { - *vp = obj->getCallObjArguments(); - } - } - return true; - } - - if (!fp) { - i += JSObject::CALL_RESERVED_SLOTS; - if (kind == JSCPK_VAR) - i += fun->nargs; - else - JS_ASSERT(kind == JSCPK_ARG); - - array = obj->getSlots(); - } else if (kind == JSCPK_ARG) { - array = fp->formalArgs(); - } else { - JS_ASSERT(kind == JSCPK_VAR); - array = fp->slots(); - } - } - - if (setter) { - GC_POKE(cx, array[i]); - array[i] = *vp; - } else { - *vp = array[i]; - } - return true; -} - namespace js { static JSBool GetCallArguments(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS); + JSStackFrame *fp = obj->maybeCallObjStackFrame(); + if (fp && !fp->hasOverriddenArgs()) { + JSObject *argsobj = js_GetArgsObject(cx, fp); + if (!argsobj) + return false; + vp->setObject(*argsobj); + } else { + *vp = obj->getCallObjArguments(); + } + return true; } static JSBool SetCallArguments(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS, true); + if (JSStackFrame *fp = obj->maybeCallObjStackFrame()) + fp->setOverriddenArgs(); + obj->setCallObjArguments(*vp); + return true; } JSBool GetCallArg(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG); + JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id)); + uintN i = (uint16) JSID_TO_INT(id); + + if (JSStackFrame *fp = obj->maybeCallObjStackFrame()) + *vp = fp->formalArg(i); + else + *vp = obj->callObjArg(i); + return true; } JSBool SetCallArg(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, true); + JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id)); + uintN i = (uint16) JSID_TO_INT(id); + + Value *argp; + if (JSStackFrame *fp = obj->maybeCallObjStackFrame()) + argp = &fp->formalArg(i); + else + argp = &obj->callObjArg(i); + + GC_POKE(cx, *argp); + *argp = *vp; + return true; } JSBool GetFlatUpvar(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - return CallPropertyOp(cx, obj, id, vp, JSCPK_UPVAR); + JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id)); + uintN i = (uint16) JSID_TO_INT(id); + + *vp = obj->getCallObjCallee().getFlatClosureUpvar(i); + return true; } JSBool SetFlatUpvar(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - return CallPropertyOp(cx, obj, id, vp, JSCPK_UPVAR, true); + JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id)); + uintN i = (uint16) JSID_TO_INT(id); + + Value *upvarp = &obj->getCallObjCallee().getFlatClosureUpvar(i); + GC_POKE(cx, *upvarp); + *upvarp = *vp; + return true; } JSBool GetCallVar(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR); + JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id)); + uintN i = (uint16) JSID_TO_INT(id); + + if (JSStackFrame *fp = obj->maybeCallObjStackFrame()) + *vp = fp->varSlot(i); + else + *vp = obj->callObjVar(i); + + return true; } JSBool GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - if (!CallPropertyOp(cx, obj, id, vp, JSCPK_VAR)) + if (!GetCallVar(cx, obj, id, vp)) return false; return CheckForEscapingClosure(cx, obj, vp); @@ -1286,7 +1250,20 @@ GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, Value *vp) JSBool SetCallVar(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, true); + JS_ASSERT(obj->isCall()); + + JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id)); + uintN i = (uint16) JSID_TO_INT(id); + + Value *varp; + if (JSStackFrame *fp = obj->maybeCallObjStackFrame()) + varp = &fp->varSlot(i); + else + varp = &obj->callObjVar(i); + + GC_POKE(cx, *varp); + *varp = *vp; + return true; } } // namespace js @@ -1296,7 +1273,7 @@ JSBool JS_FASTCALL js_SetCallArg(JSContext *cx, JSObject *obj, jsid slotid, ValueArgType arg) { Value argcopy = ValueArgToConstRef(arg); - return CallPropertyOp(cx, obj, slotid, &argcopy, JSCPK_ARG, true); + return SetCallArg(cx, obj, slotid, &argcopy); } JS_DEFINE_CALLINFO_4(extern, BOOL, js_SetCallArg, CONTEXT, OBJECT, JSID, VALUE, 0, nanojit::ACCSET_STORE_ANY) @@ -1305,7 +1282,7 @@ JSBool JS_FASTCALL js_SetCallVar(JSContext *cx, JSObject *obj, jsid slotid, ValueArgType arg) { Value argcopy = ValueArgToConstRef(arg); - return CallPropertyOp(cx, obj, slotid, &argcopy, JSCPK_VAR, true); + return SetCallVar(cx, obj, slotid, &argcopy); } JS_DEFINE_CALLINFO_4(extern, BOOL, js_SetCallVar, CONTEXT, OBJECT, JSID, VALUE, 0, nanojit::ACCSET_STORE_ANY) diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index 74a09088b733..4236856f2264 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -250,6 +250,12 @@ struct JSStackFrame return slots() + script()->nfixed; } + js::Value &varSlot(uintN i) { + JS_ASSERT(i < script()->nfixed); + JS_ASSERT_IF(maybeFun(), i < script()->bindings.countVars()); + return slots()[i]; + } + /* * Script * diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 433ae2b9352f..92d1dc02aa9f 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -888,6 +888,9 @@ struct JSObject : js::gc::Cell { /* Number of reserved slots. */ static const uint32 CALL_RESERVED_SLOTS = 2; + /* The stack frame for this Call object, if the frame is still active. */ + inline JSStackFrame *maybeCallObjStackFrame() const; + inline JSObject &getCallObjCallee() const; inline JSFunction *getCallObjCalleeFunction() const; inline void setCallObjCallee(JSObject &callee); @@ -895,6 +898,14 @@ struct JSObject : js::gc::Cell { inline const js::Value &getCallObjArguments() const; inline void setCallObjArguments(const js::Value &v); + /* Returns the formal argument at the given index. */ + inline const js::Value &callObjArg(uintN i) const; + inline js::Value &callObjArg(uintN i); + + /* Returns the variable at the given index. */ + inline const js::Value &callObjVar(uintN i) const; + inline js::Value &callObjVar(uintN i); + /* * Date-specific getters and setters. */ @@ -954,6 +965,7 @@ struct JSObject : js::gc::Cell { inline js::Value *getFlatClosureUpvars() const; inline js::Value getFlatClosureUpvar(uint32 i) const; + inline js::Value &getFlatClosureUpvar(uint32 i); inline void setFlatClosureUpvars(js::Value *upvars); inline bool hasMethodObj(const JSObject& obj) const; diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index f6895760372f..b66935129467 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -432,6 +432,13 @@ JSObject::setArgsElement(uint32 i, const js::Value &v) getArgsData()->slots[i] = v; } +inline JSStackFrame * +JSObject::maybeCallObjStackFrame() const +{ + JS_ASSERT(isCall()); + return reinterpret_cast(getPrivate()); +} + inline void JSObject::setCallObjCallee(JSObject &callee) { @@ -468,6 +475,40 @@ JSObject::setCallObjArguments(const js::Value &v) setSlot(JSSLOT_CALL_ARGUMENTS, v); } +inline const js::Value & +JSObject::callObjArg(uintN i) const +{ + JS_ASSERT(isCall()); + JS_ASSERT(i < getCallObjCalleeFunction()->nargs); + return getSlot(JSObject::CALL_RESERVED_SLOTS + i); +} + +inline js::Value & +JSObject::callObjArg(uintN i) +{ + JS_ASSERT(isCall()); + JS_ASSERT(i < getCallObjCalleeFunction()->nargs); + return getSlotRef(JSObject::CALL_RESERVED_SLOTS + i); +} + +inline const js::Value & +JSObject::callObjVar(uintN i) const +{ + JSFunction *fun = getCallObjCalleeFunction(); + JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs()); + JS_ASSERT(i < fun->script()->bindings.countVars()); + return getSlot(JSObject::CALL_RESERVED_SLOTS + fun->nargs + i); +} + +inline js::Value & +JSObject::callObjVar(uintN i) +{ + JSFunction *fun = getCallObjCalleeFunction(); + JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs()); + JS_ASSERT(i < fun->script()->bindings.countVars()); + return getSlotRef(JSObject::CALL_RESERVED_SLOTS + fun->nargs + i); +} + inline const js::Value & JSObject::getDateUTCTime() const { @@ -485,8 +526,11 @@ JSObject::setDateUTCTime(const js::Value &time) inline js::Value * JSObject::getFlatClosureUpvars() const { - JS_ASSERT(isFunction()); - JS_ASSERT(FUN_FLAT_CLOSURE(getFunctionPrivate())); +#ifdef DEBUG + JSFunction *fun = getFunctionPrivate(); + JS_ASSERT(fun->isFlatClosure()); + JS_ASSERT(fun->script()->bindings.countUpvars() == fun->script()->upvars()->length); +#endif return (js::Value *) getSlot(JSSLOT_FLAT_CLOSURE_UPVARS).toPrivate(); } @@ -497,6 +541,13 @@ JSObject::getFlatClosureUpvar(uint32 i) const return getFlatClosureUpvars()[i]; } +inline js::Value & +JSObject::getFlatClosureUpvar(uint32 i) +{ + JS_ASSERT(i < getFunctionPrivate()->script()->bindings.countUpvars()); + return getFlatClosureUpvars()[i]; +} + inline void JSObject::setFlatClosureUpvars(js::Value *upvars) {