Bug 692333 - Split setProperty into property and generic forms, and use them throughout the engine. r=bhackett
authorJeff Walden <jwalden@mit.edu>
Wed, 05 Oct 2011 17:16:25 -0700
changeset 79621 f864bf022b6923924e2951f575a51cbd4dea8de2
parent 79620 8ee42c873213ae394f454f38f17fbda056ff6c60
child 79622 5b13e63313a8b76b47db2b1066d1c5597f384441
push id506
push userclegnitto@mozilla.com
push dateWed, 09 Nov 2011 02:03:18 +0000
treeherdermozilla-aurora@63587fc7bb93 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs692333
milestone10.0a1
Bug 692333 - Split setProperty into property and generic forms, and use them throughout the engine. r=bhackett
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jsclass.h
js/src/jsinterp.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jsproxy.cpp
js/src/jsreflect.cpp
js/src/jstracer.cpp
js/src/jstypedarray.cpp
js/src/jstypedarray.h
js/src/jswrapper.cpp
js/src/jsxml.cpp
js/src/methodjit/StubCalls.cpp
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3889,17 +3889,17 @@ JS_GetMethod(JSContext *cx, JSObject *ob
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
-    return obj->setProperty(cx, id, vp, false);
+    return obj->setGeneric(cx, id, vp, false);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetElement(JSContext *cx, JSObject *obj, uint32 index, jsval *vp)
 {
     CHECK_REQUEST(cx);
     jsid id;
     if (!IndexToId(cx, index, &id))
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -476,17 +476,17 @@ SetArrayElement(JSContext *cx, JSObject 
 
     AutoIdRooter idr(cx);
 
     if (!IndexToId(cx, obj, index, NULL, idr.addr(), JS_TRUE))
         return JS_FALSE;
     JS_ASSERT(!JSID_IS_VOID(idr.id()));
 
     Value tmp = v;
-    return obj->setProperty(cx, idr.id(), &tmp, true);
+    return obj->setGeneric(cx, idr.id(), &tmp, true);
 }
 
 #ifdef JS_TRACER
 JSBool JS_FASTCALL
 js_EnsureDenseArrayCapacity(JSContext *cx, JSObject *obj, jsint i)
 {
 #ifdef DEBUG
     Class *origObjClasp = obj->getClass();
@@ -559,23 +559,20 @@ SetOrDeleteArrayElement(JSContext *cx, J
         return DeleteArrayElement(cx, obj, index, true) >= 0;
     }
     return SetArrayElement(cx, obj, index, v);
 }
 
 JSBool
 js_SetLengthProperty(JSContext *cx, JSObject *obj, jsdouble length)
 {
-    Value v;
-    jsid id;
-
-    v.setNumber(length);
-    id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
+    Value v = NumberValue(length);
+
     /* We don't support read-only array length yet. */
-    return obj->setProperty(cx, id, &v, false);
+    return obj->setProperty(cx, cx->runtime->atomState.lengthAtom, &v, false);
 }
 
 /*
  * Since SpiderMonkey supports cross-class prototype-based delegation, we have
  * to be careful about the length getter and setter being called on an object
  * not of Array class. For the getter, we search obj's prototype chain for the
  * array that caused this getter to be invoked. In the setter case to overcome
  * the JSPROP_SHARED attribute, we must define a shadowing length property.
@@ -897,17 +894,17 @@ slowarray_addProperty(JSContext *cx, JSO
 
 static JSType
 array_typeOf(JSContext *cx, JSObject *obj)
 {
     return JSTYPE_OBJECT;
 }
 
 static JSBool
-array_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
+array_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
 {
     uint32 i;
 
     if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
         return array_length_setter(cx, obj, id, strict, vp);
 
     if (!obj->isDenseArray())
         return js_SetPropertyHelper(cx, obj, id, 0, vp, strict);
@@ -933,16 +930,22 @@ array_setProperty(JSContext *cx, JSObjec
     } while (false);
 
     if (!obj->makeDenseArraySlow(cx))
         return false;
     return js_SetPropertyHelper(cx, obj, id, 0, vp, strict);
 }
 
 static JSBool
+array_setProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict)
+{
+    return array_setGeneric(cx, obj, ATOM_TO_JSID(name), vp, strict);
+}
+
+static JSBool
 array_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict)
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
 
     if (!obj->isDenseArray())
         return js_SetPropertyHelper(cx, obj, id, 0, vp, strict);
@@ -974,17 +977,17 @@ array_setElement(JSContext *cx, JSObject
     if (!obj->makeDenseArraySlow(cx))
         return false;
     return js_SetPropertyHelper(cx, obj, id, 0, vp, strict);
 }
 
 static JSBool
 array_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
 {
-    return array_setProperty(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
+    return array_setGeneric(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
 }
 
 JSBool
 js_PrototypeHasIndexedProperties(JSContext *cx, JSObject *obj)
 {
     /*
      * Walk up the prototype chain and see if this indexed element already
      * exists. If we hit the end of the prototype chain, it's safe to set the
@@ -1268,17 +1271,17 @@ Class js::ArrayClass = {
         array_defineGeneric,
         array_defineProperty,
         array_defineElement,
         array_defineSpecial,
         array_getGeneric,
         array_getProperty,
         array_getElement,
         array_getSpecial,
-        array_setProperty,
+        array_setGeneric,
         array_setProperty,
         array_setElement,
         array_setSpecial,
         array_getGenericAttributes,
         array_getPropertyAttributes,
         array_getElementAttributes,
         array_getSpecialAttributes,
         array_setGenericAttributes,
@@ -1811,17 +1814,17 @@ InitArrayElements(JSContext *cx, JSObjec
 
     JS_ASSERT(start == MAX_ARRAY_INDEX + 1);
     AutoValueRooter tvr(cx);
     AutoIdRooter idr(cx);
     Value idval = DoubleValue(MAX_ARRAY_INDEX + 1);
     do {
         *tvr.addr() = *vector++;
         if (!js_ValueToStringId(cx, idval, idr.addr()) ||
-            !obj->setProperty(cx, idr.id(), tvr.addr(), true)) {
+            !obj->setGeneric(cx, idr.id(), tvr.addr(), true)) {
             return JS_FALSE;
         }
         idval.getDoubleRef() += 1;
     } while (vector != end);
 
     return JS_TRUE;
 }
 
--- a/js/src/jsclass.h
+++ b/js/src/jsclass.h
@@ -207,17 +207,17 @@ typedef JSBool
 (* PropertyIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName *name, Value *vp);
 typedef JSBool
 (* ElementIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, uint32 index, Value *vp);
 typedef JSBool
 (* SpecialIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp);
 typedef JSBool
 (* StrictGenericIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
 typedef JSBool
-(* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
+(* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict);
 typedef JSBool
 (* StrictElementIdOp)(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict);
 typedef JSBool
 (* StrictSpecialIdOp)(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
 typedef JSBool
 (* GenericAttributesOp)(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
 typedef JSBool
 (* PropertyAttributesOp)(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp);
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -3337,34 +3337,34 @@ do_incop:
         int incr = (format & JOF_INC) ? 1 : -1;
         if (format & JOF_POST)
             ref.getInt32Ref() = tmp + incr;
         else
             ref.getInt32Ref() = tmp += incr;
 
         {
             JSAutoResolveFlags rf(cx, setPropFlags);
-            if (!obj->setProperty(cx, id, &ref, script->strictModeCode))
+            if (!obj->setGeneric(cx, id, &ref, script->strictModeCode))
                 goto error;
         }
 
         /*
          * We must set regs.sp[-1] to tmp for both post and pre increments
          * as the setter overwrites regs.sp[-1].
          */
         ref.setInt32(tmp);
     } else {
         /* We need an extra root for the result. */
         PUSH_NULL();
         if (!DoIncDec(cx, cs, &regs.sp[-2], &regs.sp[-1]))
             goto error;
 
         {
             JSAutoResolveFlags rf(cx, setPropFlags);
-            if (!obj->setProperty(cx, id, &regs.sp[-1], script->strictModeCode))
+            if (!obj->setGeneric(cx, id, &regs.sp[-1], script->strictModeCode))
                 goto error;
         }
 
         regs.sp--;
     }
 
     if (cs->nuses == 0) {
         /* regs.sp[-1] already contains the result of name increment. */
@@ -3790,17 +3790,17 @@ BEGIN_CASE(JSOP_SETMETHOD)
                 defineHow = DNP_CACHE_RESULT | DNP_SET_METHOD;
             else if (op == JSOP_SETNAME)
                 defineHow = DNP_CACHE_RESULT | DNP_UNQUALIFIED;
             else
                 defineHow = DNP_CACHE_RESULT;
             if (!js_SetPropertyHelper(cx, obj, id, defineHow, &rval, script->strictModeCode))
                 goto error;
         } else {
-            if (!obj->setProperty(cx, id, &rval, script->strictModeCode))
+            if (!obj->setGeneric(cx, id, &rval, script->strictModeCode))
                 goto error;
             ABORT_RECORDING(cx, "Non-native set");
         }
     } while (0);
 }
 END_SET_CASE_STORE_RVAL(JSOP_SETPROP, 2);
 
 BEGIN_CASE(JSOP_GETELEM)
@@ -3939,31 +3939,31 @@ BEGIN_CASE(JSOP_SETELEM)
                 goto end_setelem;
             } else {
                 if (script->hasAnalysis() && !regs.fp()->hasImacropc())
                     script->analysis()->getCode(regs.pc).arrayWriteHole = true;
             }
         }
     } while (0);
     rval = regs.sp[-1];
-    if (!obj->setProperty(cx, id, &rval, script->strictModeCode))
+    if (!obj->setGeneric(cx, id, &rval, script->strictModeCode))
         goto error;
   end_setelem:;
 }
 END_SET_CASE_STORE_RVAL(JSOP_SETELEM, 3)
 
 BEGIN_CASE(JSOP_ENUMELEM)
 {
     /* Funky: the value to set is under the [obj, id] pair. */
     JSObject *obj;
     FETCH_OBJECT(cx, -2, obj);
     jsid id;
     FETCH_ELEMENT_ID(obj, -1, id);
     Value rval = regs.sp[-3];
-    if (!obj->setProperty(cx, id, &rval, script->strictModeCode))
+    if (!obj->setGeneric(cx, id, &rval, script->strictModeCode))
         goto error;
     regs.sp -= 3;
 }
 END_CASE(JSOP_ENUMELEM)
 
 BEGIN_CASE(JSOP_EVAL)
 {
     CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
@@ -4661,18 +4661,16 @@ BEGIN_CASE(JSOP_DEFFUN)
     JSProperty *prop = NULL;
     JSObject *pobj;
     if (!parent->lookupProperty(cx, name, &pobj, &prop))
         goto error;
 
     Value rval = ObjectValue(*obj);
 
     do {
-        PropertyName *name = fun->atom->asPropertyName();
-
         /* Steps 5d, 5f. */
         if (!prop || pobj != parent) {
             if (!parent->defineProperty(cx, name, rval,
                                         JS_PropertyStub, JS_StrictPropertyStub, attrs))
             {
                 goto error;
             }
             break;
@@ -4704,17 +4702,17 @@ BEGIN_CASE(JSOP_DEFFUN)
         /*
          * Non-global properties, and global properties which we aren't simply
          * redefining, must be set.  First, this preserves their attributes.
          * Second, this will produce warnings and/or errors as necessary if the
          * specified Call object property is not writable (const).
          */
 
         /* Step 5f. */
-        if (!parent->setProperty(cx, id, &rval, script->strictModeCode))
+        if (!parent->setProperty(cx, name, &rval, script->strictModeCode))
             goto error;
     } while (false);
 }
 END_CASE(JSOP_DEFFUN)
 
 BEGIN_CASE(JSOP_DEFFUN_FC)
 {
     JSFunction *fun;
@@ -4731,20 +4729,20 @@ BEGIN_CASE(JSOP_DEFFUN_FC)
                   : JSPROP_ENUMERATE | JSPROP_PERMANENT;
 
     JSObject &parent = regs.fp()->varObj();
 
     jsid id = ATOM_TO_JSID(fun->atom);
     if (!CheckRedeclaration(cx, &parent, id, attrs))
         goto error;
 
+    PropertyName *name = fun->atom->asPropertyName();
     if ((attrs == JSPROP_ENUMERATE)
-        ? !parent.setProperty(cx, id, &rval, script->strictModeCode)
-        : !parent.defineProperty(cx, fun->atom->asPropertyName(), rval,
-                                 JS_PropertyStub, JS_StrictPropertyStub, attrs))
+        ? !parent.setProperty(cx, name, &rval, script->strictModeCode)
+        : !parent.defineProperty(cx, name, rval, JS_PropertyStub, JS_StrictPropertyStub, attrs))
     {
         goto error;
     }
 }
 END_CASE(JSOP_DEFFUN_FC)
 
 BEGIN_CASE(JSOP_DEFLOCALFUN)
 {
@@ -5575,17 +5573,17 @@ BEGIN_CASE(JSOP_BINDXMLNAME)
 END_CASE(JSOP_BINDXMLNAME)
 
 BEGIN_CASE(JSOP_SETXMLNAME)
 {
     JSObject *obj = &regs.sp[-3].toObject();
     Value rval = regs.sp[-1];
     jsid id;
     FETCH_ELEMENT_ID(obj, -2, id);
-    if (!obj->setProperty(cx, id, &rval, script->strictModeCode))
+    if (!obj->setGeneric(cx, id, &rval, script->strictModeCode))
         goto error;
     rval = regs.sp[-1];
     regs.sp -= 2;
     regs.sp[-1] = rval;
 }
 END_CASE(JSOP_SETXMLNAME)
 
 BEGIN_CASE(JSOP_CALLXMLNAME)
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3305,34 +3305,37 @@ with_GetElement(JSContext *cx, JSObject 
 
 static JSBool
 with_GetSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp)
 {
     return with_GetGeneric(cx, obj, receiver, SPECIALID_TO_JSID(sid), vp);
 }
 
 static JSBool
-with_SetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
-{
-    return obj->getProto()->setProperty(cx, id, vp, strict);
+with_SetGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
+{
+    return obj->getProto()->setGeneric(cx, id, vp, strict);
+}
+
+static JSBool
+with_SetProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict)
+{
+    return obj->getProto()->setProperty(cx, name, vp, strict);
 }
 
 static JSBool
 with_SetElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict)
 {
-    jsid id;
-    if (!IndexToId(cx, index, &id))
-        return false;
-    return with_SetProperty(cx, obj, id, vp, strict);
+    return obj->getProto()->setElement(cx, index, vp, strict);
 }
 
 static JSBool
 with_SetSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
 {
-    return with_SetProperty(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
+    return obj->getProto()->setSpecial(cx, sid, vp, strict);
 }
 
 static JSBool
 with_GetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     return obj->getProto()->getGenericAttributes(cx, id, attrsp);
 }
 
@@ -3448,17 +3451,17 @@ Class js::WithClass = {
         NULL,             /* defineGeneric */
         NULL,             /* defineProperty */
         NULL,             /* defineElement */
         NULL,             /* defineSpecial */
         with_GetGeneric,
         with_GetProperty,
         with_GetElement,
         with_GetSpecial,
-        with_SetProperty,
+        with_SetGeneric,
         with_SetProperty,
         with_SetElement,
         with_SetSpecial,
         with_GetGenericAttributes,
         with_GetPropertyAttributes,
         with_GetElementAttributes,
         with_GetSpecialAttributes,
         with_SetGenericAttributes,
@@ -3665,17 +3668,17 @@ JSBool
 JSObject::nonNativeSetProperty(JSContext *cx, jsid id, js::Value *vp, JSBool strict)
 {
     if (JS_UNLIKELY(watched())) {
         id = js_CheckForStringIndex(id);
         WatchpointMap *wpmap = cx->compartment->watchpointMap;
         if (wpmap && !wpmap->triggerWatchpoint(cx, this, id, vp))
             return false;
     }
-    return getOps()->setProperty(cx, this, id, vp, strict);
+    return getOps()->setGeneric(cx, this, id, vp, strict);
 }
 
 JSBool
 JSObject::nonNativeSetElement(JSContext *cx, uint32 index, js::Value *vp, JSBool strict)
 {
     if (JS_UNLIKELY(watched())) {
         jsid id;
         if (!IndexToId(cx, index, &id))
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1380,27 +1380,20 @@ struct JSObject : js::gc::Cell {
     inline JSBool getElement(JSContext *cx, JSObject *receiver, uint32 index, js::Value *vp);
     inline JSBool getSpecial(JSContext *cx, JSObject *receiver, js::SpecialId sid, js::Value *vp);
 
     inline JSBool getGeneric(JSContext *cx, jsid id, js::Value *vp);
     inline JSBool getProperty(JSContext *cx, js::PropertyName *name, js::Value *vp);
     inline JSBool getElement(JSContext *cx, uint32 index, js::Value *vp);
     inline JSBool getSpecial(JSContext *cx, js::SpecialId sid, js::Value *vp);
 
-    JSBool setProperty(JSContext *cx, jsid id, js::Value *vp, JSBool strict) {
-        if (getOps()->setProperty)
-            return nonNativeSetProperty(cx, id, vp, strict);
-        return js_SetPropertyHelper(cx, this, id, 0, vp, strict);
-    }
-
-    JSBool setElement(JSContext *cx, uint32 index, js::Value *vp, JSBool strict) {
-        if (getOps()->setElement)
-            return nonNativeSetElement(cx, index, vp, strict);
-        return js_SetElementHelper(cx, this, index, 0, vp, strict);
-    }
+    inline JSBool setGeneric(JSContext *cx, jsid id, js::Value *vp, JSBool strict);
+    inline JSBool setProperty(JSContext *cx, js::PropertyName *name, js::Value *vp, JSBool strict);
+    inline JSBool setElement(JSContext *cx, uint32 index, js::Value *vp, JSBool strict);
+    inline JSBool setSpecial(JSContext *cx, js::SpecialId sid, js::Value *vp, JSBool strict);
 
     JSBool nonNativeSetProperty(JSContext *cx, jsid id, js::Value *vp, JSBool strict);
 
     JSBool nonNativeSetElement(JSContext *cx, uint32 index, js::Value *vp, JSBool strict);
 
     inline JSBool getGenericAttributes(JSContext *cx, jsid id, uintN *attrsp);
     inline JSBool getPropertyAttributes(JSContext *cx, js::PropertyName *name, uintN *attrsp);
     inline JSBool getElementAttributes(JSContext *cx, uint32 index, uintN *attrsp);
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -121,16 +121,44 @@ JSObject::unbrand(JSContext *cx)
             return false;
         flags &= ~BRANDED;
     }
     setGeneric();
     return true;
 }
 
 inline JSBool
+JSObject::setGeneric(JSContext *cx, jsid id, js::Value *vp, JSBool strict)
+{
+    if (getOps()->setGeneric)
+        return nonNativeSetProperty(cx, id, vp, strict);
+    return js_SetPropertyHelper(cx, this, id, 0, vp, strict);
+}
+
+inline JSBool
+JSObject::setProperty(JSContext *cx, js::PropertyName *name, js::Value *vp, JSBool strict)
+{
+    return setGeneric(cx, ATOM_TO_JSID(name), vp, strict);
+}
+
+inline JSBool
+JSObject::setElement(JSContext *cx, uint32 index, js::Value *vp, JSBool strict)
+{
+    if (getOps()->setElement)
+        return nonNativeSetElement(cx, index, vp, strict);
+    return js_SetElementHelper(cx, this, index, 0, vp, strict);
+}
+
+inline JSBool
+JSObject::setSpecial(JSContext *cx, js::SpecialId sid, js::Value *vp, JSBool strict)
+{
+    return setGeneric(cx, SPECIALID_TO_JSID(sid), vp, strict);
+}
+
+inline JSBool
 JSObject::setGenericAttributes(JSContext *cx, jsid id, uintN *attrsp)
 {
     js::types::MarkTypePropertyConfigured(cx, this, id);
     js::GenericAttributesOp op = getOps()->setGenericAttributes;
     return (op ? op : js_SetAttributes)(cx, this, id, attrsp);
 }
 
 inline JSBool
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -1019,36 +1019,42 @@ proxy_GetElement(JSContext *cx, JSObject
 
 static JSBool
 proxy_GetSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp)
 {
     return proxy_GetGeneric(cx, obj, receiver, SPECIALID_TO_JSID(sid), vp);
 }
 
 static JSBool
-proxy_SetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
+proxy_SetGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
 {
     id = js_CheckForStringIndex(id);
 
     return Proxy::set(cx, obj, obj, id, strict, vp);
 }
 
 static JSBool
+proxy_SetProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict)
+{
+    return proxy_SetGeneric(cx, obj, ATOM_TO_JSID(name), vp, strict);
+}
+
+static JSBool
 proxy_SetElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict)
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
-    return proxy_SetProperty(cx, obj, id, vp, strict);
+    return proxy_SetGeneric(cx, obj, id, vp, strict);
 }
 
 static JSBool
 proxy_SetSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
 {
-    return proxy_SetProperty(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
+    return proxy_SetGeneric(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
 }
 
 static JSBool
 proxy_GetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     id = js_CheckForStringIndex(id);
 
     AutoPropertyDescriptorRooter desc(cx);
@@ -1241,17 +1247,17 @@ JS_FRIEND_DATA(Class) js::ObjectProxyCla
         proxy_DefineGeneric,
         proxy_DefineProperty,
         proxy_DefineElement,
         proxy_DefineSpecial,
         proxy_GetGeneric,
         proxy_GetProperty,
         proxy_GetElement,
         proxy_GetSpecial,
-        proxy_SetProperty,
+        proxy_SetGeneric,
         proxy_SetProperty,
         proxy_SetElement,
         proxy_SetSpecial,
         proxy_GetGenericAttributes,
         proxy_GetPropertyAttributes,
         proxy_GetElementAttributes,
         proxy_GetSpecialAttributes,
         proxy_SetGenericAttributes,
@@ -1302,17 +1308,17 @@ JS_FRIEND_DATA(Class) js::OuterWindowPro
         proxy_DefineGeneric,
         proxy_DefineProperty,
         proxy_DefineElement,
         proxy_DefineSpecial,
         proxy_GetGeneric,
         proxy_GetProperty,
         proxy_GetElement,
         proxy_GetSpecial,
-        proxy_SetProperty,
+        proxy_SetGeneric,
         proxy_SetProperty,
         proxy_SetElement,
         proxy_SetSpecial,
         proxy_GetGenericAttributes,
         proxy_GetPropertyAttributes,
         proxy_GetElementAttributes,
         proxy_GetSpecialAttributes,
         proxy_SetGenericAttributes,
@@ -1375,17 +1381,17 @@ JS_FRIEND_DATA(Class) js::FunctionProxyC
         proxy_DefineGeneric,
         proxy_DefineProperty,
         proxy_DefineElement,
         proxy_DefineSpecial,
         proxy_GetGeneric,
         proxy_GetProperty,
         proxy_GetElement,
         proxy_GetSpecial,
-        proxy_SetProperty,
+        proxy_SetGeneric,
         proxy_SetProperty,
         proxy_SetElement,
         proxy_SetSpecial,
         proxy_GetGenericAttributes,
         proxy_GetPropertyAttributes,
         proxy_GetElementAttributes,
         proxy_GetSpecialAttributes,
         proxy_SetGenericAttributes,
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -655,17 +655,17 @@ NodeBuilder::newArray(NodeVector &elts, 
         Value val = elts[i];
 
         JS_ASSERT_IF(val.isMagic(), val.whyMagic() == JS_SERIALIZE_NO_NODE);
 
         /* Represent "no node" as an array hole by not adding the value. */
         if (val.isMagic(JS_SERIALIZE_NO_NODE))
             continue;
 
-        if (!array->setProperty(cx, INT_TO_JSID(i), &val, false))
+        if (!array->setElement(cx, i, &val, false))
             return false;
     }
 
     dst->setObject(*array);
     return true;
 }
 
 bool
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -12848,17 +12848,17 @@ TraceRecorder::record_JSOP_GETELEM()
 static JSBool FASTCALL
 SetPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, Value* vp, JSBool strict)
 {
     TraceMonitor *tm = JS_TRACE_MONITOR_ON_TRACE(cx);
 
     LeaveTraceIfGlobalObject(cx, obj);
 
     jsid id;
-    if (!RootedStringToId(cx, namep, &id) || !obj->setProperty(cx, id, vp, strict)) {
+    if (!RootedStringToId(cx, namep, &id) || !obj->setGeneric(cx, id, vp, strict)) {
         SetBuiltinError(tm);
         return false;
     }
     return WasBuiltinSuccessful(tm);
 }
 JS_DEFINE_CALLINFO_5(static, BOOL_FAIL, SetPropertyByName,
                      CONTEXT, OBJECT, STRINGPTR, VALUEPTR, BOOL,
                      0, ACCSET_STORE_ANY)
@@ -12908,17 +12908,17 @@ TraceRecorder::initOrSetPropertyByName(L
 static JSBool FASTCALL
 SetPropertyByIndex(JSContext* cx, JSObject* obj, int32 index, Value* vp, JSBool strict)
 {
     TraceMonitor *tm = JS_TRACE_MONITOR_ON_TRACE(cx);
 
     LeaveTraceIfGlobalObject(cx, obj);
 
     AutoIdRooter idr(cx);
-    if (!js_Int32ToId(cx, index, idr.addr()) || !obj->setProperty(cx, idr.id(), vp, strict)) {
+    if (!js_Int32ToId(cx, index, idr.addr()) || !obj->setGeneric(cx, idr.id(), vp, strict)) {
         SetBuiltinError(tm);
         return false;
     }
     return WasBuiltinSuccessful(tm);
 }
 JS_DEFINE_CALLINFO_5(static, BOOL_FAIL, SetPropertyByIndex, CONTEXT, OBJECT, INT32, VALUEPTR, BOOL,
                      0, ACCSET_STORE_ANY)
 
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -394,17 +394,17 @@ ArrayBuffer::obj_getElement(JSContext *c
 
 JSBool
 ArrayBuffer::obj_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp)
 {
     return obj_getGeneric(cx, obj, receiver, SPECIALID_TO_JSID(sid), vp);
 }
 
 JSBool
-ArrayBuffer::obj_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
+ArrayBuffer::obj_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
 {
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom))
         return true;
 
     if (JSID_IS_ATOM(id, cx->runtime->atomState.protoAtom)) {
         // setting __proto__ = null
         // effectively removes the prototype chain.
         // any attempt to set __proto__ on native
@@ -448,29 +448,35 @@ ArrayBuffer::obj_setProperty(JSContext *
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
         return false;
 
     return js_SetPropertyHelper(cx, delegate, id, 0, vp, strict);
 }
 
 JSBool
+ArrayBuffer::obj_setProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict)
+{
+    return obj_setGeneric(cx, obj, ATOM_TO_JSID(name), vp, strict);
+}
+
+JSBool
 ArrayBuffer::obj_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict)
 {
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
         return false;
 
     return js_SetElementHelper(cx, delegate, index, 0, vp, strict);
 }
 
 JSBool
 ArrayBuffer::obj_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
 {
-    return obj_setProperty(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
+    return obj_setGeneric(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
 }
 
 JSBool
 ArrayBuffer::obj_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) {
         *attrsp = JSPROP_PERMANENT | JSPROP_READONLY;
         return true;
@@ -1123,17 +1129,17 @@ class TypedArrayTemplate
             int32 n = js_DoubleToECMAInt32(d);
             setIndex(tarray, index, NativeType(n));
         }
 
         return true;
     }
 
     static JSBool
-    obj_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
+    obj_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
     {
         JSObject *tarray = getTypedArray(obj);
         JS_ASSERT(tarray);
 
         if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
             vp->setNumber(getLength(tarray));
             return true;
         }
@@ -1149,16 +1155,22 @@ class TypedArrayTemplate
             vp->setUndefined();
             return true;
         }
 
         return setElementTail(cx, tarray, index, vp, strict);
     }
 
     static JSBool
+    obj_setProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict)
+    {
+        return obj_setGeneric(cx, obj, ATOM_TO_JSID(name), vp, strict);
+    }
+
+    static JSBool
     obj_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict)
     {
         JSObject *tarray = getTypedArray(obj);
         JS_ASSERT(tarray);
 
         if (index >= getLength(tarray)) {
             // Silent ignore is better than an exception here, because
             // at some point we may want to support other properties on
@@ -1170,28 +1182,28 @@ class TypedArrayTemplate
         }
 
         return setElementTail(cx, tarray, index, vp, strict);
     }
 
     static JSBool
     obj_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
     {
-        return obj_setProperty(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
+        return obj_setGeneric(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
     }
 
     static JSBool
     obj_defineGeneric(JSContext *cx, JSObject *obj, jsid id, const Value *v,
                       PropertyOp getter, StrictPropertyOp setter, uintN attrs)
     {
         if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
             return true;
 
         Value tmp = *v;
-        return obj_setProperty(cx, obj, id, &tmp, false);
+        return obj_setGeneric(cx, obj, id, &tmp, false);
     }
 
     static JSBool
     obj_defineProperty(JSContext *cx, JSObject *obj, PropertyName *name, const Value *v,
                        PropertyOp getter, StrictPropertyOp setter, uintN attrs)
     {
         return obj_defineGeneric(cx, obj, ATOM_TO_JSID(name), v, getter, setter, attrs);
     }
@@ -2089,17 +2101,17 @@ Class js::ArrayBufferClass = {
         ArrayBuffer::obj_defineGeneric,
         ArrayBuffer::obj_defineProperty,
         ArrayBuffer::obj_defineElement,
         ArrayBuffer::obj_defineSpecial,
         ArrayBuffer::obj_getGeneric,
         ArrayBuffer::obj_getProperty,
         ArrayBuffer::obj_getElement,
         ArrayBuffer::obj_getSpecial,
-        ArrayBuffer::obj_setProperty,
+        ArrayBuffer::obj_setGeneric,
         ArrayBuffer::obj_setProperty,
         ArrayBuffer::obj_setElement,
         ArrayBuffer::obj_setSpecial,
         ArrayBuffer::obj_getGenericAttributes,
         ArrayBuffer::obj_getPropertyAttributes,
         ArrayBuffer::obj_getElementAttributes,
         ArrayBuffer::obj_getSpecialAttributes,
         ArrayBuffer::obj_setGenericAttributes,
@@ -2201,17 +2213,17 @@ JSFunctionSpec _typedArray::jsfuncs[] = 
         _typedArray::obj_defineGeneric,                                        \
         _typedArray::obj_defineProperty,                                       \
         _typedArray::obj_defineElement,                                        \
         _typedArray::obj_defineSpecial,                                        \
         _typedArray::obj_getGeneric,                                           \
         _typedArray::obj_getProperty,                                          \
         _typedArray::obj_getElement,                                           \
         _typedArray::obj_getSpecial,                                           \
-        _typedArray::obj_setProperty,                                          \
+        _typedArray::obj_setGeneric,                                           \
         _typedArray::obj_setProperty,                                          \
         _typedArray::obj_setElement,                                           \
         _typedArray::obj_setSpecial,                                           \
         _typedArray::obj_getGenericAttributes,                                 \
         _typedArray::obj_getPropertyAttributes,                                \
         _typedArray::obj_getElementAttributes,                                 \
         _typedArray::obj_getSpecialAttributes,                                 \
         _typedArray::obj_setGenericAttributes,                                 \
--- a/js/src/jstypedarray.h
+++ b/js/src/jstypedarray.h
@@ -109,21 +109,21 @@ struct JS_FRIEND_API(ArrayBuffer) {
 
     static JSBool
     obj_getElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32 index, Value *vp);
 
     static JSBool
     obj_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp);
 
     static JSBool
-    obj_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
-
+    obj_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
+    static JSBool
+    obj_setProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict);
     static JSBool
     obj_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict);
-
     static JSBool
     obj_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
 
     static JSBool
     obj_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
     static JSBool
     obj_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp);
     static JSBool
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -230,17 +230,17 @@ Wrapper::get(JSContext *cx, JSObject *wr
     GET(wrappedObject(wrapper)->getGeneric(cx, receiver, id, vp));
 }
 
 bool
 Wrapper::set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, bool strict,
                Value *vp)
 {
     // FIXME (bug 596351): Need deal with strict mode.
-    SET(wrappedObject(wrapper)->setProperty(cx, id, vp, false));
+    SET(wrappedObject(wrapper)->setGeneric(cx, id, vp, false));
 }
 
 bool
 Wrapper::keys(JSContext *cx, JSObject *wrapper, AutoIdVector &props)
 {
     // if we refuse to perform this action, props remains empty
     const jsid id = JSID_VOID;
     GET(GetPropertyNames(cx, wrappedObject(wrapper), JSITER_OWNONLY, &props));
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -4858,19 +4858,19 @@ xml_getSpecial(JSContext *cx, JSObject *
 
 static JSBool
 xml_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
 {
     return PutProperty(cx, obj, id, strict, vp);
 }
 
 static JSBool
-xml_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
-{
-    return xml_setGeneric(cx, obj, id, vp, strict);
+xml_setProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict)
+{
+    return xml_setGeneric(cx, obj, ATOM_TO_JSID(name), vp, strict);
 }
 
 static JSBool
 xml_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict)
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
@@ -5340,17 +5340,17 @@ JS_FRIEND_DATA(Class) js::XMLClass = {
         xml_defineGeneric,
         xml_defineProperty,
         xml_defineElement,
         xml_defineSpecial,
         xml_getGeneric,
         xml_getProperty,
         xml_getElement,
         xml_getSpecial,
-        xml_setProperty,
+        xml_setGeneric,
         xml_setProperty,
         xml_setElement,
         xml_setSpecial,
         xml_getGenericAttributes,
         xml_getPropertyAttributes,
         xml_getElementAttributes,
         xml_getSpecialAttributes,
         xml_setGenericAttributes,
@@ -6027,17 +6027,17 @@ NamespacesToJSArray(JSContext *cx, JSXML
     *rval = OBJECT_TO_JSVAL(arrayobj);
 
     AutoValueRooter tvr(cx);
     for (uint32 i = 0, n = array->length; i < n; i++) {
         JSObject *ns = XMLARRAY_MEMBER(array, i, JSObject);
         if (!ns)
             continue;
         tvr.set(ObjectValue(*ns));
-        if (!arrayobj->setProperty(cx, INT_TO_JSID(i), tvr.addr(), false))
+        if (!arrayobj->setElement(cx, i, tvr.addr(), false))
             return false;
     }
     return true;
 }
 
 static JSBool
 xml_inScopeNamespaces(JSContext *cx, uintN argc, jsval *vp)
 {
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -249,30 +249,31 @@ stubs::SetName(VMFrame &f, JSAtom *origA
             }
             PCMETER(cache->setpcmisses++);
 
             atom = origAtom;
         } else {
             JS_ASSERT(atom);
         }
 
+        PropertyName *name = atom->asPropertyName();
         jsid id = ATOM_TO_JSID(atom);
         if (entry && JS_LIKELY(!obj->getOps()->setProperty)) {
             uintN defineHow;
             JSOp op = JSOp(*f.pc());
             if (op == JSOP_SETMETHOD)
                 defineHow = DNP_CACHE_RESULT | DNP_SET_METHOD;
             else if (op == JSOP_SETNAME)
                 defineHow = DNP_CACHE_RESULT | DNP_UNQUALIFIED;
             else
                 defineHow = DNP_CACHE_RESULT;
             if (!js_SetPropertyHelper(cx, obj, id, defineHow, &rval, strict))
                 THROW();
         } else {
-            if (!obj->setProperty(cx, id, &rval, strict))
+            if (!obj->setProperty(cx, name, &rval, strict))
                 THROW();
         }
     } while (0);
 
     f.regs.sp[-2] = f.regs.sp[-1];
 }
 
 template void JS_FASTCALL stubs::SetName<true>(VMFrame &f, JSAtom *origAtom);
@@ -282,38 +283,34 @@ template<JSBool strict>
 void JS_FASTCALL
 stubs::SetPropNoCache(VMFrame &f, JSAtom *atom)
 {
     JSObject *obj = ValueToObject(f.cx, &f.regs.sp[-2]);
     if (!obj)
          THROW();
     Value rval = f.regs.sp[-1];
 
-    if (!obj->setProperty(f.cx, ATOM_TO_JSID(atom), &f.regs.sp[-1], strict))
+    if (!obj->setGeneric(f.cx, ATOM_TO_JSID(atom), &f.regs.sp[-1], strict))
         THROW();
     f.regs.sp[-2] = rval;
 }
 
 template void JS_FASTCALL stubs::SetPropNoCache<true>(VMFrame &f, JSAtom *origAtom);
 template void JS_FASTCALL stubs::SetPropNoCache<false>(VMFrame &f, JSAtom *origAtom);
 
 template<JSBool strict>
 void JS_FASTCALL
 stubs::SetGlobalNameNoCache(VMFrame &f, JSAtom *atom)
 {
     JSContext *cx = f.cx;
 
     Value rval = f.regs.sp[-1];
     Value &lref = f.regs.sp[-2];
     JSObject *obj = ValueToObject(cx, &lref);
-    if (!obj)
-        THROW();
-    jsid id = ATOM_TO_JSID(atom);
-
-    if (!obj->setProperty(cx, id, &rval, strict))
+    if (!obj || !obj->setProperty(cx, atom->asPropertyName(), &rval, strict))
         THROW();
 
     f.regs.sp[-2] = f.regs.sp[-1];
 }
 
 template void JS_FASTCALL stubs::SetGlobalNameNoCache<true>(VMFrame &f, JSAtom *atom);
 template void JS_FASTCALL stubs::SetGlobalNameNoCache<false>(VMFrame &f, JSAtom *atom);
 
@@ -577,17 +574,17 @@ stubs::SetElem(VMFrame &f)
                 obj->setDenseArrayElementWithType(cx, i, rval);
                 goto end_setelem;
             } else {
                 if (f.script()->hasAnalysis())
                     f.script()->analysis()->getCode(f.pc()).arrayWriteHole = true;
             }
         }
     } while (0);
-    if (!obj->setProperty(cx, id, &rval, strict))
+    if (!obj->setGeneric(cx, id, &rval, strict))
         THROW();
   end_setelem:
     /* :FIXME: Moving the assigned object into the lowest stack slot
      * is a temporary hack. What we actually want is an implementation
      * of popAfterSet() that allows popping more than one value;
      * this logic can then be handled in Compiler.cpp. */
     regs.sp[-3] = regs.sp[-1];
 }
@@ -791,18 +788,16 @@ stubs::DefFun(VMFrame &f, JSFunction *fu
     JSProperty *prop = NULL;
     JSObject *pobj;
     if (!parent->lookupProperty(cx, name, &pobj, &prop))
         THROW();
 
     Value rval = ObjectValue(*obj);
 
     do {
-        PropertyName *name = fun->atom->asPropertyName();
-
         /* Steps 5d, 5f. */
         if (!prop || pobj != parent) {
             if (!parent->defineProperty(cx, name, rval,
                                         JS_PropertyStub, JS_StrictPropertyStub, attrs))
             {
                 THROW();
             }
             break;
@@ -834,17 +829,17 @@ stubs::DefFun(VMFrame &f, JSFunction *fu
         /*
          * Non-global properties, and global properties which we aren't simply
          * redefining, must be set.  First, this preserves their attributes.
          * Second, this will produce warnings and/or errors as necessary if the
          * specified Call object property is not writable (const).
          */
 
         /* Step 5f. */
-        if (!parent->setProperty(cx, id, &rval, strict))
+        if (!parent->setProperty(cx, name, &rval, strict))
             THROW();
     } while (false);
 }
 
 template void JS_FASTCALL stubs::DefFun<true>(VMFrame &f, JSFunction *fun);
 template void JS_FASTCALL stubs::DefFun<false>(VMFrame &f, JSFunction *fun);
 
 #define RELATIONAL(OP)                                                        \