diff options
Diffstat (limited to 'js/src/jit-test/tests/wasm/tail-calls/return_call_ref.js')
-rw-r--r-- | js/src/jit-test/tests/wasm/tail-calls/return_call_ref.js | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/tail-calls/return_call_ref.js b/js/src/jit-test/tests/wasm/tail-calls/return_call_ref.js new file mode 100644 index 0000000000..c5f250a41c --- /dev/null +++ b/js/src/jit-test/tests/wasm/tail-calls/return_call_ref.js @@ -0,0 +1,94 @@ +// |jit-test| --wasm-gc; skip-if: !wasmGcEnabled() +var ins = wasmEvalText(`(module + (type $t (func (param i64 i64 funcref) (result i64))) + (elem declare func $fac-acc $fac-acc-broken) + (func $fac-acc (export "fac-acc") (param i64 i64 funcref) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (local.get 1)) + (else + (return_call $vis + (i64.sub (local.get 0) (i64.const 1)) + (i64.mul (local.get 0) (local.get 1)) + (local.get 2) + ) + ) + ) + ) + ;; same as $fac-acc but fails on i == 6 + (func $fac-acc-broken (param i64 i64 funcref) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (local.get 1)) + (else + (return_call $vis + (i64.sub (local.get 0) (i64.const 1)) + (i64.mul (local.get 0) (local.get 1)) + (select (result funcref) + (ref.null func) (local.get 2) + (i64.eq (local.get 0) (i64.const 6))) + ) + ) + ) + ) + (func $vis (export "vis") (param i64 i64 funcref) (result i64) + local.get 0 + local.get 1 + local.get 2 + local.get 2 + ref.cast (ref null $t) + return_call_ref $t + ) + (func $trap (export "trap") (param i64 i64 funcref) (result i64) + unreachable + ) + (func (export "main") (param i64) (result i64) + (call $vis (local.get 0) (i64.const 1) (ref.func $fac-acc)) + ) + (func (export "main_null") (param i64) (result i64) + (return_call $vis (local.get 0) (i64.const 1) (ref.null $t)) + ) + (func (export "main_broken") (param i64) (result i64) + (return_call $vis (local.get 0) (i64.const 1) (ref.func $fac-acc-broken)) + ) +)`); + +// Check return call via wasm function +assertEq(ins.exports.main(5n), 120n); + +// Check return call directly via interpreter stub +const fac = ins.exports["fac-acc"]; +const vis = ins.exports["vis"]; +assertEq(vis(4n, 1n, fac), 24n); + +// Calling into JavaScript (and back). +if ("Function" in WebAssembly) { + const visFn = new WebAssembly.Function({ + parameters: ["i64", "i64", "funcref"], + results: ["i64"] + }, function (i, n, fn) { + if (i <= 0n) { + return n; + } + return vis(i - 1n, i * n, fn); + }); + + assertEq(vis(3n, 1n, visFn), 6n); +} + +// Check return call directly via jit stub +check_stub1: { + let options = getJitCompilerOptions(); + if (!options["baseline.enable"]) break check_stub1; + const check = function() { + vis(4n, 1n, fac); + }; + for (let i = options["baseline.warmup.trigger"] + 1; i--;) + check(); +} + +// Handling traps. +const trap = ins.exports["trap"]; +assertErrorMessage(() => vis(4n, 1n, trap), WebAssembly.RuntimeError, /unreachable executed/); +const main_broken = ins.exports["main_broken"]; +assertErrorMessage(() => main_broken(8n), WebAssembly.RuntimeError, /dereferencing null pointer/); +const main_null = ins.exports["main_null"]; +assertErrorMessage(() => main_null(5n), WebAssembly.RuntimeError, /dereferencing null pointer/); |