Bug 1268740 - Change AllocateArrayBuffer to receive byteLength with |count * unit| format. r=lth
authorTooru Fujisawa <arai_a@mac.com>
Sat, 30 Apr 2016 03:01:11 +0900
changeset 295537 3dfd039e8de2b2caaa6eb6e3be302a51f5313995
parent 295536 01067412db32dd8eee38f64e6d66942b437fa924
child 295538 c9ed1f5f53583d071883ec3b1a8716ede3f76efb
push id19015
push usercbook@mozilla.com
push dateMon, 02 May 2016 09:39:23 +0000
treeherderfx-team@2080375bc69d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslth
bugs1268740
milestone49.0a1
Bug 1268740 - Change AllocateArrayBuffer to receive byteLength with |count * unit| format. r=lth
js/src/vm/TypedArrayObject.cpp
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -632,19 +632,27 @@ class TypedArrayObjectTemplate : public 
             JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
             return nullptr; // byteOffset + len is too big for the arraybuffer
         }
 
         return makeInstance(cx, buffer, byteOffset, len, proto);
     }
 
     static bool
-    maybeCreateArrayBuffer(JSContext* cx, uint32_t byteLength, HandleObject nonDefaultProto,
+    maybeCreateArrayBuffer(JSContext* cx, uint32_t count, uint32_t unit,
+                           HandleObject nonDefaultProto,
                            MutableHandle<ArrayBufferObject*> buffer)
     {
+        if (count >= INT32_MAX / unit) {
+            JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
+                                 JSMSG_NEED_DIET, "size and count");
+            return false;
+        }
+        uint32_t byteLength = count * unit;
+
         MOZ_ASSERT(byteLength < INT32_MAX);
         static_assert(INLINE_BUFFER_LIMIT % sizeof(NativeType) == 0,
                       "ArrayBuffer inline storage shouldn't waste any space");
 
         if (!nonDefaultProto && byteLength <= INLINE_BUFFER_LIMIT) {
             // The array's data can be inline, and the buffer created lazily.
             return true;
         }
@@ -659,30 +667,26 @@ class TypedArrayObjectTemplate : public 
 
     static JSObject*
     fromLength(JSContext* cx, uint32_t nelements, HandleObject newTarget = nullptr)
     {
         RootedObject proto(cx);
         if (!GetPrototypeForInstance(cx, newTarget, &proto))
             return nullptr;
 
-        if (nelements >= INT32_MAX / BYTES_PER_ELEMENT) {
-            JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
-                                 JSMSG_NEED_DIET, "size and count");
-            return nullptr;
-        }
         Rooted<ArrayBufferObject*> buffer(cx);
-        if (!maybeCreateArrayBuffer(cx, nelements * BYTES_PER_ELEMENT, nullptr, &buffer))
+        if (!maybeCreateArrayBuffer(cx, nelements, BYTES_PER_ELEMENT, nullptr, &buffer))
             return nullptr;
 
         return makeInstance(cx, buffer, 0, nelements, proto);
     }
 
     static bool
-    AllocateArrayBuffer(JSContext* cx, HandleValue ctor, uint32_t byteLength,
+    AllocateArrayBuffer(JSContext* cx, HandleValue ctor,
+                        uint32_t count, uint32_t unit,
                         MutableHandle<ArrayBufferObject*> buffer);
 
     static bool
     CloneArrayBufferNoCopy(JSContext* cx, Handle<ArrayBufferObjectMaybeShared*> srcBuffer,
                            bool isWrapped, uint32_t srcByteOffset, uint32_t srcLength,
                            MutableHandle<ArrayBufferObject*> buffer);
 
     static JSObject*
@@ -726,43 +730,38 @@ typedef TypedArrayObjectTemplate<uint8_c
 
 template<typename T>
 struct TypedArrayObject::OfType
 {
     typedef TypedArrayObjectTemplate<T> Type;
 };
 
 // ES 2016 draft Mar 25, 2016 24.1.1.1.
+// byteLength = count * unit
 template<typename T>
 /* static */ bool
 TypedArrayObjectTemplate<T>::AllocateArrayBuffer(JSContext* cx, HandleValue ctor,
-                                                 uint32_t byteLength,
+                                                 uint32_t count, uint32_t unit,
                                                  MutableHandle<ArrayBufferObject*> buffer)
 {
     // ES 2016 draft Mar 25, 2016 24.1.1.1 step 1 (partially).
     // ES 2016 draft Mar 25, 2016 9.1.14 steps 1-2.
     MOZ_ASSERT(ctor.isObject());
     RootedObject proto(cx);
     RootedObject ctorObj(cx, &ctor.toObject());
     if (!GetPrototypeFromConstructor(cx, ctorObj, &proto))
         return false;
     JSObject* arrayBufferProto = GlobalObject::getOrCreateArrayBufferPrototype(cx, cx->global());
     if (!arrayBufferProto)
         return false;
     if (proto == arrayBufferProto)
         proto = nullptr;
 
-    if (byteLength >= INT32_MAX) {
-        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
-                             JSMSG_NEED_DIET, "size and count");
-        return false;
-    }
-
     // ES 2016 draft Mar 25, 2016 24.1.1.1 steps 1 (remaining part), 2-6.
-    if (!maybeCreateArrayBuffer(cx, byteLength, proto, buffer))
+    if (!maybeCreateArrayBuffer(cx, count, unit, proto, buffer))
         return false;
 
     return true;
 }
 
 static bool
 IsArrayBufferConstructor(const Value& v)
 {
@@ -843,17 +842,17 @@ TypedArrayObjectTemplate<T>::CloneArrayB
     if (srcBuffer->isDetached()) {
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
         return false;
     }
 
     // Steps 3-4 (skipped).
 
     // Steps 5.
-    if (!AllocateArrayBuffer(cx, cloneCtor, srcLength, buffer))
+    if (!AllocateArrayBuffer(cx, cloneCtor, srcLength, 1, buffer))
         return false;
 
     // Step 6.
     if (srcBuffer->isDetached()) {
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
         return false;
     }
 
@@ -933,36 +932,33 @@ TypedArrayObjectTemplate<T>::fromTypedAr
     // Steps 11-12.
     Scalar::Type srcType = srcArray->type();
 
     // Step 13 (skipped).
 
     // Step 14.
     uint32_t srcByteOffset = srcArray->byteOffset();
 
-    // Steps 15-16.
-    uint32_t byteLength = BYTES_PER_ELEMENT * elementLength;
-
     // Steps 8-9, 17.
     Rooted<ArrayBufferObject*> buffer(cx);
     if (ArrayTypeID() == srcType) {
         // Step 17.a.
         uint32_t srcLength = srcArray->byteLength();
 
         // Step 17.b.
         if (!CloneArrayBufferNoCopy(cx, srcData, isWrapped, srcByteOffset, srcLength, &buffer))
             return nullptr;
     } else {
         // Step 18.a.
         RootedValue bufferCtor(cx);
         if (!GetSpeciesConstructor(cx, srcData, isWrapped, &bufferCtor))
             return nullptr;
 
-        // Step 18.b.
-        if (!AllocateArrayBuffer(cx, bufferCtor, byteLength, &buffer))
+        // Step 15-16, 18.b.
+        if (!AllocateArrayBuffer(cx, bufferCtor, elementLength, BYTES_PER_ELEMENT, &buffer))
             return nullptr;
 
         // Step 18.c.
         if (srcArray->hasDetachedBuffer()) {
             JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
             return nullptr;
         }
     }
@@ -989,22 +985,17 @@ TypedArrayObjectTemplate<T>::fromObject(
 {
     RootedObject proto(cx);
     Rooted<ArrayBufferObject*> buffer(cx);
     uint32_t len;
     if (!GetLengthProperty(cx, other, &len))
         return nullptr;
     if (!GetPrototypeForInstance(cx, newTarget, &proto))
         return nullptr;
-    if (len >= INT32_MAX / BYTES_PER_ELEMENT) {
-        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
-                             JSMSG_NEED_DIET, "size and count");
-        return nullptr;
-    }
-    if (!maybeCreateArrayBuffer(cx, len * BYTES_PER_ELEMENT, nullptr, &buffer))
+    if (!maybeCreateArrayBuffer(cx, len, BYTES_PER_ELEMENT, nullptr, &buffer))
         return nullptr;
 
     Rooted<TypedArrayObject*> obj(cx, makeInstance(cx, buffer, 0, len, proto));
     if (!obj)
         return nullptr;
 
     if (!TypedArrayMethods<TypedArrayObject>::setFromNonTypedArray(cx, obj, other, len))
         return nullptr;