diff --git a/js/src/builtin/SIMD.cpp b/js/src/builtin/SIMD.cpp index 550c317f19e2..2b7114034808 100644 --- a/js/src/builtin/SIMD.cpp +++ b/js/src/builtin/SIMD.cpp @@ -1017,23 +1017,24 @@ Select(JSContext *cx, unsigned argc, Value *vp) template static bool TypedArrayFromArgs(JSContext *cx, const CallArgs &args, - MutableHandle typedArray, int32_t *byteStart) + MutableHandleObject typedArray, int32_t *byteStart) { if (!args[0].isObject()) return ErrorBadArgs(cx); JSObject &argobj = args[0].toObject(); - if (!argobj.is()) + if (!IsAnyTypedArray(&argobj)) return ErrorBadArgs(cx); - typedArray.set(&argobj.as()); + typedArray.set(&argobj); int32_t index; if (!ToInt32(cx, args[1], &index)) return false; - *byteStart = index * typedArray->bytesPerElement(); - if (*byteStart < 0 || (uint32_t(*byteStart) + NumElem * sizeof(VElem)) > typedArray->byteLength()) + *byteStart = index * AnyTypedArrayBytesPerElement(typedArray); + if (*byteStart < 0 || + (uint32_t(*byteStart) + NumElem * sizeof(VElem)) > AnyTypedArrayByteLength(typedArray)) { // Keep in sync with AsmJS OnOutOfBounds function. JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_INDEX); @@ -1054,7 +1055,7 @@ Load(JSContext *cx, unsigned argc, Value *vp) return ErrorBadArgs(cx); int32_t byteStart; - Rooted typedArray(cx); + RootedObject typedArray(cx); if (!TypedArrayFromArgs(cx, args, &typedArray, &byteStart)) return false; @@ -1064,7 +1065,7 @@ Load(JSContext *cx, unsigned argc, Value *vp) if (!result) return false; - Elem *src = reinterpret_cast(static_cast(typedArray->viewData()) + byteStart); + Elem *src = reinterpret_cast(static_cast(AnyTypedArrayViewData(typedArray)) + byteStart); Elem *dst = reinterpret_cast(result->typedMem()); memcpy(dst, src, sizeof(Elem) * NumElem); @@ -1083,7 +1084,7 @@ Store(JSContext *cx, unsigned argc, Value *vp) return ErrorBadArgs(cx); int32_t byteStart; - Rooted typedArray(cx); + RootedObject typedArray(cx); if (!TypedArrayFromArgs(cx, args, &typedArray, &byteStart)) return false; @@ -1091,7 +1092,7 @@ Store(JSContext *cx, unsigned argc, Value *vp) return ErrorBadArgs(cx); Elem *src = TypedObjectMemory(args[2]); - Elem *dst = reinterpret_cast(static_cast(typedArray->viewData()) + byteStart); + Elem *dst = reinterpret_cast(static_cast(AnyTypedArrayViewData(typedArray)) + byteStart); memcpy(dst, src, sizeof(Elem) * NumElem); args.rval().setObject(args[2].toObject()); diff --git a/js/src/tests/ecma_7/SIMD/load.js b/js/src/tests/ecma_7/SIMD/load.js index 706bc4b4212d..00fe77e86aad 100644 --- a/js/src/tests/ecma_7/SIMD/load.js +++ b/js/src/tests/ecma_7/SIMD/load.js @@ -11,9 +11,15 @@ const SIZE_64_ARRAY = 8; const SIZE_BYTES = SIZE_32_ARRAY * 4; -function MakeComparator(kind, arr) { +function IsSharedTypedArray(arr) { + return arr && arr.buffer && arr.buffer instanceof SharedArrayBuffer; +} + +function MakeComparator(kind, arr, shared) { var bpe = arr.BYTES_PER_ELEMENT; - var uint8 = (bpe != 1) ? new Uint8Array(arr.buffer) : arr; + var uint8 = (bpe != 1) ? (IsSharedTypedArray(arr) ? new SharedUint8Array(arr.buffer) + : new Uint8Array(arr.buffer)) + : arr; // Size in bytes of a single element in the SIMD vector. var sizeOfLaneElem; @@ -163,9 +169,48 @@ function testLoad(kind, TA) { assertThrowsInstanceOf(() => SIMD[kind].load(TA, obj), TypeError); } +function testSharedArrayBufferCompat() { + if (!this.SharedArrayBuffer || !this.SharedFloat32Array || !this.Atomics) + return; + + var TA = new SharedFloat32Array(16); + for (var i = 0; i < 16; i++) + TA[i] = i + 1; + + for (var ta of [ + new SharedUint8Array(TA.buffer), + new SharedInt8Array(TA.buffer), + new SharedUint16Array(TA.buffer), + new SharedInt16Array(TA.buffer), + new SharedUint32Array(TA.buffer), + new SharedInt32Array(TA.buffer), + new SharedFloat32Array(TA.buffer), + new SharedFloat64Array(TA.buffer) + ]) + { + for (var kind of ['int32x4', 'float32x4', 'float64x2']) { + var comp = MakeComparator(kind, ta); + comp.load(0); + comp.loadX(0); + comp.loadXY(0); + comp.loadXYZ(0); + + comp.load(3); + comp.loadX(3); + comp.loadXY(3); + comp.loadXYZ(3); + } + + assertThrowsInstanceOf(() => SIMD.int32x4.load(ta, 1024), RangeError); + assertThrowsInstanceOf(() => SIMD.float32x4.load(ta, 1024), RangeError); + assertThrowsInstanceOf(() => SIMD.float64x2.load(ta, 1024), RangeError); + } +} + testLoad('float32x4', new Float32Array(SIZE_32_ARRAY)); testLoad('float64x2', new Float64Array(SIZE_64_ARRAY)); testLoad('int32x4', new Int32Array(SIZE_32_ARRAY)); +testSharedArrayBufferCompat(); if (typeof reportCompare === "function") reportCompare(true, true); diff --git a/js/src/tests/ecma_7/SIMD/store.js b/js/src/tests/ecma_7/SIMD/store.js index 839cf8df5712..5d588e2e9098 100644 --- a/js/src/tests/ecma_7/SIMD/store.js +++ b/js/src/tests/ecma_7/SIMD/store.js @@ -103,9 +103,50 @@ function testStoreFloat64x2() { assertThrowsInstanceOf(() => SIMD.float32x4.store(F64, 0, v), TypeError); } +function testSharedArrayBufferCompat() { + if (!this.SharedArrayBuffer || !this.SharedFloat32Array || !this.Atomics) + return; + + var I32 = new SharedInt32Array(16); + var TA = I32; + + var F32 = new SharedFloat32Array(TA.buffer); + var F64 = new SharedFloat64Array(TA.buffer); + + var int32x4 = SIMD.int32x4(1, 2, 3, 4); + var float32x4 = SIMD.float32x4(1, 2, 3, 4); + var float64x2 = SIMD.float64x2(1, 2); + + for (var ta of [ + new SharedUint8Array(TA.buffer), + new SharedInt8Array(TA.buffer), + new SharedUint16Array(TA.buffer), + new SharedInt16Array(TA.buffer), + new SharedUint32Array(TA.buffer), + new SharedInt32Array(TA.buffer), + new SharedFloat32Array(TA.buffer), + new SharedFloat64Array(TA.buffer) + ]) + { + SIMD.int32x4.store(ta, 0, int32x4); + for (var i = 0; i < 4; i++) assertEq(I32[i], [1, 2, 3, 4][i]); + + SIMD.float32x4.store(ta, 0, float32x4); + for (var i = 0; i < 4; i++) assertEq(F32[i], [1, 2, 3, 4][i]); + + SIMD.float64x2.store(ta, 0, float64x2); + for (var i = 0; i < 2; i++) assertEq(F64[i], [1, 2][i]); + + assertThrowsInstanceOf(() => SIMD.int32x4.store(ta, 1024, int32x4), RangeError); + assertThrowsInstanceOf(() => SIMD.float32x4.store(ta, 1024, float32x4), RangeError); + assertThrowsInstanceOf(() => SIMD.float64x2.store(ta, 1024, float64x2), RangeError); + } +} + testStoreInt32x4(); testStoreFloat32x4(); testStoreFloat64x2(); +testSharedArrayBufferCompat(); if (typeof reportCompare === "function") reportCompare(true, true); diff --git a/js/src/vm/TypedArrayCommon.h b/js/src/vm/TypedArrayCommon.h index 66640dd2fb49..573409dbf219 100644 --- a/js/src/vm/TypedArrayCommon.h +++ b/js/src/vm/TypedArrayCommon.h @@ -113,6 +113,14 @@ AnyTypedArrayViewData(const JSObject *obj) return obj->as().viewData(); } +inline uint32_t +AnyTypedArrayBytesPerElement(const JSObject *obj) +{ + if (obj->is()) + return obj->as().bytesPerElement(); + return obj->as().bytesPerElement(); +} + inline uint32_t AnyTypedArrayByteLength(const JSObject *obj) {