diff options
Diffstat (limited to 'js/src/jit-test/tests/wasm/ref-types/stackmaps1.js')
-rw-r--r-- | js/src/jit-test/tests/wasm/ref-types/stackmaps1.js | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/ref-types/stackmaps1.js b/js/src/jit-test/tests/wasm/ref-types/stackmaps1.js new file mode 100644 index 0000000000..0776b490b2 --- /dev/null +++ b/js/src/jit-test/tests/wasm/ref-types/stackmaps1.js @@ -0,0 +1,85 @@ +// Tests wasm frame tracing. Only tests for direct and indirect call chains +// in wasm that lead to JS allocation. Does not test any timeout or interrupt +// related aspects. The structure is +// +// test top level: call fn2 +// fn2: call fn1 +// fn1: do 100k times { call-direct fn0; call-indirect fn0; } +// fn0: call out to JS that does allocation +// +// Eventually fn0 will trigger GC and we expect the chain of resulting frames +// to be traced correctly. fn2, fn1 and fn0 have some ref-typed args, so +// there will be traceable stack words to follow, in the sequence of frames. + +const {Module,Instance} = WebAssembly; + +let t = + `(module + (import "" "check3" (func $check3 (param externref) (param externref) (param externref))) + (import "" "alloc" (func $alloc (result externref))) + (type $typeOfFn0 + (func (param i32) (param externref) (param i32) + (param externref) (param externref) (param i32) (result i32))) + (table 1 1 funcref) + (elem (i32.const 0) $fn0) + + ;; -- fn 0 + (func $fn0 (export "fn0") + (param $arg1 i32) (param $arg2 externref) (param $arg3 i32) + (param $arg4 externref) (param $arg5 externref) (param $arg6 i32) (result i32) + (call $alloc) + drop + (i32.add (i32.add (local.get $arg1) (local.get $arg3)) (local.get $arg6)) + + ;; Poke the ref-typed arguments, to be sure that they got kept alive + ;; properly across any GC that the |alloc| call might have done. + (call $check3 (local.get $arg2) (local.get $arg4) (local.get $arg5)) + ) + + ;; -- fn 1 + (func $fn1 (export "fn1") (param $arg1 externref) (result i32) + (local $i i32) + + (loop (result i32) + ;; call direct 0 + (call $fn0 (i32.const 10) (local.get $arg1) (i32.const 12) + (local.get $arg1) (local.get $arg1) (i32.const 15)) + + ;; call indirect 0 + (call_indirect (type $typeOfFn0) + (i32.const 10) (local.get $arg1) (i32.const 12) + (local.get $arg1) (local.get $arg1) (i32.const 15) + (i32.const 0)) ;; table index + + i32.add + + ;; Do 60k iterations of this loop, to get a good amount of allocation + (local.set $i (i32.add (local.get $i) (i32.const 1))) + (br_if 0 (i32.lt_s (local.get $i) (i32.const 60000))) + ) + ) + + ;; -- fn 2 + (func $fn2 (export "fn2") (param $arg1 externref) (result i32) + (call $fn1 (local.get $arg1)) + ) + )`; + +function Croissant(chocolate, number) { + this.chocolate = chocolate; + this.number = number; +} + +function allocates() { + return new Croissant(true, 271828); +} + +function check3(a1, a2, a3) { + assertEq(a1.number, 31415927); + assertEq(a2.number, 31415927); + assertEq(a3.number, 31415927); +} + +let i = wasmEvalText(t, {"":{alloc: allocates, check3: check3}}); + +print(i.exports.fn2( new Croissant(false, 31415927) )); |