summaryrefslogtreecommitdiffstats
path: root/js/src/tests/ecma_7/SIMD/shell.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/ecma_7/SIMD/shell.js')
-rw-r--r--js/src/tests/ecma_7/SIMD/shell.js580
1 files changed, 580 insertions, 0 deletions
diff --git a/js/src/tests/ecma_7/SIMD/shell.js b/js/src/tests/ecma_7/SIMD/shell.js
new file mode 100644
index 000000000..943965390
--- /dev/null
+++ b/js/src/tests/ecma_7/SIMD/shell.js
@@ -0,0 +1,580 @@
+function makeFloat(sign, exp, mantissa) {
+ assertEq(sign, sign & 0x1);
+ assertEq(exp, exp & 0xFF);
+ assertEq(mantissa, mantissa & 0x7FFFFF);
+
+ var i32 = new Int32Array(1);
+ var f32 = new Float32Array(i32.buffer);
+
+ i32[0] = (sign << 31) | (exp << 23) | mantissa;
+ return f32[0];
+}
+
+function makeDouble(sign, exp, mantissa) {
+ assertEq(sign, sign & 0x1);
+ assertEq(exp, exp & 0x7FF);
+
+ // Can't use bitwise operations on mantissa, as it might be a double
+ assertEq(mantissa <= 0xfffffffffffff, true);
+ var highBits = (mantissa / Math.pow(2, 32)) | 0;
+ var lowBits = mantissa - highBits * Math.pow(2, 32);
+
+ var i32 = new Int32Array(2);
+ var f64 = new Float64Array(i32.buffer);
+
+ // Note that this assumes little-endian order, which is the case on tier-1
+ // platforms.
+ i32[0] = lowBits;
+ i32[1] = (sign << 31) | (exp << 20) | highBits;
+ return f64[0];
+}
+
+function GetType(v) {
+ switch (Object.getPrototypeOf(v)) {
+ case SIMD.Int8x16.prototype: return SIMD.Int8x16;
+ case SIMD.Int16x8.prototype: return SIMD.Int16x8;
+ case SIMD.Int32x4.prototype: return SIMD.Int32x4;
+ case SIMD.Uint8x16.prototype: return SIMD.Uint8x16;
+ case SIMD.Uint16x8.prototype: return SIMD.Uint16x8;
+ case SIMD.Uint32x4.prototype: return SIMD.Uint32x4;
+ case SIMD.Float32x4.prototype: return SIMD.Float32x4;
+ case SIMD.Float64x2.prototype: return SIMD.Float64x2;
+ case SIMD.Bool8x16.prototype: return SIMD.Bool8x16;
+ case SIMD.Bool16x8.prototype: return SIMD.Bool16x8;
+ case SIMD.Bool32x4.prototype: return SIMD.Bool32x4;
+ case SIMD.Bool64x2.prototype: return SIMD.Bool64x2;
+ }
+}
+
+function assertEqFloat64x2(v, arr) {
+ try {
+ assertEq(SIMD.Float64x2.extractLane(v, 0), arr[0]);
+ assertEq(SIMD.Float64x2.extractLane(v, 1), arr[1]);
+ } catch (e) {
+ print("stack trace:", e.stack);
+ throw e;
+ }
+}
+
+function assertEqBool64x2(v, arr) {
+ try {
+ assertEq(SIMD.Bool64x2.extractLane(v, 0), arr[0]);
+ assertEq(SIMD.Bool64x2.extractLane(v, 1), arr[1]);
+ } catch (e) {
+ print("stack trace:", e.stack);
+ throw e;
+ }
+}
+
+function assertEqX2(v, arr) {
+ var Type = GetType(v);
+ if (Type === SIMD.Float64x2) assertEqFloat64x2(v, arr);
+ else if (Type === SIMD.Bool64x2) assertEqBool64x2(v, arr);
+ else throw new TypeError("Unknown SIMD kind.");
+}
+
+function assertEqInt32x4(v, arr) {
+ try {
+ for (var i = 0; i < 4; i++)
+ assertEq(SIMD.Int32x4.extractLane(v, i), arr[i]);
+ } catch (e) {
+ print("stack trace:", e.stack);
+ throw e;
+ }
+}
+
+function assertEqUint32x4(v, arr) {
+ try {
+ for (var i = 0; i < 4; i++)
+ assertEq(SIMD.Uint32x4.extractLane(v, i), arr[i]);
+ } catch (e) {
+ print("stack trace:", e.stack);
+ throw e;
+ }
+}
+
+function assertEqFloat32x4(v, arr) {
+ try {
+ for (var i = 0; i < 4; i++)
+ assertEq(SIMD.Float32x4.extractLane(v, i), arr[i]);
+ } catch (e) {
+ print("stack trace:", e.stack);
+ throw e;
+ }
+}
+
+function assertEqBool32x4(v, arr) {
+ try {
+ for (var i = 0; i < 4; i++)
+ assertEq(SIMD.Bool32x4.extractLane(v, i), arr[i]);
+ } catch (e) {
+ print("stack trace:", e.stack);
+ throw e;
+ }
+}
+
+function assertEqX4(v, arr) {
+ var Type = GetType(v);
+ if (Type === SIMD.Int32x4) assertEqInt32x4(v, arr);
+ else if (Type === SIMD.Uint32x4) assertEqUint32x4(v, arr);
+ else if (Type === SIMD.Float32x4) assertEqFloat32x4(v, arr);
+ else if (Type === SIMD.Bool32x4) assertEqBool32x4(v, arr);
+ else throw new TypeError("Unknown SIMD kind.");
+}
+
+function assertEqInt16x8(v, arr) {
+ try {
+ for (var i = 0; i < 8; i++)
+ assertEq(SIMD.Int16x8.extractLane(v, i), arr[i]);
+ } catch (e) {
+ print("stack trace:", e.stack);
+ throw e;
+ }
+}
+
+function assertEqUint16x8(v, arr) {
+ try {
+ for (var i = 0; i < 8; i++)
+ assertEq(SIMD.Uint16x8.extractLane(v, i), arr[i]);
+ } catch (e) {
+ print("stack trace:", e.stack);
+ throw e;
+ }
+}
+
+function assertEqBool16x8(v, arr) {
+ try {
+ for (var i = 0; i < 8; i++){
+ assertEq(SIMD.Bool16x8.extractLane(v, i), arr[i]);
+ }
+ } catch (e) {
+ print("stack trace:", e.stack);
+ throw e;
+ }
+}
+
+function assertEqX8(v, arr) {
+ var Type = GetType(v);
+ if (Type === SIMD.Int16x8) assertEqInt16x8(v, arr);
+ else if (Type === SIMD.Uint16x8) assertEqUint16x8(v, arr);
+ else if (Type === SIMD.Bool16x8) assertEqBool16x8(v, arr);
+ else throw new TypeError("Unknown x8 vector.");
+}
+
+function assertEqInt8x16(v, arr) {
+ try {
+ for (var i = 0; i < 16; i++)
+ assertEq(SIMD.Int8x16.extractLane(v, i), arr[i]);
+ } catch (e) {
+ print("stack trace:", e.stack);
+ throw e;
+ }
+}
+
+function assertEqUint8x16(v, arr) {
+ try {
+ for (var i = 0; i < 16; i++)
+ assertEq(SIMD.Uint8x16.extractLane(v, i), arr[i]);
+ } catch (e) {
+ print("stack trace:", e.stack);
+ throw e;
+ }
+}
+
+function assertEqBool8x16(v, arr) {
+ try {
+ for (var i = 0; i < 16; i++)
+ assertEq(SIMD.Bool8x16.extractLane(v, i), arr[i]);
+ } catch (e) {
+ print("stack trace:", e.stack);
+ throw e;
+ }
+}
+
+function assertEqX16(v, arr) {
+ var Type = GetType(v);
+ if (Type === SIMD.Int8x16) assertEqInt8x16(v, arr);
+ else if (Type === SIMD.Uint8x16) assertEqUint8x16(v, arr);
+ else if (Type === SIMD.Bool8x16) assertEqBool8x16(v, arr);
+ else throw new TypeError("Unknown x16 vector.");
+}
+
+function simdLength(v) {
+ var pt = Object.getPrototypeOf(v);
+ if (pt == SIMD.Int8x16.prototype || pt == SIMD.Uint8x16.prototype ||
+ pt === SIMD.Bool8x16.prototype)
+ return 16;
+ if (pt == SIMD.Int16x8.prototype || pt == SIMD.Uint16x8.prototype ||
+ pt === SIMD.Bool16x8.prototype)
+ return 8;
+ if (pt === SIMD.Int32x4.prototype || pt === SIMD.Uint32x4.prototype ||
+ pt === SIMD.Float32x4.prototype || pt === SIMD.Bool32x4.prototype)
+ return 4;
+ if (pt === SIMD.Float64x2.prototype || pt == SIMD.Bool64x2.prototype)
+ return 2;
+ throw new TypeError("Unknown SIMD kind.");
+}
+
+function simdLengthType(t) {
+ if (t == SIMD.Int8x16 || t == SIMD.Uint8x16 || t == SIMD.Bool8x16)
+ return 16;
+ else if (t == SIMD.Int16x8 || t == SIMD.Uint16x8 || t == SIMD.Bool16x8)
+ return 8;
+ else if (t == SIMD.Int32x4 || t == SIMD.Uint32x4 || t == SIMD.Float32x4 || t == SIMD.Bool32x4)
+ return 4;
+ else if (t == SIMD.Float64x2 || t == SIMD.Bool64x2)
+ return 2;
+ else
+ throw new TypeError("Unknown SIMD kind.");
+}
+
+function getAssertFuncFromLength(l) {
+ if (l == 2)
+ return assertEqX2;
+ else if (l == 4)
+ return assertEqX4;
+ else if (l == 8)
+ return assertEqX8;
+ else if (l == 16)
+ return assertEqX16;
+ else
+ throw new TypeError("Unknown SIMD kind.");
+}
+
+function assertEqVec(v, arr) {
+ var Type = GetType(v);
+ if (Type === SIMD.Int8x16) assertEqInt8x16(v, arr);
+ else if (Type === SIMD.Int16x8) assertEqInt16x8(v, arr);
+ else if (Type === SIMD.Int32x4) assertEqInt32x4(v, arr);
+ else if (Type === SIMD.Uint8x16) assertEqUint8x16(v, arr);
+ else if (Type === SIMD.Uint16x8) assertEqUint16x8(v, arr);
+ else if (Type === SIMD.Uint32x4) assertEqUint32x4(v, arr);
+ else if (Type === SIMD.Float32x4) assertEqFloat32x4(v, arr);
+ else if (Type === SIMD.Float64x2) assertEqFloat64x2(v, arr);
+ else if (Type === SIMD.Bool8x16) assertEqBool8x16(v, arr);
+ else if (Type === SIMD.Bool16x8) assertEqBool16x8(v, arr);
+ else if (Type === SIMD.Bool32x4) assertEqBool32x4(v, arr);
+ else if (Type === SIMD.Bool64x2) assertEqBool64x2(v, arr);
+ else throw new TypeError("Unknown SIMD Kind");
+}
+
+function simdToArray(v) {
+ var Type = GetType(v);
+
+ function indexes(n) {
+ var arr = [];
+ for (var i = 0; i < n; i++) arr.push(i);
+ return arr;
+ }
+
+ if (Type === SIMD.Bool8x16) {
+ return indexes(16).map((i) => SIMD.Bool8x16.extractLane(v, i));
+ }
+
+ if (Type === SIMD.Bool16x8) {
+ return indexes(8).map((i) => SIMD.Bool16x8.extractLane(v, i));
+ }
+
+ if (Type === SIMD.Bool32x4) {
+ return indexes(4).map((i) => SIMD.Bool32x4.extractLane(v, i));
+ }
+
+ if (Type === SIMD.Bool64x2) {
+ return indexes(2).map((i) => SIMD.Bool64x2.extractLane(v, i));
+ }
+
+ if (Type === SIMD.Int8x16) {
+ return indexes(16).map((i) => SIMD.Int8x16.extractLane(v, i));
+ }
+
+ if (Type === SIMD.Int16x8) {
+ return indexes(8).map((i) => SIMD.Int16x8.extractLane(v, i));
+ }
+
+ if (Type === SIMD.Int32x4) {
+ return indexes(4).map((i) => SIMD.Int32x4.extractLane(v, i));
+ }
+
+ if (Type === SIMD.Uint8x16) {
+ return indexes(16).map((i) => SIMD.Uint8x16.extractLane(v, i));
+ }
+
+ if (Type === SIMD.Uint16x8) {
+ return indexes(8).map((i) => SIMD.Uint16x8.extractLane(v, i));
+ }
+
+ if (Type === SIMD.Uint32x4) {
+ return indexes(4).map((i) => SIMD.Uint32x4.extractLane(v, i));
+ }
+
+ if (Type === SIMD.Float32x4) {
+ return indexes(4).map((i) => SIMD.Float32x4.extractLane(v, i));
+ }
+
+ if (Type === SIMD.Float64x2) {
+ return indexes(2).map((i) => SIMD.Float64x2.extractLane(v, i));
+ }
+
+ throw new TypeError("Unknown SIMD Kind");
+}
+
+const INT8_MAX = Math.pow(2, 7) -1;
+const INT8_MIN = -Math.pow(2, 7);
+assertEq((INT8_MAX + 1) << 24 >> 24, INT8_MIN);
+const INT16_MAX = Math.pow(2, 15) - 1;
+const INT16_MIN = -Math.pow(2, 15);
+assertEq((INT16_MAX + 1) << 16 >> 16, INT16_MIN);
+const INT32_MAX = Math.pow(2, 31) - 1;
+const INT32_MIN = -Math.pow(2, 31);
+assertEq(INT32_MAX + 1 | 0, INT32_MIN);
+
+const UINT8_MAX = Math.pow(2, 8) - 1;
+const UINT16_MAX = Math.pow(2, 16) - 1;
+const UINT32_MAX = Math.pow(2, 32) - 1;
+
+function testUnaryFunc(v, simdFunc, func) {
+ var varr = simdToArray(v);
+
+ var observed = simdToArray(simdFunc(v));
+ var expected = varr.map(function(v, i) { return func(varr[i]); });
+
+ for (var i = 0; i < observed.length; i++)
+ assertEq(observed[i], expected[i]);
+}
+
+function testBinaryFunc(v, w, simdFunc, func) {
+ var varr = simdToArray(v);
+ var warr = simdToArray(w);
+
+ var observed = simdToArray(simdFunc(v, w));
+ var expected = varr.map(function(v, i) { return func(varr[i], warr[i]); });
+
+ for (var i = 0; i < observed.length; i++)
+ assertEq(observed[i], expected[i]);
+}
+
+function testBinaryCompare(v, w, simdFunc, func, outType) {
+ var varr = simdToArray(v);
+ var warr = simdToArray(w);
+
+ var inLanes = simdLength(v);
+ var observed = simdToArray(simdFunc(v, w));
+ var outTypeLen = simdLengthType(outType);
+ assertEq(observed.length, outTypeLen);
+ for (var i = 0; i < outTypeLen; i++) {
+ var j = ((i * inLanes) / outTypeLen) | 0;
+ assertEq(observed[i], func(varr[j], warr[j]));
+ }
+}
+
+function testBinaryScalarFunc(v, scalar, simdFunc, func) {
+ var varr = simdToArray(v);
+
+ var observed = simdToArray(simdFunc(v, scalar));
+ var expected = varr.map(function(v, i) { return func(varr[i], scalar); });
+
+ for (var i = 0; i < observed.length; i++)
+ assertEq(observed[i], expected[i]);
+}
+
+// Our array for Int32x4 and Float32x4 will have 16 elements
+const SIZE_8_ARRAY = 64;
+const SIZE_16_ARRAY = 32;
+const SIZE_32_ARRAY = 16;
+const SIZE_64_ARRAY = 8;
+
+const SIZE_BYTES = SIZE_32_ARRAY * 4;
+
+function MakeComparator(kind, arr, shared) {
+ var bpe = arr.BYTES_PER_ELEMENT;
+ var uint8 = (bpe != 1) ? new Uint8Array(arr.buffer) : arr;
+
+ // Size in bytes of a single element in the SIMD vector.
+ var sizeOfLaneElem;
+ // Typed array constructor corresponding to the SIMD kind.
+ var typedArrayCtor;
+ switch (kind) {
+ case 'Int8x16':
+ sizeOfLaneElem = 1;
+ typedArrayCtor = Int8Array;
+ break;
+ case 'Int16x8':
+ sizeOfLaneElem = 2;
+ typedArrayCtor = Int16Array;
+ break;
+ case 'Int32x4':
+ sizeOfLaneElem = 4;
+ typedArrayCtor = Int32Array;
+ break;
+ case 'Uint8x16':
+ sizeOfLaneElem = 1;
+ typedArrayCtor = Uint8Array;
+ break;
+ case 'Uint16x8':
+ sizeOfLaneElem = 2;
+ typedArrayCtor = Uint16Array;
+ break;
+ case 'Uint32x4':
+ sizeOfLaneElem = 4;
+ typedArrayCtor = Uint32Array;
+ break;
+ case 'Float32x4':
+ sizeOfLaneElem = 4;
+ typedArrayCtor = Float32Array;
+ break;
+ case 'Float64x2':
+ sizeOfLaneElem = 8;
+ typedArrayCtor = Float64Array;
+ break;
+ default:
+ assertEq(true, false, "unknown SIMD kind");
+ }
+ var lanes = 16 / sizeOfLaneElem;
+ // Reads (numElemToRead * sizeOfLaneElem) bytes in arr, and reinterprets
+ // these bytes as a typed array equivalent to the typed SIMD vector.
+ var slice = function(start, numElemToRead) {
+ // Read enough bytes
+ var startBytes = start * bpe;
+ var endBytes = startBytes + numElemToRead * sizeOfLaneElem;
+ var asArray = Array.prototype.slice.call(uint8, startBytes, endBytes);
+
+ // If length is less than SIZE_BYTES bytes, fill with 0.
+ // This is needed for load1, load2, load3 which do only partial
+ // reads.
+ for (var i = asArray.length; i < SIZE_BYTES; i++) asArray[i] = 0;
+ assertEq(asArray.length, SIZE_BYTES);
+
+ return new typedArrayCtor(new Uint8Array(asArray).buffer);
+ }
+
+ var assertFunc = getAssertFuncFromLength(lanes);
+ var type = SIMD[kind];
+ return {
+ load1: function(index) {
+ if (lanes >= 8) // Int8x16 and Int16x8 only support load, no load1/load2/etc.
+ return
+ var v = type.load1(arr, index);
+ assertFunc(v, slice(index, 1));
+ },
+
+ load2: function(index) {
+ if (lanes !== 4)
+ return;
+ var v = type.load2(arr, index);
+ assertFunc(v, slice(index, 2));
+ },
+
+ load3: function(index) {
+ if (lanes !== 4)
+ return;
+ var v = type.load3(arr, index);
+ assertFunc(v, slice(index, 3));
+ },
+
+ load: function(index) {
+ var v = type.load(arr, index);
+ assertFunc(v, slice(index, lanes));
+ }
+ }
+}
+
+function testLoad(kind, TA) {
+ var lanes = TA.length / 4;
+ for (var i = TA.length; i--;)
+ TA[i] = i;
+
+ for (var ta of [
+ new Uint8Array(TA.buffer),
+ new Int8Array(TA.buffer),
+ new Uint16Array(TA.buffer),
+ new Int16Array(TA.buffer),
+ new Uint32Array(TA.buffer),
+ new Int32Array(TA.buffer),
+ new Float32Array(TA.buffer),
+ new Float64Array(TA.buffer)
+ ])
+ {
+ // Invalid args
+ assertThrowsInstanceOf(() => SIMD[kind].load(), TypeError);
+ assertThrowsInstanceOf(() => SIMD[kind].load(ta), TypeError);
+ assertThrowsInstanceOf(() => SIMD[kind].load("hello", 0), TypeError);
+ // Indexes must be integers, there is no rounding.
+ assertThrowsInstanceOf(() => SIMD[kind].load(ta, 1.5), RangeError);
+ assertThrowsInstanceOf(() => SIMD[kind].load(ta, -1), RangeError);
+ assertThrowsInstanceOf(() => SIMD[kind].load(ta, "hello"), RangeError);
+ assertThrowsInstanceOf(() => SIMD[kind].load(ta, NaN), RangeError);
+ // Try to trip up the bounds checking. Int32 is enough for everybody.
+ assertThrowsInstanceOf(() => SIMD[kind].load(ta, 0x100000000), RangeError);
+ assertThrowsInstanceOf(() => SIMD[kind].load(ta, 0x80000000), RangeError);
+ assertThrowsInstanceOf(() => SIMD[kind].load(ta, 0x40000000), RangeError);
+ assertThrowsInstanceOf(() => SIMD[kind].load(ta, 0x20000000), RangeError);
+ assertThrowsInstanceOf(() => SIMD[kind].load(ta, (1<<30) * (1<<23) - 1), RangeError);
+ assertThrowsInstanceOf(() => SIMD[kind].load(ta, (1<<30) * (1<<23)), RangeError);
+
+ // Valid and invalid reads
+ var C = MakeComparator(kind, ta);
+ var bpe = ta.BYTES_PER_ELEMENT;
+
+ var lastValidArgLoad1 = (SIZE_BYTES - (16 / lanes)) / bpe | 0;
+ var lastValidArgLoad2 = (SIZE_BYTES - 8) / bpe | 0;
+ var lastValidArgLoad3 = (SIZE_BYTES - 12) / bpe | 0;
+ var lastValidArgLoad = (SIZE_BYTES - 16) / bpe | 0;
+
+ C.load(0);
+ C.load(1);
+ C.load(2);
+ C.load(3);
+ C.load(lastValidArgLoad);
+
+ C.load1(0);
+ C.load1(1);
+ C.load1(2);
+ C.load1(3);
+ C.load1(lastValidArgLoad1);
+
+ C.load2(0);
+ C.load2(1);
+ C.load2(2);
+ C.load2(3);
+ C.load2(lastValidArgLoad2);
+
+ C.load3(0);
+ C.load3(1);
+ C.load3(2);
+ C.load3(3);
+ C.load3(lastValidArgLoad3);
+
+ assertThrowsInstanceOf(() => SIMD[kind].load(ta, lastValidArgLoad + 1), RangeError);
+ if (lanes <= 4) {
+ assertThrowsInstanceOf(() => SIMD[kind].load1(ta, lastValidArgLoad1 + 1), RangeError);
+ }
+ if (lanes == 4) {
+ assertThrowsInstanceOf(() => SIMD[kind].load2(ta, lastValidArgLoad2 + 1), RangeError);
+ assertThrowsInstanceOf(() => SIMD[kind].load3(ta, lastValidArgLoad3 + 1), RangeError);
+ }
+
+ // Indexes are coerced with ToNumber. Try some strings that
+ // CanonicalNumericIndexString() would reject.
+ C.load("1.0e0");
+ C.load(" 2");
+ }
+
+ if (lanes == 4) {
+ // Test ToNumber behavior.
+ var obj = {
+ valueOf: function() { return 12 }
+ }
+ var v = SIMD[kind].load(TA, obj);
+ assertEqX4(v, [12, 13, 14, 15]);
+ }
+
+ var obj = {
+ valueOf: function() { throw new TypeError("i ain't a number"); }
+ }
+ assertThrowsInstanceOf(() => SIMD[kind].load(TA, obj), TypeError);
+}
+
+var Helpers = {
+ testLoad,
+ MakeComparator
+};