Bug 1176214 - Part 2: Preliminary adjustments. r=waldo
authorLars T Hansen <lhansen@mozilla.com>
Mon, 23 Nov 2015 19:51:50 +0100
changeset 309416 f10d0e915f9605eb1dedd989c84cd07d40f4dc3d
parent 309415 49a370926c908b8b24634981c0d8ec8b99e58b96
child 309417 20570b526b355c4739a92072cb181ed8faf5bbaf
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswaldo
bugs1176214
milestone45.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 1176214 - Part 2: Preliminary adjustments. r=waldo
js/src/jsfriendapi.h
js/src/jsgc.h
js/src/jsobj.cpp
js/src/jsprototypes.h
js/src/vm/ArrayBufferObject-inl.h
js/src/vm/ArrayBufferObject.h
js/src/vm/SharedArrayObject.h
js/src/vm/SharedMem.h
js/src/vm/TypedArrayCommon.h
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -1585,35 +1585,16 @@ extern JS_FRIEND_API(JSObject*)
 JS_NewInt32Array(JSContext* cx, uint32_t nelements);
 extern JS_FRIEND_API(JSObject*)
 JS_NewUint32Array(JSContext* cx, uint32_t nelements);
 extern JS_FRIEND_API(JSObject*)
 JS_NewFloat32Array(JSContext* cx, uint32_t nelements);
 extern JS_FRIEND_API(JSObject*)
 JS_NewFloat64Array(JSContext* cx, uint32_t nelements);
 
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedInt8Array(JSContext* cx, uint32_t nelements);
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedUint8Array(JSContext* cx, uint32_t nelements);
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedUint8ClampedArray(JSContext* cx, uint32_t nelements);
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedInt16Array(JSContext* cx, uint32_t nelements);
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedUint16Array(JSContext* cx, uint32_t nelements);
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedInt32Array(JSContext* cx, uint32_t nelements);
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedUint32Array(JSContext* cx, uint32_t nelements);
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedFloat32Array(JSContext* cx, uint32_t nelements);
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedFloat64Array(JSContext* cx, uint32_t nelements);
-
 /*
  * Create a new typed array and copy in values from the given object. The
  * object is used as if it were an array; that is, the new array (if
  * successfully created) will have length given by array.length, and its
  * elements will be those specified by array[0], array[1], and so on, after
  * conversion to the typed array element type.
  */
 
@@ -1632,19 +1613,20 @@ JS_NewInt32ArrayFromArray(JSContext* cx,
 extern JS_FRIEND_API(JSObject*)
 JS_NewUint32ArrayFromArray(JSContext* cx, JS::HandleObject array);
 extern JS_FRIEND_API(JSObject*)
 JS_NewFloat32ArrayFromArray(JSContext* cx, JS::HandleObject array);
 extern JS_FRIEND_API(JSObject*)
 JS_NewFloat64ArrayFromArray(JSContext* cx, JS::HandleObject array);
 
 /*
- * Create a new typed array using the given ArrayBuffer for storage.  The
- * length value is optional; if -1 is passed, enough elements to use up the
- * remainder of the byte array is used as the default value.
+ * Create a new typed array using the given ArrayBuffer or
+ * SharedArrayBuffer for storage.  The length value is optional; if -1
+ * is passed, enough elements to use up the remainder of the byte
+ * array is used as the default value.
  */
 
 extern JS_FRIEND_API(JSObject*)
 JS_NewInt8ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
                           uint32_t byteOffset, int32_t length);
 extern JS_FRIEND_API(JSObject*)
 JS_NewUint8ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
                            uint32_t byteOffset, int32_t length);
@@ -1665,47 +1647,16 @@ JS_NewUint32ArrayWithBuffer(JSContext* c
                             uint32_t byteOffset, int32_t length);
 extern JS_FRIEND_API(JSObject*)
 JS_NewFloat32ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
                              uint32_t byteOffset, int32_t length);
 extern JS_FRIEND_API(JSObject*)
 JS_NewFloat64ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
                              uint32_t byteOffset, int32_t length);
 
-// As for the above, passing length==(uint32_t)-1 signifies "up to the
-// end of the buffer".
-
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedInt8ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
-                                uint32_t byteOffset, uint32_t length);
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedUint8ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
-                                 uint32_t byteOffset, uint32_t length);
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedUint8ClampedArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
-                                        uint32_t byteOffset, uint32_t length);
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedInt16ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
-                                 uint32_t byteOffset, uint32_t length);
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedUint16ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
-                                  uint32_t byteOffset, uint32_t length);
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedInt32ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
-                                 uint32_t byteOffset, uint32_t length);
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedUint32ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
-                                  uint32_t byteOffset, uint32_t length);
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedFloat32ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
-                                   uint32_t byteOffset, uint32_t length);
-extern JS_FRIEND_API(JSObject*)
-JS_NewSharedFloat64ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
-                                   uint32_t byteOffset, uint32_t length);
-
 /**
  * Create a new SharedArrayBuffer with the given byte length.
  */
 extern JS_FRIEND_API(JSObject*)
 JS_NewSharedArrayBuffer(JSContext* cx, uint32_t nbytes);
 
 /**
  * Create a new ArrayBuffer with the given byte length.
@@ -1718,22 +1669,16 @@ JS_NewArrayBuffer(JSContext* cx, uint32_
  * false if a security wrapper is encountered that denies the unwrapping. If
  * this test or one of the JS_Is*Array tests succeeds, then it is safe to call
  * the various accessor JSAPI calls defined below.
  */
 extern JS_FRIEND_API(bool)
 JS_IsTypedArrayObject(JSObject* obj);
 
 /**
- * Ditto for JS_GetSharedTypedArray* APIs.
- */
-extern JS_FRIEND_API(bool)
-JS_IsSharedTypedArrayObject(JSObject* obj);
-
-/**
  * Check whether obj supports JS_GetArrayBufferView* APIs. Note that this may
  * return false if a security wrapper is encountered that denies the
  * unwrapping. If this test or one of the more specific tests succeeds, then it
  * is safe to call the various ArrayBufferView accessor JSAPI calls defined
  * below.
  */
 extern JS_FRIEND_API(bool)
 JS_IsArrayBufferViewObject(JSObject* obj);
@@ -1756,35 +1701,16 @@ extern JS_FRIEND_API(bool)
 JS_IsInt32Array(JSObject* obj);
 extern JS_FRIEND_API(bool)
 JS_IsUint32Array(JSObject* obj);
 extern JS_FRIEND_API(bool)
 JS_IsFloat32Array(JSObject* obj);
 extern JS_FRIEND_API(bool)
 JS_IsFloat64Array(JSObject* obj);
 
-extern JS_FRIEND_API(bool)
-JS_IsSharedInt8Array(JSObject* obj);
-extern JS_FRIEND_API(bool)
-JS_IsSharedUint8Array(JSObject* obj);
-extern JS_FRIEND_API(bool)
-JS_IsSharedUint8ClampedArray(JSObject* obj);
-extern JS_FRIEND_API(bool)
-JS_IsSharedInt16Array(JSObject* obj);
-extern JS_FRIEND_API(bool)
-JS_IsSharedUint16Array(JSObject* obj);
-extern JS_FRIEND_API(bool)
-JS_IsSharedInt32Array(JSObject* obj);
-extern JS_FRIEND_API(bool)
-JS_IsSharedUint32Array(JSObject* obj);
-extern JS_FRIEND_API(bool)
-JS_IsSharedFloat32Array(JSObject* obj);
-extern JS_FRIEND_API(bool)
-JS_IsSharedFloat64Array(JSObject* obj);
-
 /*
  * Test for specific typed array types (ArrayBufferView subtypes) and return
  * the unwrapped object if so, else nullptr.  Never throws.
  */
 
 namespace js {
 
 extern JS_FRIEND_API(JSObject*)
@@ -1808,147 +1734,119 @@ UnwrapFloat64Array(JSObject* obj);
 
 extern JS_FRIEND_API(JSObject*)
 UnwrapArrayBuffer(JSObject* obj);
 
 extern JS_FRIEND_API(JSObject*)
 UnwrapArrayBufferView(JSObject* obj);
 
 extern JS_FRIEND_API(JSObject*)
-UnwrapSharedInt8Array(JSObject* obj);
-extern JS_FRIEND_API(JSObject*)
-UnwrapSharedUint8Array(JSObject* obj);
-extern JS_FRIEND_API(JSObject*)
-UnwrapSharedUint8ClampedArray(JSObject* obj);
-extern JS_FRIEND_API(JSObject*)
-UnwrapSharedInt16Array(JSObject* obj);
-extern JS_FRIEND_API(JSObject*)
-UnwrapSharedUint16Array(JSObject* obj);
-extern JS_FRIEND_API(JSObject*)
-UnwrapSharedInt32Array(JSObject* obj);
-extern JS_FRIEND_API(JSObject*)
-UnwrapSharedUint32Array(JSObject* obj);
-extern JS_FRIEND_API(JSObject*)
-UnwrapSharedFloat32Array(JSObject* obj);
-extern JS_FRIEND_API(JSObject*)
-UnwrapSharedFloat64Array(JSObject* obj);
-
-extern JS_FRIEND_API(JSObject*)
 UnwrapSharedArrayBuffer(JSObject* obj);
 
-extern JS_FRIEND_API(JSObject*)
-UnwrapSharedArrayBufferView(JSObject* obj);
-
 
 namespace detail {
 
 extern JS_FRIEND_DATA(const Class* const) Int8ArrayClassPtr;
 extern JS_FRIEND_DATA(const Class* const) Uint8ArrayClassPtr;
 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;
 
-extern JS_FRIEND_DATA(const Class* const) SharedInt8ArrayClassPtr;
-extern JS_FRIEND_DATA(const Class* const) SharedUint8ArrayClassPtr;
-extern JS_FRIEND_DATA(const Class* const) SharedUint8ClampedArrayClassPtr;
-extern JS_FRIEND_DATA(const Class* const) SharedInt16ArrayClassPtr;
-extern JS_FRIEND_DATA(const Class* const) SharedUint16ArrayClassPtr;
-extern JS_FRIEND_DATA(const Class* const) SharedInt32ArrayClassPtr;
-extern JS_FRIEND_DATA(const Class* const) SharedUint32ArrayClassPtr;
-extern JS_FRIEND_DATA(const Class* const) SharedFloat32ArrayClassPtr;
-extern JS_FRIEND_DATA(const Class* const) SharedFloat64ArrayClassPtr;
-
 const size_t TypedArrayLengthSlot = 1;
+const size_t TypedArrayIsSharedmemSlot = 3;
 
 } // namespace detail
 
 /*
  * Test for specific typed array types (ArrayBufferView subtypes) and return
  * the unwrapped object if so, else nullptr.  Never throws.
  */
 
 #define JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Type, type) \
 inline void \
-Get ## Type ## ArrayLengthAndData(JSObject* obj, uint32_t* length, type** data) \
+Get ## Type ## ArrayLengthAndData(JSObject* obj, uint32_t* length, bool* isSharedMemory, type** data) \
 { \
     MOZ_ASSERT(GetObjectClass(obj) == detail::Type ## ArrayClassPtr); \
-    const JS::Value& slot = GetReservedSlot(obj, detail::TypedArrayLengthSlot); \
-    *length = mozilla::AssertedCast<uint32_t>(slot.toInt32()); \
+    const JS::Value& lenSlot = GetReservedSlot(obj, detail::TypedArrayLengthSlot); \
+    *length = mozilla::AssertedCast<uint32_t>(lenSlot.toInt32()); \
+    const JS::Value& isSharedmemSlot = GetReservedSlot(obj, detail::TypedArrayIsSharedmemSlot); \
+    *isSharedMemory = mozilla::AssertedCast<bool>(isSharedmemSlot.toBoolean()); \
     *data = static_cast<type*>(GetObjectPrivate(obj)); \
 }
 
 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int8, int8_t)
 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8, uint8_t)
 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8Clamped, uint8_t)
 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int16, int16_t)
 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint16, uint16_t)
 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int32, int32_t)
 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint32, uint32_t)
 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float32, float)
 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float64, double)
 
-JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(SharedInt8, int8_t)
-JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(SharedUint8, uint8_t)
-JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(SharedUint8Clamped, uint8_t)
-JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(SharedInt16, int16_t)
-JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(SharedUint16, uint16_t)
-JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(SharedInt32, int32_t)
-JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(SharedUint32, uint32_t)
-JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(SharedFloat32, float)
-JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(SharedFloat64, double)
-
 #undef JS_DEFINE_DATA_AND_LENGTH_ACCESSOR
 
 // This one isn't inlined because it's rather tricky (by dint of having to deal
 // with a dozen-plus classes and varying slot layouts.
 extern JS_FRIEND_API(void)
-GetArrayBufferViewLengthAndData(JSObject* obj, uint32_t* length, uint8_t** data);
-
-extern JS_FRIEND_API(void)
-GetSharedArrayBufferViewLengthAndData(JSObject* obj, uint32_t* length, uint8_t** data);
+GetArrayBufferViewLengthAndData(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
 
 // This one isn't inlined because there are a bunch of different ArrayBuffer
 // classes that would have to be individually handled here.
+//
+// There is an isShared out argument for API consistency (eases use from DOM).
+// It will always be set to false.
 extern JS_FRIEND_API(void)
-GetArrayBufferLengthAndData(JSObject* obj, uint32_t* length, uint8_t** data);
-
+GetArrayBufferLengthAndData(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
+
+// Ditto for SharedArrayBuffer.
+//
+// There is an isShared out argument for API consistency (eases use from DOM).
+// It will always be set to true.
 extern JS_FRIEND_API(void)
-GetSharedArrayBufferLengthAndData(JSObject* obj, uint32_t* length, uint8_t** data);
+GetSharedArrayBufferLengthAndData(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
 
 } // namespace js
 
+JS_FRIEND_API(uint8_t*)
+JS_GetSharedArrayBufferData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
+
 /*
  * Unwrap Typed arrays all at once. Return nullptr without throwing if the
  * object cannot be viewed as the correct typed array, or the typed array
  * object on success, filling both outparameters.
  */
 extern JS_FRIEND_API(JSObject*)
-JS_GetObjectAsInt8Array(JSObject* obj, uint32_t* length, int8_t** data);
+JS_GetObjectAsInt8Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, int8_t** data);
 extern JS_FRIEND_API(JSObject*)
-JS_GetObjectAsUint8Array(JSObject* obj, uint32_t* length, uint8_t** data);
+JS_GetObjectAsUint8Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
+extern JS_FRIEND_API(JSObject*)
+JS_GetObjectAsUint8ClampedArray(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
 extern JS_FRIEND_API(JSObject*)
-JS_GetObjectAsUint8ClampedArray(JSObject* obj, uint32_t* length, uint8_t** data);
+JS_GetObjectAsInt16Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, int16_t** data);
 extern JS_FRIEND_API(JSObject*)
-JS_GetObjectAsInt16Array(JSObject* obj, uint32_t* length, int16_t** data);
+JS_GetObjectAsUint16Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint16_t** data);
 extern JS_FRIEND_API(JSObject*)
-JS_GetObjectAsUint16Array(JSObject* obj, uint32_t* length, uint16_t** data);
+JS_GetObjectAsInt32Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, int32_t** data);
 extern JS_FRIEND_API(JSObject*)
-JS_GetObjectAsInt32Array(JSObject* obj, uint32_t* length, int32_t** data);
+JS_GetObjectAsUint32Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint32_t** data);
 extern JS_FRIEND_API(JSObject*)
-JS_GetObjectAsUint32Array(JSObject* obj, uint32_t* length, uint32_t** data);
+JS_GetObjectAsFloat32Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, float** data);
+extern JS_FRIEND_API(JSObject*)
+JS_GetObjectAsFloat64Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, double** data);
 extern JS_FRIEND_API(JSObject*)
-JS_GetObjectAsFloat32Array(JSObject* obj, uint32_t* length, float** data);
-extern JS_FRIEND_API(JSObject*)
-JS_GetObjectAsFloat64Array(JSObject* obj, uint32_t* length, double** data);
-extern JS_FRIEND_API(JSObject*)
-JS_GetObjectAsArrayBufferView(JSObject* obj, uint32_t* length, uint8_t** data);
+JS_GetObjectAsArrayBufferView(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
+
+/*
+ * Unwrap an ArrayBuffer, return nullptr if it's a different type.
+ */
 extern JS_FRIEND_API(JSObject*)
 JS_GetObjectAsArrayBuffer(JSObject* obj, uint32_t* length, uint8_t** data);
 
 /*
  * Get the type of elements in a typed array, or MaxTypedArrayViewType if a DataView.
  *
  * |obj| must have passed a JS_IsArrayBufferView/JS_Is*Array test, or somehow
  * be known that it would pass such a test: it is an ArrayBufferView or a
@@ -1977,28 +1875,48 @@ JS_IsSharedArrayBufferObject(JSObject* o
  *
  * |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
  * that it would pass such a test: it is an ArrayBuffer or a wrapper of an
  * ArrayBuffer, and the unwrapping will succeed.
  */
 extern JS_FRIEND_API(uint32_t)
 JS_GetArrayBufferByteLength(JSObject* obj);
 
+extern JS_FRIEND_API(uint32_t)
+JS_GetSharedArrayBufferByteLength(JSObject* obj);
+
 /**
  * Return true if the arrayBuffer contains any data. This will return false for
  * ArrayBuffer.prototype and neutered ArrayBuffers.
  *
  * |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
  * that it would pass such a test: it is an ArrayBuffer or a wrapper of an
  * ArrayBuffer, and the unwrapping will succeed.
  */
 extern JS_FRIEND_API(bool)
 JS_ArrayBufferHasData(JSObject* obj);
 
 /**
+ * Return a pointer to the start of the data referenced by a typed array. The
+ * data is still owned by the typed array, and should not be modified on
+ * another thread. Furthermore, the pointer can become invalid on GC (if the
+ * data is small and fits inside the array's GC header), so callers must take
+ * care not to hold on across anything that could GC.
+ *
+ * |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
+ * that it would pass such a test: it is an ArrayBuffer or a wrapper of an
+ * ArrayBuffer, and the unwrapping will succeed.
+ *
+ * *isSharedMemory will be set to false, the argument is present to simplify
+ * its use from code that also interacts with SharedArrayBuffer.
+ */
+extern JS_FRIEND_API(uint8_t*)
+JS_GetArrayBufferData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
+
+/**
  * Check whether the obj is ArrayBufferObject and memory mapped. Note that this
  * may return false if a security wrapper is encountered that denies the
  * unwrapping.
  */
 extern JS_FRIEND_API(bool)
 JS_IsMappedArrayBufferObject(JSObject* obj);
 
 /**
@@ -2028,16 +1946,27 @@ JS_GetTypedArrayByteOffset(JSObject* obj
  * |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
  * be known that it would pass such a test: it is a typed array or a wrapper of
  * a typed array, and the unwrapping will succeed.
  */
 extern JS_FRIEND_API(uint32_t)
 JS_GetTypedArrayByteLength(JSObject* obj);
 
 /**
+ * Return the isShared flag of a typed array, which denotes whether
+ * the underlying buffer is a SharedArrayBuffer.
+ *
+ * |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
+ * be known that it would pass such a test: it is a typed array or a wrapper of
+ * a typed array, and the unwrapping will succeed.
+ */
+extern JS_FRIEND_API(bool)
+JS_GetTypedArraySharedness(JSObject* obj);
+
+/**
  * Check whether obj supports JS_ArrayBufferView* APIs. Note that this may
  * return false if a security wrapper is encountered that denies the
  * unwrapping.
  */
 extern JS_FRIEND_API(bool)
 JS_IsArrayBufferViewObject(JSObject* obj);
 
 /**
@@ -2051,74 +1980,55 @@ JS_GetArrayBufferViewByteLength(JSObject
  * data is still owned by the typed array, and should not be modified on
  * another thread. Furthermore, the pointer can become invalid on GC (if the
  * data is small and fits inside the array's GC header), so callers must take
  * care not to hold on across anything that could GC.
  *
  * |obj| must have passed a JS_Is*Array test, or somehow be known that it would
  * pass such a test: it is a typed array or a wrapper of a typed array, and the
  * unwrapping will succeed.
+ *
+ * *isSharedMemory will be set to true if the typed array maps a
+ * SharedArrayBuffer, otherwise to false.
  */
 
+extern JS_FRIEND_API(int8_t*)
+JS_GetInt8ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 extern JS_FRIEND_API(uint8_t*)
-JS_GetArrayBufferData(JSObject* obj, const JS::AutoCheckCannotGC&);
-extern JS_FRIEND_API(int8_t*)
-JS_GetInt8ArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
-extern JS_FRIEND_API(uint8_t*)
-JS_GetUint8ArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
+JS_GetUint8ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 extern JS_FRIEND_API(uint8_t*)
-JS_GetUint8ClampedArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
+JS_GetUint8ClampedArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 extern JS_FRIEND_API(int16_t*)
-JS_GetInt16ArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
+JS_GetInt16ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 extern JS_FRIEND_API(uint16_t*)
-JS_GetUint16ArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
+JS_GetUint16ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 extern JS_FRIEND_API(int32_t*)
-JS_GetInt32ArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
+JS_GetInt32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 extern JS_FRIEND_API(uint32_t*)
-JS_GetUint32ArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
+JS_GetUint32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 extern JS_FRIEND_API(float*)
-JS_GetFloat32ArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
+JS_GetFloat32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 extern JS_FRIEND_API(double*)
-JS_GetFloat64ArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
-
-extern JS_FRIEND_API(uint8_t*)
-JS_GetSharedArrayBufferData(JSObject* obj, const JS::AutoCheckCannotGC&);
-extern JS_FRIEND_API(int8_t*)
-JS_GetSharedInt8ArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
-extern JS_FRIEND_API(uint8_t*)
-JS_GetSharedUint8ArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
-extern JS_FRIEND_API(uint8_t*)
-JS_GetSharedUint8ClampedArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
-extern JS_FRIEND_API(int16_t*)
-JS_GetSharedInt16ArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
-extern JS_FRIEND_API(uint16_t*)
-JS_GetSharedUint16ArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
-extern JS_FRIEND_API(int32_t*)
-JS_GetSharedInt32ArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
-extern JS_FRIEND_API(uint32_t*)
-JS_GetSharedUint32ArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
-extern JS_FRIEND_API(float*)
-JS_GetSharedFloat32ArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
-extern JS_FRIEND_API(double*)
-JS_GetSharedFloat64ArrayData(JSObject* obj, const JS::AutoCheckCannotGC&);
+JS_GetFloat64ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 
 /**
  * Same as above, but for any kind of ArrayBufferView. Prefer the type-specific
  * versions when possible.
  */
 extern JS_FRIEND_API(void*)
-JS_GetArrayBufferViewData(JSObject* obj, const JS::AutoCheckCannotGC&);
+JS_GetArrayBufferViewData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 
 /**
- * Return the ArrayBuffer underlying an ArrayBufferView. If the buffer has been
- * neutered, this will still return the neutered buffer. |obj| must be an
- * object that would return true for JS_IsArrayBufferViewObject().
+ * Return the ArrayBuffer or SharedArrayBuffer underlying an
+ * ArrayBufferView. If the buffer has been neutered, this will still
+ * return the neutered buffer. |obj| must be an object that would
+ * return true for JS_IsArrayBufferViewObject().
  */
 extern JS_FRIEND_API(JSObject*)
-JS_GetArrayBufferViewBuffer(JSContext* cx, JS::HandleObject obj);
+JS_GetArrayBufferViewBuffer(JSContext* cx, JS::HandleObject obj, bool* isSharedMemory);
 
 typedef enum {
     ChangeData,
     KeepData
 } NeuterDataDisposition;
 
 /**
  * Set an ArrayBuffer's length to 0 and neuter all of its views.
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -71,17 +71,16 @@ enum State {
     D(ModuleEnvironmentObject*) \
     D(ModuleNamespaceObject*) \
     D(NestedScopeObject*) \
     D(PlainObject*) \
     D(SavedFrame*) \
     D(ScopeObject*) \
     D(ScriptSourceObject*) \
     D(SharedArrayBufferObject*) \
-    D(SharedTypedArrayObject*) \
     D(ImportEntryObject*) \
     D(ExportEntryObject*) \
     D(JSScript*) \
     D(LazyScript*) \
     D(Shape*) \
     D(JSAtom*) \
     D(JSString*) \
     D(JSFlatString*) \
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3555,17 +3555,17 @@ JSObject::allocKindForTenure(const js::N
 
     if (is<JSFunction>())
         return as<JSFunction>().getAllocKind();
 
     /*
      * Typed arrays in the nursery may have a lazily allocated buffer, make
      * sure there is room for the array's fixed data when moving the array.
      */
-    if (is<TypedArrayObject>() && !as<TypedArrayObject>().buffer()) {
+    if (is<TypedArrayObject>() && !as<TypedArrayObject>().hasBuffer()) {
         size_t nbytes = as<TypedArrayObject>().byteLength();
         return GetBackgroundAllocKind(TypedArrayObject::AllocKindForLazyBuffer(nbytes));
     }
 
     // Proxies have finalizers and are not nursery allocated.
     MOZ_ASSERT(!IsProxy(this));
 
     // Unboxed plain objects are sized according to the data they store.
--- a/js/src/jsprototypes.h
+++ b/js/src/jsprototypes.h
@@ -31,17 +31,16 @@
  * distinction can simply pass the same macro to both, which is exactly what
  * JS_FOR_EACH_PROTOTYPE does.
  */
 
 #define CLASP(name)                 (&name##Class)
 #define OCLASP(name)                (&name##Object::class_)
 #define TYPED_ARRAY_CLASP(type)     (&TypedArrayObject::classes[Scalar::type])
 #define ERROR_CLASP(type)           (&ErrorObject::classes[type])
-#define SHARED_TYPED_ARRAY_CLASP(type) (&SharedTypedArrayObject::classes[Scalar::type])
 
 #ifdef EXPOSE_INTL_API
 #define IF_INTL(real,imaginary) real
 #else
 #define IF_INTL(real,imaginary) imaginary
 #endif
 
 #ifdef ENABLE_BINARYDATA
@@ -95,27 +94,18 @@
     real(DataView,              35,     InitDataViewClass,      OCLASP(DataView)) \
     real(Symbol,                36,     InitSymbolClass,        OCLASP(Symbol)) \
 IF_SAB(real,imaginary)(SharedArrayBuffer,       37,     InitSharedArrayBufferClass, &js::SharedArrayBufferObject::protoClass) \
 IF_INTL(real,imaginary) (Intl,                  38,     InitIntlClass,          CLASP(Intl)) \
 IF_BDATA(real,imaginary)(TypedObject,           39,     InitTypedObjectModuleObject,   OCLASP(TypedObjectModule)) \
     real(Reflect,               40,     InitReflect,            nullptr) \
 IF_BDATA(real,imaginary)(SIMD,                  41,     InitSIMDClass, OCLASP(SIMD)) \
     real(WeakSet,               42,     InitWeakSetClass,       OCLASP(WeakSet)) \
-IF_SAB(real,imaginary)(SharedInt8Array,         43,     InitViaClassSpec,       SHARED_TYPED_ARRAY_CLASP(Int8)) \
-IF_SAB(real,imaginary)(SharedUint8Array,        44,     InitViaClassSpec,       SHARED_TYPED_ARRAY_CLASP(Uint8)) \
-IF_SAB(real,imaginary)(SharedInt16Array,        45,     InitViaClassSpec,       SHARED_TYPED_ARRAY_CLASP(Int16)) \
-IF_SAB(real,imaginary)(SharedUint16Array,       46,     InitViaClassSpec,       SHARED_TYPED_ARRAY_CLASP(Uint16)) \
-IF_SAB(real,imaginary)(SharedInt32Array,        47,     InitViaClassSpec,       SHARED_TYPED_ARRAY_CLASP(Int32)) \
-IF_SAB(real,imaginary)(SharedUint32Array,       48,     InitViaClassSpec,       SHARED_TYPED_ARRAY_CLASP(Uint32)) \
-IF_SAB(real,imaginary)(SharedFloat32Array,      49,     InitViaClassSpec,       SHARED_TYPED_ARRAY_CLASP(Float32)) \
-IF_SAB(real,imaginary)(SharedFloat64Array,      50,     InitViaClassSpec,       SHARED_TYPED_ARRAY_CLASP(Float64)) \
-IF_SAB(real,imaginary)(SharedUint8ClampedArray, 51,     InitViaClassSpec,       SHARED_TYPED_ARRAY_CLASP(Uint8Clamped)) \
-    real(TypedArray,            52,      InitViaClassSpec,      &js::TypedArrayObject::sharedTypedArrayPrototypeClass) \
-IF_SAB(real,imaginary)(Atomics,                 53,     InitAtomicsClass, OCLASP(Atomics)) \
-    real(SavedFrame,            54,      InitViaClassSpec,      &js::SavedFrame::class_) \
-    real(Module,                55,      InitModuleClass,       OCLASP(Module)) \
-    real(ImportEntry,           56,      InitImportEntryClass,  OCLASP(ImportEntry)) \
-    real(ExportEntry,           57,      InitExportEntryClass,  OCLASP(ExportEntry)) \
+    real(TypedArray,            43,      InitViaClassSpec,      &js::TypedArrayObject::sharedTypedArrayPrototypeClass) \
+IF_SAB(real,imaginary)(Atomics,                 44,     InitAtomicsClass, OCLASP(Atomics)) \
+    real(SavedFrame,            45,      InitViaClassSpec,      &js::SavedFrame::class_) \
+    real(Module,                46,      InitModuleClass,       OCLASP(Module)) \
+    real(ImportEntry,           47,      InitImportEntryClass,  OCLASP(ImportEntry)) \
+    real(ExportEntry,           48,      InitExportEntryClass,  OCLASP(ExportEntry)) \
 
 #define JS_FOR_EACH_PROTOTYPE(macro) JS_FOR_PROTOTYPES(macro,macro)
 
 #endif /* jsprototypes_h */
--- a/js/src/vm/ArrayBufferObject-inl.h
+++ b/js/src/vm/ArrayBufferObject-inl.h
@@ -14,17 +14,17 @@
 #include "js/Value.h"
 
 #include "vm/SharedArrayObject.h"
 #include "vm/SharedMem.h"
 
 namespace js {
 
 inline SharedMem<uint8_t*>
-ArrayBufferObjectMaybeShared::dataPointerMaybeShared()
+ArrayBufferObjectMaybeShared::dataPointerEither()
 {
     ArrayBufferObjectMaybeShared* buf = this;
     if (buf->is<ArrayBufferObject>())
         return buf->as<ArrayBufferObject>().dataPointerShared();
     return buf->as<SharedArrayBufferObject>().dataPointerShared();
 }
 
 inline uint32_t
--- a/js/src/vm/ArrayBufferObject.h
+++ b/js/src/vm/ArrayBufferObject.h
@@ -28,42 +28,36 @@ class ArrayBufferViewObject;
 //     - ArrayBufferObject
 //     - SharedArrayBufferObject
 //   - DataViewObject
 //   - TypedArrayObject (declared in vm/TypedArrayObject.h)
 //     - TypedArrayObjectTemplate
 //       - Int8ArrayObject
 //       - Uint8ArrayObject
 //       - ...
-//   - SharedTypedArrayObject (declared in vm/SharedTypedArrayObject.h)
-//     - SharedTypedArrayObjectTemplate
-//       - SharedInt8ArrayObject
-//       - SharedUint8ArrayObject
-//       - ...
 // - JSObject
 //   - ArrayBufferViewObject
 //   - TypedObject (declared in builtin/TypedObject.h)
 //
-// Note that |TypedArrayObjectTemplate| and |SharedTypedArrayObjectTemplate| are
-// just implementation details that make implementing their various subclasses easier.
+// Note that |TypedArrayObjectTemplate| is just an implementation
+// detail that makes implementing its various subclasses easier.
 //
 // ArrayBufferObject and SharedArrayBufferObject are unrelated data types:
 // the racy memory of the latter cannot substitute for the non-racy memory of
 // the former; the non-racy memory of the former cannot be used with the atomics;
-// the former can be neutered and the latter not; and they have different
-// method suites.  Hence they have been separated completely.
-//
-// Most APIs will only accept ArrayBufferObject.  ArrayBufferObjectMaybeShared exists
-// as a join point to allow APIs that can take or use either, notably AsmJS.
+// the former can be neutered and the latter not.  Hence they have been separated
+// completely.
 //
-// As ArrayBufferObject and SharedArrayBufferObject are separated, so are the
-// TypedArray hierarchies below the two.  However, the TypedArrays have the
-// same layout (see TypedArrayObject.h), so there is little code duplication.
+// Most APIs will only accept ArrayBufferObject.  ArrayBufferObjectMaybeShared
+// exists as a join point to allow APIs that can take or use either, notably AsmJS.
 //
-// The possible data ownership and reference relationships with array buffers
+// In contrast with the separation of ArrayBufferObject and
+// SharedArrayBufferObject, the TypedArray types can map either.
+//
+// The possible data ownership and reference relationships with ArrayBuffers
 // and related classes are enumerated below. These are the possible locations
 // for typed data:
 //
 // (1) malloc'ed or mmap'ed data owned by an ArrayBufferObject.
 // (2) Data allocated inline with an ArrayBufferObject.
 // (3) Data allocated inline with a TypedArrayObject.
 // (4) Data allocated inline with an InlineTypedObject.
 //
@@ -81,17 +75,17 @@ ArrayBufferObjectMaybeShared& AsAnyArray
 
 class ArrayBufferObjectMaybeShared : public NativeObject
 {
   public:
     uint32_t byteLength() {
         return AnyArrayBufferByteLength(this);
     }
 
-    inline SharedMem<uint8_t*> dataPointerMaybeShared();
+    inline SharedMem<uint8_t*> dataPointerEither();
 };
 
 /*
  * ArrayBufferObject
  *
  * This class holds the underlying raw buffer that the various ArrayBufferViews
  * (eg DataViewObject, the TypedArrays, TypedObjects) access. It can be created
  * explicitly and used to construct an ArrayBufferView, or can be created
@@ -379,22 +373,24 @@ class ArrayBufferObject : public ArrayBu
  * ArrayBufferViewObject
  *
  * Common definitions shared by all array buffer views.
  */
 
 class ArrayBufferViewObject : public JSObject
 {
   public:
-    static ArrayBufferObject* bufferObject(JSContext* cx, Handle<ArrayBufferViewObject*> obj);
+    static ArrayBufferObjectMaybeShared* bufferObject(JSContext* cx, Handle<ArrayBufferViewObject*> obj);
 
     void neuter(void* newData);
 
-    uint8_t* dataPointer();
-    void setDataPointer(uint8_t* data);
+    // By construction we only need unshared variants here.  See
+    // comments in ArrayBufferObject.cpp.
+    uint8_t* dataPointerUnshared();
+    void setDataPointerUnshared(uint8_t* data);
 
     static void trace(JSTracer* trc, JSObject* obj);
 };
 
 bool
 ToClampedIndex(JSContext* cx, HandleValue v, uint32_t length, uint32_t* out);
 
 /*
--- a/js/src/vm/SharedArrayObject.h
+++ b/js/src/vm/SharedArrayObject.h
@@ -98,19 +98,19 @@ class SharedArrayRawBuffer
  * (across workers and/or processes).  The SharedArrayBuffer object
  * has a finalizer that decrements the refcount, the last one to leave
  * (globally) unmaps the memory.  The sender ups the refcount before
  * transmitting the memory to another worker.
  *
  * SharedArrayBufferObject (or really the underlying memory) /is
  * racy/: more than one worker can access the memory at the same time.
  *
- * A SharedTypedArrayObject (a view) references a SharedArrayBuffer
+ * A TypedArrayObject (a view) references a SharedArrayBuffer
  * and keeps it alive.  The SharedArrayBuffer does /not/ reference its
- * views, nor do the views reference each other in any way.
+ * views.
  */
 class SharedArrayBufferObject : public ArrayBufferObjectMaybeShared
 {
     static bool byteLengthGetterImpl(JSContext* cx, const CallArgs& args);
 
   public:
     // RAWBUF_SLOT holds a pointer (as "private" data) to the
     // SharedArrayRawBuffer object, which is manually managed storage.
@@ -161,14 +161,15 @@ class SharedArrayBufferObject : public A
 
 private:
     void acceptRawBuffer(SharedArrayRawBuffer* buffer);
     void dropRawBuffer();
 };
 
 bool IsSharedArrayBuffer(HandleValue v);
 bool IsSharedArrayBuffer(HandleObject o);
+bool IsSharedArrayBuffer(JSObject* o);
 
 SharedArrayBufferObject& AsSharedArrayBuffer(HandleObject o);
 
 } // namespace js
 
 #endif // vm_SharedArrayObject_h
--- a/js/src/vm/SharedMem.h
+++ b/js/src/vm/SharedMem.h
@@ -128,16 +128,20 @@ class SharedMem
     T unwrap() const {
         return ptr_;
     }
 
     T unwrapUnshared() const {
         MOZ_ASSERT(sharedness_ == IsUnshared);
         return ptr_;
     }
+
+    uintptr_t unwrapValue() const {
+        return reinterpret_cast<uintptr_t>(ptr_);
+    }
 };
 
 template<typename T>
 inline bool
 operator >=(const SharedMem<T>& a, const SharedMem<T>& b)
 {
     return a.unwrap() >= b.unwrap();
 }
--- a/js/src/vm/TypedArrayCommon.h
+++ b/js/src/vm/TypedArrayCommon.h
@@ -70,79 +70,59 @@ template<> struct TypeIDOfType<int32_t> 
 template<> struct TypeIDOfType<uint32_t> { static const Scalar::Type id = Scalar::Uint32; };
 template<> struct TypeIDOfType<float> { static const Scalar::Type id = Scalar::Float32; };
 template<> struct TypeIDOfType<double> { static const Scalar::Type id = Scalar::Float64; };
 template<> struct TypeIDOfType<uint8_clamped> { static const Scalar::Type id = Scalar::Uint8Clamped; };
 
 inline bool
 IsAnyTypedArray(JSObject* obj)
 {
-    return obj->is<TypedArrayObject>() || obj->is<SharedTypedArrayObject>();
+    return obj->is<TypedArrayObject>();
 }
 
 inline uint32_t
 AnyTypedArrayLength(JSObject* obj)
 {
-    if (obj->is<TypedArrayObject>())
-        return obj->as<TypedArrayObject>().length();
-    return obj->as<SharedTypedArrayObject>().length();
+    return obj->as<TypedArrayObject>().length();
 }
 
 inline Scalar::Type
 AnyTypedArrayType(JSObject* obj)
 {
-    if (obj->is<TypedArrayObject>())
-        return obj->as<TypedArrayObject>().type();
-    return obj->as<SharedTypedArrayObject>().type();
+    return obj->as<TypedArrayObject>().type();
 }
 
 inline Shape*
 AnyTypedArrayShape(JSObject* obj)
 {
-    if (obj->is<TypedArrayObject>())
-        return obj->as<TypedArrayObject>().lastProperty();
-    return obj->as<SharedTypedArrayObject>().lastProperty();
-}
-
-inline const TypedArrayLayout&
-AnyTypedArrayLayout(const JSObject* obj)
-{
-    if (obj->is<TypedArrayObject>())
-        return obj->as<TypedArrayObject>().layout();
-    return obj->as<SharedTypedArrayObject>().layout();
+    return obj->as<TypedArrayObject>().lastProperty();
 }
 
 inline SharedMem<void*>
 AnyTypedArrayViewData(const JSObject* obj)
 {
-    if (obj->is<TypedArrayObject>())
-        return obj->as<TypedArrayObject>().viewDataShared();
-    return obj->as<SharedTypedArrayObject>().viewDataShared();
+    return obj->as<TypedArrayObject>().viewDataEither();
 }
 
 inline uint32_t
 AnyTypedArrayBytesPerElement(const JSObject* obj)
 {
-    if (obj->is<TypedArrayObject>())
-        return obj->as<TypedArrayObject>().bytesPerElement();
-    return obj->as<SharedTypedArrayObject>().bytesPerElement();
+    return obj->as<TypedArrayObject>().bytesPerElement();
 }
 
 inline uint32_t
 AnyTypedArrayByteLength(const JSObject* obj)
 {
-    if (obj->is<TypedArrayObject>())
-        return obj->as<TypedArrayObject>().byteLength();
-    return obj->as<SharedTypedArrayObject>().byteLength();
+    return obj->as<TypedArrayObject>().byteLength();
 }
 
 inline bool
 IsAnyTypedArrayClass(const Class* clasp)
 {
-    return IsTypedArrayClass(clasp) || IsSharedTypedArrayClass(clasp);
+    return IsTypedArrayClass(clasp);
 }
 
 class SharedOps
 {
   public:
     template<typename T>
     static T load(SharedMem<T*> addr) {
         return js::jit::AtomicOperations::loadSafeWhenRacy(addr);
@@ -157,16 +137,20 @@ class SharedOps
     static void memcpy(SharedMem<T*> dest, SharedMem<T*> src, size_t size) {
         js::jit::AtomicOperations::memcpySafeWhenRacy(dest, src, size);
     }
 
     template<typename T>
     static void memmove(SharedMem<T*> dest, SharedMem<T*> src, size_t size) {
         js::jit::AtomicOperations::memmoveSafeWhenRacy(dest, src, size);
     }
+
+    static SharedMem<void*> extract(TypedArrayObject* obj) {
+        return obj->viewDataEither();
+    }
 };
 
 class UnsharedOps
 {
   public:
     template<typename T>
     static T load(SharedMem<T*> addr) {
         return *addr.unwrapUnshared();
@@ -181,16 +165,20 @@ class UnsharedOps
     static void memcpy(SharedMem<T*> dest, SharedMem<T*> src, size_t size) {
         ::memcpy(dest.unwrapUnshared(), src.unwrapUnshared(), size);
     }
 
     template<typename T>
     static void memmove(SharedMem<T*> dest, SharedMem<T*> src, size_t size) {
         ::memmove(dest.unwrapUnshared(), src.unwrapUnshared(), size);
     }
+
+    static SharedMem<void*> extract(TypedArrayObject* obj) {
+        return SharedMem<void*>::unshared(obj->viewDataUnshared());
+    }
 };
 
 template<class SpecificArray, typename Ops>
 class ElementSpecific
 {
     typedef typename SpecificArray::ElementType T;
     typedef typename SpecificArray::SomeTypedArray SomeTypedArray;
 
@@ -227,17 +215,17 @@ class ElementSpecific
 
         // Inhibit unaligned accesses on ARM (bug 1097253, a compiler bug).
 #ifdef __arm__
 #  define JS_VOLATILE_ARM volatile
 #else
 #  define JS_VOLATILE_ARM
 #endif
 
-        SharedMem<void*> data = AnyTypedArrayViewData(source);
+        SharedMem<void*> data = Ops::extract(source.as<TypedArrayObject>());
         switch (AnyTypedArrayType(source)) {
           case Scalar::Int8: {
             SharedMem<JS_VOLATILE_ARM int8_t*> src = data.cast<JS_VOLATILE_ARM int8_t*>();
             for (uint32_t i = 0; i < count; ++i)
                 Ops::store(dest++, T(Ops::load(src++)));
             break;
           }
           case Scalar::Uint8:
@@ -499,42 +487,20 @@ class ElementSpecific
         if (SpecificArray::ArrayTypeID() == Scalar::Uint8Clamped)
             return T(d);
         if (TypeIsUnsigned<T>())
             return T(JS::ToUint32(d));
         return T(JS::ToInt32(d));
     }
 };
 
-template<class SomeTypedArray>
-inline bool
-EitherShared(Handle<SomeTypedArray*> target, HandleObject source)
-{
-    return target->template is<SharedTypedArrayObject>() || source->is<SharedTypedArrayObject>();
-}
-
-template<>
-inline bool
-EitherShared(Handle<SharedTypedArrayObject*> target, HandleObject source)
-{
-    return true;
-}
-
-template<>
-inline bool
-EitherShared(Handle<TypedArrayObject*> target, HandleObject source)
-{
-    return source->is<SharedTypedArrayObject>();
-}
-
 template<typename SomeTypedArray>
 class TypedArrayMethods
 {
-    static_assert(mozilla::IsSame<SomeTypedArray, TypedArrayObject>::value ||
-                  mozilla::IsSame<SomeTypedArray, SharedTypedArrayObject>::value,
+    static_assert(mozilla::IsSame<SomeTypedArray, TypedArrayObject>::value,
                   "methods must be shared/unshared-specific, not "
                   "element-type-specific");
 
     typedef typename SomeTypedArray::BufferType BufferType;
 
     typedef typename SomeTypedArray::template OfType<int8_t>::Type Int8ArrayType;
     typedef typename SomeTypedArray::template OfType<uint8_t>::Type Uint8ArrayType;
     typedef typename SomeTypedArray::template OfType<int16_t>::Type Int16ArrayType;
@@ -792,77 +758,77 @@ class TypedArrayMethods
 
         if (IsAnyTypedArray(source))
             return setFromAnyTypedArray(cx, target, source, offset);
 
         return setFromNonTypedArray(cx, target, source, len, offset);
     }
 
   private:
-    static bool
-    setFromAnyTypedArray(JSContext* cx, Handle<SomeTypedArray*> target, HandleObject source,
-                         uint32_t offset)
-    {
-        MOZ_ASSERT(IsAnyTypedArray(source), "use setFromNonTypedArray");
+     static bool
+     setFromAnyTypedArray(JSContext* cx, Handle<SomeTypedArray*> target, HandleObject source,
+                          uint32_t offset)
+     {
+         MOZ_ASSERT(IsAnyTypedArray(source), "use setFromNonTypedArray");
 
-        bool isShared = EitherShared(target, source);
+         bool isShared = target->isSharedMemory() || source->as<TypedArrayObject>().isSharedMemory();
 
-        switch (target->type()) {
-          case Scalar::Int8:
-            if (isShared)
-                return ElementSpecific<Int8ArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-            return ElementSpecific<Int8ArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-          case Scalar::Uint8:
-            if (isShared)
-                return ElementSpecific<Uint8ArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-            return ElementSpecific<Uint8ArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-          case Scalar::Int16:
-            if (isShared)
-                return ElementSpecific<Int16ArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-            return ElementSpecific<Int16ArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-          case Scalar::Uint16:
-            if (isShared)
-                return ElementSpecific<Uint16ArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-            return ElementSpecific<Uint16ArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-          case Scalar::Int32:
-            if (isShared)
-                return ElementSpecific<Int32ArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-            return ElementSpecific<Int32ArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-          case Scalar::Uint32:
-            if (isShared)
-                return ElementSpecific<Uint32ArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-            return ElementSpecific<Uint32ArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-          case Scalar::Float32:
-            if (isShared)
-                return ElementSpecific<Float32ArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-            return ElementSpecific<Float32ArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-          case Scalar::Float64:
-            if (isShared)
-                return ElementSpecific<Float64ArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-            return ElementSpecific<Float64ArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-          case Scalar::Uint8Clamped:
-            if (isShared)
-                return ElementSpecific<Uint8ClampedArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-            return ElementSpecific<Uint8ClampedArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
-          case Scalar::Float32x4:
-          case Scalar::Int32x4:
-          case Scalar::MaxTypedArrayViewType:
-            break;
-        }
+         switch (target->type()) {
+           case Scalar::Int8:
+             if (isShared)
+                 return ElementSpecific<Int8ArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+             return ElementSpecific<Int8ArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+           case Scalar::Uint8:
+             if (isShared)
+                 return ElementSpecific<Uint8ArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+             return ElementSpecific<Uint8ArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+           case Scalar::Int16:
+             if (isShared)
+                 return ElementSpecific<Int16ArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+             return ElementSpecific<Int16ArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+           case Scalar::Uint16:
+             if (isShared)
+                 return ElementSpecific<Uint16ArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+             return ElementSpecific<Uint16ArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+           case Scalar::Int32:
+             if (isShared)
+                 return ElementSpecific<Int32ArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+             return ElementSpecific<Int32ArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+           case Scalar::Uint32:
+             if (isShared)
+                 return ElementSpecific<Uint32ArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+             return ElementSpecific<Uint32ArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+           case Scalar::Float32:
+             if (isShared)
+                 return ElementSpecific<Float32ArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+             return ElementSpecific<Float32ArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+           case Scalar::Float64:
+             if (isShared)
+                 return ElementSpecific<Float64ArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+             return ElementSpecific<Float64ArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+           case Scalar::Uint8Clamped:
+             if (isShared)
+                 return ElementSpecific<Uint8ClampedArrayType, SharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+             return ElementSpecific<Uint8ClampedArrayType, UnsharedOps>::setFromAnyTypedArray(cx, target, source, offset);
+           case Scalar::Float32x4:
+           case Scalar::Int32x4:
+           case Scalar::MaxTypedArrayViewType:
+             break;
+         }
 
-        MOZ_CRASH("nonsense target element type");
-    }
+         MOZ_CRASH("nonsense target element type");
+     }
 
     static bool
     setFromNonTypedArray(JSContext* cx, Handle<SomeTypedArray*> target, HandleObject source,
                          uint32_t len, uint32_t offset)
     {
         MOZ_ASSERT(!IsAnyTypedArray(source), "use setFromAnyTypedArray");
 
-        bool isShared = EitherShared(target, source);
+        bool isShared = target->isSharedMemory();
 
         switch (target->type()) {
           case Scalar::Int8:
             if (isShared)
                 return ElementSpecific<Int8ArrayType, SharedOps>::setFromNonTypedArray(cx, target, source, len, offset);
             return ElementSpecific<Int8ArrayType, UnsharedOps>::setFromNonTypedArray(cx, target, source, len, offset);
           case Scalar::Uint8:
             if (isShared)
@@ -896,16 +862,15 @@ class TypedArrayMethods
             if (isShared)
                 return ElementSpecific<Uint8ClampedArrayType, SharedOps>::setFromNonTypedArray(cx, target, source, len, offset);
             return ElementSpecific<Uint8ClampedArrayType, UnsharedOps>::setFromNonTypedArray(cx, target, source, len, offset);
           case Scalar::Float32x4:
           case Scalar::Int32x4:
           case Scalar::MaxTypedArrayViewType:
             break;
         }
-
         MOZ_CRASH("bad target array type");
     }
 };
 
 } // namespace js
 
 #endif // vm_TypedArrayCommon_h