Bug 686582 - Begin to specialize ObjectOps::defineElement to not just delegate to ObjectOps::defineProperty. r=dvander
authorJeff Walden <jwalden@mit.edu>
Wed, 10 Aug 2011 14:54:52 -0700
changeset 77034 4e647045ee7b60feb7e73fb2108fa27c599b1201
parent 77033 5df430079b0608a6659f479c0426e2a39d0d3a88
child 77035 8ddc354ef2a744f658603c70e7da417d88c3749b
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersdvander
bugs686582
milestone9.0a1
Bug 686582 - Begin to specialize ObjectOps::defineElement to not just delegate to ObjectOps::defineProperty. r=dvander
js/src/jsarray.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jstypedarray.cpp
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -980,20 +980,48 @@ array_defineProperty(JSContext *cx, JSOb
     return js_DefineProperty(cx, obj, id, value, getter, setter, attrs);
 }
 
 /* non-static for direct definition of array elements within the engine */
 JSBool
 array_defineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *value,
                     PropertyOp getter, StrictPropertyOp setter, uintN attrs)
 {
+    if (!obj->isDenseArray())
+        return js_DefineElement(cx, obj, index, value, getter, setter, attrs);
+
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
-    return array_defineProperty(cx, obj, id, value, getter, setter, attrs);
+
+    do {
+        /*
+         * UINT32_MAX is not an array index and must not affect the length
+         * property, so specifically reject it.
+         */
+        if (attrs != JSPROP_ENUMERATE || index == UINT32_MAX)
+            break;
+
+        JSObject::EnsureDenseResult result = obj->ensureDenseArrayElements(cx, index, 1);
+        if (result != JSObject::ED_OK) {
+            if (result == JSObject::ED_FAILED)
+                return false;
+            JS_ASSERT(result == JSObject::ED_SPARSE);
+            break;
+        }
+
+        if (index >= obj->getArrayLength())
+            obj->setDenseArrayLength(index + 1);
+        obj->setDenseArrayElementWithType(cx, index, *value);
+        return true;
+    } while (false);
+
+    if (!obj->makeDenseArraySlow(cx))
+        return false;
+    return js_DefineElement(cx, obj, index, value, getter, setter, attrs);
 }
 
 } // namespace js
 
 static JSBool
 array_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     *attrsp = JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -5061,16 +5061,26 @@ js_ChangeNativePropertyAttrs(JSContext *
 
 JSBool
 js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value,
                   PropertyOp getter, StrictPropertyOp setter, uintN attrs)
 {
     return !!DefineNativeProperty(cx, obj, id, *value, getter, setter, attrs, 0, 0);
 }
 
+JSBool
+js_DefineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *value,
+                 PropertyOp getter, StrictPropertyOp setter, uintN attrs)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return !!DefineNativeProperty(cx, obj, id, *value, getter, setter, attrs, 0, 0);
+}
+
 /*
  * Backward compatibility requires allowing addProperty hooks to mutate the
  * nominal initial value of a slotful property, while GC safety wants that
  * value to be stored before the call-out through the hook.  Optimize to do
  * both while saving cycles for classes that stub their addProperty hook.
  */
 static inline bool
 CallAddPropertyHook(JSContext *cx, Class *clasp, JSObject *obj, const Shape *shape, Value *vp)
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -250,16 +250,20 @@ js_LookupProperty(JSContext *cx, JSObjec
 extern JS_FRIEND_API(JSBool)
 js_LookupElement(JSContext *cx, JSObject *obj, uint32 index, JSObject **objp, JSProperty **propp);
 
 extern JSBool
 js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value *value,
                   js::PropertyOp getter, js::StrictPropertyOp setter, uintN attrs);
 
 extern JSBool
+js_DefineElement(JSContext *cx, JSObject *obj, uint32 index, const js::Value *value,
+                 js::PropertyOp getter, js::StrictPropertyOp setter, uintN attrs);
+
+extern JSBool
 js_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, js::Value *vp);
 
 extern JSBool
 js_GetElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32, js::Value *vp);
 
 inline JSBool
 js_GetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp)
 {
@@ -1402,20 +1406,24 @@ struct JSObject : js::gc::Cell {
     JSBool defineProperty(JSContext *cx, jsid id, const js::Value &value,
                           js::PropertyOp getter = js::PropertyStub,
                           js::StrictPropertyOp setter = js::StrictPropertyStub,
                           uintN attrs = JSPROP_ENUMERATE) {
         js::DefinePropOp op = getOps()->defineProperty;
         return (op ? op : js_DefineProperty)(cx, this, id, &value, getter, setter, attrs);
     }
 
-    inline JSBool defineElement(JSContext *cx, uint32 index, const js::Value &value,
-                                js::PropertyOp getter = js::PropertyStub,
-                                js::StrictPropertyOp setter = js::StrictPropertyStub,
-                                uintN attrs = JSPROP_ENUMERATE);
+    JSBool defineElement(JSContext *cx, uint32 index, const js::Value &value,
+                         js::PropertyOp getter = js::PropertyStub,
+                         js::StrictPropertyOp setter = js::StrictPropertyStub,
+                         uintN attrs = JSPROP_ENUMERATE)
+    {
+        js::DefineElementOp op = getOps()->defineElement;
+        return (op ? op : js_DefineElement)(cx, this, index, &value, getter, setter, attrs);
+    }
 
     inline JSBool getProperty(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp);
 
     inline JSBool getElement(JSContext *cx, JSObject *receiver, uint32 index, js::Value *vp);
 
     inline JSBool getProperty(JSContext *cx, jsid id, js::Value *vp);
 
     inline JSBool getElement(JSContext *cx, uint32 index, js::Value *vp);
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -1096,26 +1096,16 @@ JSObject::setSharedNonNativeMap()
 inline JSBool
 JSObject::lookupElement(JSContext *cx, uint32 index, JSObject **objp, JSProperty **propp)
 {
     js::LookupElementOp op = getOps()->lookupElement;
     return (op ? op : js_LookupElement)(cx, this, index, objp, propp);
 }
 
 inline JSBool
-JSObject::defineElement(JSContext *cx, uint32 index, const js::Value &value,
-                        js::PropertyOp getter, js::StrictPropertyOp setter, uintN attrs)
-{
-    jsid id;
-    if (!js::IndexToId(cx, index, &id))
-        return false;
-    return defineProperty(cx, id, value, getter, setter, attrs);
-}
-
-inline JSBool
 JSObject::getElement(JSContext *cx, JSObject *receiver, uint32 index, js::Value *vp)
 {
     jsid id;
     if (!js::IndexToId(cx, index, &id))
         return false;
     return getProperty(cx, receiver, id, vp);
 }
 
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -322,20 +322,20 @@ ArrayBuffer::obj_defineProperty(JSContex
         return false;
     return js_DefineProperty(cx, delegate, id, v, getter, setter, attrs);
 }
 
 JSBool
 ArrayBuffer::obj_defineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *v,
                    PropertyOp getter, StrictPropertyOp setter, uintN attrs)
 {
-    jsid id;
-    if (!IndexToId(cx, index, &id))
+    JSObject *delegate = DelegateObject(cx, obj);
+    if (!delegate)
         return false;
-    return obj_defineProperty(cx, obj, id, v, getter, setter, attrs);
+    return js_DefineElement(cx, delegate, index, v, getter, setter, attrs);
 }
 
 JSBool
 ArrayBuffer::obj_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
 {
     obj = getArrayBuffer(obj);
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) {
         vp->setInt32(obj->arrayBufferByteLength());
@@ -1031,20 +1031,18 @@ class TypedArrayTemplate
         Value tmp = *v;
         return obj_setProperty(cx, obj, id, &tmp, false);
     }
 
     static JSBool
     obj_defineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *v,
                        PropertyOp getter, StrictPropertyOp setter, uintN attrs)
     {
-        jsid id;
-        if (!IndexToId(cx, index, &id))
-            return false;
-        return obj_defineProperty(cx, obj, id, v, getter, setter, attrs);
+        Value tmp = *v;
+        return obj_setElement(cx, obj, index, &tmp, false);
     }
 
     static JSBool
     obj_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
     {
         if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
             rval->setBoolean(false);
             return true;