Bug 1437065: Tests; r=luke
authorBenjamin Bouvier <benj@benj.me>
Thu, 23 Aug 2018 15:28:16 +0200
changeset 481626 b415b7af0bf68b1f7ecf1b9ce6a28cb0f720896f
parent 481625 79e9e6a709b04ecb89f2a87bba6e1967a2326cc8
child 481627 059e8dfd41bebc195bec821587fb8915fd8b2403
push id232
push userfmarier@mozilla.com
push dateWed, 05 Sep 2018 20:45:54 +0000
reviewersluke
bugs1437065
milestone63.0a1
Bug 1437065: Tests; r=luke
js/src/jit-test/tests/wasm/ion-args.js
js/src/jit-test/tests/wasm/ion-error-i64.js
js/src/jit-test/tests/wasm/ion-error-ool.js
js/src/jit-test/tests/wasm/ion-error-throw.js
js/src/jit-test/tests/wasm/ion-lazy-tables.js
js/src/jit-test/tests/wasm/profiling.js
--- a/js/src/jit-test/tests/wasm/ion-args.js
+++ b/js/src/jit-test/tests/wasm/ion-args.js
@@ -5,20 +5,27 @@ let { exports } = wasmEvalText(`(module
 
     (func (export "f32") (result f32) (param f32)
      get_local 0
     )
 
     (func (export "f64") (result f64) (param f64)
      get_local 0
     )
+
+    (func (export "mixed_args") (result f64)
+        (param i32) (param i32) (param i32) (param i32) (param i32) ;; 5 i32
+        (param $f64 f64) ;; 1 f64
+        (param i32)
+     get_local $f64
+    )
 )`);
 
 const options = getJitCompilerOptions();
-const jitThreshold = options['ion.warmup.trigger'] * 2;
+const jitThreshold = options['ion.warmup.trigger'] * 2 + 2;
 
 let coercions = {
     i32(x) { return x|0; },
     f32(x) { return Math.fround(x); },
     f64(x) { return +x; }
 }
 
 function call(func, coercion, arg) {
@@ -33,28 +40,98 @@ function call(func, coercion, arg) {
         try {
             assertEq(func(arg), expected);
         } catch(e) {
             assertEq(e.message, expected);
         }
     }
 }
 
-const inputs = [
-    42,
-    3.5,
-    -0,
-    -Infinity,
-    2**32,
-    true,
-    Symbol(),
-    undefined,
-    null,
-    {},
-    { valueOf() { return 13.37; } },
-    "bonjour"
-];
+// Test misc kinds of arguments.
+(function() {
+    const inputs = [
+        42,
+        3.5,
+        -0,
+        -Infinity,
+        2**32,
+        true,
+        Symbol(),
+        undefined,
+        null,
+        {},
+        { valueOf() { return 13.37; } },
+        "bonjour"
+    ];
+
+    for (let arg of inputs) {
+        for (let func of ['i32', 'f32', 'f64']) {
+            call(exports[func], coercions[func], arg);
+        }
+    }
+})();
+
+// Test mixup of float and int arguments.
+(function() {
+    for (let i = 0; i < 10; i++) {
+        assertEq(exports.mixed_args(i, i+1, i+2, i+3, i+4, i+0.5, i+5), i+0.5);
+    }
+})();
+
+// Test high number of arguments.
+// All integers.
+let {func} = wasmEvalText(`(module
+    (func (export "func") (result i32)
+        ${Array(32).join('(param i32)')}
+        (param $last i32)
+     get_local $last
+    )
+)`).exports;
 
-for (let arg of inputs) {
-    for (let func of ['i32', 'f32', 'f64']) {
-        call(exports[func], coercions[func], arg);
+(function() {
+    for (let i = 0; i < 10; i++) {
+        assertEq(func(i, i+1, i+2, i+3, i+4, i+5, i+6, i+7, i+8, i+9, i+10, i+11, i+12, i+13, i+14, i+15,
+                      i+16, i+17, i+18, i+19, i+20, i+21, i+22, i+23, i+24, i+25, i+26, i+27, i+28, i+29, i+30, i+31
+                 ), i+31);
+    }
+})();
+
+// All floats.
+func = wasmEvalText(`(module
+    (func (export "func") (result i32)
+        ${Array(32).join('(param f64)')}
+        (param $last i32)
+     get_local $last
+    )
+)`).exports.func;
+
+(function() {
+    for (let i = 0; i < 10; i++) {
+        assertEq(func(i, i+1, i+2, i+3, i+4, i+5, i+6, i+7, i+8, i+9, i+10, i+11, i+12, i+13, i+14, i+15,
+                      i+16, i+17, i+18, i+19, i+20, i+21, i+22, i+23, i+24, i+25, i+26, i+27, i+28, i+29, i+30, i+31
+                 ), i+31);
     }
+})();
+
+// Mix em up! 1 i32, then 1 f32, then 1 f64, and again up to 32 args.
+let params = [];
+for (let i = 0; i < 32; i++) {
+    params.push((i % 3 == 0) ? 'i32' :
+                (i % 3 == 1) ? 'f32' :
+                'f64'
+               );
 }
+
+func = wasmEvalText(`(module
+    (func (export "func") (result i32)
+        ${Array(32).join('(param f64)')}
+        (param $last i32)
+     get_local $last
+    )
+)`).exports.func;
+
+(function() {
+    for (let i = 0; i < 10; i++) {
+        assertEq(func(i, i+1, i+2, i+3, i+4, i+5, i+6, i+7, i+8, i+9, i+10, i+11, i+12, i+13, i+14, i+15,
+                      i+16, i+17, i+18, i+19, i+20, i+21, i+22, i+23, i+24, i+25, i+26, i+27, i+28, i+29, i+30, i+31
+                 ), i+31);
+    }
+})();
--- a/js/src/jit-test/tests/wasm/ion-error-i64.js
+++ b/js/src/jit-test/tests/wasm/ion-error-i64.js
@@ -5,33 +5,45 @@ if (!options['baseline.enable'])
     quit();
 
 const { nextLineNumber, startProfiling, endProfiling, assertEqPreciseStacks } = WasmHelpers;
 
 const TRIGGER = options['ion.warmup.trigger'] + 10;
 const ITER = 2 * TRIGGER;
 const EXCEPTION_ITER = ITER - 2;
 
-enableGeckoProfiling();
-
 var instance = wasmEvalText(`(module
     (func $add (export "add") (result i32) (param i32) (param i32)
      get_local 0
      get_local 1
      i32.add
     )
 
     (func $addi64 (export "add64") (result i64) (param i32) (param i32)
      get_local 0
      get_local 1
      call $add
      i64.extend_s/i32
     )
+
+    (func $add_two_i64 (export "add_two_i64") (result i64) (param i64) (param i64)
+     get_local 0
+     get_local 1
+     i64.add
+    )
 )`).exports;
 
+(function() {
+    // In ion-eager mode, make sure we don't try to inline a function that
+    // takes or returns i64 arguments.
+    assertErrorMessage(() => instance.add_two_i64(0, 1), TypeError, /cannot pass i64 to or from JS/);
+})();
+
+enableGeckoProfiling();
+
 var callToMain;
 
 function main() {
     var arrayCallLine = nextLineNumber(13);
     for (var i = 0; i < ITER; i++) {
         var arr = [instance.add, (x,y)=>x+y];
         if (i === EXCEPTION_ITER) {
             arr[0] = instance.add64;
@@ -68,17 +80,19 @@ function main() {
             assertEq(callsites[0], 'main');
             assertEq(callsites[1], ''); // global scope
 
             // Which line numbers appear in the error stack.
             let lines = stack.map(s => s.split(':')[1]);
             assertEq(+lines[0], arrayCallLine);
             assertEq(+lines[1], callToMain);
         } else if ((i % 2) == 0) {
+            // Regular call to wasm add on 32 bits integers.
             assertEqPreciseStacks(profilingStack, [
+                ['', '0', ''],                // supa-dupa fast path
                 ['', '>', '0,>', '>', ''],    // fast path
                 ['', '!>', '0,!>', '!>', ''], // slow path
             ]);
         }
     }
 }
 
 callToMain = nextLineNumber();
--- a/js/src/jit-test/tests/wasm/ion-error-ool.js
+++ b/js/src/jit-test/tests/wasm/ion-error-ool.js
@@ -7,16 +7,17 @@ if (!options['baseline.enable'])
 const { assertStackTrace, startProfiling, endProfiling, assertEqPreciseStacks } = WasmHelpers;
 
 const TRIGGER = options['baseline.warmup.trigger'] + 10;
 const ITER = 2 * TRIGGER;
 const EXCEPTION_ITER = TRIGGER + 5;
 
 const SLOW_ENTRY_STACK = ['', '!>', '0,!>', '!>', ''];
 const FAST_ENTRY_STACK = ['', '>', '0,>', '>', ''];
+const INLINED_CALL_STACK = ['', '0', ''];
 const FAST_OOL_ENTRY_STACK = ['', '>', '<,>', 'ool>,>', '<,>', '>', '0,>', '>', ''];
 const EXCEPTION_ENTRY_STACK = ['', '>', '<,>', 'ool>,>', '<,>', '>', ''];
 
 enableGeckoProfiling();
 
 for (let type of ['i32', 'f32', 'f64']) {
     var instance = wasmEvalText(`(module
         (func $add (export "add") (result ${type}) (param ${type}) (param ${type})
@@ -39,17 +40,17 @@ for (let type of ['i32', 'f32', 'f64']) 
     }
 
     var x = 0;
     function main() {
         let observedStacks = [0, 0, 0];
         for (var i = 0; i < ITER; i++) {
             startProfiling();
             loopBody(i + 1, i + EXCEPTION_ITER + 1);
-            assertEqPreciseStacks(endProfiling(), [FAST_ENTRY_STACK, SLOW_ENTRY_STACK]);
+            assertEqPreciseStacks(endProfiling(), [INLINED_CALL_STACK, FAST_ENTRY_STACK, SLOW_ENTRY_STACK]);
 
             if (i === EXCEPTION_ITER) {
                 x = { valueOf: function innerValueOf() { throw new Error("ph34r"); }};
             } else {
                 x = i;
             }
 
             startProfiling();
--- a/js/src/jit-test/tests/wasm/ion-error-throw.js
+++ b/js/src/jit-test/tests/wasm/ion-error-throw.js
@@ -20,25 +20,26 @@ let { add } = wasmEvalText(`(module
      get_local 0
      get_local 1
      i32.add
     )
 )`).exports;
 
 const SLOW_ENTRY_STACK = ['', '!>', '0,!>', '!>', ''];
 const FAST_ENTRY_STACK = ['', '>', '0,>', '>', ''];
+const INLINED_CALL_STACK = ['', '0', ''];
 
 function main() {
     for (let i = 0; i < 50; i++) {
         startProfiling();
         try {
             assertEq(add(i, i+1), 2*i+1);
         } catch (e) {
             assertEq(i, 42);
             assertEq(e.message.includes("unreachable"), true);
             assertStackTrace(e, ['wasm-function[0]', 'main', '']);
         }
         let stack = endProfiling();
-        assertEqPreciseStacks(stack, [FAST_ENTRY_STACK, SLOW_ENTRY_STACK]);
+        assertEqPreciseStacks(stack, [INLINED_CALL_STACK, FAST_ENTRY_STACK, SLOW_ENTRY_STACK]);
     }
 }
 
 main();
--- a/js/src/jit-test/tests/wasm/ion-lazy-tables.js
+++ b/js/src/jit-test/tests/wasm/ion-lazy-tables.js
@@ -7,32 +7,34 @@ if (!options['baseline.enable'])
 const { assertStackTrace, startProfiling, endProfiling, assertEqPreciseStacks } = WasmHelpers;
 
 const TRIGGER = options['baseline.warmup.trigger'] + 10;
 const ITER = 2 * TRIGGER;
 const EXCEPTION_ITER = TRIGGER + 5;
 
 const SLOW_ENTRY_STACK = ['', '!>', '0,!>', '!>', ''];
 const FAST_ENTRY_STACK = ['', '>', '0,>', '>', ''];
+const INLINED_CALL_STACK = ['', '0', ''];
+const EXPECTED_STACKS = [SLOW_ENTRY_STACK, FAST_ENTRY_STACK, INLINED_CALL_STACK];
 
 function main() {
     var { table } = wasmEvalText(`(module
         (func $add (result i32) (param i32) (param i32)
          get_local 0
          get_local 1
          i32.add
         )
         (table (export "table") 10 anyfunc)
         (elem (i32.const 0) $add)
     )`).exports;
 
     for (var i = 0; i < ITER; i++) {
         startProfiling();
         assertEq(table.get(0)(i, i+1), i*2+1);
-        assertEqPreciseStacks(endProfiling(), [FAST_ENTRY_STACK, SLOW_ENTRY_STACK]);
+        assertEqPreciseStacks(endProfiling(), EXPECTED_STACKS);
     }
 }
 
 function withTier2() {
     setJitCompilerOption('wasm.delay-tier2', 1);
 
     var module = new WebAssembly.Module(wasmTextToBinary(`(module
         (func $add (result i32) (param i32) (param i32)
@@ -45,23 +47,23 @@ function withTier2() {
     )`));
     var { table } = new WebAssembly.Instance(module).exports;
 
     let i = 0;
     do {
         i++;
         startProfiling();
         assertEq(table.get(0)(i, i+1), i*2+1);
-        assertEqPreciseStacks(endProfiling(), [FAST_ENTRY_STACK, SLOW_ENTRY_STACK]);
+        assertEqPreciseStacks(endProfiling(), EXPECTED_STACKS);
     } while (!wasmHasTier2CompilationCompleted(module));
 
     for (i = 0; i < ITER; i++) {
         startProfiling();
         assertEq(table.get(0)(i, i+1), i*2+1);
-        assertEqPreciseStacks(endProfiling(), [FAST_ENTRY_STACK, SLOW_ENTRY_STACK]);
+        assertEqPreciseStacks(endProfiling(), EXPECTED_STACKS);
     }
 
     setJitCompilerOption('wasm.delay-tier2', 0);
 }
 
 enableGeckoProfiling();
 main();
 withTier2();
--- a/js/src/jit-test/tests/wasm/profiling.js
+++ b/js/src/jit-test/tests/wasm/profiling.js
@@ -1,16 +1,21 @@
 if (!WasmHelpers.isSingleStepProfilingEnabled)
     quit();
 
 const Module = WebAssembly.Module;
 const Instance = WebAssembly.Instance;
 const Table = WebAssembly.Table;
 
-const { assertEqImpreciseStacks, startProfiling, endProfiling } = WasmHelpers;
+const {
+    assertEqImpreciseStacks,
+    assertEqPreciseStacks,
+    startProfiling,
+    endProfiling
+} = WasmHelpers;
 
 function test(code, importObj, expectedStacks)
 {
     enableGeckoProfiling();
 
     var f = wasmEvalText(code, importObj).exports[""];
     startProfiling();
     f();
@@ -375,8 +380,38 @@ for (let type of ['f32', 'f64']) {
     var code = wasmTextToBinary('(module (func (export "run") (result i32) i32.const 42))');
     var i = new WebAssembly.Instance(new WebAssembly.Module(code));
     assertEq(i.exports.run(), 42);
  `);
 
  disableSingleStepProfiling();
  disableGeckoProfiling();
 })();
+
+// Ion->wasm calls.
+let func = wasmEvalText(`(module
+    (func $inner (result i32) (param i32) (param i32)
+        get_local 0
+        get_local 1
+        i32.add
+    )
+    (func (export "add") (result i32) (param i32) (param i32)
+     get_local 0
+     get_local 1
+     call $inner
+    )
+)`).exports.add;
+
+(function() {
+    enableGeckoProfiling();
+    // 10 is enough in ion eager mode.
+    for (let i = 0; i < 10; i++) {
+        enableSingleStepProfiling();
+        let res = func(i - 1, i + 1);
+        assertEqPreciseStacks(disableSingleStepProfiling(), [
+            ['', '>', '1,>', '0,1,>' , '1,>', '>', ''],      // slow entry
+            ['', '!>', '1,!>', '0,1,!>' , '1,!>', '!>', ''], // fast entry
+            ['', '1', '0,1' , '1', ''],                      // inlined jit call
+        ]);
+        assertEq(res, i+i);
+    }
+    disableGeckoProfiling();
+})();