Bug 989276 -- Remove BYTELENGTH in favor of just LENGTH r=sfink
authorNicholas D. Matsakis <nmatsakis@mozilla.com>
Fri, 28 Mar 2014 06:36:41 -0400
changeset 207184 b1e0a1050d9b8afb8916608b04417ae290ba7794
parent 207183 7792ac87eb27c950519e95d9aacd2675957c1d3a
child 207185 039b9e7b3616d4f9dcc0fa9d67d932a9053b298b
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [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 -- Remove BYTELENGTH in favor of just LENGTH 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-test/tests/gc/bug-948423.js
js/src/jsfriendapi.h
js/src/vm/ArrayBufferObject.h
js/src/vm/TypedArrayObject.cpp
js/src/vm/TypedArrayObject.h
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -1475,20 +1475,19 @@ TypedObject::createUnattachedWithClass(J
     }
 
     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_BYTELENGTH, 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->initReservedSlot(JS_TYPEDOBJ_SLOT_LENGTH, Int32Value(length));
     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))
@@ -2161,17 +2160,17 @@ TypedObject::obj_enumerate(JSContext *cx
         switch (enum_op) {
           case JSENUMERATE_INIT_ALL:
           case JSENUMERATE_INIT:
             statep.setInt32(0);
             idp.set(INT_TO_JSID(typedObj->length()));
             break;
 
           case JSENUMERATE_NEXT:
-            index = static_cast<int32_t>(statep.toInt32());
+            index = statep.toInt32();
 
             if (index < typedObj->length()) {
                 idp.set(INT_TO_JSID(index));
                 statep.setInt32(index + 1);
             } else {
                 JS_ASSERT(index == typedObj->length());
                 statep.setNull();
             }
@@ -2232,17 +2231,16 @@ TypedObject::offsetOfByteOffsetSlot()
 {
     return JSObject::getFixedSlotOffset(JS_TYPEDOBJ_SLOT_BYTEOFFSET);
 }
 
 void
 TypedObject::neuter(void *newData)
 {
     setSlot(JS_TYPEDOBJ_SLOT_LENGTH, Int32Value(0));
-    setSlot(JS_TYPEDOBJ_SLOT_BYTELENGTH, Int32Value(0));
     setSlot(JS_TYPEDOBJ_SLOT_BYTEOFFSET, Int32Value(0));
     setPrivate(newData);
 }
 
 /******************************************************************************
  * Typed Objects
  */
 
--- a/js/src/builtin/TypedObject.h
+++ b/js/src/builtin/TypedObject.h
@@ -658,20 +658,16 @@ class TypedObject : public ArrayBufferVi
     TypeDescr &typeDescr() const {
         return getReservedSlot(JS_TYPEDOBJ_SLOT_TYPE_DESCR).toObject().as<TypeDescr>();
     }
 
     uint8_t *typedMem() const {
         return (uint8_t*) getPrivate();
     }
 
-    int32_t byteLength() const {
-        return getReservedSlot(JS_TYPEDOBJ_SLOT_BYTELENGTH).toInt32();
-    }
-
     int32_t length() const {
         return getReservedSlot(JS_TYPEDOBJ_SLOT_LENGTH).toInt32();
     }
 
     int32_t size() const {
         switch (typeDescr().kind()) {
           case TypeDescr::Scalar:
           case TypeDescr::X4:
--- a/js/src/builtin/TypedObject.js
+++ b/js/src/builtin/TypedObject.js
@@ -27,18 +27,16 @@
     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))
-#define TYPEDOBJ_BYTELENGTH(obj) \
-    TO_INT32(UnsafeGetReservedSlot(obj, JS_TYPEDOBJ_SLOT_BYTELENGTH))
 #define TYPEDOBJ_TYPE_DESCR(obj) \
     UnsafeGetReservedSlot(obj, JS_TYPEDOBJ_SLOT_TYPE_DESCR)
 #define TYPEDOBJ_OWNER(obj) \
     UnsafeGetReservedSlot(obj, JS_TYPEDOBJ_SLOT_OWNER)
 #define TYPEDOBJ_LENGTH(obj) \
     TO_INT32(UnsafeGetReservedSlot(obj, JS_TYPEDOBJ_SLOT_LENGTH))
 
 #define HAS_PROPERTY(obj, prop) \
@@ -566,20 +564,28 @@ function ArrayShorthand(...dims) {
 // typed object, it returns null. Otherwise it throws.
 //
 // Warning: user exposed!
 function StorageOfTypedObject(obj) {
   if (IsObject(obj)) {
     if (ObjectIsOpaqueTypedObject(obj))
       return null;
 
-    if (ObjectIsTransparentTypedObject(obj))
+    if (ObjectIsTransparentTypedObject(obj)) {
+      var descr = TYPEDOBJ_TYPE_DESCR(obj);
+      var byteLength;
+      if (DESCR_KIND(descr) == JS_TYPEREPR_UNSIZED_ARRAY_KIND)
+        byteLength = DESCR_SIZE(descr.elementType) * obj.length;
+      else
+        byteLength = DESCR_SIZE(descr);
+
       return { buffer: TYPEDOBJ_OWNER(obj),
-               byteLength: TYPEDOBJ_BYTELENGTH(obj),
+               byteLength: byteLength,
                byteOffset: TYPEDOBJ_BYTEOFFSET(obj) };
+    }
   }
 
   ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   return null; // pacify silly "always returns a value" lint
 }
 
 // This is the `objectType()` function defined in the spec.
 // It returns the type of its argument.
--- a/js/src/builtin/TypedObjectConstants.h
+++ b/js/src/builtin/TypedObjectConstants.h
@@ -87,26 +87,25 @@
 // 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_BYTELENGTH       1
+#define JS_TYPEDOBJ_SLOT_LENGTH           1 // Length of array (see (*) below)
 #define JS_TYPEDOBJ_SLOT_OWNER            2
 #define JS_TYPEDOBJ_SLOT_NEXT_VIEW        3
 
-#define JS_DATAVIEW_SLOTS              4 // Number of slots for data views
+#define JS_DATAVIEW_SLOTS                 4 // Number of slots for data views
 
-#define JS_TYPEDOBJ_SLOT_LENGTH           4 // Length of array (see (*) below)
-#define JS_TYPEDOBJ_SLOT_TYPE_DESCR       5 // For typed objects, type descr
+#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                 6 // Number of slots for typed objs
+#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.
 
 #endif
--- a/js/src/jit-test/tests/gc/bug-948423.js
+++ b/js/src/jit-test/tests/gc/bug-948423.js
@@ -15,9 +15,10 @@ function runTests() {
 	FiveUintsA.equivalent(FiveUintsB)
 	);
   })();
   (function PrototypeHierarchy() {
     schedulegc(3);
     var Uint8s = uint8.array();
   })();
 }
+
 runTests();
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -1332,17 +1332,17 @@ extern JS_FRIEND_DATA(const Class* const
 extern JS_FRIEND_DATA(const Class* const) Uint8ClampedArrayClassPtr;
 extern JS_FRIEND_DATA(const Class* const) Int16ArrayClassPtr;
 extern JS_FRIEND_DATA(const Class* const) Uint16ArrayClassPtr;
 extern JS_FRIEND_DATA(const Class* const) Int32ArrayClassPtr;
 extern JS_FRIEND_DATA(const Class* const) Uint32ArrayClassPtr;
 extern JS_FRIEND_DATA(const Class* const) Float32ArrayClassPtr;
 extern JS_FRIEND_DATA(const Class* const) Float64ArrayClassPtr;
 
-const size_t TypedArrayLengthSlot = 4;
+const size_t TypedArrayLengthSlot = 1;
 
 } // namespace detail
 
 /*
  * Test for specific typed array types (ArrayBufferView subtypes) and return
  * the unwrapped object if so, else nullptr.  Never throws.
  */
 
--- a/js/src/vm/ArrayBufferObject.h
+++ b/js/src/vm/ArrayBufferObject.h
@@ -235,17 +235,17 @@ class ArrayBufferObject : public JSObjec
 
 class ArrayBufferViewObject : public JSObject
 {
   protected:
     /* Offset of view in underlying ArrayBufferObject */
     static const size_t BYTEOFFSET_SLOT  = JS_TYPEDOBJ_SLOT_BYTEOFFSET;
 
     /* Byte length of view */
-    static const size_t BYTELENGTH_SLOT  = JS_TYPEDOBJ_SLOT_BYTELENGTH;
+    static const size_t LENGTH_SLOT      = JS_TYPEDOBJ_SLOT_LENGTH;
 
     /* Underlying ArrayBufferObject */
     static const size_t BUFFER_SLOT      = JS_TYPEDOBJ_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;
 
   public:
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -90,17 +90,16 @@ ValueIsLength(const Value &v, uint32_t *
  * This class holds all the member variables that are used by
  * the subclasses.
  */
 
 void
 TypedArrayObject::neuter(void *newData)
 {
     setSlot(LENGTH_SLOT, Int32Value(0));
-    setSlot(BYTELENGTH_SLOT, Int32Value(0));
     setSlot(BYTEOFFSET_SLOT, Int32Value(0));
     setPrivate(newData);
 }
 
 ArrayBufferObject *
 TypedArrayObject::sharedBuffer() const
 {
     return &bufferValue(const_cast<TypedArrayObject*>(this)).toObject().as<SharedArrayBufferObject>();
@@ -167,40 +166,40 @@ js::ClampDoubleToUint8(const double x)
          * want.
          */
         return y & ~1;
     }
 
     return y;
 }
 
-template<typename NativeType> static inline int TypeIDOfType();
-template<> inline int TypeIDOfType<int8_t>() { return ScalarTypeDescr::TYPE_INT8; }
-template<> inline int TypeIDOfType<uint8_t>() { return ScalarTypeDescr::TYPE_UINT8; }
-template<> inline int TypeIDOfType<int16_t>() { return ScalarTypeDescr::TYPE_INT16; }
-template<> inline int TypeIDOfType<uint16_t>() { return ScalarTypeDescr::TYPE_UINT16; }
-template<> inline int TypeIDOfType<int32_t>() { return ScalarTypeDescr::TYPE_INT32; }
-template<> inline int TypeIDOfType<uint32_t>() { return ScalarTypeDescr::TYPE_UINT32; }
-template<> inline int TypeIDOfType<float>() { return ScalarTypeDescr::TYPE_FLOAT32; }
-template<> inline int TypeIDOfType<double>() { return ScalarTypeDescr::TYPE_FLOAT64; }
-template<> inline int TypeIDOfType<uint8_clamped>() { return ScalarTypeDescr::TYPE_UINT8_CLAMPED; }
+template<typename NativeType> static inline ScalarTypeDescr::Type TypeIDOfType();
+template<> inline ScalarTypeDescr::Type TypeIDOfType<int8_t>() { return ScalarTypeDescr::TYPE_INT8; }
+template<> inline ScalarTypeDescr::Type TypeIDOfType<uint8_t>() { return ScalarTypeDescr::TYPE_UINT8; }
+template<> inline ScalarTypeDescr::Type TypeIDOfType<int16_t>() { return ScalarTypeDescr::TYPE_INT16; }
+template<> inline ScalarTypeDescr::Type TypeIDOfType<uint16_t>() { return ScalarTypeDescr::TYPE_UINT16; }
+template<> inline ScalarTypeDescr::Type TypeIDOfType<int32_t>() { return ScalarTypeDescr::TYPE_INT32; }
+template<> inline ScalarTypeDescr::Type TypeIDOfType<uint32_t>() { return ScalarTypeDescr::TYPE_UINT32; }
+template<> inline ScalarTypeDescr::Type TypeIDOfType<float>() { return ScalarTypeDescr::TYPE_FLOAT32; }
+template<> inline ScalarTypeDescr::Type TypeIDOfType<double>() { return ScalarTypeDescr::TYPE_FLOAT64; }
+template<> inline ScalarTypeDescr::Type TypeIDOfType<uint8_clamped>() { return ScalarTypeDescr::TYPE_UINT8_CLAMPED; }
 
 template<typename ElementType>
 static inline JSObject *
 NewArray(JSContext *cx, uint32_t nelements);
 
 namespace {
 
 template<typename NativeType>
 class TypedArrayObjectTemplate : public TypedArrayObject
 {
   public:
     typedef NativeType ThisType;
     typedef TypedArrayObjectTemplate<NativeType> ThisTypedArrayObject;
-    static int ArrayTypeID() { return TypeIDOfType<NativeType>(); }
+    static ScalarTypeDescr::Type ArrayTypeID() { return TypeIDOfType<NativeType>(); }
     static bool ArrayTypeIsUnsigned() { return TypeIsUnsigned<NativeType>(); }
     static bool ArrayTypeIsFloatingPoint() { return TypeIsFloatingPoint<NativeType>(); }
 
     static const size_t BYTES_PER_ELEMENT = sizeof(ThisType);
 
     static inline const Class *protoClass()
     {
         return &TypedArrayObject::protoClasses[ArrayTypeID()];
@@ -315,17 +314,16 @@ class TypedArrayObjectTemplate : public 
         } else {
             void *data = obj->fixedData(FIXED_DATA_START);
             obj->initPrivate(data);
             memset(data, 0, len * sizeof(NativeType));
         }
 
         obj->setSlot(LENGTH_SLOT, Int32Value(len));
         obj->setSlot(BYTEOFFSET_SLOT, Int32Value(byteOffset));
-        obj->setSlot(BYTELENGTH_SLOT, Int32Value(len * sizeof(NativeType)));
         obj->setSlot(NEXT_VIEW_SLOT, PrivateValue(nullptr));
 
 #ifdef DEBUG
         if (buffer) {
             uint32_t arrayByteLength = obj->byteLength();
             uint32_t arrayByteOffset = obj->byteOffset();
             uint32_t bufferByteLength = buffer->byteLength();
             JS_ASSERT_IF(!buffer->isNeutered(), buffer->dataPointer() <= obj->viewData());
@@ -1344,17 +1342,17 @@ DataViewObject::create(JSContext *cx, ui
         if (script) {
             if (!types::SetInitializerObjectType(cx, script, pc, obj, newKind))
                 return nullptr;
         }
     }
 
     DataViewObject &dvobj = obj->as<DataViewObject>();
     dvobj.setFixedSlot(BYTEOFFSET_SLOT, Int32Value(byteOffset));
-    dvobj.setFixedSlot(BYTELENGTH_SLOT, Int32Value(byteLength));
+    dvobj.setFixedSlot(LENGTH_SLOT, Int32Value(byteLength));
     dvobj.setFixedSlot(BUFFER_SLOT, ObjectValue(*arrayBuffer));
     dvobj.setFixedSlot(NEXT_VIEW_SLOT, PrivateValue(nullptr));
     InitArrayBufferViewDataPointer(&dvobj, arrayBuffer, byteOffset);
     JS_ASSERT(byteOffset + byteLength <= arrayBuffer->byteLength());
 
     // Verify that the private slot is at the expected place
     JS_ASSERT(dvobj.numFixedSlots() == DATA_SLOT);
 
@@ -2490,17 +2488,17 @@ DataViewObject::initClass(JSContext *cx)
     global->setCreateDataViewForThis(fun);
 
     return true;
 }
 
 void
 DataViewObject::neuter(void *newData)
 {
-    setSlot(BYTELENGTH_SLOT, Int32Value(0));
+    setSlot(LENGTH_SLOT, Int32Value(0));
     setSlot(BYTEOFFSET_SLOT, Int32Value(0));
     setPrivate(newData);
 }
 
 JSObject *
 js_InitDataViewClass(JSContext *cx, HandleObject obj)
 {
     if (!DataViewObject::initClass(cx))
@@ -2651,105 +2649,105 @@ JS_GetArrayBufferViewType(JSObject *obj)
 
 JS_FRIEND_API(int8_t *)
 JS_GetInt8ArrayData(JSObject *obj)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
-    JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_INT8);
+    JS_ASSERT((int32_t) tarr->type() == ArrayBufferView::TYPE_INT8);
     return static_cast<int8_t *>(tarr->viewData());
 }
 
 JS_FRIEND_API(uint8_t *)
 JS_GetUint8ArrayData(JSObject *obj)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
-    JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_UINT8);
+    JS_ASSERT((int32_t) tarr->type() == ArrayBufferView::TYPE_UINT8);
     return static_cast<uint8_t *>(tarr->viewData());
 }
 
 JS_FRIEND_API(uint8_t *)
 JS_GetUint8ClampedArrayData(JSObject *obj)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
-    JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_UINT8_CLAMPED);
+    JS_ASSERT((int32_t) tarr->type() == ArrayBufferView::TYPE_UINT8_CLAMPED);
     return static_cast<uint8_t *>(tarr->viewData());
 }
 
 JS_FRIEND_API(int16_t *)
 JS_GetInt16ArrayData(JSObject *obj)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
-    JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_INT16);
+    JS_ASSERT((int32_t) tarr->type() == ArrayBufferView::TYPE_INT16);
     return static_cast<int16_t *>(tarr->viewData());
 }
 
 JS_FRIEND_API(uint16_t *)
 JS_GetUint16ArrayData(JSObject *obj)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
-    JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_UINT16);
+    JS_ASSERT((int32_t) tarr->type() == ArrayBufferView::TYPE_UINT16);
     return static_cast<uint16_t *>(tarr->viewData());
 }
 
 JS_FRIEND_API(int32_t *)
 JS_GetInt32ArrayData(JSObject *obj)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
-    JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_INT32);
+    JS_ASSERT((int32_t) tarr->type() == ArrayBufferView::TYPE_INT32);
     return static_cast<int32_t *>(tarr->viewData());
 }
 
 JS_FRIEND_API(uint32_t *)
 JS_GetUint32ArrayData(JSObject *obj)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
-    JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_UINT32);
+    JS_ASSERT((int32_t) tarr->type() == ArrayBufferView::TYPE_UINT32);
     return static_cast<uint32_t *>(tarr->viewData());
 }
 
 JS_FRIEND_API(float *)
 JS_GetFloat32ArrayData(JSObject *obj)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
-    JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_FLOAT32);
+    JS_ASSERT((int32_t) tarr->type() == ArrayBufferView::TYPE_FLOAT32);
     return static_cast<float *>(tarr->viewData());
 }
 
 JS_FRIEND_API(double *)
 JS_GetFloat64ArrayData(JSObject *obj)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
-    JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_FLOAT64);
+    JS_ASSERT((int32_t) tarr->type() == ArrayBufferView::TYPE_FLOAT64);
     return static_cast<double *>(tarr->viewData());
 }
 
 JS_FRIEND_API(bool)
 JS_IsDataViewObject(JSObject *obj)
 {
     obj = CheckedUnwrap(obj);
     return obj ? obj->is<DataViewObject>() : false;
--- a/js/src/vm/TypedArrayObject.h
+++ b/js/src/vm/TypedArrayObject.h
@@ -55,24 +55,29 @@ class TypedArrayObject : public ArrayBuf
     {
         JS_ASSERT(nbytes <= INLINE_BUFFER_LIMIT);
         /* For GGC we need at least one slot in which to store a forwarding pointer. */
         size_t dataSlots = Max(size_t(1), AlignBytes(nbytes, sizeof(Value)) / sizeof(Value));
         JS_ASSERT(nbytes <= dataSlots * sizeof(Value));
         return gc::GetGCObjectKind(FIXED_DATA_START + dataSlots);
     }
 
+    ScalarTypeDescr::Type type() const {
+        return (ScalarTypeDescr::Type) getFixedSlot(TYPE_SLOT).toInt32();
+    }
+
     static Value bufferValue(TypedArrayObject *tarr) {
         return tarr->getFixedSlot(BUFFER_SLOT);
     }
     static Value byteOffsetValue(TypedArrayObject *tarr) {
         return tarr->getFixedSlot(BYTEOFFSET_SLOT);
     }
     static Value byteLengthValue(TypedArrayObject *tarr) {
-        return tarr->getFixedSlot(BYTELENGTH_SLOT);
+        int32_t size = ScalarTypeDescr::size(tarr->type());
+        return Int32Value(tarr->getFixedSlot(LENGTH_SLOT).toInt32() * size);
     }
     static Value lengthValue(TypedArrayObject *tarr) {
         return tarr->getFixedSlot(LENGTH_SLOT);
     }
 
     static bool
     ensureHasBuffer(JSContext *cx, Handle<TypedArrayObject *> tarray);
 
@@ -90,19 +95,16 @@ class TypedArrayObject : public ArrayBuf
     }
     uint32_t byteLength() const {
         return byteLengthValue(const_cast<TypedArrayObject*>(this)).toInt32();
     }
     uint32_t length() const {
         return lengthValue(const_cast<TypedArrayObject*>(this)).toInt32();
     }
 
-    uint32_t type() const {
-        return getFixedSlot(TYPE_SLOT).toInt32();
-    }
     void *viewData() const {
         // Keep synced with js::Get<Type>ArrayLengthAndData in jsfriendapi.h!
         return static_cast<void*>(getPrivate(DATA_SLOT));
     }
 
     Value getElement(uint32_t index);
     static void setElement(TypedArrayObject &obj, uint32_t index, double d);
 
@@ -250,17 +252,17 @@ class DataViewObject : public ArrayBuffe
 
     static Value byteOffsetValue(DataViewObject *view) {
         Value v = view->getReservedSlot(BYTEOFFSET_SLOT);
         JS_ASSERT(v.toInt32() >= 0);
         return v;
     }
 
     static Value byteLengthValue(DataViewObject *view) {
-        Value v = view->getReservedSlot(BYTELENGTH_SLOT);
+        Value v = view->getReservedSlot(LENGTH_SLOT);
         JS_ASSERT(v.toInt32() >= 0);
         return v;
     }
 
     static Value bufferValue(DataViewObject *view) {
         return view->getReservedSlot(BUFFER_SLOT);
     }