diff options
Diffstat (limited to 'js/src/jit-test/tests/wasm/tail-calls/litmus11.js')
-rw-r--r-- | js/src/jit-test/tests/wasm/tail-calls/litmus11.js | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/tail-calls/litmus11.js b/js/src/jit-test/tests/wasm/tail-calls/litmus11.js new file mode 100644 index 0000000000..78c7cd4c49 --- /dev/null +++ b/js/src/jit-test/tests/wasm/tail-calls/litmus11.js @@ -0,0 +1,66 @@ +// |jit-test| skip-if: !wasmTailCallsEnabled() + +// Once we exhaust the register arguments this will alternately grow and then +// shrink the stack frame across tail call boundaries because the increment of +// stack allocation is 16 bytes and our variability exceeds that. +// +// (This is not redundant with eg litmus0, because in that case all the +// functions have the same ballast. Here we have different ballast, so we get growing and +// shrinking.) +// +// See litmus13 for the same-module call_indirect case. +// See litmus16 for the cross-module call_indirect case. + +function ntimes(n, v) { + if (typeof v == "function") + return iota(n).map(v).join(' '); + return iota(n).map(_ => v).join(' '); +} + +function get_local(n) { + return `(local.get ${n})` +} + +function compute(ballast) { + return iota(ballast).reduce((p,g,n) => `(i32.or ${p} (local.get ${n}))`, + `(i32.const ${1 << ballast})`) +} + +function build(n, ballast) { + switch (n) { + case 0: + return ` +(func $f0 (export "f") (result i32) + (return_call $f1 (i32.const ${1 << n}))) +`; + case ballast: + return ` +(func $f${ballast} (param ${ntimes(ballast, 'i32')}) (result i32) + (if (result i32) (i32.eqz (global.get $glob)) + (then (return ${compute(ballast)})) + (else (block (result i32) + (global.set $glob (i32.sub (global.get $glob) (i32.const 1))) + (return_call $f0))))) +`; + default: + return ` +(func $f${n} (param ${ntimes(n, 'i32')}) (result i32) + (return_call $f${n+1} (i32.const ${1 << n}) ${ntimes(n, get_local)})) +` + } +} + +for ( let ballast=1; ballast < TailCallBallast; ballast++ ) { + + let vals = iota(ballast+1).map(v => 1 << v); + let sumv = vals.reduce((p,c) => p|c); + let text = ` +(module + (global $glob (mut i32) (i32.const ${TailCallIterations})) + ${ntimes(ballast, n => build(n, ballast))} + ${build(ballast, ballast)}) +`; + + let ins = wasmEvalText(text); + assertEq(ins.exports.f(), sumv); +} |