summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/regress/current-memory-tls.js
blob: 6bd46b2b5f88dd28104e077efb2d066e67bf0646 (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
86
87
88
89
90
91
92
93
94
95
// Bug 1341650:
// - when compiled with Ion, pass the TLS register to memory.size;
// - when compiled with Baseline, don't clobber the last stack slot when
// calling into memory.size/memory.grow;

// This toy module starts with an empty memory, then tries to set values at different
// indexes, automatically growing memory when that would trigger an out of
// bounds access, for the exact right amount of pages. Note it's not made for
// efficiency, but optimizing it doesn't trigger the bugs mentioned above.

let i = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(`
(module
    (memory $mem (export "mem") 0 65535)

    (func (export "cur_mem") (result i32) (memory.size))

    (func $maybeGrow (param $i i32) (local $smem i32)
     ;; get memory.size in number of bytes, not pages.
     memory.size
     i64.extend_u/i32
     i64.const 65536
     i64.mul

     ;; get the last byte index accessed by an int32 access.
     local.get $i
     i32.const 3
     i32.add
     tee_local $i
     i64.extend_u/i32

     ;; if the memory is too small, grow it.
     i64.le_u
     if
         ;; get the floor of the accessed *page* index.
         local.get $i
         i64.extend_u/i32
         i64.const 65536
         i64.div_u

         ;; subtract to that the size of the current memory in pages;
         ;; that's the amount of pages we want to grow, minus one.
         memory.size
         i64.extend_u/i32

         i64.sub

         ;; add 1 to that amount.
         i64.const 1
         i64.add

         ;; get back to i32 and grow memory.
         i32.wrap/i64
         memory.grow
         drop
     end
    )

    (func (export "set") (param $i i32) (param $v i32)
     local.get $i
     call $maybeGrow
     local.get $i
     local.get $v
     i32.store
    )

    (func (export "get") (param $i i32) (result i32)
     local.get $i
     i32.load
    )
)
`))).exports;

assertEq(i.cur_mem(), 0);

i.set(0, 1);
assertEq(i.get(0), 1);

assertEq(i.cur_mem(), 1);

i.set(1234, 1);
assertEq(i.get(1234), 1);

assertEq(i.cur_mem(), 1);

i.set(65532, 1);
assertEq(i.get(65532), 1);

assertErrorMessage(() => i.get(65533), WebAssembly.RuntimeError, /index out of bounds/);

assertEq(i.cur_mem(), 1);

i.set(65533, 1);
assertEq(i.get(65533), 1);

assertEq(i.cur_mem(), 2);