Bug 989276 Part 2 -- Refactor the slots to group by subtype r=sfink
authorNicholas D. Matsakis <nmatsakis@mozilla.com>
Fri, 28 Mar 2014 10:38:49 -0400
changeset 186877 039b9e7b3616d4f9dcc0fa9d67d932a9053b298b
parent 186876 b1e0a1050d9b8afb8916608b04417ae290ba7794
child 186878 7084e7ad795193b162f4399e8275267e35dd0024
child 186916 c08a299f21639dfcbc4dd05c72f4e32c56885de4
push id44456
push usernmatsakis@mozilla.com
push dateThu, 05 Jun 2014 19:50:03 +0000
treeherdermozilla-inbound@039b9e7b3616 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs989276
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 989276 Part 2 -- Refactor the slots to group by subtype r=sfink
js/src/builtin/TypedObject.cpp
js/src/builtin/TypedObject.h
js/src/builtin/TypedObject.js
js/src/builtin/TypedObjectConstants.h
js/src/jit/IonBuilder.cpp
js/src/vm/ArrayBufferObject.h
js/src/vm/TypedArrayObject.h
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -1473,21 +1473,21 @@ TypedObject::createUnattachedWithClass(J
         }
         proto = &protoVal.toObject();
     }
 
     RootedObject obj(cx, NewObjectWithClassProto(cx, clasp, &*proto, nullptr));
     if (!obj)
         return nullptr;
 
-    obj->setPrivate(nullptr);
-    obj->initReservedSlot(JS_TYPEDOBJ_SLOT_BYTEOFFSET, Int32Value(0));
-    obj->initReservedSlot(JS_TYPEDOBJ_SLOT_LENGTH, Int32Value(length));
-    obj->initReservedSlot(JS_TYPEDOBJ_SLOT_OWNER, NullValue());
-    obj->initReservedSlot(JS_TYPEDOBJ_SLOT_NEXT_VIEW, PrivateValue(nullptr));
+    obj->initPrivate(nullptr);
+    obj->initReservedSlot(JS_BUFVIEW_SLOT_BYTEOFFSET, Int32Value(0));
+    obj->initReservedSlot(JS_BUFVIEW_SLOT_LENGTH, Int32Value(length));
+    obj->initReservedSlot(JS_BUFVIEW_SLOT_OWNER, NullValue());
+    obj->initReservedSlot(JS_BUFVIEW_SLOT_NEXT_VIEW, PrivateValue(nullptr));
     obj->initReservedSlot(JS_TYPEDOBJ_SLOT_TYPE_DESCR, ObjectValue(*type));
 
     // Tag the type object for this instance with the type
     // representation, if that has not been done already.
     if (!type->is<SimpleTypeDescr>()) { // FIXME Bug 929651
         RootedTypeObject typeObj(cx, obj->getType(cx));
         if (typeObj) {
             if (!typeObj->addTypedObjectAddendum(cx, type))
@@ -1501,18 +1501,18 @@ TypedObject::createUnattachedWithClass(J
 void
 TypedObject::attach(ArrayBufferObject &buffer, int32_t offset)
 {
     JS_ASSERT(offset >= 0);
     JS_ASSERT((size_t) (offset + size()) <= buffer.byteLength());
 
     buffer.addView(this);
     InitArrayBufferViewDataPointer(this, &buffer, offset);
-    setReservedSlot(JS_TYPEDOBJ_SLOT_BYTEOFFSET, Int32Value(offset));
-    setReservedSlot(JS_TYPEDOBJ_SLOT_OWNER, ObjectValue(buffer));
+    setReservedSlot(JS_BUFVIEW_SLOT_BYTEOFFSET, Int32Value(offset));
+    setReservedSlot(JS_BUFVIEW_SLOT_OWNER, ObjectValue(buffer));
 }
 
 void
 TypedObject::attach(TypedObject &typedObj, int32_t offset)
 {
     JS_ASSERT(!typedObj.owner().isNeutered());
     JS_ASSERT(typedObj.typedMem() != NULL);
 
@@ -2211,37 +2211,45 @@ TypedObject::obj_enumerate(JSContext *cx
     }
 
     return true;
 }
 
 /* static */ size_t
 TypedObject::offsetOfOwnerSlot()
 {
-    return JSObject::getFixedSlotOffset(JS_TYPEDOBJ_SLOT_OWNER);
+    return JSObject::getFixedSlotOffset(JS_BUFVIEW_SLOT_OWNER);
 }
 
 /* static */ size_t
 TypedObject::offsetOfDataSlot()
 {
-    // the offset of 7 is based on the alloc kind
+#   ifdef DEBUG
+    // Compute offset of private data based on TransparentTypedObject;
+    // both OpaqueTypedObject and TransparentTypedObject have the same
+    // number of slots, so no problem there.
+    gc::AllocKind allocKind = gc::GetGCObjectKind(&TransparentTypedObject::class_);
+    size_t nfixed = gc::GetGCKindSlots(allocKind);
+    JS_ASSERT(JS_TYPEDOBJ_SLOT_DATA == nfixed - 1);
+#   endif
+
     return JSObject::getPrivateDataOffset(JS_TYPEDOBJ_SLOT_DATA);
 }
 
 /* static */ size_t
 TypedObject::offsetOfByteOffsetSlot()
 {
-    return JSObject::getFixedSlotOffset(JS_TYPEDOBJ_SLOT_BYTEOFFSET);
+    return JSObject::getFixedSlotOffset(JS_BUFVIEW_SLOT_BYTEOFFSET);
 }
 
 void
 TypedObject::neuter(void *newData)
 {
-    setSlot(JS_TYPEDOBJ_SLOT_LENGTH, Int32Value(0));
-    setSlot(JS_TYPEDOBJ_SLOT_BYTEOFFSET, Int32Value(0));
+    setSlot(JS_BUFVIEW_SLOT_LENGTH, Int32Value(0));
+    setSlot(JS_BUFVIEW_SLOT_BYTEOFFSET, Int32Value(0));
     setPrivate(newData);
 }
 
 /******************************************************************************
  * Typed Objects
  */
 
 const Class TransparentTypedObject::class_ = {
@@ -2716,17 +2724,17 @@ js::SetTypedObjectOffset(ThreadSafeConte
 
     TypedObject &typedObj = args[0].toObject().as<TypedObject>();
     int32_t offset = args[1].toInt32();
 
     JS_ASSERT(!typedObj.owner().isNeutered());
     JS_ASSERT(typedObj.typedMem() != nullptr); // must be attached already
 
     typedObj.setPrivate(typedObj.owner().dataPointer() + offset);
-    typedObj.setReservedSlot(JS_TYPEDOBJ_SLOT_BYTEOFFSET, Int32Value(offset));
+    typedObj.setReservedSlot(JS_BUFVIEW_SLOT_BYTEOFFSET, Int32Value(offset));
     args.rval().setUndefined();
     return true;
 }
 
 bool
 js::intrinsic_SetTypedObjectOffset(JSContext *cx, unsigned argc, Value *vp)
 {
     // Do not use JSNativeThreadSafeWrapper<> so that ion can reference
--- a/js/src/builtin/TypedObject.h
+++ b/js/src/builtin/TypedObject.h
@@ -643,33 +643,33 @@ class TypedObject : public ArrayBufferVi
 
     // Otherwise, use this to attach to memory referenced by another typedObj.
     void attach(TypedObject &typedObj, int32_t offset);
 
     // Invoked when array buffer is transferred elsewhere
     void neuter(void *newData);
 
     int32_t offset() const {
-        return getReservedSlot(JS_TYPEDOBJ_SLOT_BYTEOFFSET).toInt32();
+        return getReservedSlot(JS_BUFVIEW_SLOT_BYTEOFFSET).toInt32();
     }
 
     ArrayBufferObject &owner() const {
-        return getReservedSlot(JS_TYPEDOBJ_SLOT_OWNER).toObject().as<ArrayBufferObject>();
+        return getReservedSlot(JS_BUFVIEW_SLOT_OWNER).toObject().as<ArrayBufferObject>();
     }
 
     TypeDescr &typeDescr() const {
         return getReservedSlot(JS_TYPEDOBJ_SLOT_TYPE_DESCR).toObject().as<TypeDescr>();
     }
 
     uint8_t *typedMem() const {
         return (uint8_t*) getPrivate();
     }
 
     int32_t length() const {
-        return getReservedSlot(JS_TYPEDOBJ_SLOT_LENGTH).toInt32();
+        return getReservedSlot(JS_BUFVIEW_SLOT_LENGTH).toInt32();
     }
 
     int32_t size() const {
         switch (typeDescr().kind()) {
           case TypeDescr::Scalar:
           case TypeDescr::X4:
           case TypeDescr::Reference:
           case TypeDescr::Struct:
--- a/js/src/builtin/TypedObject.js
+++ b/js/src/builtin/TypedObject.js
@@ -26,23 +26,23 @@
 #define DESCR_STRUCT_FIELD_TYPES(obj) \
     UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_STRUCT_FIELD_TYPES)
 #define DESCR_STRUCT_FIELD_OFFSETS(obj) \
     UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS)
 
 // Typed object slots
 
 #define TYPEDOBJ_BYTEOFFSET(obj) \
-    TO_INT32(UnsafeGetReservedSlot(obj, JS_TYPEDOBJ_SLOT_BYTEOFFSET))
+    TO_INT32(UnsafeGetReservedSlot(obj, JS_BUFVIEW_SLOT_BYTEOFFSET))
 #define TYPEDOBJ_TYPE_DESCR(obj) \
     UnsafeGetReservedSlot(obj, JS_TYPEDOBJ_SLOT_TYPE_DESCR)
 #define TYPEDOBJ_OWNER(obj) \
-    UnsafeGetReservedSlot(obj, JS_TYPEDOBJ_SLOT_OWNER)
+    UnsafeGetReservedSlot(obj, JS_BUFVIEW_SLOT_OWNER)
 #define TYPEDOBJ_LENGTH(obj) \
-    TO_INT32(UnsafeGetReservedSlot(obj, JS_TYPEDOBJ_SLOT_LENGTH))
+    TO_INT32(UnsafeGetReservedSlot(obj, JS_BUFVIEW_SLOT_LENGTH))
 
 #define HAS_PROPERTY(obj, prop) \
     callFunction(std_Object_hasOwnProperty, obj, prop)
 
 ///////////////////////////////////////////////////////////////////////////
 // Getting values
 //
 // The methods in this section read from the memory pointed at
--- a/js/src/builtin/TypedObjectConstants.h
+++ b/js/src/builtin/TypedObjectConstants.h
@@ -86,26 +86,42 @@
 // you to write a switch which will receive a warning if you omit a
 // case.
 #define JS_X4TYPEREPR_INT32         0
 #define JS_X4TYPEREPR_FLOAT32       1
 
 ///////////////////////////////////////////////////////////////////////////
 // Slots for typed objects
 
-#define JS_TYPEDOBJ_SLOT_BYTEOFFSET       0
-#define JS_TYPEDOBJ_SLOT_LENGTH           1 // Length of array (see (*) below)
-#define JS_TYPEDOBJ_SLOT_OWNER            2
-#define JS_TYPEDOBJ_SLOT_NEXT_VIEW        3
+
+// Common to data view, typed arrays, and typed objects:
+#define JS_BUFVIEW_SLOT_BYTEOFFSET       0
+#define JS_BUFVIEW_SLOT_LENGTH           1 // see (*) below
+#define JS_BUFVIEW_SLOT_OWNER            2
+#define JS_BUFVIEW_SLOT_NEXT_VIEW        3
 
-#define JS_DATAVIEW_SLOTS                 4 // Number of slots for data views
+// Specific to data view:
+#define JS_DATAVIEW_SLOT_DATA            7 // see (**) below
+#define JS_DATAVIEW_SLOTS                4 // Number of slots for data views
+
+// Specific to typed arrays:
+#define JS_TYPEDARR_SLOT_TYPE            4 // A ScalarTypeDescr::Type constant
+#define JS_TYPEDARR_SLOT_DATA            7 // see (**) below
+#define JS_TYPEDARR_SLOTS                5 // Number of slots for typed arrays
 
-#define JS_TYPEDOBJ_SLOT_TYPE_DESCR       4 // For typed objects, type descr
-
-#define JS_TYPEDOBJ_SLOT_DATA             7 // private slot, based on alloc kind
-#define JS_TYPEDOBJ_SLOTS                 5 // Number of slots for typed objs
+// Specific to typed objects:
+#define JS_TYPEDOBJ_SLOT_TYPE_DESCR      4 // A ScalarTypeDescr::Type constant
+#define JS_TYPEDOBJ_SLOT_DATA            7
+#define JS_TYPEDOBJ_SLOTS                5 // Number of slots for typed objs
 
-// (*) The JS_TYPEDOBJ_SLOT_LENGTH slot stores the length for typed objects of
-// sized and unsized array type. The slot contains 0 for non-arrays.
-// The slot also contains 0 for *unattached* typed objects, no matter what
-// type they have.
+// (*) The interpretation of the JS_BUFVIEW_SLOT_LENGTH slot depends on
+// the kind of view:
+// - DataView: stores the length in bytes
+// - TypedArray: stores the array length
+// - TypedObject: for arrays, stores the array length, else 0
+
+// (**) This is the index of the slot that will be used for private data.
+// It is hardcoded here based on the GC Kind that will be assigned. It is
+// a function of the total number of slots, but it is non-trivial to encode
+// that function at compile-time, so we instead use a hardcoded constant
+// coupled with some handy assertions.
 
 #endif
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -6839,17 +6839,17 @@ IonBuilder::checkTypedObjectIndexInBound
     MDefinition *length;
     if (objDescrs.hasKnownArrayLength(&lenOfAll)) {
         length = constantInt(lenOfAll);
 
         // If we are not loading the length from the object itself,
         // then we still need to check if the object was neutered.
         *canBeNeutered = true;
     } else {
-        MInstruction *lengthValue = MLoadFixedSlot::New(alloc(), obj, JS_TYPEDOBJ_SLOT_LENGTH);
+        MInstruction *lengthValue = MLoadFixedSlot::New(alloc(), obj, JS_BUFVIEW_SLOT_LENGTH);
         current->add(lengthValue);
 
         MInstruction *length32 = MTruncateToInt32::New(alloc(), lengthValue);
         current->add(length32);
 
         length = length32;
 
         // If we are loading the length from the object itself,
--- a/js/src/vm/ArrayBufferObject.h
+++ b/js/src/vm/ArrayBufferObject.h
@@ -232,26 +232,26 @@ class ArrayBufferObject : public JSObjec
  *
  * Common definitions shared by all ArrayBufferViews.
  */
 
 class ArrayBufferViewObject : public JSObject
 {
   protected:
     /* Offset of view in underlying ArrayBufferObject */
-    static const size_t BYTEOFFSET_SLOT  = JS_TYPEDOBJ_SLOT_BYTEOFFSET;
+    static const size_t BYTEOFFSET_SLOT  = JS_BUFVIEW_SLOT_BYTEOFFSET;
 
     /* Byte length of view */
-    static const size_t LENGTH_SLOT      = JS_TYPEDOBJ_SLOT_LENGTH;
+    static const size_t LENGTH_SLOT      = JS_BUFVIEW_SLOT_LENGTH;
 
     /* Underlying ArrayBufferObject */
-    static const size_t BUFFER_SLOT      = JS_TYPEDOBJ_SLOT_OWNER;
+    static const size_t BUFFER_SLOT      = JS_BUFVIEW_SLOT_OWNER;
 
     /* ArrayBufferObjects point to a linked list of views, chained through this slot */
-    static const size_t NEXT_VIEW_SLOT   = JS_TYPEDOBJ_SLOT_NEXT_VIEW;
+    static const size_t NEXT_VIEW_SLOT   = JS_BUFVIEW_SLOT_NEXT_VIEW;
 
   public:
     static ArrayBufferObject *bufferObject(JSContext *cx, Handle<ArrayBufferViewObject *> obj);
 
     ArrayBufferViewObject *nextView() const {
         return static_cast<ArrayBufferViewObject*>(getFixedSlot(NEXT_VIEW_SLOT).toPrivate());
     }
 
--- a/js/src/vm/TypedArrayObject.h
+++ b/js/src/vm/TypedArrayObject.h
@@ -26,20 +26,19 @@ namespace js {
  * the subclasses.
  */
 
 class TypedArrayObject : public ArrayBufferViewObject
 {
   protected:
     // Typed array properties stored in slots, beyond those shared by all
     // ArrayBufferViews.
-    static const size_t LENGTH_SLOT    = JS_TYPEDOBJ_SLOT_LENGTH;
-    static const size_t TYPE_SLOT      = JS_TYPEDOBJ_SLOT_TYPE_DESCR;
-    static const size_t RESERVED_SLOTS = JS_TYPEDOBJ_SLOTS;
-    static const size_t DATA_SLOT      = JS_TYPEDOBJ_SLOT_DATA;
+    static const size_t TYPE_SLOT      = JS_TYPEDARR_SLOT_TYPE;
+    static const size_t RESERVED_SLOTS = JS_TYPEDARR_SLOTS;
+    static const size_t DATA_SLOT      = JS_TYPEDARR_SLOT_DATA;
 
     static_assert(js::detail::TypedArrayLengthSlot == LENGTH_SLOT,
                   "bad inlined constant in jsfriendapi.h");
 
   public:
     static const Class classes[ScalarTypeDescr::TYPE_MAX];
     static const Class protoClasses[ScalarTypeDescr::TYPE_MAX];
 
@@ -217,17 +216,17 @@ TypedArrayShift(ArrayBufferView::ViewTyp
       default:;
     }
     MOZ_ASSUME_UNREACHABLE("Unexpected array type");
 }
 
 class DataViewObject : public ArrayBufferViewObject
 {
     static const size_t RESERVED_SLOTS = JS_DATAVIEW_SLOTS;
-    static const size_t DATA_SLOT      = JS_TYPEDOBJ_SLOT_DATA;
+    static const size_t DATA_SLOT      = JS_DATAVIEW_SLOT_DATA;
 
   private:
     static const Class protoClass;
 
     static bool is(HandleValue v) {
         return v.isObject() && v.toObject().hasClass(&class_);
     }