summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/ref-types/stackmaps4-params-n-locals.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/wasm/ref-types/stackmaps4-params-n-locals.js')
-rw-r--r--js/src/jit-test/tests/wasm/ref-types/stackmaps4-params-n-locals.js143
1 files changed, 143 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/ref-types/stackmaps4-params-n-locals.js b/js/src/jit-test/tests/wasm/ref-types/stackmaps4-params-n-locals.js
new file mode 100644
index 0000000000..2b95ea14a6
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/ref-types/stackmaps4-params-n-locals.js
@@ -0,0 +1,143 @@
+// A stress test for stackmap creation as it relates to params and locals.
+
+function Stuff(n) {
+ this.n = n;
+}
+function allocate(n) {
+ const res = new Stuff(n);
+ // The webassembly loop below will provide us with 254 as an arg after not
+ // very long.
+ if (n == 254) {
+ gc();
+ }
+ return res;
+}
+
+function visit(aStuff) {
+ return aStuff.n;
+}
+
+let bin = wasmTextToBinary(
+`
+(module
+ (import "" "allocate" (func $allocate (param i32) (result externref)))
+ (import "" "visit" (func $visit (param externref) (result i32)))
+
+ ;; A function with many params and locals, most of which are ref-typed.
+ ;; The purpose of having so many is to defeat any reasonable attempt at
+ ;; allocating them all in registers. The asymmetrically-placed i32s are
+ ;; an attempt to expose any misalignment or inversion of the stack layout
+ ;; vs what the stackmap claims the layout to be.
+
+ (func $manyParamsAndLocals (export "manyParamsAndLocals")
+ (param $p1 externref) (param $p2 i32) (param $p3 externref)
+ (param $p4 externref) (param $p5 externref) (param $p6 externref)
+ (param $p7 externref) (param $p8 externref) (param $p9 i32)
+ (result i32)
+ (local $l1 externref) (local $l2 externref) (local $l3 externref)
+ (local $l4 i32) (local $l5 externref) (local $l6 i32)
+ (local $l7 externref) (local $l8 externref) (local $l9 externref)
+
+ (local $i i32)
+ (local $runningTotal i32)
+
+ ;; Bind some objects to l1 .. l9. The JS harness will already
+ ;; have done the same for p1 .. p9.
+ (local.set $l1 (call $allocate (i32.const 1)))
+ (local.set $l2 (call $allocate (i32.const 3)))
+ (local.set $l3 (call $allocate (i32.const 5)))
+ (local.set $l4 (i32.const 7))
+ (local.set $l5 (call $allocate (i32.const 9)))
+ (local.set $l6 (i32.const 11))
+ (local.set $l7 (call $allocate (i32.const 13)))
+ (local.set $l8 (call $allocate (i32.const 15)))
+ (local.set $l9 (call $allocate (i32.const 17)))
+
+ ;; Now loop, allocating as we go, and forcing GC every 256 iterations.
+ ;; Also in each iteration, visit all the locals and params, in the hope
+ ;; of exposing any cases where they are not held live across GC.
+ (loop $CONT
+ ;; Allocate, and hold on to the resulting value, so that Ion can't
+ ;; delete the allocation.
+ (local.set $l9 (call $allocate (i32.and (local.get $i) (i32.const 255))))
+
+ ;; Visit all params and locals
+
+ local.get $runningTotal
+
+ (call $visit (local.get $p1))
+ i32.add
+ local.get $p2
+ i32.add
+ (call $visit (local.get $p3))
+ i32.add
+ (call $visit (local.get $p4))
+ i32.add
+ (call $visit (local.get $p5))
+ i32.add
+ (call $visit (local.get $p6))
+ i32.add
+ (call $visit (local.get $p7))
+ i32.add
+ (call $visit (local.get $p8))
+ i32.add
+ local.get $p9
+ i32.add
+
+ (call $visit (local.get $l1))
+ i32.add
+ (call $visit (local.get $l2))
+ i32.add
+ (call $visit (local.get $l3))
+ i32.add
+ local.get $l4
+ i32.add
+ (call $visit (local.get $l5))
+ i32.add
+ local.get $l6
+ i32.add
+ (call $visit (local.get $l7))
+ i32.add
+ (call $visit (local.get $l8))
+ i32.add
+ (call $visit (local.get $l9))
+ i32.add
+
+ local.set $runningTotal
+
+ (local.set $i (i32.add (local.get $i) (i32.const 1)))
+ (br_if $CONT (i32.lt_s (local.get $i) (i32.const 10000)))
+ ) ;; loop
+
+ local.get $runningTotal
+ ) ;; func
+)
+`);
+
+let mod = new WebAssembly.Module(bin);
+let ins = new WebAssembly.Instance(mod, {"":{allocate, visit}});
+
+let p1 = allocate(97);
+let p2 = 93;
+let p3 = allocate(91);
+let p4 = allocate(83);
+let p5 = allocate(79);
+let p6 = allocate(73);
+let p7 = allocate(71);
+let p8 = allocate(67);
+let p9 = 61;
+
+let res = ins.exports.manyParamsAndLocals(p1, p2, p3, p4, p5, p6, p7, p8, p9);
+
+// Check that GC didn't mess up p1 .. p9
+res += visit(p1);
+res += p2;
+res += visit(p3);
+res += visit(p4);
+res += visit(p5);
+res += visit(p6);
+res += visit(p7);
+res += visit(p8);
+res += p9;
+
+assertEq(res, 9063795);