Bug 1135039: Throw on non-int32 or out-of-bounds lanes arguments to swizzle/shuffle; r=sunfish
authorBenjamin Bouvier <benj@benj.me>
Thu, 05 Mar 2015 11:55:10 +0100
changeset 233932 36be55e9a4ff3852a506bfb8c8aeb83c1492d2b7
parent 233931 f017644da2e27af4ab3941acf03b4e9f5e94013f
child 233933 6a42e09d9a26440640e40ac96aadbe8b4bb32cf8
push id28426
push usercbook@mozilla.com
push dateTue, 17 Mar 2015 10:46:54 +0000
treeherdermozilla-central@008b3f65a7e0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssunfish
bugs1135039
milestone39.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 1135039: Throw on non-int32 or out-of-bounds lanes arguments to swizzle/shuffle; r=sunfish
js/src/builtin/SIMD.cpp
js/src/tests/ecma_7/SIMD/swizzle-shuffle.js
--- a/js/src/builtin/SIMD.cpp
+++ b/js/src/builtin/SIMD.cpp
@@ -743,19 +743,19 @@ Swizzle(JSContext *cx, unsigned argc, Va
     typedef typename V::Elem Elem;
 
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.length() != (V::lanes + 1) || !IsVectorObject<V>(args[0]))
         return ErrorBadArgs(cx);
 
     uint32_t lanes[V::lanes];
     for (unsigned i = 0; i < V::lanes; i++) {
-        int32_t lane = -1;
-        if (!ToInt32(cx, args[i + 1], &lane))
-            return false;
+        if (!args[i + 1].isInt32())
+            return ErrorBadArgs(cx);
+        int32_t lane = args[i + 1].toInt32();
         if (lane < 0 || uint32_t(lane) >= V::lanes)
             return ErrorBadArgs(cx);
         lanes[i] = uint32_t(lane);
     }
 
     Elem *val = TypedObjectMemory<Elem *>(args[0]);
 
     Elem result[V::lanes];
@@ -772,19 +772,19 @@ Shuffle(JSContext *cx, unsigned argc, Va
     typedef typename V::Elem Elem;
 
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.length() != (V::lanes + 2) || !IsVectorObject<V>(args[0]) || !IsVectorObject<V>(args[1]))
         return ErrorBadArgs(cx);
 
     uint32_t lanes[V::lanes];
     for (unsigned i = 0; i < V::lanes; i++) {
-        int32_t lane = -1;
-        if (!ToInt32(cx, args[i + 2], &lane))
-            return false;
+        if (!args[i + 2].isInt32())
+            return ErrorBadArgs(cx);
+        int32_t lane = args[i + 2].toInt32();
         if (lane < 0 || uint32_t(lane) >= (2 * V::lanes))
             return ErrorBadArgs(cx);
         lanes[i] = uint32_t(lane);
     }
 
     Elem *lhs = TypedObjectMemory<Elem *>(args[0]);
     Elem *rhs = TypedObjectMemory<Elem *>(args[1]);
 
--- a/js/src/tests/ecma_7/SIMD/swizzle-shuffle.js
+++ b/js/src/tests/ecma_7/SIMD/swizzle-shuffle.js
@@ -30,62 +30,62 @@ function getNumberOfLanesFromType(type) 
 
 function testSwizzleForType(type) {
     var lanes = getNumberOfLanesFromType(type);
     var v = lanes == 4 ? type(1, 2, 3, 4) : type(1, 2);
 
     assertThrowsInstanceOf(() => type.swizzle()               , TypeError);
     assertThrowsInstanceOf(() => type.swizzle(v, 0)           , TypeError);
     assertThrowsInstanceOf(() => type.swizzle(v, 0, 1, 2)     , TypeError);
-    assertThrowsInstanceOf(() => type.swizzle(v, 0, 1, 2, 4)  , TypeError);
-    assertThrowsInstanceOf(() => type.swizzle(v, 0, 1, 2, -1) , TypeError);
     assertThrowsInstanceOf(() => type.swizzle(0, 1, 2, 3, v)  , TypeError);
 
-    if (lanes == 2) {
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, -1)   , TypeError);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 2)    , TypeError);
-    } else {
-        assertEq(lanes, 4);
-        assertThrowsInstanceOf(() => type.swizzle(v, 0, 1), TypeError);
-    }
-
     // Test all possible swizzles.
     if (lanes == 4) {
         var x, y, z, w;
         for (var i = 0; i < Math.pow(4, 4); i++) {
             [x, y, z, w] = [i & 3, (i >> 2) & 3, (i >> 4) & 3, (i >> 6) & 3];
             assertEqVec(type.swizzle(v, x, y, z, w), swizzle4(simdToArray(v), x, y, z, w));
         }
     } else {
         assertEq(lanes, 2);
         var x, y;
         for (var i = 0; i < Math.pow(2, 2); i++) {
           [x, y] = [x & 1, (y >> 1) & 1];
           assertEqVec(type.swizzle(v, x, y), swizzle2(simdToArray(v), x, y));
         }
     }
 
-    // Test that the lane inputs are converted into an int32.
-    // n.b, order of evaluation of args is left-to-right.
-    var obj = {
-        x: 0,
-        valueOf: function() { return this.x++ }
-    };
+    // Test that we throw if an lane argument isn't an int32 or isn't in bounds.
     if (lanes == 4) {
-        assertEqVec(type.swizzle(v, obj, obj, obj, obj), swizzle4(simdToArray(v), 0, 1, 2, 3));
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 0.5), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, {}), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, {valueOf: function(){return 42}}), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, "one"), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, null), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, undefined), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, true), TypeError);
+
+        // In bounds is [0, 3]
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, -1), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0, 0, 4), TypeError);
     } else {
         assertEq(lanes, 2);
-        assertEqVec(type.swizzle(v, obj, obj), swizzle2(simdToArray(v), 0, 1));
-    }
 
-    // Object for which ToInt32 will fail.
-    obj = {
-        valueOf: function() { throw new Error; }
-    };
-    assertThrowsInstanceOf(() => type.swizzle(v, 0, 1, 2, obj), Error);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 0.5), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, {}), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, {valueOf: function(){return 42}}), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, "one"), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, null), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, undefined), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, true), TypeError);
+
+        // In bounds is [0, 1]
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, -1), TypeError);
+        assertThrowsInstanceOf(() => type.swizzle(v, 0, 2), TypeError);
+    }
 }
 
 function testSwizzleInt32x4() {
     var v = int32x4(1, 2, 3, 4);
 
     assertThrowsInstanceOf(function() {
         float32x4.swizzle(v, 0, 0, 0, 0);
     }, TypeError);
@@ -105,17 +105,17 @@ function testSwizzleFloat32x4() {
 
 function testSwizzleFloat64x2() {
     var v = float64x2(1, 2);
 
     assertThrowsInstanceOf(function() {
         float32x4.swizzle(v, 0, 0, 0, 0);
     }, TypeError);
 
-   testSwizzleForType(float64x2);
+    testSwizzleForType(float64x2);
 }
 
 function shuffle2(lhsa, rhsa, x, y) {
     return [(x < 2 ? lhsa : rhsa)[x % 2],
             (y < 2 ? lhsa : rhsa)[y % 2]];
 }
 function shuffle4(lhsa, rhsa, x, y, z, w) {
     return [(x < 4 ? lhsa : rhsa)[x % 4],
@@ -135,28 +135,18 @@ function testShuffleForType(type) {
         lhs = type(1, 2);
         rhs = type(3, 4);
     }
 
     assertThrowsInstanceOf(() => type.shuffle(lhs)                   , TypeError);
     assertThrowsInstanceOf(() => type.shuffle(lhs, rhs)              , TypeError);
     assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0)           , TypeError);
     assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 1, 2)     , TypeError);
-    assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 1, 2, -1) , TypeError);
-    assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 1, 2, 8)  , TypeError);
     assertThrowsInstanceOf(() => type.shuffle(lhs, 0, 1, 2, 7, rhs)  , TypeError);
 
-    if (lanes == 2) {
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 4)    , TypeError);
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, -1)   , TypeError);
-    } else {
-        assertEq(lanes, 4);
-        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 1) , TypeError);
-    }
-
     // Test all possible shuffles.
     var x, y, z, w;
     if (lanes == 4) {
         var x, y, z, w;
         for (var i = 0; i < Math.pow(8, 4); i++) {
             [x, y, z, w] = [i & 7, (i >> 3) & 7, (i >> 6) & 7, (i >> 9) & 7];
             assertEqVec(type.shuffle(lhs, rhs, x, y, z, w),
                         shuffle4(simdToArray(lhs), simdToArray(rhs), x, y, z, w));
@@ -166,36 +156,44 @@ function testShuffleForType(type) {
         var x, y;
         for (var i = 0; i < Math.pow(4, 2); i++) {
             [x, y] = [i & 3, (i >> 3) & 3];
             assertEqVec(type.shuffle(lhs, rhs, x, y),
                         shuffle2(simdToArray(lhs), simdToArray(rhs), x, y));
         }
     }
 
-    // Test that the lane inputs are converted into an int32.
-    // n.b, order of evaluation of args is left-to-right.
-    var obj = {
-        x: 0,
-        valueOf: function() { return this.x++ }
-    };
+    // Test that we throw if an lane argument isn't an int32 or isn't in bounds.
     if (lanes == 4) {
-        assertEqVec(type.shuffle(lhs, rhs, obj, obj, obj, obj),
-                    shuffle4(simdToArray(lhs), simdToArray(rhs), 0, 1, 2, 3));
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 0.5), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, {}), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, {valueOf: function(){return 42}}), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, "one"), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, null), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, undefined), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, true), TypeError);
+
+        // In bounds is [0, 7]
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, -1), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0, 0, 8), TypeError);
     } else {
         assertEq(lanes, 2);
-        assertEqVec(type.shuffle(lhs, rhs, obj, obj),
-                    shuffle2(simdToArray(lhs), simdToArray(rhs), 0, 1));
-    }
 
-    // Object for which ToInt32 will fail.
-    obj = {
-        valueOf: function() { throw new Error; }
-    };
-    assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 1, 2, obj), Error);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 0.5), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, {}), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, {valueOf: function(){return 42}}), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, "one"), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, null), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, undefined), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, true), TypeError);
+
+        // In bounds is [0, 3]
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, -1), TypeError);
+        assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 4), TypeError);
+    }
 }
 
 function testShuffleInt32x4() {
     var v = int32x4(1, 2, 3, 4);
 
     assertThrowsInstanceOf(function() {
         float32x4.shuffle(v, v, 0, 0, 0, 0);
     }, TypeError);