WebAssembly: don't eagerly checksum
[WebKit-https.git] / JSTests / wasm / function-tests / stack-overflow.js
1 import Builder from '../Builder.js'
2 import * as assert from '../assert.js'
3
4 {
5     function makeInstance() {
6         const tableDescription = {initial: 1, element: "anyfunc"};
7         const builder = new Builder()
8             .Type()
9                 .Func(["i32"], "void")
10             .End()
11             .Import()
12                 .Table("imp", "table", tableDescription)
13             .End()
14             .Function().End()
15             .Export()
16                 .Function("foo")
17             .End()
18             .Code()
19                 .Function("foo", 0 /*['i32'] => 'void'*/)
20                     .GetLocal(0) // parameter to call
21                     .GetLocal(0) // call index
22                     .CallIndirect(0, 0) // calling function of type ['i32'] => 'i32'
23                     .Return()
24                 .End()
25             .End();
26
27
28         const bin = builder.WebAssembly().get();
29         const module = new WebAssembly.Module(bin);
30         const table = new WebAssembly.Table(tableDescription);
31         return {instance: new WebAssembly.Instance(module, {imp: {table}}), table};
32     }
33
34     const {instance: i1, table: t1} = makeInstance();
35     const {instance: i2, table: t2} = makeInstance();
36     t2.set(0, i1.exports.foo);
37     t1.set(0, i2.exports.foo);
38
39     function assertOverflows(instance) {
40         let stack;
41         try {
42             instance.exports.foo(0)
43         } catch(e) {
44             stack = e.stack;
45         }
46         stack = stack.split("\n");
47         assert.truthy(stack.length > 50);
48         for (let i = 0; i < 50; ++i) {
49             let item = stack[stack.length - i - 1];
50             assert.eq(item, '<?>.wasm-function[0]@[wasm code]');
51         } 
52     }
53     assertOverflows(i1);
54     assertOverflows(i2);
55
56 }
57
58 {
59     function makeInstance() {
60         const tableDescription = {initial: 1, element: "anyfunc"};
61         const builder = new Builder()
62             .Type()
63                 .Func([], "void")
64             .End()
65             .Import()
66                 .Table("imp", "table", tableDescription)
67             .End()
68             .Function().End()
69             .Export()
70                 .Function("foo")
71             .End()
72             .Code()
73                 .Function("foo", {params:["i32"], ret:"void"})
74                     .GetLocal(0) // parameter to call
75                     .GetLocal(0) // call index
76                     .CallIndirect(0, 0) // calling function of type [] => 'void'
77                     .Return()
78                 .End()
79             .End();
80
81
82         const bin = builder.WebAssembly().get();
83         const module = new WebAssembly.Module(bin);
84         const table = new WebAssembly.Table(tableDescription);
85         return {instance: new WebAssembly.Instance(module, {imp: {table}}), table};
86     }
87
88     function makeInstance2(f) {
89         const builder = new Builder()
90             .Type()
91             .End()
92             .Import()
93                 .Function("imp", "f", {params:['i32'], ret:"void"})
94             .End()
95             .Function().End()
96             .Export()
97                 .Function("foo")
98             .End()
99             .Code()
100                 .Function("foo", {params: [], ret: "void" })
101                     .I32Const(0)
102                     .Call(0)
103                     .Return()
104                 .End()
105             .End();
106
107
108         const bin = builder.WebAssembly().get();
109         const module = new WebAssembly.Module(bin);
110         return new WebAssembly.Instance(module, {imp: {f}});
111     }
112
113     const {instance: i1, table: t1} = makeInstance();
114     const foo = i1.exports.foo;
115     const i2 = makeInstance2(i1.exports.foo);
116     t1.set(0, i2.exports.foo);
117
118     function assertThrows(instance) {
119         let stack;
120         try {
121             instance.exports.foo();
122         } catch(e) {
123             stack = e.stack;
124         }
125         assert.truthy(stack);
126
127         stack = stack.split("\n");
128         assert.truthy(stack.length > 50);
129         const one = '<?>.wasm-function[1]@[wasm code]';
130         const zero = '<?>.wasm-function[0]@[wasm code]';
131         let currentIndex = (one === stack[stack.length - 1]) ? 1 : 0;
132         for (let i = 0; i < 50; ++i) {
133             let item = stack[stack.length - 1 - i];
134             if (currentIndex === 1) {
135                 assert.eq(item, one);
136                 currentIndex = 0;
137             } else {
138                 assert.eq(currentIndex, 0);
139                 assert.eq(item, zero);
140                 currentIndex = 1;
141             }
142         }
143     }
144
145     for (let i = 0; i < 20; ++i) {
146         assertThrows(i2);
147         assertThrows(i1);
148     }
149
150     for (let i = 0; i < 20; ++i) {
151         assertThrows(i1);
152         assertThrows(i2);
153     }
154 }
155
156 {
157     function test(numArgs) {
158         function makeSignature() {
159             let args = [];
160             for (let i = 0; i < numArgs; ++i) {
161                 args.push("i32");
162             }
163             return {params: args};
164         }
165         function makeInstance(f) {
166             let builder = new Builder()
167                 .Type()
168                     .Func([], "void")
169                 .End()
170                 .Import()
171                     .Function("imp", "f", makeSignature())
172                 .End()
173                 .Function().End()
174                 .Export()
175                     .Function("foo")
176                 .End()
177                 .Code()
178                     .Function("foo", {params:[], ret:"void"});
179             for (let i = 0; i < numArgs; ++i) {
180                 builder = builder.I32Const(i);
181             }
182
183             builder = builder.Call(0).Return().End().End();
184             const bin = builder.WebAssembly().get();
185             const module = new WebAssembly.Module(bin);
186             return new WebAssembly.Instance(module, {imp: {f}});
187         }
188
189         function f(...args) {
190             assert.eq(args.length, numArgs);
191             for (let i = 0; i < args.length; ++i)
192                 assert.eq(args[i], i);
193
194             instance.exports.foo();
195         }
196         let instance = makeInstance(f);
197
198         let stack;
199         try {
200             instance.exports.foo();
201         } catch(e) {
202             stack = e.stack;
203         }
204         assert.truthy(stack.split("\n").length > 25);
205     }
206
207     for (let i = 0; i < 70; ++i) {
208         let r = Math.random() * 1000 | 0;
209         test(r);
210     }
211
212     test(20);
213     test(20);
214     test(1000);
215     test(2);
216     test(1);
217     test(0);
218     test(700);
219     test(433);
220     test(42);
221 }