summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/ref-types/stackmaps1.js
diff options
context:
space:
mode:
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.js85
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) ));