From d8781fab296f028c5d2456a3763987c619d06bcf Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Tue, 3 Feb 2015 20:37:05 +0100 Subject: [PATCH] Bug 1123777: Have SIMD shifts + splat + with functions apply ToInt32 to their scalar arguments; r=till --HG-- extra : rebase_source : 9d7aa748738c8ec1a13ac53d15946a5c8665c956 --- js/src/builtin/SIMD.cpp | 29 +++----- js/src/builtin/SIMD.h | 8 +- js/src/tests/ecma_7/SIMD/float32x4with.js | 91 ----------------------- js/src/tests/ecma_7/SIMD/float64x2with.js | 36 --------- js/src/tests/ecma_7/SIMD/int32x4with.js | 28 ------- js/src/tests/ecma_7/SIMD/shifts.js | 14 ++++ js/src/tests/ecma_7/SIMD/splat.js | 38 ++++++++++ js/src/tests/ecma_7/SIMD/with.js | 90 ++++++++++++++++++++++ 8 files changed, 157 insertions(+), 177 deletions(-) delete mode 100644 js/src/tests/ecma_7/SIMD/float32x4with.js delete mode 100644 js/src/tests/ecma_7/SIMD/float64x2with.js delete mode 100644 js/src/tests/ecma_7/SIMD/int32x4with.js create mode 100644 js/src/tests/ecma_7/SIMD/splat.js create mode 100644 js/src/tests/ecma_7/SIMD/with.js diff --git a/js/src/builtin/SIMD.cpp b/js/src/builtin/SIMD.cpp index b82578119aa1..550c317f19e2 100644 --- a/js/src/builtin/SIMD.cpp +++ b/js/src/builtin/SIMD.cpp @@ -722,27 +722,18 @@ FuncWith(JSContext *cx, unsigned argc, Value *vp) typedef typename V::Elem Elem; CallArgs args = CallArgsFromVp(argc, vp); - if (args.length() != 2 || !IsVectorObject(args[0]) || - (!args[1].isNumber() && !args[1].isBoolean())) - { + if (args.length() != 2 || !IsVectorObject(args[0])) return ErrorBadArgs(cx); - } - Elem *val = TypedObjectMemory(args[0]); + Elem *vec = TypedObjectMemory(args[0]); Elem result[V::lanes]; - if (args[1].isNumber()) { - Elem withAsNumber; - if (!V::toType(cx, args[1], &withAsNumber)) - return false; - for (unsigned i = 0; i < V::lanes; i++) - result[i] = OpWith::apply(i, withAsNumber, val[i]); - } else { - MOZ_ASSERT(args[1].isBoolean()); - bool withAsBool = args[1].toBoolean(); - for (unsigned i = 0; i < V::lanes; i++) - result[i] = OpWith::apply(i, withAsBool, val[i]); - } + Elem value; + if (!V::toType(cx, args[1], &value)) + return false; + + for (unsigned i = 0; i < V::lanes; i++) + result[i] = OpWith::apply(i, value, vec[i]); return StoreResult(cx, args, result); } @@ -816,7 +807,7 @@ Int32x4BinaryScalar(JSContext *cx, unsigned argc, Value *vp) return ErrorBadArgs(cx); int32_t result[4]; - if (!IsVectorObject(args[0]) || !args[1].isNumber()) + if (!IsVectorObject(args[0])) return ErrorBadArgs(cx); int32_t *val = TypedObjectMemory(args[0]); @@ -911,7 +902,7 @@ FuncSplat(JSContext *cx, unsigned argc, Value *vp) typedef typename Vret::Elem RetElem; CallArgs args = CallArgsFromVp(argc, vp); - if (args.length() != 1 || !args[0].isNumber()) + if (args.length() != 1) return ErrorBadArgs(cx); RetElem arg; diff --git a/js/src/builtin/SIMD.h b/js/src/builtin/SIMD.h index 239f4591ce6a..3f666d7d2897 100644 --- a/js/src/builtin/SIMD.h +++ b/js/src/builtin/SIMD.h @@ -273,7 +273,10 @@ struct Float32x4 { return a; } static bool toType(JSContext *cx, JS::HandleValue v, Elem *out) { - *out = v.toNumber(); + double d; + if (!ToNumber(cx, v, &d)) + return false; + *out = float(d); return true; } static void setReturn(CallArgs &args, Elem value) { @@ -293,8 +296,7 @@ struct Float64x2 { return a; } static bool toType(JSContext *cx, JS::HandleValue v, Elem *out) { - *out = v.toNumber(); - return true; + return ToNumber(cx, v, out); } static void setReturn(CallArgs &args, Elem value) { args.rval().setDouble(JS::CanonicalizeNaN(value)); diff --git a/js/src/tests/ecma_7/SIMD/float32x4with.js b/js/src/tests/ecma_7/SIMD/float32x4with.js deleted file mode 100644 index 24a2bda54d9e..000000000000 --- a/js/src/tests/ecma_7/SIMD/float32x4with.js +++ /dev/null @@ -1,91 +0,0 @@ -// |reftest| skip-if(!this.hasOwnProperty("SIMD")) -var BUGNUMBER = 946042; -var float32x4 = SIMD.float32x4; -var int32x4 = SIMD.int32x4; - -var summary = 'float32x4 with'; - -function test() { - print(BUGNUMBER + ": " + summary); - - var a = float32x4(1, 2, 3, 4); - var x = SIMD.float32x4.withX(a, 5); - var y = SIMD.float32x4.withY(a, 5); - var z = SIMD.float32x4.withZ(a, 5); - var w = SIMD.float32x4.withW(a, 5); - assertEq(x.x, 5); - assertEq(x.y, 2); - assertEq(x.z, 3); - assertEq(x.w, 4); - - assertEq(y.x, 1); - assertEq(y.y, 5); - assertEq(y.z, 3); - assertEq(y.w, 4); - - assertEq(z.x, 1); - assertEq(z.y, 2); - assertEq(z.z, 5); - assertEq(z.w, 4); - - assertEq(w.x, 1); - assertEq(w.y, 2); - assertEq(w.z, 3); - assertEq(w.w, 5); - - var b = float32x4(1.87, 2.08, 3.84, 4.17); - var x1 = SIMD.float32x4.withX(b, 5.38); - var y1 = SIMD.float32x4.withY(b, 5.19); - var z1 = SIMD.float32x4.withZ(b, 5.11); - var w1 = SIMD.float32x4.withW(b, 5.07); - assertEq(x1.x, Math.fround(5.38)); - assertEq(x1.y, Math.fround(2.08)); - assertEq(x1.z, Math.fround(3.84)); - assertEq(x1.w, Math.fround(4.17)); - - assertEq(y1.x, Math.fround(1.87)); - assertEq(y1.y, Math.fround(5.19)); - assertEq(y1.z, Math.fround(3.84)); - assertEq(y1.w, Math.fround(4.17)); - - assertEq(z1.x, Math.fround(1.87)); - assertEq(z1.y, Math.fround(2.08)); - assertEq(z1.z, Math.fround(5.11)); - assertEq(z1.w, Math.fround(4.17)); - - assertEq(w1.x, Math.fround(1.87)); - assertEq(w1.y, Math.fround(2.08)); - assertEq(w1.z, Math.fround(3.84)); - assertEq(w1.w, Math.fround(5.07)); - - var c = float32x4(NaN, -0, Infinity, -Infinity); - var x2 = SIMD.float32x4.withX(c, 0); - var y2 = SIMD.float32x4.withY(c, 0); - var z2 = SIMD.float32x4.withZ(c, 0); - var w2 = SIMD.float32x4.withW(c, 0); - assertEq(x2.x, 0); - assertEq(x2.y, -0); - assertEq(x2.z, Infinity); - assertEq(x2.w, -Infinity); - - assertEq(y2.x, NaN); - assertEq(y2.y, 0); - assertEq(y2.z, Infinity); - assertEq(y2.w, -Infinity); - - assertEq(z2.x, NaN); - assertEq(z2.y, -0); - assertEq(z2.z, 0); - assertEq(z2.w, -Infinity); - - assertEq(w2.x, NaN); - assertEq(w2.y, -0); - assertEq(w2.z, Infinity); - assertEq(w2.w, 0); - - if (typeof reportCompare === "function") - reportCompare(true, true); -} - -test(); - diff --git a/js/src/tests/ecma_7/SIMD/float64x2with.js b/js/src/tests/ecma_7/SIMD/float64x2with.js deleted file mode 100644 index e188d6a4d427..000000000000 --- a/js/src/tests/ecma_7/SIMD/float64x2with.js +++ /dev/null @@ -1,36 +0,0 @@ -// |reftest| skip-if(!this.hasOwnProperty("SIMD")) -var BUGNUMBER = 1031203; -var float64x2 = SIMD.float64x2; - -var summary = 'float64x2 with'; - -/* - * Any copyright is dedicated to the Public Domain. - * https://creativecommons.org/publicdomain/zero/1.0/ - */ - -function test() { - print(BUGNUMBER + ": " + summary); - - var a = float64x2(1, 2); - var x = float64x2.withX(a, 5); - var y = float64x2.withY(a, 5); - assertEq(x.x, 5); - assertEq(x.y, 2); - assertEq(y.x, 1); - assertEq(y.y, 5); - - var b = float64x2(NaN, -0); - var x1 = float64x2.withX(b, Infinity); - var y1 = float64x2.withY(b, -Infinity); - assertEq(x1.x, Infinity); - assertEq(x1.y, -0); - assertEq(y1.x, NaN); - assertEq(y1.y, -Infinity); - - if (typeof reportCompare === "function") - reportCompare(true, true); -} - -test(); - diff --git a/js/src/tests/ecma_7/SIMD/int32x4with.js b/js/src/tests/ecma_7/SIMD/int32x4with.js deleted file mode 100644 index ccfa9babd9ab..000000000000 --- a/js/src/tests/ecma_7/SIMD/int32x4with.js +++ /dev/null @@ -1,28 +0,0 @@ -// |reftest| skip-if(!this.hasOwnProperty("SIMD")) -var BUGNUMBER = 946042; -var float32x4 = SIMD.float32x4; -var int32x4 = SIMD.int32x4; - -var summary = 'int32x4 with'; - -function test() { - print(BUGNUMBER + ": " + summary); - - var INT32_MAX = Math.pow(2, 31) - 1; - - var a = int32x4(1, 2, 3, 4); - var x = SIMD.int32x4.withX(a, 5); - var y = SIMD.int32x4.withY(a, 5); - var z = SIMD.int32x4.withZ(a, 5); - var w = SIMD.int32x4.withW(a, INT32_MAX + 1); - assertEq(x.x, 5); - assertEq(y.y, 5); - assertEq(z.z, 5); - assertEq(w.w, (INT32_MAX + 1) | 0); - - if (typeof reportCompare === "function") - reportCompare(true, true); -} - -test(); - diff --git a/js/src/tests/ecma_7/SIMD/shifts.js b/js/src/tests/ecma_7/SIMD/shifts.js index cf45a97ba9c0..e4d1925e3e30 100644 --- a/js/src/tests/ecma_7/SIMD/shifts.js +++ b/js/src/tests/ecma_7/SIMD/shifts.js @@ -18,6 +18,11 @@ function ursh(a, b) { } function test() { + function TestError() {}; + + var good = {valueOf: () => 21}; + var bad = {valueOf: () => {throw new TestError(); }}; + for (var v of [ int32x4(-1, 2, -3, 4), int32x4(INT32_MAX, INT32_MIN, INT32_MAX - 1, INT32_MIN + 1) @@ -28,8 +33,17 @@ function test() { testBinaryScalarFunc(v, bits, int32x4.shiftRightArithmeticByScalar, rsh); testBinaryScalarFunc(v, bits, int32x4.shiftRightLogicalByScalar, ursh); } + // Test that the shift count is coerced to an int32. + testBinaryScalarFunc(v, undefined, int32x4.shiftLeftByScalar, lsh); + testBinaryScalarFunc(v, 3.5, int32x4.shiftLeftByScalar, lsh); + testBinaryScalarFunc(v, good, int32x4.shiftLeftByScalar, lsh); } + var v = SIMD.int32x4(1,2,3,4); + assertThrowsInstanceOf(() => SIMD.int32x4.shiftLeftByScalar(v, bad), TestError); + assertThrowsInstanceOf(() => SIMD.int32x4.shiftRightArithmeticByScalar(v, bad), TestError); + assertThrowsInstanceOf(() => SIMD.int32x4.shiftRightLogicalByScalar(v, bad), TestError); + if (typeof reportCompare === "function") reportCompare(true, true); } diff --git a/js/src/tests/ecma_7/SIMD/splat.js b/js/src/tests/ecma_7/SIMD/splat.js new file mode 100644 index 000000000000..730e0420623d --- /dev/null +++ b/js/src/tests/ecma_7/SIMD/splat.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty("SIMD")) + +var float64x2 = SIMD.float64x2; +var float32x4 = SIMD.float32x4; +var int32x4 = SIMD.int32x4; + +function TestSplatX4(type, inputs, coerceFunc) { + for (var x of inputs) { + assertEqX4(SIMD[type].splat(x), [x, x, x, x].map(coerceFunc)); + } +} + +function TestSplatX2(type, inputs, coerceFunc) { + for (var x of inputs) { + assertEqX2(SIMD[type].splat(x), [x, x].map(coerceFunc)); + } +} + +function test() { + function TestError(){}; + + var good = {valueOf: () => 19.89}; + var bad = {valueOf: () => { throw new TestError(); }}; + + TestSplatX4('int32x4', [0, undefined, 3.5, 42, -1337, INT32_MAX, INT32_MAX + 1, good], (x) => x | 0); + assertThrowsInstanceOf(() => SIMD.int32x4.splat(bad), TestError); + + TestSplatX4('float32x4', [0, undefined, 3.5, 42, -13.37, Infinity, NaN, -0, good], (x) => Math.fround(x)); + assertThrowsInstanceOf(() => SIMD.float32x4.splat(bad), TestError); + + TestSplatX2('float64x2', [0, undefined, 3.5, 42, -13.37, Infinity, NaN, -0, good], (x) => +x); + assertThrowsInstanceOf(() => SIMD.float64x2.splat(bad), TestError); + + if (typeof reportCompare === "function") + reportCompare(true, true); +} + +test(); diff --git a/js/src/tests/ecma_7/SIMD/with.js b/js/src/tests/ecma_7/SIMD/with.js new file mode 100644 index 000000000000..4316e9f96a2b --- /dev/null +++ b/js/src/tests/ecma_7/SIMD/with.js @@ -0,0 +1,90 @@ +// |reftest| skip-if(!this.hasOwnProperty("SIMD")) +var BUGNUMBER = 946042; +var float32x4 = SIMD.float32x4; +var int32x4 = SIMD.int32x4; +var float64x2 = SIMD.float64x2; + +var summary = 'with{X,Y,Z,W}'; + +function withX(arr, x) { + if (arr.length == 2) + return [x, arr[1]]; + return [x, arr[1], arr[2], arr[3]]; +} +function withY(arr, x) { + if (arr.length == 2) + return [arr[0], x]; + return [arr[0], x, arr[2], arr[3]]; +} +function withZ(arr, x) { + return [arr[0], arr[1], x, arr[3]]; +} +function withW(arr, x) { + return [arr[0], arr[1], arr[2], x]; +} + +function testWith(vec, scalar, simdFunc, func) { + var varr = simdToArray(vec); + var observed = simdToArray(simdFunc(vec, scalar)); + var expected = func(varr, scalar); + for (var i = 0; i < observed.length; i++) + assertEq(observed[i], expected[i]); +} + +function test() { + print(BUGNUMBER + ": " + summary); + + function testType(type, inputs) { + var length = simdToArray(inputs[0][0]).length; + for (var [vec, s] of inputs) { + testWith(vec, s, SIMD[type].withX, withX); + testWith(vec, s, SIMD[type].withY, withY); + if (length <= 2) + continue; + testWith(vec, s, SIMD[type].withZ, withZ); + testWith(vec, s, SIMD[type].withW, withW); + } + } + + function TestError(){}; + var good = {valueOf: () => 42}; + var bad = {valueOf: () => {throw new TestError(); }}; + + var float32x4inputs = [ + [float32x4(1, 2, 3, 4), 5], + [float32x4(1.87, 2.08, 3.84, 4.17), Math.fround(13.37)], + [float32x4(NaN, -0, Infinity, -Infinity), 0] + ]; + testType('float32x4', float32x4inputs); + + var v = float32x4inputs[1][0]; + assertEqX4(float32x4.withX(v, good), withX(simdToArray(v), good | 0)); + assertThrowsInstanceOf(() => float32x4.withX(v, bad), TestError); + + var float64x2inputs = [ + [float64x2(1, 2), 5], + [float64x2(1.87, 2.08), Math.fround(13.37)], + [float64x2(NaN, -0), 0] + ]; + testType('float64x2', float64x2inputs); + + var v = float64x2inputs[1][0]; + assertEqX4(float64x2.withX(v, good), withX(simdToArray(v), good | 0)); + assertThrowsInstanceOf(() => float64x2.withX(v, bad), TestError); + + var int32x4inputs = [ + [int32x4(1, 2, 3, 4), 5], + [int32x4(INT32_MIN, INT32_MAX, 3, 4), INT32_MIN], + ]; + testType('int32x4', int32x4inputs); + + var v = int32x4inputs[1][0]; + assertEqX4(int32x4.withX(v, good), withX(simdToArray(v), good | 0)); + assertThrowsInstanceOf(() => int32x4.withX(v, bad), TestError); + + if (typeof reportCompare === "function") + reportCompare(true, true); +} + +test(); +