Bug 1061229: Implement SIMD coercive calls; r=h4writer
authorBenjamin Bouvier <benj@benj.me>
Tue, 02 Sep 2014 12:23:06 +0200
changeset 202974 2cd12da0c4e6f60f53236eb4cc4061bebc892777
parent 202973 9678f9a596d851eb3f8e1dd6ccb07015c12dc332
child 202975 0a76964b8d8dc4f4e06748335731c1f02e8711e1
push id48536
push userbenj@benj.me
push dateTue, 02 Sep 2014 10:24:24 +0000
treeherdermozilla-inbound@2cd12da0c4e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersh4writer
bugs1061229
milestone34.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 1061229: Implement SIMD coercive calls; r=h4writer
js/src/builtin/SIMD.cpp
js/src/tests/ecma_6/TypedObject/simd/coercions.js
--- a/js/src/builtin/SIMD.cpp
+++ b/js/src/builtin/SIMD.cpp
@@ -33,32 +33,38 @@ extern const JSFunctionSpec Float32x4Met
 extern const JSFunctionSpec Int32x4Methods[];
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // X4
 
 static const char *laneNames[] = {"lane 0", "lane 1", "lane 2", "lane3"};
 
-template<typename V>
-bool
-js::IsVectorObject(HandleValue v)
+static bool
+CheckVectorObject(HandleValue v, X4TypeDescr::Type expectedType)
 {
     if (!v.isObject())
         return false;
 
     JSObject &obj = v.toObject();
     if (!obj.is<TypedObject>())
         return false;
 
     TypeDescr &typeRepr = obj.as<TypedObject>().typeDescr();
     if (typeRepr.kind() != type::X4)
         return false;
 
-    return typeRepr.as<X4TypeDescr>().type() == V::type;
+    return typeRepr.as<X4TypeDescr>().type() == expectedType;
+}
+
+template<class V>
+bool
+js::IsVectorObject(HandleValue v)
+{
+    return CheckVectorObject(v, V::type);
 }
 
 template bool js::IsVectorObject<Int32x4>(HandleValue v);
 template bool js::IsVectorObject<Float32x4>(HandleValue v);
 
 template<typename V>
 bool
 js::ToSimdConstant(JSContext *cx, HandleValue v, jit::SimdConstant *out)
@@ -295,29 +301,40 @@ CreateX4Class(JSContext *cx,
 }
 
 bool
 X4TypeDescr::call(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     const unsigned LANES = 4;
 
+    Rooted<X4TypeDescr*> descr(cx, &args.callee().as<X4TypeDescr>());
+    if (args.length() == 1) {
+        // X4 type used as a coercion
+        if (!CheckVectorObject(args[0], descr->type())) {
+            JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SIMD_NOT_A_VECTOR);
+            return false;
+        }
+
+        args.rval().setObject(args[0].toObject());
+        return true;
+    }
+
     if (args.length() < LANES) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
                              args.callee().getClass()->name, "3", "s");
         return false;
     }
 
     double values[LANES];
     for (unsigned i = 0; i < LANES; i++) {
         if (!ToNumber(cx, args[i], &values[i]))
             return false;
     }
 
-    Rooted<X4TypeDescr*> descr(cx, &args.callee().as<X4TypeDescr>());
     Rooted<TypedObject*> result(cx, TypedObject::createZeroed(cx, descr, 0));
     if (!result)
         return false;
 
     MOZ_ASSERT(!result->owner().isNeutered());
     switch (descr->type()) {
 #define STORE_LANES(_constant, _type, _name)                                  \
       case _constant:                                                         \
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/coercions.js
@@ -0,0 +1,66 @@
+// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
+var BUGNUMBER = 1061229;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+var {StructType, int32} = TypedObject;
+var summary = 'constructors used as coercions';
+
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+function assertCaught(f) {
+    var caught = false;
+    var args = Array.slice(arguments, 1);
+    try {
+        f.apply(null, args);
+    } catch (e) {
+        caught = true;
+        print(e)
+    }
+    assertEq(caught, true);
+}
+
+function test() {
+    var x = int32x4(1, 2, 3, 4);
+    var y = int32x4(x);
+
+    assertEq(x, y);
+
+    assertEq(y.x, x.x);
+    assertEq(y.x, 1);
+    assertEq(y.y, x.y);
+    assertEq(y.y, 2);
+    assertEq(y.z, x.z);
+    assertEq(y.z, 3);
+    assertEq(y.w, x.w);
+    assertEq(y.w, 4);
+
+    assertCaught(int32x4, 3);
+    assertCaught(int32x4, float32x4(1, 2, 3, 4));
+    assertCaught(int32x4, 'pony x 4');
+
+    var x = float32x4(NaN, 13.37, -Infinity, 4);
+    var y = float32x4(x);
+
+    assertEq(x, y);
+
+    assertEq(y.x, x.x);
+    assertEq(y.x, Math.fround(NaN));
+    assertEq(y.y, x.y);
+    assertEq(y.y, Math.fround(13.37));
+    assertEq(y.z, x.z);
+    assertEq(y.z, Math.fround(-Infinity));
+    assertEq(y.w, x.w);
+    assertEq(y.w, Math.fround(4));
+
+    assertCaught(float32x4, 3);
+    assertCaught(float32x4, int32x4(1, 2, 3, 4));
+    assertCaught(float32x4, 'pony x 4');
+
+    if (typeof reportCompare === "function")
+        reportCompare(true, true);
+}
+
+test();