summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/exceptions/memory.js
blob: fef249ddf5f69aea5b36d55d9ab11771aecfd084 (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
// Ensure memory operations work after a throw coming from a function call.
// These are also testing that the InstanceReg/HeapReg are set correctly after
// catching an exception. There are some variations to the kind of calls here;
// we test for direct/indirect calls of local/imported functions, and the
// indirect calls may come from a local table or an imported table.

// Throw from a direct/indirect call of a local/imported function.
{
  let exports = wasmEvalText(
    `(module $m
       (memory $mem (data "bar"))
       (tag $exn (export "exn"))
       (tag $dummyExn (export "dummyExn"))
       (func $throwsExn (export "throwsExn")
         (throw $exn))
       (func $anotherThrowsExn
         (throw $exn))
       (func $throwsDummyExn (export "throwsDummyExn")
         (throw $dummyExn))
       (table (export "tab") funcref (elem $anotherThrowsExn $throwsDummyExn)))`
  ).exports;

  function testMemoryAfterCall(callInstruction) {
    assertEq(
      wasmEvalText(
        `(module
           (import "m" "exn" (tag $exn))
           (tag $localExn (param i32))
           (type $t (func))
           (import "m" "tab" (table $importTable 2 funcref))
           (import "m" "throwsExn" (func $importFuncThrowsExn))
           (memory $mem (data "foo"))
           (func $localFuncThrowsExn
             (throw $exn))
           (table $localTable funcref
                  (elem $localFuncThrowsExn $importFuncThrowsExn))
           (func $anotherLocalFuncThrowsExn
             (throw $exn))
           (func $throwsLocalExn
             (throw $localExn
               (i32.const 9)))
           (func (export "testFunc") (result i32)
             (try (result i32)
               (do
                 ${callInstruction}
                 ;; All the rest should not be reachable.
                 (call $anotherLocalFuncThrowsExn)
                 (throw $exn)
                 (call $throwsLocalExn)
                 unreachable)
               (catch $localExn)
               (catch $exn
                 (i32.load8_u
                   (i32.const 0)))
               (catch $exn
                 ;; This should be ignored.
                 unreachable))))`,
        { m: exports }
      ).exports.testFunc(),
      'foo'.charCodeAt(0)
    );
  };

  // Run test for various calls.
  let callInstructions =
      ["(call $anotherLocalFuncThrowsExn)",
       "(call $importFuncThrowsExn)",
       // Calls $localFuncThrowsExn.
       "(call_indirect $localTable (type $t) (i32.const 0))",
       // Calls $importFuncThrowsExn.
       "(call_indirect $localTable (type $t) (i32.const 1))",
       // Calls non exported function of the exports module $anotherThrowsExn.
       "(call_indirect $importTable (type $t) (i32.const 0))"];

  for (let callInstruction of callInstructions) {
    testMemoryAfterCall(callInstruction);
  }
}