Bug 1314564 - override constructor for TypedArray construction when argument is shared memory. r=arai
authorLars T Hansen <lhansen@mozilla.com>
Fri, 04 Nov 2016 10:25:47 +0100
changeset 351421 3e3ae9ca5f809c355799fe04e4f81315a8104f3d
parent 351420 7185f2eb656a242c0bf4b56ac2f9731dc833bbdb
child 351422 334620bedacab85bcfed7934a714d95d9945455d
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarai
bugs1314564
milestone52.0a1
Bug 1314564 - override constructor for TypedArray construction when argument is shared memory. r=arai
js/src/vm/TypedArrayObject.cpp
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -300,16 +300,21 @@ GetPrototypeForInstance(JSContext* cx, H
         if (!GetPrototypeFromConstructor(cx, newTarget, proto))
             return false;
     } else {
         proto.set(nullptr);
     }
     return true;
 }
 
+enum class SpeciesConstructorOverride {
+    None,
+    ArrayBuffer
+};
+
 template<typename NativeType>
 class TypedArrayObjectTemplate : public TypedArrayObject
 {
     friend class TypedArrayObject;
 
   public:
     typedef NativeType ElementType;
 
@@ -936,16 +941,17 @@ class TypedArrayObjectTemplate : public 
     static bool
     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,
+                           SpeciesConstructorOverride override,
                            MutableHandle<ArrayBufferObject*> buffer);
 
     static JSObject*
     fromArray(JSContext* cx, HandleObject other, HandleObject newTarget = nullptr);
 
     static JSObject*
     fromTypedArray(JSContext* cx, HandleObject other, bool isWrapped, HandleObject newTarget);
 
@@ -1055,58 +1061,61 @@ IsArrayBufferSpecies(JSContext* cx, Hand
 
     if (!getter)
         return false;
 
     return IsSelfHostedFunctionWithName(getter, cx->names().ArrayBufferSpecies);
 }
 
 static bool
-GetSpeciesConstructor(JSContext* cx, HandleObject obj, bool isWrapped, MutableHandleValue ctor)
+GetSpeciesConstructor(JSContext* cx, HandleObject obj, bool isWrapped,
+                      SpeciesConstructorOverride override, MutableHandleValue ctor)
 {
     if (!isWrapped) {
         if (!GlobalObject::ensureConstructor(cx, cx->global(), JSProto_ArrayBuffer))
             return false;
         RootedValue defaultCtor(cx, cx->global()->getConstructor(JSProto_ArrayBuffer));
-        if (IsArrayBufferSpecies(cx, obj)) {
+        // The second disjunct is an optimization.
+        if (override == SpeciesConstructorOverride::ArrayBuffer || IsArrayBufferSpecies(cx, obj))
             ctor.set(defaultCtor);
-            return true;
-        }
-        if (!SpeciesConstructor(cx, obj, defaultCtor, ctor))
+        else if (!SpeciesConstructor(cx, obj, defaultCtor, ctor))
             return false;
 
         return true;
     }
 
     {
         JSAutoCompartment ac(cx, obj);
         if (!GlobalObject::ensureConstructor(cx, cx->global(), JSProto_ArrayBuffer))
             return false;
         RootedValue defaultCtor(cx, cx->global()->getConstructor(JSProto_ArrayBuffer));
-        if (!SpeciesConstructor(cx, obj, defaultCtor, ctor))
+        if (override == SpeciesConstructorOverride::ArrayBuffer)
+            ctor.set(defaultCtor);
+        else if (!SpeciesConstructor(cx, obj, defaultCtor, ctor))
             return false;
     }
 
     return JS_WrapValue(cx, ctor);
 }
 
 // ES 2017 draft rev 8633ffd9394b203b8876bb23cb79aff13eb07310 24.1.1.4.
 template<typename T>
 /* static */ bool
 TypedArrayObjectTemplate<T>::CloneArrayBufferNoCopy(JSContext* cx,
                                                     Handle<ArrayBufferObjectMaybeShared*> srcBuffer,
                                                     bool isWrapped, uint32_t srcByteOffset,
                                                     uint32_t srcLength,
+                                                    SpeciesConstructorOverride override,
                                                     MutableHandle<ArrayBufferObject*> buffer)
 {
     // Step 1 (skipped).
 
     // Step 2.a.
     RootedValue cloneCtor(cx);
-    if (!GetSpeciesConstructor(cx, srcBuffer, isWrapped, &cloneCtor))
+    if (!GetSpeciesConstructor(cx, srcBuffer, isWrapped, override, &cloneCtor))
         return false;
 
     // Step 2.b.
     if (srcBuffer->isDetached()) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
         return false;
     }
 
@@ -1198,29 +1207,37 @@ TypedArrayObjectTemplate<T>::fromTypedAr
     // Steps 11-12.
     Scalar::Type srcType = srcArray->type();
 
     // Step 13 (skipped).
 
     // Step 14.
     uint32_t srcByteOffset = srcArray->byteOffset();
 
+    // Step 17, modified for SharedArrayBuffer.
+    bool isShared = srcArray->isSharedMemory();
+    SpeciesConstructorOverride override = isShared ? SpeciesConstructorOverride::ArrayBuffer
+                                                   : SpeciesConstructorOverride::None;
+
     // 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))
+        // Step 17.b, modified for SharedArrayBuffer
+        if (!CloneArrayBufferNoCopy(cx, srcData, isWrapped, srcByteOffset, srcLength, override,
+                                    &buffer))
+        {
             return nullptr;
+        }
     } else {
-        // Step 18.a.
+        // Step 18.a, modified for SharedArrayBuffer
         RootedValue bufferCtor(cx);
-        if (!GetSpeciesConstructor(cx, srcData, isWrapped, &bufferCtor))
+        if (!GetSpeciesConstructor(cx, srcData, isWrapped, override, &bufferCtor))
             return nullptr;
 
         // Step 15-16, 18.b.
         if (!AllocateArrayBuffer(cx, bufferCtor, elementLength, BYTES_PER_ELEMENT, &buffer))
             return nullptr;
 
         // Step 18.c.
         if (srcArray->hasDetachedBuffer()) {