Bug 562872 - encapsulate Arguments-related dslots accesses. r=brendan.
authorNicholas Nethercote <nnethercote@mozilla.com>
Sun, 02 May 2010 21:42:09 -0700
changeset 41871 c3ee09da6532cd84ac69c2d2c02df9f16bd0a8a5
parent 41870 c63d6b20c590bc25cef46fbd97bd79b06fa76fe1
child 41874 436e0e572d06411a04e3d01e6706c539f43fc5de
push id13126
push userrsayre@mozilla.com
push dateTue, 04 May 2010 17:34:44 +0000
treeherdermozilla-central@13bcf4386e12 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbrendan
bugs562872
milestone1.9.3a5pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
Bug 562872 - encapsulate Arguments-related dslots accesses. r=brendan.
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jsops.cpp
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -132,17 +132,17 @@ js_GetArgsProperty(JSContext *cx, JSStac
     }
 
     *vp = JSVAL_VOID;
     if (JSID_IS_INT(id)) {
         uint32 arg = uint32(JSID_TO_INT(id));
         JSObject *argsobj = JSVAL_TO_OBJECT(fp->argsobj);
         if (arg < fp->argc) {
             if (argsobj) {
-                jsval v = GetArgsSlot(argsobj, arg);
+                jsval v = argsobj->getArgsElement(arg);
                 if (v == JSVAL_HOLE)
                     return argsobj->getProperty(cx, id, vp);
             }
             *vp = fp->argv[arg];
         } else {
             /*
              * Per ECMA-262 Ed. 3, 10.1.8, last bulleted item, do not share
              * storage between the formal parameter and arguments[k] for all
@@ -192,19 +192,19 @@ NewArguments(JSContext *cx, JSObject *pa
     return argsobj;
 }
 
 static void
 PutArguments(JSContext *cx, JSObject *argsobj, jsval *args)
 {
     uint32 argc = argsobj->getArgsLength();
     for (uint32 i = 0; i != argc; ++i) {
-        jsval v = argsobj->dslots[i];
+        jsval v = argsobj->getArgsElement(i);
         if (v != JSVAL_HOLE)
-            argsobj->dslots[i] = args[i];
+            argsobj->setArgsElement(i, args[i]);
     }
 }
 
 JSObject *
 js_GetArgsObject(JSContext *cx, JSStackFrame *fp)
 {
     /*
      * We must be in a function activation; the function must be lightweight
@@ -296,17 +296,17 @@ JS_DEFINE_CALLINFO_3(extern, BOOL, js_Pu
 static JSBool
 args_delProperty(JSContext *cx, JSObject *obj, jsval idval, jsval *vp)
 {
     JS_ASSERT(obj->isArguments());
 
     if (JSVAL_IS_INT(idval)) {
         uintN arg = uintN(JSVAL_TO_INT(idval));
         if (arg < obj->getArgsLength())
-            SetArgsSlot(obj, arg, JSVAL_HOLE);
+            obj->setArgsElement(arg, JSVAL_HOLE);
     } else if (idval == ATOM_KEY(cx->runtime->atomState.lengthAtom)) {
         obj->setArgsLengthOverridden();
     } else if (idval == ATOM_KEY(cx->runtime->atomState.calleeAtom)) {
         obj->setArgsCallee(JSVAL_HOLE);
     }
     return true;
 }
 
@@ -503,17 +503,17 @@ ArgGetter(JSContext *cx, JSObject *obj, 
                 return false;
             }
 #endif
 
             JSStackFrame *fp = (JSStackFrame *) obj->getPrivate();
             if (fp) {
                 *vp = fp->argv[arg];
             } else {
-                jsval v = GetArgsSlot(obj, arg);
+                jsval v = obj->getArgsElement(arg);
                 if (v != JSVAL_HOLE)
                     *vp = v;
             }
         }
     } else if (idval == ATOM_KEY(cx->runtime->atomState.lengthAtom)) {
         if (!obj->isArgsLengthOverridden())
             *vp = INT_TO_JSVAL(obj->getArgsLength());
     } else {
@@ -590,17 +590,17 @@ args_resolve(JSContext *cx, JSObject *ob
              JSObject **objp)
 {
     JS_ASSERT(obj->isArguments());
 
     *objp = NULL;
     jsid id = 0;
     if (JSVAL_IS_INT(idval)) {
         uint32 arg = uint32(JSVAL_TO_INT(idval));
-        if (arg < obj->getArgsLength() && GetArgsSlot(obj, arg) != JSVAL_HOLE)
+        if (arg < obj->getArgsLength() && obj->getArgsElement(arg) != JSVAL_HOLE)
             id = INT_JSVAL_TO_JSID(idval);
     } else if (idval == ATOM_KEY(cx->runtime->atomState.lengthAtom)) {
         if (!obj->isArgsLengthOverridden())
             id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
     } else if (idval == ATOM_KEY(cx->runtime->atomState.calleeAtom)) {
         if (obj->getArgsCallee() != JSVAL_HOLE)
             id = ATOM_TO_JSID(cx->runtime->atomState.calleeAtom);
     }
@@ -2035,29 +2035,29 @@ js_fun_apply(JSContext *cx, uintN argc, 
     /* Push fval, obj, and aobj's elements as args. */
     sp = invokevp;
     *sp++ = fval;
     *sp++ = OBJECT_TO_JSVAL(obj);
     if (aobj && aobj->isArguments() && !aobj->isArgsLengthOverridden()) {
         /*
          * Two cases, two loops: note how in the case of an active stack frame
          * backing aobj, even though we copy from fp->argv, we still must check
-         * aobj->dslots[i] for a hole, to handle a delete on the corresponding
-         * arguments element. See args_delProperty.
+         * aobj->getArgsElement(i) for a hole, to handle a delete on the
+         * corresponding arguments element. See args_delProperty.
          */
         JSStackFrame *fp = (JSStackFrame *) aobj->getPrivate();
         if (fp) {
             memcpy(sp, fp->argv, argc * sizeof(jsval));
             for (i = 0; i < argc; i++) {
-                if (aobj->dslots[i] == JSVAL_HOLE) // suppress deleted element
+                if (aobj->getArgsElement(i) == JSVAL_HOLE) // suppress deleted element
                     sp[i] = JSVAL_VOID;
             }
         } else {
-            memcpy(sp, aobj->dslots, argc * sizeof(jsval));
             for (i = 0; i < argc; i++) {
+                sp[i] = aobj->getArgsElement(i);
                 if (sp[i] == JSVAL_HOLE)
                     sp[i] = JSVAL_VOID;
             }
         }
     } else {
         for (i = 0; i < argc; i++) {
             ok = aobj->getProperty(cx, INT_TO_JSID(jsint(i)), sp);
             if (!ok)
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -424,32 +424,16 @@ const uint32 JS_ARGS_LENGTH_MAX = JS_BIT
 /*
  * JSSLOT_ARGS_LENGTH stores ((argc << 1) | overwritten_flag) as int jsval.
  * Thus (JS_ARGS_LENGTH_MAX << 1) | 1 must fit JSVAL_INT_MAX. To assert that
  * we check first that the shift does not overflow uint32.
  */
 JS_STATIC_ASSERT(JS_ARGS_LENGTH_MAX <= JS_BIT(30));
 JS_STATIC_ASSERT(jsval((JS_ARGS_LENGTH_MAX << 1) | 1) <= JSVAL_INT_MAX);
 
-namespace js {
-
-inline jsval
-GetArgsSlot(JSObject *argsobj, uint32 arg)
-{
-    return argsobj->dslots[arg];
-}
-
-inline void
-SetArgsSlot(JSObject *argsobj, uint32 arg, jsval v)
-{
-    argsobj->dslots[arg] = v;
-}
-
-} /* namespace js */
-
 extern JSBool
 js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp);
 
 typedef enum JSLocalKind {
     JSLOCAL_NONE,
     JSLOCAL_ARG,
     JSLOCAL_VAR,
     JSLOCAL_CONST,
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -287,17 +287,17 @@ struct JSObject {
     bool isSystem() const {
         return (classword & jsuword(2)) != jsuword(0);
     }
 
     void setSystem() {
         classword |= jsuword(2);
     }
 
-    uint32 numSlots(void) {
+    uint32 numSlots(void) const {
         return dslots ? (uint32)dslots[-1] : (uint32)JS_INITIAL_NSLOTS;
     }
 
     jsval& getSlotRef(uintN slot) {
         return (slot < JS_INITIAL_NSLOTS)
                ? fslots[slot]
                : (JS_ASSERT(slot < (uint32)dslots[-1]),
                   dslots[slot - JS_INITIAL_NSLOTS]);
@@ -456,35 +456,38 @@ struct JSObject {
      *
      * JSSLOT_PRIVATE       - the corresponding frame until the frame exits.
      * JSSLOT_ARGS_LENGTH   - the number of actual arguments and a flag
      *                        indicating whether arguments.length was
      *                        overwritten.
      * JSSLOT_ARGS_CALLEE   - the arguments.callee value or JSVAL_HOLE if that
      *                        was overwritten.
      *
-     * Argument index i is stored in dslots[i].  But future-proof your code by
-     * using {Get,Set}ArgsSlot instead of naked dslots references.
+     * Argument index i is stored in dslots[i], accessible via
+     * {get,set}ArgsElement().
      */
   private:
     static const uint32 JSSLOT_ARGS_LENGTH = JSSLOT_PRIVATE + 1;
     static const uint32 JSSLOT_ARGS_CALLEE = JSSLOT_PRIVATE + 2;
 
   public:
     /* Number of extra fixed slots besides JSSLOT_PRIVATE. */
     static const uint32 ARGS_FIXED_RESERVED_SLOTS = 2;
 
     inline uint32 getArgsLength() const;
     inline void setArgsLength(uint32 argc);
     inline void setArgsLengthOverridden();
-    inline bool isArgsLengthOverridden();
+    inline bool isArgsLengthOverridden() const;
 
     inline jsval getArgsCallee() const;
     inline void setArgsCallee(jsval callee);
 
+    inline jsval getArgsElement(uint32 i) const;
+    inline void setArgsElement(uint32 i, jsval v);
+
     /*
      * Date-specific getters and setters.
      */
 
   private:
     // The second slot caches the local time;  it's initialized to NaN.
     static const uint32 JSSLOT_DATE_UTC_TIME   = JSSLOT_PRIVATE;
     static const uint32 JSSLOT_DATE_LOCAL_TIME = JSSLOT_PRIVATE + 1;
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -273,17 +273,17 @@ JSObject::setArgsLengthOverridden()
     JS_ASSERT(isArguments());
     jsval v = fslots[JSSLOT_ARGS_LENGTH];
     v = INT_TO_JSVAL(JSVAL_TO_INT(v) | 1);
     JS_ASSERT(JSVAL_IS_INT(v));
     fslots[JSSLOT_ARGS_LENGTH] = v;
 }
 
 inline bool
-JSObject::isArgsLengthOverridden()
+JSObject::isArgsLengthOverridden() const
 {
     JS_ASSERT(isArguments());
     jsval v = fslots[JSSLOT_ARGS_LENGTH];
     return (JSVAL_TO_INT(v) & 1) != 0;
 }
 
 inline jsval 
 JSObject::getArgsCallee() const
@@ -295,16 +295,32 @@ JSObject::getArgsCallee() const
 inline void 
 JSObject::setArgsCallee(jsval callee)
 {
     JS_ASSERT(isArguments());
     fslots[JSSLOT_ARGS_CALLEE] = callee;
 }
 
 inline jsval
+JSObject::getArgsElement(uint32 i) const
+{
+    JS_ASSERT(isArguments());
+    JS_ASSERT(i < numSlots() - JS_INITIAL_NSLOTS);
+    return dslots[i];
+}
+
+inline void
+JSObject::setArgsElement(uint32 i, jsval v)
+{
+    JS_ASSERT(isArguments());
+    JS_ASSERT(i < numSlots() - JS_INITIAL_NSLOTS);
+    dslots[i] = v;
+}
+
+inline jsval
 JSObject::getDateLocalTime() const
 {
     JS_ASSERT(isDate());
     return fslots[JSSLOT_DATE_LOCAL_TIME];
 }
 
 inline jsval *
 JSObject::addressOfDateLocalTime()
--- a/js/src/jsops.cpp
+++ b/js/src/jsops.cpp
@@ -1867,17 +1867,17 @@ BEGIN_CASE(JSOP_GETELEM)
 
             if (arg < obj->getArgsLength()) {
                 JSStackFrame *afp = (JSStackFrame *) obj->getPrivate();
                 if (afp) {
                     rval = afp->argv[arg];
                     goto end_getelem;
                 }
 
-                rval = GetArgsSlot(obj, arg);
+                rval = obj->getArgsElement(arg);
                 if (rval != JSVAL_HOLE)
                     goto end_getelem;
                 rval = FETCH_OPND(-1);
             }
         }
         id = INT_JSVAL_TO_JSID(rval);
     } else {
         if (!js_InternNonIntElementId(cx, obj, rval, &id))