Bug 1262402: Use the new int64 testing features; r=luke
authorBenjamin Bouvier <benj@benj.me>
Wed, 06 Apr 2016 12:18:32 +0200
changeset 331482 76f72d05c83a081d861ba104bdc11bfae677f649
parent 331481 f76c9c94629ca4f2936cf4602adf74e0491061c1
child 331483 4a6678c781c9f84b1b15f51360f62d48648a2887
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1262402
milestone48.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 1262402: Use the new int64 testing features; r=luke MozReview-Commit-ID: 4sfNzBxqt13
js/src/jit-test/lib/wasm.js
js/src/jit-test/tests/wasm/basic-const.js
js/src/jit-test/tests/wasm/basic-conversion.js
js/src/jit-test/tests/wasm/basic-integer.js
js/src/jit-test/tests/wasm/basic.js
--- a/js/src/jit-test/lib/wasm.js
+++ b/js/src/jit-test/lib/wasm.js
@@ -6,8 +6,47 @@ load(libdir + "asserts.js");
 function wasmEvalText(str, imports) {
     return Wasm.instantiateModule(wasmTextToBinary(str), imports).exports;
 }
 
 function mismatchError(actual, expect) {
     var str = `type mismatch: expression has type ${actual} but expected ${expect}`;
     return RegExp(str);
 }
+
+function hasI64() {
+    return getBuildConfiguration().x64;
+}
+
+// Assert that the expected value is equal to the int64 value, as passed by
+// Baldr with --wasm-extra-tests {low: int32, high: int32}.
+// - if the expected value is in the int32 range, it can be just a number.
+// - otherwise, an object with the properties "high" and "low".
+function assertEqI64(obj, expect) {
+    assertEq(typeof obj, 'object');
+    assertEq(typeof expect === 'object' || typeof expect === 'number', true);
+
+    let {low, high} = obj;
+    if (typeof expect === 'number') {
+        assertEq(expect, expect | 0, "in int32 range");
+        assertEq(low, expect | 0, "low");
+        assertEq(high, expect < 0 ? -1 : 0), "high";
+    } else {
+        assertEq(typeof expect.low, 'number');
+        assertEq(typeof expect.high, 'number');
+        assertEq(low, expect.low | 0, "low");
+        assertEq(high, expect.high | 0, "high");
+    }
+}
+
+function createI64(val) {
+    let ret;
+    if (typeof val === 'number') {
+        assertEq(val, val|0, "number input to createI64 must be an int32");
+        ret = { low: val, high: val < 0 ? -1 : 0 };
+    } else {
+        assertEq(typeof val, 'string');
+        assertEq(val.slice(0, 2), "0x");
+        val = val.slice(2).padStart(16, '0');
+        ret = { low: parseInt(val.slice(8, 16), 16), high: parseInt(val.slice(0, 8), 16) };
+    }
+    return ret;
+}
--- a/js/src/jit-test/tests/wasm/basic-const.js
+++ b/js/src/jit-test/tests/wasm/basic-const.js
@@ -1,15 +1,15 @@
 load(libdir + "wasm.js");
 
-if (!wasmIsSupported())
-    quit();
-
 function testConst(type, str, expect) {
-  assertEq(wasmEvalText('(module (func (result ' + type + ') (' + type + '.const ' + str + ')) (export "" 0))')(), expect);
+    if (type === 'i64')
+        assertEqI64(wasmEvalText('(module (func (result i64) (i64.const ' + str + ')) (export "" 0))')(), expect);
+    else
+        assertEq(wasmEvalText('(module (func (result ' + type + ') (' + type + '.const ' + str + ')) (export "" 0))')(), expect);
 }
 
 function testConstError(type, str) {
   // For now at least, we don't distinguish between parse errors and OOMs.
   assertErrorMessage(() => wasmEvalText('(module (func (result ' + type + ') (' + type + '.const ' + str + ')) (export "" 0))')(), Error, /parsing wasm text/);
 }
 
 testConst('i32', '0', 0);
@@ -21,29 +21,69 @@ testConst('i32', '-0x23', -35);
 testConst('i32', '2147483647', 2147483647);
 testConst('i32', '4294967295', -1);
 testConst('i32', '-2147483648', -2147483648);
 testConst('i32', '0x7fffffff', 2147483647);
 testConst('i32', '0x80000000', -2147483648);
 testConst('i32', '-0x80000000', -2147483648);
 testConst('i32', '0xffffffff', -1);
 
-//testConst('i64', '0', 0); // TODO: NYI
-//testConst('i64', '-0', 0); // TODO: NYI
-//testConst('i64', '23', 23); // TODO: NYI
-//testConst('i64', '-23', -23); // TODO: NYI
-//testConst('i64', '0x23', 35); // TODO: NYI
-//testConst('i64', '-0x23', -35); // TODO: NYI
-//testConst('i64', '9223372036854775807', 9223372036854775807); // TODO: NYI
-//testConst('i64', '18446744073709551615', -1); // TODO: NYI
-//testConst('i64', '-9223372036854775808', -9223372036854775808); // TODO: NYI
-//testConst('i64', '0x7fffffffffffffff', 9223372036854775807); // TODO: NYI
-//testConst('i64', '0x8000000000000000', -9223372036854775808); // TODO: NYI
-//testConst('i64', '-0x8000000000000000', -9223372036854775808); // TODO: NYI
-//testConst('i64', '0xffffffffffffffff', -1); // TODO: NYI
+if (hasI64()) {
+
+    assertErrorMessage(() => wasmEvalText('(module (func (result i64) (i64.const 0)) (export "" 0))'), TypeError, /cannot .* i64/);
+
+    setJitCompilerOption('wasm.test-mode', 1);
+
+    testConst('i64', '0', 0);
+    testConst('i64', '-0', 0);
+
+    testConst('i64', '23', 23);
+    testConst('i64', '-23', -23);
+
+    testConst('i64', '0x23', 35);
+    testConst('i64', '-0x23', -35);
+
+    testConst('i64', '-0x1', -1);
+    testConst('i64', '-1', -1);
+    testConst('i64', '0xffffffffffffffff', -1);
+
+    testConst('i64', '0xdeadc0de', {low: 0xdeadc0de, high: 0x0});
+    testConst('i64', '0x1337c0de00000000', {low: 0x0, high: 0x1337c0de});
+
+    testConst('i64', '0x0102030405060708', {low: 0x05060708, high: 0x01020304});
+    testConst('i64', '-0x0102030405060708', {low: -0x05060708, high: -0x01020305});
+
+    // INT64_MAX
+    testConst('i64', '9223372036854775807', {low: 0xffffffff, high: 0x7fffffff});
+    testConst('i64', '0x7fffffffffffffff',  {low: 0xffffffff, high: 0x7fffffff});
+
+    // INT64_MAX + 1
+    testConst('i64', '9223372036854775808', {low: 0x00000000, high: 0x80000000});
+    testConst('i64', '0x8000000000000000', {low: 0x00000000, high: 0x80000000});
+
+    // UINT64_MAX
+    testConst('i64', '18446744073709551615', {low: 0xffffffff, high: 0xffffffff});
+
+    // INT64_MIN
+    testConst('i64', '-9223372036854775808', {low: 0x00000000, high: 0x80000000});
+    testConst('i64', '-0x8000000000000000',  {low: 0x00000000, high: 0x80000000});
+
+    // INT64_MIN - 1
+    testConstError('i64', '-9223372036854775809');
+
+    testConstError('i64', '');
+    testConstError('i64', '0.0');
+    testConstError('i64', 'not an i64');
+
+    setJitCompilerOption('wasm.test-mode', 0);
+
+    assertErrorMessage(() => wasmEvalText('(module (func (result i64) (i64.const 0)) (export "" 0))'), TypeError, /cannot .* i64/);
+} else {
+    assertErrorMessage(() => wasmEvalText('(module (func (result i64) (i64.const 0)) (export "" 0))'), TypeError, /NYI/);
+}
 
 testConst('f32', '0.0', 0.0);
 testConst('f32', '-0', -0.0);
 testConst('f32', '-0.0', -0.0);
 testConst('f32', '0x0.0', 0.0);
 testConst('f32', '-0x0.0', -0.0);
 testConst('f32', '-0x0', -0.0);
 testConst('f32', '0x0.0p0', 0.0);
@@ -210,22 +250,16 @@ testConst('f64', '0x24c6.004d0deaa3p-103
 testConst('f64', '0', 0);
 
 testConstError('i32', '');
 testConstError('i32', '0.0');
 testConstError('i32', 'not an i32');
 testConstError('i32', '4294967296');
 testConstError('i32', '-2147483649');
 
-//testConstError('i64', ''); // TODO: NYI
-//testConstError('i64', '0.0'); // TODO: NYI
-//testConstError('i64', 'not an i64'); // TODO: NYI
-//testConstError('i64', '9223372036854775808'); // TODO: NYI
-//testConstError('i64', '-9223372036854775809'); // TODO: NYI
-
 testConstError('f32', '');
 testConstError('f32', 'not an f32');
 testConstError('f32', 'nan:');
 testConstError('f32', 'nan:0');
 testConstError('f32', 'nan:0x');
 testConstError('f32', 'nan:0x0');
 
 testConstError('f64', '');
--- a/js/src/jit-test/tests/wasm/basic-conversion.js
+++ b/js/src/jit-test/tests/wasm/basic-conversion.js
@@ -1,55 +1,61 @@
 load(libdir + "wasm.js");
 
-if (!wasmIsSupported())
-    quit();
-
 function testConversion(resultType, opcode, paramType, op, expect) {
   if (paramType === 'i64') {
     // i64 cannot be imported, so we use a wrapper function.
     assertEq(wasmEvalText(`(module
                             (func (param i64) (result ${resultType}) (${resultType}.${opcode}/i64 (get_local 0)))
-                            (func (result ${resultType}) (call 0 (i64.const ${op})))
-                            (export "" 1))`)(), expect);
+                            (export "" 0))`)(createI64(op)), expect);
     // The same, but now the input is a constant.
     assertEq(wasmEvalText(`(module
                             (func (result ${resultType}) (${resultType}.${opcode}/i64 (i64.const ${op})))
                             (export "" 0))`)(), expect);
   } else if (resultType === 'i64') {
-    assertEq(wasmEvalText(`(module
+    assertEqI64(wasmEvalText(`(module
                             (func (param ${paramType}) (result i64) (i64.${opcode}/${paramType} (get_local 0)))
-                            (func (result i32) (i64.eq (i64.const ${expect}) (call 0 (${paramType}.const ${op}))))
-                            (export "" 1))`)(), 1);
+                            (export "" 0))`)(op), createI64(expect));
     // The same, but now the input is a constant.
-    assertEq(wasmEvalText(`(module
+    assertEqI64(wasmEvalText(`(module
                             (func (result i64) (i64.${opcode}/${paramType} (${paramType}.const ${op})))
-                            (func (result i32) (i64.eq (i64.const ${expect}) (call 0)))
-                            (export "" 1))`)(), 1);
+                            (export "" 0))`)(), createI64(expect));
   } else {
     assertEq(wasmEvalText('(module (func (param ' + paramType + ') (result ' + resultType + ') (' + resultType + '.' + opcode + '/' + paramType + ' (get_local 0))) (export "" 0))')(op), expect);
   }
 
-  // TODO: i64 NYI
-  for (var bad of ['i32', 'f32', 'f64']) {
-    if (bad != resultType)
-      assertErrorMessage(() => wasmEvalText('(module (func (param ' + paramType + ') (result ' + bad + ') (' + resultType + '.' + opcode + '/' + paramType + ' (get_local 0))))'),
-                         TypeError,
-                         mismatchError(resultType, bad)
-                        );
-    if (bad != paramType)
-      assertErrorMessage(() => wasmEvalText('(module (func (param ' + bad + ') (result ' + resultType + ') (' + resultType + '.' + opcode + '/' + paramType + ' (get_local 0))))'),
-                         TypeError,
-                         mismatchError(bad, paramType)
-                        );
+  let formerWasmExtraTests = getJitCompilerOptions()['wasm.test-mode'];
+  setJitCompilerOption('wasm.test-mode', 1);
+  for (var bad of ['i32', 'f32', 'f64', 'i64']) {
+      if (bad === 'i64' && !hasI64())
+          continue;
+
+      if (bad != resultType) {
+          assertErrorMessage(
+              () => wasmEvalText(`(module (func (param ${paramType}) (result ${bad}) (${resultType}.${opcode}/${paramType} (get_local 0))))`),
+              TypeError,
+              mismatchError(resultType, bad)
+          );
+      }
+
+      if (bad != paramType) {
+          assertErrorMessage(
+              () => wasmEvalText(`(module (func (param ${bad}) (result ${resultType}) (${resultType}.${opcode}/${paramType} (get_local 0))))`),
+              TypeError,
+              mismatchError(bad, paramType)
+          );
+      }
   }
+  setJitCompilerOption('wasm.test-mode', formerWasmExtraTests);
 }
 
-if (getBuildConfiguration().x64) {
-    testConversion('i32', 'wrap', 'i64', 4294967336, 40);
+if (hasI64()) {
+    setJitCompilerOption('wasm.test-mode', 1);
+
+    testConversion('i32', 'wrap', 'i64', '0x100000028', 40);
     testConversion('i32', 'wrap', 'i64', -10, -10);
     testConversion('i32', 'wrap', 'i64', "0xffffffff7fffffff", 0x7fffffff);
     testConversion('i32', 'wrap', 'i64', "0xffffffff00000000", 0);
     testConversion('i32', 'wrap', 'i64', "0xfffffffeffffffff", -1);
     testConversion('i32', 'wrap', 'i64', "0x1234567801abcdef", 0x01abcdef);
     testConversion('i32', 'wrap', 'i64', "0x8000000000000002", 2);
 
     testConversion('i64', 'extend_s', 'i32', 0, 0);
@@ -63,101 +69,101 @@ if (getBuildConfiguration().x64) {
     testConversion('i64', 'extend_u', 'i32', -567, "0x00000000fffffdc9");
     testConversion('i64', 'extend_u', 'i32', -1, "0x00000000ffffffff");
     testConversion('i64', 'extend_u', 'i32', 0x7fffffff, "0x000000007fffffff");
     testConversion('i64', 'extend_u', 'i32', 0x80000000, "0x0000000080000000");
 
     testConversion('f32', 'convert_s', 'i64', 1, 1.0);
     testConversion('f32', 'convert_s', 'i64', -1, -1.0);
     testConversion('f32', 'convert_s', 'i64', 0, 0.0);
-    testConversion('f32', 'convert_s', 'i64', "9223372036854775807", 9223372036854775807.0);
-    testConversion('f32', 'convert_s', 'i64', "-9223372036854775808", -9223372036854775808.0);
-    testConversion('f32', 'convert_s', 'i64', "314159265358979", 314159275180032.0);
+    testConversion('f32', 'convert_s', 'i64', "0x7fffffffffffffff", 9223372036854775807.0);
+    testConversion('f32', 'convert_s', 'i64', "0x8000000000000000", -9223372036854775808.0);
+    testConversion('f32', 'convert_s', 'i64', "0x11db9e76a2483", 314159275180032.0);
 
     testConversion('f64', 'convert_s', 'i64', 1, 1.0);
     testConversion('f64', 'convert_s', 'i64', -1, -1.0);
     testConversion('f64', 'convert_s', 'i64', 0, 0.0);
-    testConversion('f64', 'convert_s', 'i64', "9223372036854775807", 9223372036854775807.0);
-    testConversion('f64', 'convert_s', 'i64', "-9223372036854775808", -9223372036854775808.0);
-    testConversion('f64', 'convert_s', 'i64', "4669201609102990", 4669201609102990);
+    testConversion('f64', 'convert_s', 'i64', "0x7fffffffffffffff", 9223372036854775807.0);
+    testConversion('f64', 'convert_s', 'i64', "0x8000000000000000", -9223372036854775808.0);
+    testConversion('f64', 'convert_s', 'i64', "0x10969d374b968e", 4669201609102990);
 
     testConversion('f32', 'convert_u', 'i64', 1, 1.0);
     testConversion('f32', 'convert_u', 'i64', 0, 0.0);
-    testConversion('f32', 'convert_u', 'i64', "9223372036854775807", 9223372036854775807.0);
-    testConversion('f32', 'convert_u', 'i64', "-9223372036854775808", 9223372036854775808.0);
+    testConversion('f32', 'convert_u', 'i64', "0x7fffffffffffffff", 9223372036854775807.0);
+    testConversion('f32', 'convert_u', 'i64', "0x8000000000000000", 9223372036854775808.0);
     testConversion('f32', 'convert_u', 'i64', -1, 18446744073709551616.0);
     testConversion('f32', 'convert_u', 'i64', "0xffff0000ffff0000", 18446462598732840000.0);
 
     testConversion('f64', 'convert_u', 'i64', 1, 1.0);
     testConversion('f64', 'convert_u', 'i64', 0, 0.0);
-    testConversion('f64', 'convert_u', 'i64', "9223372036854775807", 9223372036854775807.0);
-    testConversion('f64', 'convert_u', 'i64', "-9223372036854775808", 9223372036854775808.0);
+    testConversion('f64', 'convert_u', 'i64', "0x7fffffffffffffff", 9223372036854775807.0);
+    testConversion('f64', 'convert_u', 'i64', "0x8000000000000000", 9223372036854775808.0);
     testConversion('f64', 'convert_u', 'i64', -1, 18446744073709551616.0);
     testConversion('f64', 'convert_u', 'i64', "0xffff0000ffff0000", 18446462603027743000.0);
 
     testConversion('i64', 'trunc_s', 'f64', 0.0, 0);
     testConversion('i64', 'trunc_s', 'f64', "-0.0", 0);
     testConversion('i64', 'trunc_s', 'f64', 1.0, 1);
     testConversion('i64', 'trunc_s', 'f64', 1.1, 1);
     testConversion('i64', 'trunc_s', 'f64', 1.5, 1);
     testConversion('i64', 'trunc_s', 'f64', 1.99, 1);
     testConversion('i64', 'trunc_s', 'f64', 40.1, 40);
     testConversion('i64', 'trunc_s', 'f64', -1.0, -1);
     testConversion('i64', 'trunc_s', 'f64', -1.1, -1);
     testConversion('i64', 'trunc_s', 'f64', -1.5, -1);
     testConversion('i64', 'trunc_s', 'f64', -1.99, -1);
     testConversion('i64', 'trunc_s', 'f64', -2.0, -2);
-    testConversion('i64', 'trunc_s', 'f64', 4294967296.1, "4294967296");
-    testConversion('i64', 'trunc_s', 'f64', -4294967296.8, "-4294967296");
-    testConversion('i64', 'trunc_s', 'f64', 9223372036854774784.8, "9223372036854774784");
-    testConversion('i64', 'trunc_s', 'f64', -9223372036854775808.3, "-9223372036854775808");
+    testConversion('i64', 'trunc_s', 'f64', 4294967296.1, "0x100000000");
+    testConversion('i64', 'trunc_s', 'f64', -4294967296.8, "0xffffffff00000000");
+    testConversion('i64', 'trunc_s', 'f64', 9223372036854774784.8, "0x7ffffffffffffc00");
+    testConversion('i64', 'trunc_s', 'f64', -9223372036854775808.3, "0x8000000000000000");
 
     testConversion('i64', 'trunc_u', 'f64', 0.0, 0);
     testConversion('i64', 'trunc_u', 'f64', "-0.0", 0);
     testConversion('i64', 'trunc_u', 'f64', 1.0, 1);
     testConversion('i64', 'trunc_u', 'f64', 1.1, 1);
     testConversion('i64', 'trunc_u', 'f64', 1.5, 1);
     testConversion('i64', 'trunc_u', 'f64', 1.99, 1);
     testConversion('i64', 'trunc_u', 'f64', -0.9, 0);
     testConversion('i64', 'trunc_u', 'f64', 40.1, 40);
     testConversion('i64', 'trunc_u', 'f64', 4294967295, "0xffffffff");
-    testConversion('i64', 'trunc_u', 'f64', 4294967296.1, "4294967296");
-    testConversion('i64', 'trunc_u', 'f64', 1e8, "100000000");
-    testConversion('i64', 'trunc_u', 'f64', 1e16, "10000000000000000");
-    testConversion('i64', 'trunc_u', 'f64', 9223372036854775808, "-9223372036854775808");
+    testConversion('i64', 'trunc_u', 'f64', 4294967296.1, "0x100000000");
+    testConversion('i64', 'trunc_u', 'f64', 1e8, "0x5f5e100");
+    testConversion('i64', 'trunc_u', 'f64', 1e16, "0x2386f26fc10000");
+    testConversion('i64', 'trunc_u', 'f64', 9223372036854775808, "0x8000000000000000");
     testConversion('i64', 'trunc_u', 'f64', 18446744073709549568.1, -2048);
 
     testConversion('i64', 'trunc_s', 'f32', 0.0, 0);
     testConversion('i64', 'trunc_s', 'f32', "-0.0", 0);
     testConversion('i64', 'trunc_s', 'f32', 1.0, 1);
     testConversion('i64', 'trunc_s', 'f32', 1.1, 1);
     testConversion('i64', 'trunc_s', 'f32', 1.5, 1);
     testConversion('i64', 'trunc_s', 'f32', 1.99, 1);
     testConversion('i64', 'trunc_s', 'f32', 40.1, 40);
     testConversion('i64', 'trunc_s', 'f32', -1.0, -1);
     testConversion('i64', 'trunc_s', 'f32', -1.1, -1);
     testConversion('i64', 'trunc_s', 'f32', -1.5, -1);
     testConversion('i64', 'trunc_s', 'f32', -1.99, -1);
     testConversion('i64', 'trunc_s', 'f32', -2.0, -2);
-    testConversion('i64', 'trunc_s', 'f32', 4294967296.1, "4294967296");
-    testConversion('i64', 'trunc_s', 'f32', -4294967296.8, "-4294967296");
-    testConversion('i64', 'trunc_s', 'f32', 9223371487098961920.0, "9223371487098961920");
-    testConversion('i64', 'trunc_s', 'f32', -9223372036854775808.3, "-9223372036854775808");
+    testConversion('i64', 'trunc_s', 'f32', 4294967296.1, "0x100000000");
+    testConversion('i64', 'trunc_s', 'f32', -4294967296.8, "0xffffffff00000000");
+    testConversion('i64', 'trunc_s', 'f32', 9223371487098961920.0, "0x7fffff8000000000");
+    testConversion('i64', 'trunc_s', 'f32', -9223372036854775808.3, "0x8000000000000000");
 
     testConversion('i64', 'trunc_u', 'f32', 0.0, 0);
     testConversion('i64', 'trunc_u', 'f32', "-0.0", 0);
     testConversion('i64', 'trunc_u', 'f32', 1.0, 1);
     testConversion('i64', 'trunc_u', 'f32', 1.1, 1);
     testConversion('i64', 'trunc_u', 'f32', 1.5, 1);
     testConversion('i64', 'trunc_u', 'f32', 1.99, 1);
     testConversion('i64', 'trunc_u', 'f32', -0.9, 0);
     testConversion('i64', 'trunc_u', 'f32', 40.1, 40);
-    testConversion('i64', 'trunc_u', 'f32', 1e8, "100000000");
-    testConversion('i64', 'trunc_u', 'f32', 4294967296, "4294967296");
-    testConversion('i64', 'trunc_u', 'f32', 18446742974197923840.0, "-1099511627776");
+    testConversion('i64', 'trunc_u', 'f32', 1e8, "0x5f5e100");
+    testConversion('i64', 'trunc_u', 'f32', 4294967296, "0x100000000");
+    testConversion('i64', 'trunc_u', 'f32', 18446742974197923840.0, "0xffffff0000000000");
 
     // TODO: these should trap.
     testConversion('i64', 'trunc_s', 'f64', 9223372036854775808.0, "0x8000000000000000");
     testConversion('i64', 'trunc_s', 'f64', -9223372036854777856.0, "0x8000000000000000");
     testConversion('i64', 'trunc_s', 'f64', "nan", "0x8000000000000000");
     testConversion('i64', 'trunc_s', 'f64', "infinity", "0x8000000000000000");
     testConversion('i64', 'trunc_s', 'f64', "-infinity", "0x8000000000000000");
 
@@ -174,18 +180,20 @@ if (getBuildConfiguration().x64) {
     testConversion('i64', 'trunc_s', 'f32', "-infinity", "0x8000000000000000");
 
     testConversion('i64', 'trunc_u', 'f32', 18446744073709551616.0, "0x8000000000000000");
     testConversion('i64', 'trunc_u', 'f32', -1, "0x8000000000000000");
     testConversion('i64', 'trunc_u', 'f32', "nan", "0x8000000000000000");
     testConversion('i64', 'trunc_u', 'f32', "infinity", "0x8000000000000000");
     testConversion('i64', 'trunc_u', 'f32', "-infinity", "0x8000000000000000");
 
-    testConversion('i64', 'reinterpret', 'f64', 40.09999999999968, 4630840390592548000);
-    testConversion('f64', 'reinterpret', 'i64', 4630840390592548000, 40.09999999999968);
+    testConversion('i64', 'reinterpret', 'f64', 40.09999999999968, "0x40440ccccccccca0");
+    testConversion('f64', 'reinterpret', 'i64', "0x40440ccccccccca0", 40.09999999999968);
+
+    setJitCompilerOption('wasm.test-mode', 0);
 } else {
     // Sleeper test: once i64 works on more platforms, remove this if-else.
     try {
         testConversion('i32', 'wrap', 'i64', 4294967336, 40);
         assertEq(0, 1);
     } catch(e) {
         assertEq(e.toString().indexOf("NYI on this platform") >= 0, true);
     }
--- a/js/src/jit-test/tests/wasm/basic-integer.js
+++ b/js/src/jit-test/tests/wasm/basic-integer.js
@@ -4,55 +4,50 @@ assertEq(wasmEvalText('(module (func (re
 assertEq(wasmEvalText('(module (func (result i32) (i32.const -2147483648)) (export "" 0))')(), -2147483648);
 assertEq(wasmEvalText('(module (func (result i32) (i32.const 4294967295)) (export "" 0))')(), -1);
 
 function testUnary(type, opcode, op, expect) {
   assertEq(wasmEvalText('(module (func (param ' + type + ') (result ' + type + ') (' + type + '.' + opcode + ' (get_local 0))) (export "" 0))')(op), expect);
 }
 
 function testBinary(type, opcode, lhs, rhs, expect) {
-  if (type === 'i64') {
-    // i64 cannot be imported/exported, so we use a wrapper function.
-    assertEq(wasmEvalText(`(module
-                            (func (param i64) (param i64) (result i64) (i64.${opcode} (get_local 0) (get_local 1)))
-                            (func (result i32) (i64.eq (call 0 (i64.const ${lhs}) (i64.const ${rhs})) (i64.const ${expect})))
-                            (export "" 1))`)(), 1);
-    // The same, but now the RHS is a constant.
-    assertEq(wasmEvalText(`(module
-                            (func (param i64) (result i64) (i64.${opcode} (get_local 0) (i64.const ${rhs})))
-                            (func (result i32) (i64.eq (call 0 (i64.const ${lhs})) (i64.const ${expect})))
-                            (export "" 1))`)(), 1);
-    // LHS and RHS are constants.
-    assertEq(wasmEvalText(`(module
-                            (func (result i64) (i64.${opcode} (i64.const ${lhs}) (i64.const ${rhs})))
-                            (func (result i32) (i64.eq (call 0) (i64.const ${expect})))
-                            (export "" 1))`)(), 1);
-  } else {
-    assertEq(wasmEvalText('(module (func (param ' + type + ') (param ' + type + ') (result ' + type + ') (' + type + '.' + opcode + ' (get_local 0) (get_local 1))) (export "" 0))')(lhs, rhs), expect);
-  }
+    if (type === 'i64') {
+        let lobj = createI64(lhs);
+        let robj = createI64(rhs);
+        expect = createI64(expect);
+
+        assertEqI64(wasmEvalText(`(module (func (param i64) (param i64) (result i64) (i64.${opcode} (get_local 0) (get_local 1))) (export "" 0))`)(lobj, robj), expect);
+        // The same, but now the RHS is a constant.
+        assertEqI64(wasmEvalText(`(module (func (param i64) (param i64) (result i64) (i64.${opcode} (get_local 0) (i64.const ${rhs}))) (export "" 0))`)(lobj, robj), expect);
+        // LHS and RHS are constants.
+        assertEqI64(wasmEvalText(`(module (func (param i64) (param i64) (result i64) (i64.${opcode} (i64.const ${lhs}) (i64.const ${rhs}))) (export "" 0))`)(lobj, robj), expect);
+    } else {
+        assertEq(wasmEvalText(`(module (func (param ${type}) (param ${type}) (result ${type}) (${type}.${opcode} (get_local 0) (get_local 1))) (export "" 0))`)(lhs, rhs), expect);
+    }
 }
 
 function testComparison(type, opcode, lhs, rhs, expect) {
-  if (type === 'i64') {
-    // i64 cannot be imported/exported, so we use a wrapper function.
-    assertEq(wasmEvalText(`(module
-                            (func (param i64) (param i64) (result i32) (i64.${opcode} (get_local 0) (get_local 1)))
-                            (func (result i32) (call 0 (i64.const ${lhs}) (i64.const ${rhs})))
-                            (export "" 1))`)(), expect);
-    // Also test if, for the compare-and-branch path.
-    assertEq(wasmEvalText(`(module
-                            (func (param i64) (param i64) (result i32)
-                              (if (i64.${opcode} (get_local 0) (get_local 1))
-                                (i32.const 1)
-                                (i32.const 0)))
-                            (func (result i32) (call 0 (i64.const ${lhs}) (i64.const ${rhs})))
-                            (export "" 1))`)(), expect);
-  } else {
-    assertEq(wasmEvalText('(module (func (param ' + type + ') (param ' + type + ') (result i32) (' + type + '.' + opcode + ' (get_local 0) (get_local 1))) (export "" 0))')(lhs, rhs), expect);
-  }
+    if (type === 'i64') {
+        let lobj = createI64(lhs);
+        let robj = createI64(rhs);
+
+        assertEq(wasmEvalText(`(module
+                                (func (param i64) (param i64) (result i32) (i64.${opcode} (get_local 0) (get_local 1)))
+                                (export "" 0))`)(lobj, robj), expect);
+
+        // Also test if, for the compare-and-branch path.
+        assertEq(wasmEvalText(`(module
+                                (func (param i64) (param i64) (result i32)
+                                 (if (i64.${opcode} (get_local 0) (get_local 1))
+                                  (i32.const 1)
+                                  (i32.const 0)))
+                                  (export "" 0))`)(lobj, robj), expect);
+    } else {
+        assertEq(wasmEvalText('(module (func (param ' + type + ') (param ' + type + ') (result i32) (' + type + '.' + opcode + ' (get_local 0) (get_local 1))) (export "" 0))')(lhs, rhs), expect);
+    }
 }
 
 testUnary('i32', 'clz', 40, 26);
 testUnary('i32', 'ctz', 40, 3);
 testUnary('i32', 'ctz', 0, 32);
 testUnary('i32', 'ctz', -2147483648, 31);
 
 testUnary('i32', 'popcnt', 40, 2);
@@ -90,17 +85,20 @@ testComparison('i32', 'gt_u', 40, 40, 0)
 testComparison('i32', 'ge_s', 40, 40, 1);
 testComparison('i32', 'ge_u', 40, 40, 1);
 
 //testUnary('i64', 'clz', 40, 58); // TODO: NYI
 //testUnary('i64', 'ctz', 40, 0); // TODO: NYI
 //testUnary('i64', 'popcnt', 40, 0); // TODO: NYI
 //testUnary('i64', 'eqz', 40, 0); // TODO: NYI
 
-if (getBuildConfiguration().x64) {
+if (hasI64()) {
+
+    setJitCompilerOption('wasm.test-mode', 1);
+
     testBinary('i64', 'add', 40, 2, 42);
     testBinary('i64', 'add', "0x1234567887654321", -1, "0x1234567887654320");
     testBinary('i64', 'add', "0xffffffffffffffff", 1, 0);
     testBinary('i64', 'sub', 40, 2, 38);
     testBinary('i64', 'sub', "0x1234567887654321", "0x123456789", "0x12345677641fdb98");
     testBinary('i64', 'sub', 3, 5, -2);
     testBinary('i64', 'mul', 40, 2, 80);
     testBinary('i64', 'mul', -1, 2, -2);
@@ -152,25 +150,27 @@ if (getBuildConfiguration().x64) {
     testComparison('i64', 'le_u', 40, 40, 1);
     testComparison('i64', 'gt_s', 40, 40, 0);
     testComparison('i64', 'gt_u', 40, 40, 0);
     testComparison('i64', 'ge_s', 40, 40, 1);
     testComparison('i64', 'ge_u', 40, 40, 1);
     testComparison('i64', 'eq', "0x400012345678", "0x400012345678", 1);
     testComparison('i64', 'ne', "0x400012345678", "0x400012345678", 0);
     testComparison('i64', 'ne', "0x400012345678", "0x500012345678", 1);
-    testComparison('i64', 'eq', "0xffffffffffffffff", "-1", 1);
+    testComparison('i64', 'eq', "0xffffffffffffffff", -1, 1);
     testComparison('i64', 'lt_s', "0x8000000012345678", "0x1", 1);
     testComparison('i64', 'lt_u', "0x8000000012345678", "0x1", 0);
-    testComparison('i64', 'le_s', "-1", "0", 1);
-    testComparison('i64', 'le_u', "-1", "-1", 1);
-    testComparison('i64', 'gt_s', "1", "0x8000000000000000", 1);
-    testComparison('i64', 'gt_u', "1", "0x8000000000000000", 0);
-    testComparison('i64', 'ge_s', "1", "0x8000000000000000", 1);
-    testComparison('i64', 'ge_u', "1", "0x8000000000000000", 0);
+    testComparison('i64', 'le_s', -1, 0, 1);
+    testComparison('i64', 'le_u', -1, -1, 1);
+    testComparison('i64', 'gt_s', 1, "0x8000000000000000", 1);
+    testComparison('i64', 'gt_u', 1, "0x8000000000000000", 0);
+    testComparison('i64', 'ge_s', 1, "0x8000000000000000", 1);
+    testComparison('i64', 'ge_u', 1, "0x8000000000000000", 0);
+
+    setJitCompilerOption('wasm.test-mode', 0);
 } else {
     // Sleeper test: once i64 works on more platforms, remove this if-else.
     try {
         testComparison('i64', 'eq', 40, 40, 1);
         assertEq(0, 1);
     } catch(e) {
         assertEq(e.toString().indexOf("NYI on this platform") >= 0, true);
     }
--- a/js/src/jit-test/tests/wasm/basic.js
+++ b/js/src/jit-test/tests/wasm/basic.js
@@ -82,21 +82,32 @@ assertErrorMessage(() => wasmEvalText('(
 wasmEvalText('(module (func (nop)))');
 wasmEvalText('(module (func (result i32) (i32.const 42)))');
 wasmEvalText('(module (func (param i32)))');
 wasmEvalText('(module (func (param i32) (result i32) (i32.const 42)))');
 wasmEvalText('(module (func (result i32) (param i32) (i32.const 42)))');
 wasmEvalText('(module (func (param f32)))');
 wasmEvalText('(module (func (param f64)))');
 
-var hasI64 = getBuildConfiguration().x64;
-if (!hasI64) {
+if (!hasI64()) {
     assertErrorMessage(() => wasmEvalText('(module (func (param i64)))'), TypeError, /NYI/);
     assertErrorMessage(() => wasmEvalText('(module (func (result i64)))'), TypeError, /NYI/);
     assertErrorMessage(() => wasmEvalText('(module (func (result i32) (i32.wrap/i64 (i64.add (i64.const 1) (i64.const 2)))))'), TypeError, /NYI/);
+} else {
+    assertErrorMessage(() => wasmEvalText('(module (func (param i64) (result i32) (i32.const 123)) (export "" 0))'), TypeError, /i64 argument/);
+    assertErrorMessage(() => wasmEvalText('(module (func (param i32) (result i64) (i64.const 123)) (export "" 0))'), TypeError, /i64 return type/);
+
+    setJitCompilerOption('wasm.test-mode', 1);
+
+    assertEqI64(wasmEvalText('(module (func (result i64) (i64.const 123)) (export "" 0))')(), {low: 123, high: 0});
+    assertEqI64(wasmEvalText('(module (func (param i64) (result i64) (get_local 0)) (export "" 0))')({ low: 0x7fffffff, high: 0x12340000}),
+                {low: 0x7fffffff, high: 0x12340000});
+    assertEqI64(wasmEvalText('(module (func (param i64) (result i64) (i64.add (get_local 0) (i64.const 1))) (export "" 0))')({ low: 0xffffffff, high: 0x12340000}), {low: 0x0, high: 0x12340001});
+
+    setJitCompilerOption('wasm.test-mode', 0);
 }
 
 // ----------------------------------------------------------------------------
 // imports
 
 assertErrorMessage(() => wasmEvalText('(module (import "a" "b"))', 1), Error, /second argument, if present, must be an object/);
 assertErrorMessage(() => wasmEvalText('(module (import "a" "b"))', null), Error, /second argument, if present, must be an object/);
 
@@ -255,17 +266,17 @@ assertErrorMessage(() => wasmEvalText('(
 assertErrorMessage(() => wasmEvalText('(module (func (local f32) (set_local 0 (nop))))'), TypeError, mismatchError("void", "f32"));
 assertErrorMessage(() => wasmEvalText('(module (func (local i32) (local f32) (set_local 0 (get_local 1))))'), TypeError, mismatchError("f32", "i32"));
 assertErrorMessage(() => wasmEvalText('(module (func (local i32) (local f32) (set_local 1 (get_local 0))))'), TypeError, mismatchError("i32", "f32"));
 wasmEvalText('(module (func (local i32) (local f32) (set_local 0 (get_local 0))))');
 wasmEvalText('(module (func (local i32) (local f32) (set_local 1 (get_local 1))))');
 assertEq(wasmEvalText('(module (func (result i32) (local i32) (set_local 0 (i32.const 42))) (export "" 0))')(), 42);
 assertEq(wasmEvalText('(module (func (result i32) (local i32) (set_local 0 (get_local 0))) (export "" 0))')(), 0);
 
-if (!hasI64)
+if (!hasI64())
     assertErrorMessage(() => wasmEvalText('(module (func (local i64)))'), TypeError, /NYI/);
 
 assertEq(wasmEvalText('(module (func (param $a i32) (result i32) (get_local $a)) (export "" 0))')(), 0);
 assertEq(wasmEvalText('(module (func (param $a i32) (local $b i32) (result i32) (block (set_local $b (get_local $a)) (get_local $b))) (export "" 0))')(42), 42);
 
 wasmEvalText('(module (func (local i32) (local $a f32) (set_local 0 (i32.const 1)) (set_local $a (f32.const nan))))');
 
 // ----------------------------------------------------------------------------
@@ -342,16 +353,77 @@ var code = '(module (import "one" "" (re
 var imports = {one:()=>1, two:()=>2};
 assertEq(wasmEvalText(code.replace('BODY', '(call_import 0)'), imports)(), 1);
 assertEq(wasmEvalText(code.replace('BODY', '(call_import 1)'), imports)(), 2);
 assertEq(wasmEvalText(code.replace('BODY', '(call 0)'), imports)(), 3);
 assertEq(wasmEvalText(code.replace('BODY', '(call 1)'), imports)(), 4);
 
 assertEq(wasmEvalText(`(module (import "evalcx" "" (param i32) (result i32)) (func (result i32) (call_import 0 (i32.const 0))) (export "" 0))`, {evalcx})(), 0);
 
+if (hasI64()) {
+    assertErrorMessage(() => wasmEvalText('(module (import "a" "" (param i64) (result i32)))'), TypeError, /i64 argument/);
+    assertErrorMessage(() => wasmEvalText('(module (import "a" "" (result i64)))'), TypeError, /i64 return type/);
+
+    setJitCompilerOption('wasm.test-mode', 1);
+
+    let imp = {
+        param(i64) {
+            assertEqI64(i64, {
+                low: 0x9abcdef0,
+                high: 0x12345678
+            });
+            return 42;
+        },
+        result(i32) {
+            return {
+                low: 0xabcdef01,
+                high: 0x12345678 + i32
+            }
+        },
+        paramAndResult(i64) {
+            assertEqI64(i64, {
+                low: 0x9abcdef0,
+                high: 0x12345678
+            });
+            i64.low = 1337;
+            return i64;
+        }
+    }
+
+    assertEq(wasmEvalText(`(module
+        (import "param" "" (param i64) (result i32))
+        (func (result i32) (call_import 0 (i64.const 0x123456789abcdef0)))
+        (export "" 0))`, imp)(), 42);
+
+    assertEqI64(wasmEvalText(`(module
+        (import "result" "" (param i32) (result i64))
+        (func (result i64) (call_import 0 (i32.const 3)))
+        (export "" 0))`, imp)(), { low: 0xabcdef01, high: 0x1234567b });
+
+    // Ensure the ion exit is never taken.
+    let ionThreshold = 2 * getJitCompilerOptions()['ion.warmup.trigger'];
+    assertEqI64(wasmEvalText(`(module
+        (import "paramAndResult" "" (param i64) (result i64))
+        (func (result i64) (local i32) (local i64)
+         (set_local 0 (i32.const 0))
+         (loop $out $in
+             (set_local 1 (call_import 0 (i64.const 0x123456789abcdef0)))
+             (set_local 0 (i32.add (get_local 0) (i32.const 1)))
+             (if (i32.le_s (get_local 0) (i32.const ${ionThreshold})) (br $in))
+         )
+         (get_local 1)
+        )
+    (export "" 0))`, imp)(), { low: 1337, high: 0x12345678 });
+
+    setJitCompilerOption('wasm.test-mode', 0);
+} else {
+    assertErrorMessage(() => wasmEvalText('(module (import "a" "" (param i64) (result i32)))'), TypeError, /NYI/);
+    assertErrorMessage(() => wasmEvalText('(module (import "a" "" (result i64)))'), TypeError, /NYI/);
+}
+
 var {v2i, i2i, i2v} = wasmEvalText(`(module
     (type (func (result i32)))
     (type (func (param i32) (result i32)))
     (type (func (param i32)))
     (func (type 0) (i32.const 13))
     (func (type 0) (i32.const 42))
     (func (type 1) (i32.add (get_local 0) (i32.const 1)))
     (func (type 1) (i32.add (get_local 0) (i32.const 2)))
@@ -402,23 +474,16 @@ assertErrorMessage(() => i2v(5), Error, 
 }
 
 for (bad of [6, 7, 100, Math.pow(2,31)-1, Math.pow(2,31), Math.pow(2,31)+1, Math.pow(2,32)-2, Math.pow(2,32)-1]) {
     assertThrowsInstanceOf(() => v2i(bad), RangeError);
     assertThrowsInstanceOf(() => i2i(bad, 0), RangeError);
     assertThrowsInstanceOf(() => i2v(bad, 0), RangeError);
 }
 
-if (hasI64) {
-    assertErrorMessage(() => wasmEvalText('(module (func (param i64) (result i32) (i32.const 123)) (export "" 0))'), TypeError, /i64 argument/);
-    assertErrorMessage(() => wasmEvalText('(module (func (param i32) (result i64) (i64.const 123)) (export "" 0))'), TypeError, /i64 return type/);
-    assertErrorMessage(() => wasmEvalText('(module (import "a" "" (param i64) (result i32)))'), TypeError, /i64 argument/);
-    assertErrorMessage(() => wasmEvalText('(module (import "a" "" (result i64)))'), TypeError, /i64 return type/);
-}
-
 var {v2i, i2i, i2v} = wasmEvalText(`(module
     (type $a (func (result i32)))
     (type $b (func (param i32) (result i32)))
     (type $c (func (param i32)))
     (func $a (type $a) (i32.const 13))
     (func $b (type $a) (i32.const 42))
     (func $c (type $b) (i32.add (get_local 0) (i32.const 1)))
     (func $d (type $b) (i32.add (get_local 0) (i32.const 2)))
@@ -577,31 +642,33 @@ testSelect('i32', Math.pow(2, 31) - 1, -
 testSelect('f32', Math.fround(13.37), Math.fround(19.89));
 testSelect('f32', 'infinity', '-0');
 testSelect('f32', 'nan', Math.pow(2, -31));
 
 testSelect('f64', 13.37, 19.89);
 testSelect('f64', 'infinity', '-0');
 testSelect('f64', 'nan', Math.pow(2, -31));
 
-if (!hasI64) {
+if (!hasI64()) {
     assertErrorMessage(() => wasmEvalText('(module (func (select (i64.const 0) (i64.const 1) (i32.const 0))))'), TypeError, /NYI/);
 } else {
+
+    setJitCompilerOption('wasm.test-mode', 1);
+
     var f = wasmEvalText(`
     (module
-     (func (result i32) (param i32)
-      (i64.gt_s
-       (select
-        (i64.const ${Math.pow(2, 31) + 1})
-        (i64.const ${-Math.pow(2, 31) - 1})
-        (get_local 0)
-       )
-       (i64.const ${Math.pow(2, 31)})
+     (func (result i64) (param i32)
+      (select
+       (i64.const 0xc0010ff08badf00d)
+       (i64.const 0x12345678deadc0de)
+       (get_local 0)
       )
      )
      (export "" 0)
-    )
-    `, imports);
+    )`, imports);
 
-    assertEq(f(0), 0);
-    assertEq(f(1), 1);
-    assertEq(f(-1), 1);
+    assertEqI64(f(0),  { low: 0xdeadc0de, high: 0x12345678});
+    assertEqI64(f(1),  { low: 0x8badf00d, high: 0xc0010ff0});
+    assertEqI64(f(-1), { low: 0x8badf00d, high: 0xc0010ff0});
+
+    setJitCompilerOption('wasm.test-mode', 0);
 }
+