WebAssembly JS API: implement more sections
[WebKit-https.git] / Source / JavaScriptCore / testWasm.cpp
1 /*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #include "B3Common.h"
29 #include "B3Compilation.h"
30 #include "InitializeThreading.h"
31 #include "JSCJSValueInlines.h"
32 #include "JSString.h"
33 #include "LLIntThunks.h"
34 #include "ProtoCallFrame.h"
35 #include "VM.h"
36 #include "WasmMemory.h"
37 #include "WasmPlan.h"
38
39 #include <wtf/DataLog.h>
40 #include <wtf/LEBDecoder.h>
41
42 class CommandLine {
43 public:
44     CommandLine(int argc, char** argv)
45     {
46         parseArguments(argc, argv);
47     }
48
49     Vector<String> m_arguments;
50     bool m_runLEBTests { false };
51     bool m_runWasmTests { false };
52
53     void parseArguments(int, char**);
54 };
55
56 static NO_RETURN void printUsageStatement(bool help = false)
57 {
58     fprintf(stderr, "Usage: testWasm [options]\n");
59     fprintf(stderr, "  -h|--help  Prints this help message\n");
60     fprintf(stderr, "  -l|--leb   Runs the LEB decoder tests\n");
61     fprintf(stderr, "  -w|--web   Run the Wasm tests\n");
62     fprintf(stderr, "\n");
63
64     exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
65 }
66
67 void CommandLine::parseArguments(int argc, char** argv)
68 {
69     int i = 1;
70
71     for (; i < argc; ++i) {
72         const char* arg = argv[i];
73         if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
74             printUsageStatement(true);
75
76         if (!strcmp(arg, "-l") || !strcmp(arg, "--leb"))
77             m_runLEBTests = true;
78
79         if (!strcmp(arg, "-w") || !strcmp(arg, "--web"))
80             m_runWasmTests = true;
81     }
82
83     for (; i < argc; ++i)
84         m_arguments.append(argv[i]);
85
86 }
87
88 StaticLock crashLock;
89
90 #define CHECK_EQ(x, y) do { \
91         auto __x = (x); \
92         auto __y = (y); \
93         if (__x == __y) \
94         break; \
95         crashLock.lock(); \
96         WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, toCString(#x " == " #y, " (" #x " == ", __x, ", " #y " == ", __y, ")").data()); \
97         CRASH(); \
98     } while (false)
99
100 #define CHECK(x) CHECK_EQ(x, true)
101
102 #define FOR_EACH_UNSIGNED_LEB_TEST(macro) \
103     /* Simple tests that use all the bits in the array */ \
104     macro(({ 0x07 }), 0, true, 0x7lu, 1lu) \
105     macro(({ 0x77 }), 0, true, 0x77lu, 1lu) \
106     macro(({ 0x80, 0x07 }), 0, true, 0x380lu, 2lu) \
107     macro(({ 0x89, 0x12 }), 0, true, 0x909lu, 2lu) \
108     macro(({ 0xf3, 0x85, 0x02 }), 0, true, 0x82f3lu, 3lu) \
109     macro(({ 0xf3, 0x85, 0xff, 0x74 }), 0, true, 0xe9fc2f3lu, 4lu) \
110     macro(({ 0xf3, 0x85, 0xff, 0xf4, 0x7f }), 0, true, 0xfe9fc2f3lu, 5lu) \
111     /* Test with extra trailing numbers */ \
112     macro(({ 0x07, 0x80 }), 0, true, 0x7lu, 1lu) \
113     macro(({ 0x07, 0x75 }), 0, true, 0x7lu, 1lu) \
114     macro(({ 0xf3, 0x85, 0xff, 0x74, 0x43 }), 0, true, 0xe9fc2f3lu, 4lu) \
115     macro(({ 0xf3, 0x85, 0xff, 0x74, 0x80 }), 0, true, 0xe9fc2f3lu, 4lu) \
116     /* Test with preceeding numbers */ \
117     macro(({ 0xf3, 0x07 }), 1, true, 0x7lu, 2lu) \
118     macro(({ 0x03, 0x07 }), 1, true, 0x7lu, 2lu) \
119     macro(({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77 }), 5, true, 0x77lu, 6lu) \
120     macro(({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77 }), 5, true, 0x77lu, 6ul) \
121     macro(({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02 }), 3, true, 0x82f3lu, 6lu) \
122     /* Test in the middle */ \
123     macro(({ 0xf3, 0x07, 0x89 }), 1, true, 0x7lu, 2lu) \
124     macro(({ 0x03, 0x07, 0x23 }), 1, true, 0x7lu, 2lu) \
125     macro(({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77, 0x43 }), 5, true, 0x77lu, 6lu) \
126     macro(({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77, 0xf9 }), 5, true, 0x77lu, 6lu) \
127     macro(({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02, 0xa4 }), 3, true, 0x82f3lu, 6lu) \
128     /* Test decode too long */ \
129     macro(({ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}), 0, false, 0x0lu, 0lu) \
130     macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 1, false, 0x0lu, 0lu) \
131     macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 0, false, 0x0lu, 0lu) \
132     /* Test decode off end of array */ \
133     macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 2, false, 0x0lu, 0lu) \
134
135
136 #define TEST_UNSIGNED_LEB_DECODE(init, startOffset, expectedStatus, expectedResult, expectedOffset) \
137     { \
138         Vector<uint8_t> vector = Vector<uint8_t> init; \
139         size_t offset = startOffset; \
140         uint32_t result; \
141         bool status = WTF::LEBDecoder::decodeUInt32(vector.data(), vector.size(), offset, result); \
142         CHECK_EQ(status, expectedStatus); \
143         if (expectedStatus) { \
144             CHECK_EQ(result, expectedResult); \
145             CHECK_EQ(offset, expectedOffset); \
146         } \
147     };
148
149
150 #define FOR_EACH_SIGNED_LEB_TEST(macro) \
151     /* Simple tests that use all the bits in the array */ \
152     macro(({ 0x07 }), 0, true, 0x7, 1lu) \
153     macro(({ 0x77 }), 0, true, -0x9, 1lu) \
154     macro(({ 0x80, 0x07 }), 0, true, 0x380, 2lu) \
155     macro(({ 0x89, 0x12 }), 0, true, 0x909, 2lu) \
156     macro(({ 0xf3, 0x85, 0x02 }), 0, true, 0x82f3, 3lu) \
157     macro(({ 0xf3, 0x85, 0xff, 0x74 }), 0, true, 0xfe9fc2f3, 4lu) \
158     macro(({ 0xf3, 0x85, 0xff, 0xf4, 0x7f }), 0, true, 0xfe9fc2f3, 5lu) \
159     /* Test with extra trailing numbers */ \
160     macro(({ 0x07, 0x80 }), 0, true, 0x7, 1lu) \
161     macro(({ 0x07, 0x75 }), 0, true, 0x7, 1lu) \
162     macro(({ 0xf3, 0x85, 0xff, 0x74, 0x43 }), 0, true, 0xfe9fc2f3, 4lu) \
163     macro(({ 0xf3, 0x85, 0xff, 0x74, 0x80 }), 0, true, 0xfe9fc2f3, 4lu) \
164     /* Test with preceeding numbers */ \
165     macro(({ 0xf3, 0x07 }), 1, true, 0x7, 2lu) \
166     macro(({ 0x03, 0x07 }), 1, true, 0x7, 2lu) \
167     macro(({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77 }), 5, true, -0x9, 6lu) \
168     macro(({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77 }), 5, true, -0x9, 6lu) \
169     macro(({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02 }), 3, true, 0x82f3, 6lu) \
170     /* Test in the middle */ \
171     macro(({ 0xf3, 0x07, 0x89 }), 1, true, 0x7, 2lu) \
172     macro(({ 0x03, 0x07, 0x23 }), 1, true, 0x7, 2lu) \
173     macro(({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77, 0x43 }), 5, true, -0x9, 6lu) \
174     macro(({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77, 0xf9 }), 5, true, -0x9, 6lu) \
175     macro(({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02, 0xa4 }), 3, true, 0x82f3, 6lu) \
176     /* Test decode too long */ \
177     macro(({ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}), 0, false, 0x0, 0lu) \
178     macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 1, false, 0x0, 0lu) \
179     macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 0, false, 0x0, 0lu) \
180     /* Test decode off end of array */ \
181     macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 2, false, 0x0, 0lu) \
182
183
184 #define TEST_SIGNED_LEB_DECODE(init, startOffset, expectedStatus, expectedResult, expectedOffset) \
185     { \
186         Vector<uint8_t> vector = Vector<uint8_t> init; \
187         size_t offset = startOffset; \
188         int32_t result; \
189         bool status = WTF::LEBDecoder::decodeInt32(vector.data(), vector.size(), offset, result); \
190         CHECK_EQ(status, expectedStatus); \
191         if (expectedStatus) { \
192             int32_t expected = expectedResult; \
193             CHECK_EQ(result, expected); \
194             CHECK_EQ(offset, expectedOffset); \
195         } \
196     };
197
198
199 static void runLEBTests()
200 {
201     FOR_EACH_UNSIGNED_LEB_TEST(TEST_UNSIGNED_LEB_DECODE)
202     FOR_EACH_SIGNED_LEB_TEST(TEST_SIGNED_LEB_DECODE)
203 }
204
205 #if ENABLE(WEBASSEMBLY)
206
207 static JSC::VM* vm;
208
209 using namespace JSC;
210 using namespace Wasm;
211 using namespace B3;
212
213 template<typename T>
214 T cast(EncodedJSValue value)
215 {
216     return static_cast<T>(value);
217 }
218
219 template<>
220 double cast(EncodedJSValue value)
221 {
222     return bitwise_cast<double>(value);
223 }
224
225 template<>
226 float cast(EncodedJSValue value)
227 {
228     return bitwise_cast<float>(static_cast<int>(value));
229 }
230
231 template<typename T>
232 T invoke(MacroAssemblerCodePtr ptr, std::initializer_list<JSValue> args)
233 {
234     JSValue firstArgument;
235     // Since vmEntryToJavaScript expects a this value we claim there is one... there isn't.
236     int argCount = 1;
237     JSValue* remainingArguments = nullptr;
238     if (args.size()) {
239         remainingArguments = const_cast<JSValue*>(args.begin());
240         firstArgument = *remainingArguments;
241         remainingArguments++;
242         argCount = args.size();
243     }
244
245     ProtoCallFrame protoCallFrame;
246     protoCallFrame.init(nullptr, nullptr, firstArgument, argCount, remainingArguments);
247
248     return cast<T>(vmEntryToWasm(ptr.executableAddress(), vm, &protoCallFrame));
249 }
250
251 template<typename T>
252 T invoke(const Compilation& code, std::initializer_list<JSValue> args)
253 {
254     return invoke<T>(code.code(), args);
255 }
256
257 inline JSValue box(uint64_t value)
258 {
259     return JSValue::decode(value);
260 }
261
262 inline JSValue boxf(float value)
263 {
264     return box(bitwise_cast<uint32_t>(value));
265 }
266
267 inline JSValue boxd(double value)
268 {
269     return box(bitwise_cast<uint64_t>(value));
270 }
271
272 static void checkPlan(Plan& plan, unsigned expectedNumberOfFunctions)
273 {
274     if (plan.failed()) {
275         dataLogLn("Module failed to compile with error: ", plan.errorMessage());
276         CRASH();
277     }
278
279     if (plan.compiledFunctionCount() != expectedNumberOfFunctions) {
280         dataLogLn("Incorrect number of functions");
281         CRASH();
282     }
283
284     for (unsigned i = 0; i < expectedNumberOfFunctions; ++i) {
285         if (!plan.compiledFunction(i)) {
286             dataLogLn("Function at index, " , i, " failed to compile correctly");
287             CRASH();
288         }
289     }
290
291 }
292
293 // For now we inline the test files.
294 static void runWasmTests()
295 {
296     {
297         // Generated from:
298         //    (module
299         //     (func (export "if-then-both-fallthrough") (param $x i32) (param $y i32) (result i32)
300         //      (block $block i32
301         //       (if i32 (i32.eq (get_local $x) (i32.const 0))
302         //        (then (i32.const 1))
303         //        (else
304         //         (i32.const 2)
305         //         (br $block))
306         //        )
307         //       )
308         //      )
309         //     )
310         Vector<uint8_t> vector = {
311             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
312             0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x9c, 0x80,
313             0x80, 0x80, 0x00, 0x01, 0x18, 0x69, 0x66, 0x2d, 0x74, 0x68, 0x65, 0x6e, 0x2d, 0x62, 0x6f, 0x74,
314             0x68, 0x2d, 0x66, 0x61, 0x6c, 0x6c, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x00, 0x00, 0x0a,
315             0x9a, 0x80, 0x80, 0x80, 0x00, 0x01, 0x94, 0x80, 0x80, 0x80, 0x00, 0x00, 0x01, 0x01, 0x14, 0x00,
316             0x10, 0x00, 0x4d, 0x03, 0x01, 0x10, 0x01, 0x04, 0x10, 0x02, 0x06, 0x01, 0x0f, 0x0f, 0x0f
317         };
318
319         Plan plan(*vm, vector);
320         checkPlan(plan, 1);
321
322         // Test this doesn't crash.
323         CHECK(isIdentical(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(0), boxf(32) }), 1));
324         CHECK(isIdentical(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(1), boxf(32) }), 2));
325     }
326
327     {
328         // Generated from:
329         //    (module
330         //     (func (export "if-then-both-fallthrough") (param $x i32) (param $y i32) (result i32)
331         //      (if i32 (i32.eq (get_local $x) (i32.const 0))
332         //       (then (i32.const 1))
333         //       (else (i32.const 2))
334         //       )
335         //      )
336         //     )
337         Vector<uint8_t> vector = {
338             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
339             0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x9c, 0x80,
340             0x80, 0x80, 0x00, 0x01, 0x18, 0x69, 0x66, 0x2d, 0x74, 0x68, 0x65, 0x6e, 0x2d, 0x62, 0x6f, 0x74,
341             0x68, 0x2d, 0x66, 0x61, 0x6c, 0x6c, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x00, 0x00, 0x0a,
342             0x95, 0x80, 0x80, 0x80, 0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x10, 0x00,
343             0x4d, 0x03, 0x01, 0x10, 0x01, 0x04, 0x10, 0x02, 0x0f, 0x0f
344         };
345
346         Plan plan(*vm, vector);
347         checkPlan(plan, 1);
348
349         // Test this doesn't crash.
350         CHECK(isIdentical(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(0), boxf(32) }), 1));
351         CHECK(isIdentical(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(1), boxf(32) }), 2));
352     }
353
354     {
355         // Generated from:
356         //    (module
357         //     (func (export "dumb-less-than") (param $x i32) (param $y i32) (result i32)
358         //      (loop $loop i32
359         //       (i32.eq (get_local $x) (get_local $y))
360         //       (if i32
361         //        (then (return (i32.const 0)))
362         //        (else
363         //         (get_local $x)
364         //         (set_local $x (i32.sub (get_local $x) (i32.const 1)))
365         //         (i32.const 0)
366         //         (i32.ne)
367         //         (br_if $loop)
368         //         (i32.const 1)
369         //         )
370         //        )
371         //       )
372         //      )
373         //     )
374         Vector<uint8_t> vector = {
375             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
376             0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x92, 0x80,
377             0x80, 0x80, 0x00, 0x01, 0x0e, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6c, 0x65, 0x73, 0x73, 0x2d, 0x74,
378             0x68, 0x61, 0x6e, 0x00, 0x00, 0x0a, 0xa7, 0x80, 0x80, 0x80, 0x00, 0x01, 0xa1, 0x80, 0x80, 0x80,
379             0x00, 0x00, 0x02, 0x01, 0x14, 0x00, 0x14, 0x01, 0x4d, 0x03, 0x01, 0x10, 0x00, 0x09, 0x04, 0x14,
380             0x00, 0x14, 0x00, 0x10, 0x01, 0x41, 0x15, 0x00, 0x10, 0x00, 0x4e, 0x07, 0x01, 0x10, 0x01, 0x0f,
381             0x0f, 0x0f
382         };
383
384         Plan plan(*vm, vector);
385         checkPlan(plan, 1);
386
387         // Test this doesn't crash.
388         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1);
389         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 0);
390         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 0);
391         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 1);
392         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 0);
393         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(1) }), 0);
394         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 1);
395         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 0);
396     }
397
398     {
399         // Generated from:
400         //    (module
401         //     (func $f32-sub (export "f32-sub") (param f32) (param f32) (result f32) (return (f32.sub (get_local 0) (get_local 1))))
402         //     (func (export "indirect-f32-sub") (param f32) (param f32) (result f32) (return (call $f32-sub (get_local 0) (get_local 1))))
403         //     )
404         Vector<uint8_t> vector = {
405             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
406             0x02, 0x03, 0x03, 0x01, 0x03, 0x03, 0x83, 0x80, 0x80, 0x80, 0x00, 0x02, 0x00, 0x00, 0x07, 0x9e,
407             0x80, 0x80, 0x80, 0x00, 0x02, 0x07, 0x66, 0x33, 0x32, 0x2d, 0x73, 0x75, 0x62, 0x00, 0x00, 0x10,
408             0x69, 0x6e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x2d, 0x66, 0x33, 0x32, 0x2d, 0x73, 0x75, 0x62,
409             0x00, 0x01, 0x0a, 0x9c, 0x80, 0x80, 0x80, 0x00, 0x02, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14,
410             0x00, 0x14, 0x01, 0x76, 0x09, 0x0f, 0x89, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01,
411             0x16, 0x00, 0x09, 0x0f
412         };
413
414         Plan plan(*vm, vector);
415         checkPlan(plan, 2);
416
417         // Test this doesn't crash.
418         CHECK(isIdentical(invoke<float>(*plan.compiledFunction(1)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f));
419         CHECK(isIdentical(invoke<float>(*plan.compiledFunction(1)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f));
420         CHECK(isIdentical(invoke<float>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f));
421         CHECK(isIdentical(invoke<float>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f));
422     }
423
424     {
425         // Generated from:
426         //    (module
427         //     (func $f32-add (export "f32-add") (param f32) (param f32) (result f32) (return (f32.add (get_local 0) (get_local 1))))
428         //     (func (export "indirect-f32-add") (param f32) (param f32) (result f32) (return (call $f32-add (get_local 0) (get_local 1))))
429         //     )
430         Vector<uint8_t> vector = {
431             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
432             0x02, 0x03, 0x03, 0x01, 0x03, 0x03, 0x83, 0x80, 0x80, 0x80, 0x00, 0x02, 0x00, 0x00, 0x07, 0x9e,
433             0x80, 0x80, 0x80, 0x00, 0x02, 0x07, 0x66, 0x33, 0x32, 0x2d, 0x61, 0x64, 0x64, 0x00, 0x00, 0x10,
434             0x69, 0x6e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x2d, 0x66, 0x33, 0x32, 0x2d, 0x61, 0x64, 0x64,
435             0x00, 0x01, 0x0a, 0x9c, 0x80, 0x80, 0x80, 0x00, 0x02, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14,
436             0x00, 0x14, 0x01, 0x75, 0x09, 0x0f, 0x89, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01,
437             0x16, 0x00, 0x09, 0x0f
438         };
439
440         Plan plan(*vm, vector);
441         checkPlan(plan, 2);
442
443         // Test this doesn't crash.
444         CHECK(isIdentical(invoke<float>(*plan.compiledFunction(1)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f));
445         CHECK(isIdentical(invoke<float>(*plan.compiledFunction(1)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f));
446         CHECK(isIdentical(invoke<float>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f));
447         CHECK(isIdentical(invoke<float>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f));
448     }
449
450     {
451         // Generated from:
452         //    (module
453         //     (memory 1)
454         //     (func $sum12 (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (result i32) (return (i32.add (get_local 0) (i32.add (get_local 1) (i32.add (get_local 2) (i32.add (get_local 3) (i32.add (get_local 4) (i32.add (get_local 5) (i32.add (get_local 6) (i32.add (get_local 7) (i32.add (get_local 8) (i32.add (get_local 9) (i32.add (get_local 10) (get_local 11))))))))))))))
455         //     (func (export "mult12") (param i32) (result i32) (return (call $sum12 (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0))))
456         //     )
457
458         Vector<uint8_t> vector = {
459             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x96, 0x80, 0x80, 0x80, 0x00, 0x02, 0x40,
460             0x0c, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40,
461             0x01, 0x01, 0x01, 0x01, 0x03, 0x83, 0x80, 0x80, 0x80, 0x00, 0x02, 0x00, 0x01, 0x05, 0x83, 0x80,
462             0x80, 0x80, 0x00, 0x01, 0x00, 0x01, 0x07, 0x8a, 0x80, 0x80, 0x80, 0x00, 0x01, 0x06, 0x6d, 0x75,
463             0x6c, 0x74, 0x31, 0x32, 0x00, 0x01, 0x0a, 0xce, 0x80, 0x80, 0x80, 0x00, 0x02, 0xa6, 0x80, 0x80,
464             0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x14, 0x02, 0x14, 0x03, 0x14, 0x04, 0x14, 0x05, 0x14,
465             0x06, 0x14, 0x07, 0x14, 0x08, 0x14, 0x09, 0x14, 0x0a, 0x14, 0x0b, 0x40, 0x40, 0x40, 0x40, 0x40,
466             0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x09, 0x0f, 0x9d, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00,
467             0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00,
468             0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x16, 0x00, 0x09, 0x0f
469         };
470
471         Plan plan(*vm, vector);
472         checkPlan(plan, 2);
473
474         // Test this doesn't crash.
475         CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(0) }), 0);
476         CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(100) }), 1200);
477         CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(1) }), 12);
478         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(12) }), 78);
479         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(100) }), 166);
480     }
481
482     {
483         // Generated from:
484         //    (module
485         //     (memory 1)
486         //     (func $fac (export "fac") (param i64) (result i64)
487         //      (if (i64.eqz (get_local 0))
488         //       (return (i64.const 1))
489         //       )
490         //      (return (i64.mul (get_local 0) (call $fac (i64.sub (get_local 0) (i64.const 1)))))
491         //      )
492         //     )
493         Vector<uint8_t> vector = {
494             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
495             0x01, 0x02, 0x01, 0x02, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 0x80,
496             0x80, 0x00, 0x01, 0x00, 0x01, 0x07, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x03, 0x66, 0x61, 0x63,
497             0x00, 0x00, 0x0a, 0x9e, 0x80, 0x80, 0x80, 0x00, 0x01, 0x98, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14,
498             0x00, 0x11, 0x00, 0x68, 0x03, 0x00, 0x11, 0x01, 0x09, 0x0f, 0x14, 0x00, 0x14, 0x00, 0x11, 0x01,
499             0x5c, 0x16, 0x00, 0x5d, 0x09, 0x0f
500         };
501
502         Plan plan(*vm, vector);
503         checkPlan(plan, 1);
504
505         // Test this doesn't crash.
506         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 1);
507         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1);
508         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2) }), 2);
509         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(4) }), 24);
510     }
511
512     {
513         // Generated from:
514         //    (module
515         //     (memory 1)
516         //     (func (export "double") (param i64) (result i64) (return (call 1 (get_local 0) (get_local 0))))
517         //     (func $sum (param i64) (param i64) (result i64) (return (i64.add (get_local 0) (get_local 1))))
518         //     )
519         Vector<uint8_t> vector = {
520             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x8c, 0x80, 0x80, 0x80, 0x00, 0x02, 0x40,
521             0x01, 0x02, 0x01, 0x02, 0x40, 0x02, 0x02, 0x02, 0x01, 0x02, 0x03, 0x83, 0x80, 0x80, 0x80, 0x00,
522             0x02, 0x00, 0x01, 0x05, 0x83, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x01, 0x07, 0x8a, 0x80, 0x80,
523             0x80, 0x00, 0x01, 0x06, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x0a, 0x9c, 0x80, 0x80,
524             0x80, 0x00, 0x02, 0x89, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x16, 0x01, 0x09,
525             0x0f, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x5b, 0x09, 0x0f
526         };
527
528         Plan plan(*vm, vector);
529         if (plan.compiledFunctionCount() != 2 || !plan.compiledFunction(0) || !plan.compiledFunction(1)) {
530             dataLogLn("Module failed to compile correctly.");
531             CRASH();
532         }
533
534         // Test this doesn't crash.
535         CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(0), box(0) }), 0);
536         CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(100), box(0) }), 100);
537         CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(1), box(15) }), 16);
538         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
539         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 200);
540         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 2);
541     }
542
543     {
544         // Generated from:
545         //    (module
546         //     (memory 1)
547         //     (func $id (param $value i32) (result i32) (return (get_local $value)))
548         //     (func (export "id-call") (param $value i32) (result i32) (return (call $id (get_local $value))))
549         //     )
550         Vector<uint8_t> vector = {
551             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
552             0x01, 0x01, 0x01, 0x01, 0x03, 0x83, 0x80, 0x80, 0x80, 0x00, 0x02, 0x00, 0x00, 0x05, 0x83, 0x80,
553             0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8b, 0x80, 0x80, 0x80, 0x00, 0x01, 0x07, 0x69, 0x64,
554             0x2d, 0x63, 0x61, 0x6c, 0x6c, 0x00, 0x01, 0x0a, 0x97, 0x80, 0x80, 0x80, 0x00, 0x02, 0x85, 0x80,
555             0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x09, 0x0f, 0x87, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00,
556             0x16, 0x00, 0x09, 0x0f
557         };
558
559         Plan plan(*vm, vector);
560         checkPlan(plan, 2);
561
562         // Test this doesn't crash.
563         CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(0) }), 0);
564         CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(100) }), 100);
565         CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(1) }), 1);
566         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
567         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 100);
568         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1);
569     }
570
571     {
572         // Generated from:
573         //    (module
574         //     (memory 1)
575         //     (func (export "i64") (param $i i64) (param $ptr i32) (result i64)
576         //      (i64.store (get_local $ptr) (get_local $i))
577         //      (return (i64.load (get_local $ptr)))
578         //      )
579         //     )
580         Vector<uint8_t> vector = {
581             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
582             0x02, 0x02, 0x01, 0x01, 0x02, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
583             0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x03, 0x69, 0x36,
584             0x34, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80, 0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00,
585             0x14, 0x01, 0x14, 0x00, 0x34, 0x03, 0x00, 0x14, 0x01, 0x2b, 0x03, 0x00, 0x09, 0x0f
586         };
587
588         Plan plan(*vm, vector);
589         checkPlan(plan, 1);
590
591         // Test this doesn't crash.
592         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
593         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
594         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
595     }
596
597     {
598         // Generated from:
599         // (module
600         //  (memory 1)
601         //  (func (export "i32_load8_s") (param $i i32) (param $ptr i32) (result i32)
602         //   (i32.store (get_local $ptr) (get_local $i))
603         //   (return (i32.load (get_local $ptr)))
604         //   )
605         //  )
606         Vector<uint8_t> vector = {
607             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
608             0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
609             0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33,
610             0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80,
611             0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x33, 0x02, 0x00, 0x14,
612             0x01, 0x2a, 0x02, 0x00, 0x09, 0x0f
613         };
614
615         Plan plan(*vm, vector);
616         checkPlan(plan, 1);
617
618         // Test this doesn't crash.
619         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
620         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
621         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
622     }
623
624     {
625         // Generated from:
626         //    (module
627         //     (memory 1)
628         //     (func (export "write_array") (param $x i32) (param $p i32) (param $length i32) (local $i i32)
629         //      (set_local $i (i32.const 0))
630         //      (block
631         //       (loop
632         //        (br_if 1 (i32.ge_u (get_local $i) (get_local $length)))
633         //        (i32.store (i32.add (get_local $p) (i32.mul (get_local $i) (i32.const 4))) (get_local $x))
634         //        (set_local $i (i32.add (i32.const 1) (get_local $i)))
635         //        (br 0)
636         //        )
637         //       )
638         //      (return)
639         //      )
640         //     )
641         Vector<uint8_t> vector = {
642             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
643             0x03, 0x01, 0x01, 0x01, 0x00, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
644             0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x77, 0x72,
645             0x69, 0x74, 0x65, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x00, 0x00, 0x0a, 0xb2, 0x80, 0x80, 0x80,
646             0x00, 0x01, 0xac, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x03, 0x01, 0x00,
647             0x02, 0x00, 0x14, 0x03, 0x14, 0x02, 0x56, 0x07, 0x01, 0x14, 0x01, 0x14, 0x03, 0x10, 0x04, 0x42,
648             0x40, 0x14, 0x00, 0x33, 0x02, 0x00, 0x10, 0x01, 0x14, 0x03, 0x40, 0x15, 0x03, 0x06, 0x00, 0x0f,
649             0x0f, 0x09, 0x0f
650         };
651
652         Plan plan(*vm, vector);
653         checkPlan(plan, 1);
654         ASSERT(plan.memory()->size());
655
656         // Test this doesn't crash.
657         unsigned length = 5;
658         unsigned offset = sizeof(uint32_t);
659         uint32_t* memory = static_cast<uint32_t*>(plan.memory()->memory());
660         invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(offset), box(length) });
661         offset /= sizeof(uint32_t);
662         CHECK_EQ(memory[offset - 1], 0u);
663         CHECK_EQ(memory[offset + length], 0u);
664         for (unsigned i = 0; i < length; ++i)
665             CHECK_EQ(memory[i + offset], 100u);
666
667         length = 10;
668         offset = 5 * sizeof(uint32_t);
669         invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(5), box(offset), box(length) });
670         offset /= sizeof(uint32_t);
671         CHECK_EQ(memory[offset - 1], 100u);
672         CHECK_EQ(memory[offset + length], 0u);
673         for (unsigned i = 0; i < length; ++i)
674             CHECK_EQ(memory[i + offset], 5u);
675     }
676
677     {
678         // Generated from:
679         //    (module
680         //     (memory 1)
681         //     (func (export "write_array") (param $x i32) (param $p i32) (param $length i32) (local $i i32)
682         //      (set_local $i (i32.const 0))
683         //      (block
684         //       (loop
685         //        (br_if 1 (i32.ge_u (get_local $i) (get_local $length)))
686         //        (i32.store8 (i32.add (get_local $p) (get_local $i)) (get_local $x))
687         //        (set_local $i (i32.add (i32.const 1) (get_local $i)))
688         //        (br 0)
689         //        )
690         //       )
691         //      (return)
692         //      )
693         //     )
694         Vector<uint8_t> vector = {
695             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
696             0x03, 0x01, 0x01, 0x01, 0x00, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
697             0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x77, 0x72,
698             0x69, 0x74, 0x65, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x00, 0x00, 0x0a, 0xaf, 0x80, 0x80, 0x80,
699             0x00, 0x01, 0xa9, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x03, 0x01, 0x00,
700             0x02, 0x00, 0x14, 0x03, 0x14, 0x02, 0x56, 0x07, 0x01, 0x14, 0x01, 0x14, 0x03, 0x40, 0x14, 0x00,
701             0x2e, 0x00, 0x00, 0x10, 0x01, 0x14, 0x03, 0x40, 0x15, 0x03, 0x06, 0x00, 0x0f, 0x0f, 0x09, 0x0f
702         };
703
704         Plan plan(*vm, vector);
705         checkPlan(plan, 1);
706         ASSERT(plan.memory()->size());
707
708         // Test this doesn't crash.
709         unsigned length = 5;
710         unsigned offset = 1;
711         uint8_t* memory = static_cast<uint8_t*>(plan.memory()->memory());
712         invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(offset), box(length) });
713         CHECK_EQ(memory[offset - 1], 0u);
714         CHECK_EQ(memory[offset + length], 0u);
715         for (unsigned i = 0; i < length; ++i)
716             CHECK_EQ(memory[i + offset], 100u);
717
718         length = 10;
719         offset = 5;
720         invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(5), box(offset), box(length) });
721         CHECK_EQ(memory[offset - 1], 100u);
722         CHECK_EQ(memory[offset + length], 0u);
723         for (unsigned i = 0; i < length; ++i)
724             CHECK_EQ(memory[i + offset], 5u);
725     }
726
727     {
728         // Generated from:
729         //    (module
730         //     (memory 1)
731         //     (func (export "i32_load8_s") (param $i i32) (param $ptr i32) (result i32)
732         //      (i32.store8 (get_local $ptr) (get_local $i))
733         //      (return (i32.load8_s (get_local $ptr)))
734         //      )
735         //     )
736         Vector<uint8_t> vector = {
737             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
738             0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
739             0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33,
740             0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80,
741             0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x2e, 0x00, 0x00, 0x14,
742             0x01, 0x20, 0x00, 0x00, 0x09, 0x0f
743         };
744
745         Plan plan(*vm, vector);
746         checkPlan(plan, 1);
747         ASSERT(plan.memory()->size());
748
749         // Test this doesn't crash.
750         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
751         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
752         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
753     }
754
755     {
756         // Generated from:
757         //    (module
758         //     (memory 1)
759         //     (func (export "i32_load8_s") (param $i i32) (result i32)
760         //      (i32.store8 (i32.const 8) (get_local $i))
761         //      (return (i32.load8_s (i32.const 8)))
762         //      )
763         //     )
764         Vector<uint8_t> vector = {
765             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
766             0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 0x80,
767             0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33, 0x32,
768             0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80, 0x00,
769             0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x08, 0x14, 0x00, 0x2e, 0x00, 0x00, 0x10, 0x08,
770             0x20, 0x00, 0x00, 0x09, 0x0f
771         };
772
773         Plan plan(*vm, vector);
774         checkPlan(plan, 1);
775
776         // Test this doesn't crash.
777         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
778         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 100);
779         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1);
780     }
781
782     {
783         // Generated from:
784         // (module
785         //  (memory 1)
786         //  (func (export "i32_load8_s") (param $i i32) (param $ptr i32) (result i32)
787         //   (i32.store (get_local $ptr) (get_local $i))
788         //   (return (i32.load (get_local $ptr)))
789         //   )
790         //  )
791         Vector<uint8_t> vector = {
792             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
793             0x02, 0x02, 0x01, 0x01, 0x02, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
794             0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33,
795             0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80,
796             0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x34, 0x03, 0x00, 0x14,
797             0x01, 0x2b, 0x03, 0x00, 0x09, 0x0f
798         };
799
800         Plan plan(*vm, vector);
801         checkPlan(plan, 1);
802
803         // Test this doesn't crash.
804         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
805         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
806         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
807         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(-12), box(plan.memory()->size() - sizeof(uint64_t)) }), -12);
808     }
809
810     {
811         // Generated from:
812         // (module
813         //  (memory 1)
814         //  (func (export "i32_load8_s") (param $i i32) (param $ptr i32) (result i32)
815         //   (i32.store (get_local $ptr) (get_local $i))
816         //   (return (i32.load (get_local $ptr)))
817         //   )
818         //  )
819         Vector<uint8_t> vector = {
820             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
821             0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
822             0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33,
823             0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80,
824             0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x33, 0x02, 0x00, 0x14,
825             0x01, 0x2a, 0x02, 0x00, 0x09, 0x0f
826         };
827
828         Plan plan(*vm, vector);
829         checkPlan(plan, 1);
830
831         // Test this doesn't crash.
832         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
833         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
834         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
835     }
836
837     {
838         // Generated from:
839         //    (module
840         //     (memory 1)
841         //     (func (export "write_array") (param $x i32) (param $p i32) (param $length i32) (local $i i32)
842         //      (set_local $i (i32.const 0))
843         //      (block
844         //       (loop
845         //        (br_if 1 (i32.ge_u (get_local $i) (get_local $length)))
846         //        (i32.store (i32.add (get_local $p) (i32.mul (get_local $i) (i32.const 4))) (get_local $x))
847         //        (set_local $i (i32.add (i32.const 1) (get_local $i)))
848         //        (br 0)
849         //        )
850         //       )
851         //      (return)
852         //      )
853         //     )
854         Vector<uint8_t> vector = {
855             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
856             0x03, 0x01, 0x01, 0x01, 0x00, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
857             0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x77, 0x72,
858             0x69, 0x74, 0x65, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x00, 0x00, 0x0a, 0xb2, 0x80, 0x80, 0x80,
859             0x00, 0x01, 0xac, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x03, 0x01, 0x00,
860             0x02, 0x00, 0x14, 0x03, 0x14, 0x02, 0x56, 0x07, 0x01, 0x14, 0x01, 0x14, 0x03, 0x10, 0x04, 0x42,
861             0x40, 0x14, 0x00, 0x33, 0x02, 0x00, 0x10, 0x01, 0x14, 0x03, 0x40, 0x15, 0x03, 0x06, 0x00, 0x0f,
862             0x0f, 0x09, 0x0f
863         };
864
865         Plan plan(*vm, vector);
866         checkPlan(plan, 1);
867         ASSERT(plan.memory()->size());
868
869         // Test this doesn't crash.
870         unsigned length = 5;
871         unsigned offset = sizeof(uint32_t);
872         uint32_t* memory = static_cast<uint32_t*>(plan.memory()->memory());
873         invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(offset), box(length) });
874         offset /= sizeof(uint32_t);
875         CHECK_EQ(memory[offset - 1], 0u);
876         CHECK_EQ(memory[offset + length], 0u);
877         for (unsigned i = 0; i < length; ++i)
878             CHECK_EQ(memory[i + offset], 100u);
879
880         length = 10;
881         offset = 5 * sizeof(uint32_t);
882         invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(5), box(offset), box(length) });
883         offset /= sizeof(uint32_t);
884         CHECK_EQ(memory[offset - 1], 100u);
885         CHECK_EQ(memory[offset + length], 0u);
886         for (unsigned i = 0; i < length; ++i)
887             CHECK_EQ(memory[i + offset], 5u);
888     }
889
890     {
891         // Generated from:
892         //    (module
893         //     (memory 1)
894         //     (func (export "write_array") (param $x i32) (param $p i32) (param $length i32) (local $i i32)
895         //      (set_local $i (i32.const 0))
896         //      (block
897         //       (loop
898         //        (br_if 1 (i32.ge_u (get_local $i) (get_local $length)))
899         //        (i32.store8 (i32.add (get_local $p) (get_local $i)) (get_local $x))
900         //        (set_local $i (i32.add (i32.const 1) (get_local $i)))
901         //        (br 0)
902         //        )
903         //       )
904         //      (return)
905         //      )
906         //     )
907         Vector<uint8_t> vector = {
908             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
909             0x03, 0x01, 0x01, 0x01, 0x00, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
910             0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x77, 0x72,
911             0x69, 0x74, 0x65, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x00, 0x00, 0x0a, 0xaf, 0x80, 0x80, 0x80,
912             0x00, 0x01, 0xa9, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x03, 0x01, 0x00,
913             0x02, 0x00, 0x14, 0x03, 0x14, 0x02, 0x56, 0x07, 0x01, 0x14, 0x01, 0x14, 0x03, 0x40, 0x14, 0x00,
914             0x2e, 0x00, 0x00, 0x10, 0x01, 0x14, 0x03, 0x40, 0x15, 0x03, 0x06, 0x00, 0x0f, 0x0f, 0x09, 0x0f
915         };
916
917         Plan plan(*vm, vector);
918         checkPlan(plan, 1);
919         ASSERT(plan.memory()->size());
920
921         // Test this doesn't crash.
922         unsigned length = 5;
923         unsigned offset = 1;
924         uint8_t* memory = static_cast<uint8_t*>(plan.memory()->memory());
925         invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(offset), box(length) });
926         CHECK_EQ(memory[offset - 1], 0u);
927         CHECK_EQ(memory[offset + length], 0u);
928         for (unsigned i = 0; i < length; ++i)
929             CHECK_EQ(memory[i + offset], 100u);
930
931         length = 10;
932         offset = 5;
933         invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(5), box(offset), box(length) });
934         CHECK_EQ(memory[offset - 1], 100u);
935         CHECK_EQ(memory[offset + length], 0u);
936         for (unsigned i = 0; i < length; ++i)
937             CHECK_EQ(memory[i + offset], 5u);
938     }
939
940     {
941         // Generated from:
942         //    (module
943         //     (memory 1)
944         //     (func (export "i32_load8_s") (param $i i32) (param $ptr i32) (result i32)
945         //      (i32.store8 (get_local $ptr) (get_local $i))
946         //      (return (i32.load8_s (get_local $ptr)))
947         //      )
948         //     )
949         Vector<uint8_t> vector = {
950             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
951             0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
952             0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33,
953             0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80,
954             0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x2e, 0x00, 0x00, 0x14,
955             0x01, 0x20, 0x00, 0x00, 0x09, 0x0f
956         };
957
958         Plan plan(*vm, vector);
959         checkPlan(plan, 1);
960         ASSERT(plan.memory()->size());
961
962         // Test this doesn't crash.
963         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
964         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
965         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
966     }
967
968     {
969         // Generated from:
970         //    (module
971         //     (memory 1)
972         //     (func (export "i32_load8_s") (param $i i32) (result i32)
973         //      (i32.store8 (i32.const 8) (get_local $i))
974         //      (return (i32.load8_s (i32.const 8)))
975         //      )
976         //     )
977         Vector<uint8_t> vector = {
978             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
979             0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 0x80,
980             0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33, 0x32,
981             0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80, 0x00,
982             0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x08, 0x14, 0x00, 0x2e, 0x00, 0x00, 0x10, 0x08,
983             0x20, 0x00, 0x00, 0x09, 0x0f
984         };
985
986         Plan plan(*vm, vector);
987         checkPlan(plan, 1);
988
989         // Test this doesn't crash.
990         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
991         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 100);
992         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1);
993     }
994
995     {
996         // Generated from:
997         //    (module
998         //     (func "dumb-eq" (param $x i32) (param $y i32) (result i32)
999         //      (if (i32.eq (get_local $x) (get_local $y))
1000         //       (then (br 0))
1001         //       (else (return (i32.const 1))))
1002         //      (return (i32.const 0))
1003         //      )
1004         //     )
1005         Vector<uint8_t> vector = {
1006             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
1007             0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8b, 0x80,
1008             0x80, 0x80, 0x00, 0x01, 0x07, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x65, 0x71, 0x00, 0x00, 0x0a, 0x99,
1009             0x80, 0x80, 0x80, 0x00, 0x01, 0x93, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x4d,
1010             0x03, 0x00, 0x06, 0x00, 0x04, 0x10, 0x01, 0x09, 0x0f, 0x10, 0x00, 0x09, 0x0f
1011         };
1012
1013         Plan plan(*vm, vector);
1014         checkPlan(plan, 1);
1015
1016         // Test this doesn't crash.
1017         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1);
1018         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 1);
1019         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 1);
1020         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 1);
1021         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 0);
1022         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(1) }), 0);
1023         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 1);
1024         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 1);
1025     }
1026
1027     {
1028         // Generated from:
1029         //    (module
1030         //     (func (export "dumb-less-than") (param $x i32) (param $y i32) (result i32)
1031         //      (loop
1032         //       (if (i32.eq (get_local $x) (get_local $y))
1033         //        (then (return (i32.const 0)))
1034         //        (else (if (i32.eq (get_local $x) (i32.const 0))
1035         //               (return (i32.const 1)))))
1036         //       (set_local $x (i32.sub (get_local $x) (i32.const 1)))
1037         //       (br 0)
1038         //       )
1039         //      )
1040         //     )
1041         Vector<uint8_t> vector = {
1042             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
1043             0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x92, 0x80,
1044             0x80, 0x80, 0x00, 0x01, 0x0e, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6c, 0x65, 0x73, 0x73, 0x2d, 0x74,
1045             0x68, 0x61, 0x6e, 0x00, 0x00, 0x0a, 0xac, 0x80, 0x80, 0x80, 0x00, 0x01, 0xa6, 0x80, 0x80, 0x80,
1046             0x00, 0x00, 0x02, 0x00, 0x14, 0x00, 0x14, 0x01, 0x4d, 0x03, 0x00, 0x10, 0x00, 0x09, 0x04, 0x14,
1047             0x00, 0x10, 0x00, 0x4d, 0x03, 0x00, 0x10, 0x01, 0x09, 0x0f, 0x0f, 0x14, 0x00, 0x10, 0x01, 0x41,
1048             0x15, 0x00, 0x06, 0x00, 0x0f, 0x00, 0x0f
1049         };
1050
1051         Plan plan(*vm, vector);
1052         checkPlan(plan, 1);
1053
1054         // Test this doesn't crash.
1055         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1);
1056         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 0);
1057         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 0);
1058         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 1);
1059         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 0);
1060         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(1) }), 0);
1061         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 1);
1062         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 0);
1063     }
1064
1065
1066     {
1067         // Generated from: (module (func (export "return-i32") (result i32) (return (i32.const 5))) )
1068         Vector<uint8_t> vector = {
1069             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x85, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
1070             0x00, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8e, 0x80, 0x80, 0x80,
1071             0x00, 0x01, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x00, 0x00, 0x0a,
1072             0x8b, 0x80, 0x80, 0x80, 0x00, 0x01, 0x85, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x05, 0x09, 0x0f
1073         };
1074
1075         Plan plan(*vm, vector);
1076         checkPlan(plan, 1);
1077
1078         // Test this doesn't crash.
1079         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { }), 5);
1080     }
1081
1082
1083     {
1084         // Generated from: (module (func (export "return-i32") (result i32) (return (i32.add (i32.const 5) (i32.const 6)))) )
1085         Vector<uint8_t> vector = {
1086             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x85, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
1087             0x00, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8e, 0x80, 0x80, 0x80,
1088             0x00, 0x01, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x00, 0x00, 0x0a,
1089             0x8e, 0x80, 0x80, 0x80, 0x00, 0x01, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x05, 0x10, 0x06,
1090             0x40, 0x09, 0x0f
1091         };
1092
1093         Plan plan(*vm, vector);
1094         checkPlan(plan, 1);
1095
1096         // Test this doesn't crash.
1097         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { }), 11);
1098     }
1099
1100     {
1101         // Generated from: (module (func (export "return-i32") (result i32) (return (i32.add (i32.add (i32.const 5) (i32.const 3)) (i32.const 3)))) )
1102         Vector<uint8_t> vector = {
1103             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x85, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
1104             0x00, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8e, 0x80, 0x80, 0x80,
1105             0x00, 0x01, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x00, 0x00, 0x0a,
1106             0x91, 0x80, 0x80, 0x80, 0x00, 0x01, 0x8b, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x05, 0x10, 0x03,
1107             0x40, 0x10, 0x03, 0x40, 0x09, 0x0f
1108         };
1109
1110         Plan plan(*vm, vector);
1111         checkPlan(plan, 1);
1112
1113         // Test this doesn't crash.
1114         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { }), 11);
1115     }
1116
1117     {
1118         // Generated from: (module (func (export "return-i32") (result i32) (block (return (i32.add (i32.add (i32.const 5) (i32.const 3)) (i32.const 3)))) (unreachable)) )
1119         Vector<uint8_t> vector = {
1120             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x85, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
1121             0x00, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8e, 0x80, 0x80, 0x80,
1122             0x00, 0x01, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x00, 0x00, 0x0a,
1123             0x95, 0x80, 0x80, 0x80, 0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x01, 0x00, 0x10, 0x05,
1124             0x10, 0x03, 0x40, 0x10, 0x03, 0x40, 0x09, 0x0f, 0x00, 0x0f
1125         };
1126
1127         Plan plan(*vm, vector);
1128         checkPlan(plan, 1);
1129
1130         // Test this doesn't crash.
1131         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { }), 11);
1132     }
1133
1134     {
1135         // Generated from: (module (func (export "add") (param $x i32) (param $y i32) (result i32) (return (i32.add (get_local $x) (get_local $y)))) )
1136         Vector<uint8_t> vector = {
1137             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
1138             0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x87, 0x80,
1139             0x80, 0x80, 0x00, 0x01, 0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x8e, 0x80, 0x80, 0x80, 0x00,
1140             0x01, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x40, 0x09, 0x0f
1141         };
1142
1143         Plan plan(*vm, vector);
1144         checkPlan(plan, 1);
1145
1146         // Test this doesn't crash.
1147         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1);
1148         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(1) }), 101);
1149         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(-1), box(1)}), 0);
1150         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(std::numeric_limits<int>::max()), box(1) }), std::numeric_limits<int>::min());
1151     }
1152
1153     {
1154         // Generated from:
1155         //    (module
1156         //     (func (export "locals") (param $x i32) (result i32) (local $num i32)
1157         //      (set_local $num (get_local $x))
1158         //      (return (get_local $num))
1159         //      )
1160         //     )
1161         Vector<uint8_t> vector = {
1162             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
1163             0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8a, 0x80, 0x80,
1164             0x80, 0x00, 0x01, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73, 0x00, 0x00, 0x0a, 0x91, 0x80, 0x80,
1165             0x80, 0x00, 0x01, 0x8b, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x14, 0x00, 0x15, 0x01, 0x14,
1166             0x01, 0x09, 0x0f
1167         };
1168
1169         Plan plan(*vm, vector);
1170         checkPlan(plan, 1);
1171
1172         // Test this doesn't crash.
1173         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
1174         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(10) }), 10);
1175     }
1176
1177     {
1178         // Generated from:
1179         //    (module
1180         //     (func (export "sum") (param $x i32) (result i32) (local $y i32)
1181         //      (set_local $y (i32.const 0))
1182         //      (loop
1183         //       (block
1184         //        (br_if 0 (i32.eq (get_local $x) (i32.const 0)))
1185         //        (set_local $y (i32.add (get_local $x) (get_local $y)))
1186         //        (set_local $x (i32.sub (get_local $x) (i32.const 1)))
1187         //        (br 1)
1188         //        )
1189         //       )
1190         //      (return (get_local $y))
1191         //      )
1192         //     )
1193         Vector<uint8_t> vector = {
1194             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
1195             0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x87, 0x80, 0x80,
1196             0x80, 0x00, 0x01, 0x03, 0x73, 0x75, 0x6d, 0x00, 0x00, 0x0a, 0xae, 0x80, 0x80, 0x80, 0x00, 0x01,
1197             0xa8, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x01, 0x02, 0x00, 0x01, 0x00,
1198             0x14, 0x00, 0x10, 0x00, 0x4d, 0x07, 0x00, 0x14, 0x00, 0x14, 0x01, 0x40, 0x15, 0x01, 0x14, 0x00,
1199             0x10, 0x01, 0x41, 0x15, 0x00, 0x06, 0x01, 0x0f, 0x0f, 0x14, 0x01, 0x09, 0x0f
1200         };
1201
1202         Plan plan(*vm, vector);
1203         checkPlan(plan, 1);
1204
1205         // Test this doesn't crash.
1206         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
1207         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1);
1208         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2)}), 3);
1209         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 5050);
1210     }
1211
1212     {
1213         // Generated from:
1214         //    (module
1215         //     (func (export "dumb-mult") (param $x i32) (param $y i32) (result i32) (local $total i32) (local $i i32) (local $j i32)
1216         //      (set_local $total (i32.const 0))
1217         //      (set_local $i (i32.const 0))
1218         //      (block (loop
1219         //              (br_if 1 (i32.eq (get_local $i) (get_local $x)))
1220         //              (set_local $j (i32.const 0))
1221         //              (set_local $i (i32.add (get_local $i) (i32.const 1)))
1222         //              (loop
1223         //               (br_if 1 (i32.eq (get_local $j) (get_local $y)))
1224         //               (set_local $total (i32.add (get_local $total) (i32.const 1)))
1225         //               (set_local $j (i32.add (get_local $j) (i32.const 1)))
1226         //               (br 0)
1227         //               )
1228         //              ))
1229         //      (return (get_local $total))
1230         //      )
1231         //     )
1232         Vector<uint8_t> vector = {
1233             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
1234             0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8d, 0x80,
1235             0x80, 0x80, 0x00, 0x01, 0x09, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6d, 0x75, 0x6c, 0x74, 0x00, 0x00,
1236             0x0a, 0xc7, 0x80, 0x80, 0x80, 0x00, 0x01, 0xc1, 0x80, 0x80, 0x80, 0x00, 0x01, 0x03, 0x01, 0x10,
1237             0x00, 0x15, 0x02, 0x10, 0x00, 0x15, 0x03, 0x01, 0x00, 0x02, 0x00, 0x14, 0x03, 0x14, 0x00, 0x4d,
1238             0x07, 0x01, 0x10, 0x00, 0x15, 0x04, 0x14, 0x03, 0x10, 0x01, 0x40, 0x15, 0x03, 0x02, 0x00, 0x14,
1239             0x04, 0x14, 0x01, 0x4d, 0x07, 0x01, 0x14, 0x02, 0x10, 0x01, 0x40, 0x15, 0x02, 0x14, 0x04, 0x10,
1240             0x01, 0x40, 0x15, 0x04, 0x06, 0x00, 0x0f, 0x0f, 0x0f, 0x14, 0x02, 0x09, 0x0f
1241         };
1242
1243         Plan plan(*vm, vector);
1244         checkPlan(plan, 1);
1245
1246         // Test this doesn't crash.
1247         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 0);
1248         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 0);
1249         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 2);
1250         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 2);
1251         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 4);
1252         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 12);
1253         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 600);
1254         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(100) }), 10000);
1255     }
1256
1257     {
1258         // Generated from:
1259         //    (module
1260         //     (func "dumb-less-than" (param $x i32) (param $y i32) (result i32)
1261         //      (loop
1262         //       (block
1263         //        (block
1264         //         (br_if 0 (i32.eq (get_local $x) (get_local $y)))
1265         //         (br 1)
1266         //         )
1267         //        (return (i32.const 0))
1268         //        )
1269         //       (block
1270         //        (block
1271         //         (br_if 0 (i32.eq (get_local $x) (i32.const 0)))
1272         //         (br 1)
1273         //         )
1274         //        (return (i32.const 1))
1275         //        )
1276         //       (set_local $x (i32.sub (get_local $x) (i32.const 1)))
1277         //       (br 0)
1278         //       )
1279         //       (unreachable)
1280         //      )
1281         //     )
1282         Vector<uint8_t> vector = {
1283             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
1284             0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x92, 0x80,
1285             0x80, 0x80, 0x00, 0x01, 0x0e, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6c, 0x65, 0x73, 0x73, 0x2d, 0x74,
1286             0x68, 0x61, 0x6e, 0x00, 0x00, 0x0a, 0xb9, 0x80, 0x80, 0x80, 0x00, 0x01, 0xb3, 0x80, 0x80, 0x80,
1287             0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x14, 0x00, 0x14, 0x01, 0x4d, 0x07, 0x00, 0x06,
1288             0x01, 0x0f, 0x10, 0x00, 0x09, 0x0f, 0x01, 0x00, 0x01, 0x00, 0x14, 0x00, 0x10, 0x00, 0x4d, 0x07,
1289             0x00, 0x06, 0x01, 0x0f, 0x10, 0x01, 0x09, 0x0f, 0x14, 0x00, 0x10, 0x01, 0x41, 0x15, 0x00, 0x06,
1290             0x00, 0x0f, 0x00, 0x0f
1291         };
1292
1293         Plan plan(*vm, vector);
1294         checkPlan(plan, 1);
1295
1296         // Test this doesn't crash.
1297         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1);
1298         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 0);
1299         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 0);
1300         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 1);
1301         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 0);
1302         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(1) }), 0);
1303         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 1);
1304         CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 0);
1305     }
1306
1307 }
1308
1309 #endif // ENABLE(WEBASSEMBLY)
1310
1311 int main(int argc, char** argv)
1312 {
1313     CommandLine options(argc, argv);
1314
1315     if (options.m_runLEBTests)
1316         runLEBTests();
1317
1318     if (options.m_runWasmTests) {
1319 #if ENABLE(WEBASSEMBLY)
1320         JSC::initializeThreading();
1321         vm = &JSC::VM::create(JSC::LargeHeap).leakRef();
1322         runWasmTests();
1323 #else
1324         dataLogLn("Wasm is not enabled!");
1325         return EXIT_FAILURE;
1326 #endif // ENABLE(WEBASSEMBLY)
1327     }
1328
1329     return EXIT_SUCCESS;
1330 }
1331