summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/ref-types/stackmaps1.js
blob: 0776b490b2f31a3dd33109da1effac0bb155e159 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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) ));