• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <stdint.h>
6 #include <stdlib.h>
7 #include <string.h>
8 
9 #include "src/base/platform/elapsed-timer.h"
10 
11 #include "src/wasm/wasm-macro-gen.h"
12 
13 #include "test/cctest/cctest.h"
14 #include "test/cctest/compiler/value-helper.h"
15 #include "test/cctest/wasm/test-signatures.h"
16 #include "test/cctest/wasm/wasm-run-utils.h"
17 
18 using namespace v8::base;
19 using namespace v8::internal;
20 using namespace v8::internal::compiler;
21 using namespace v8::internal::wasm;
22 
23 // for even shorter tests.
24 #define B2(a, b) kExprBlock, a, b, kExprEnd
25 #define B1(a) kExprBlock, a, kExprEnd
26 #define RET(x) x, kExprReturn, 1
27 #define RET_I8(x) kExprI8Const, x, kExprReturn, 1
28 
29 namespace {
GetMatchingRelocInfoCount(Handle<Code> code,RelocInfo::Mode rmode)30 uint32_t GetMatchingRelocInfoCount(Handle<Code> code, RelocInfo::Mode rmode) {
31   int filter = 1 << rmode;
32   uint32_t ret = 0;
33   for (RelocIterator it(*code, filter); !it.done(); it.next()) {
34     ++ret;
35   }
36   return ret;
37 }
38 }
39 
WASM_EXEC_TEST(Int32AsmjsDivS)40 WASM_EXEC_TEST(Int32AsmjsDivS) {
41   WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
42                         MachineType::Int32());
43   BUILD(r, WASM_BINOP(kExprI32AsmjsDivS, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
44   const int32_t kMin = std::numeric_limits<int32_t>::min();
45   CHECK_EQ(0, r.Call(0, 100));
46   CHECK_EQ(0, r.Call(100, 0));
47   CHECK_EQ(0, r.Call(-1001, 0));
48   CHECK_EQ(kMin, r.Call(kMin, -1));
49   CHECK_EQ(0, r.Call(kMin, 0));
50 }
51 
WASM_EXEC_TEST(Int32AsmjsRemS)52 WASM_EXEC_TEST(Int32AsmjsRemS) {
53   WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
54                         MachineType::Int32());
55   BUILD(r, WASM_BINOP(kExprI32AsmjsRemS, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
56   const int32_t kMin = std::numeric_limits<int32_t>::min();
57   CHECK_EQ(33, r.Call(133, 100));
58   CHECK_EQ(0, r.Call(kMin, -1));
59   CHECK_EQ(0, r.Call(100, 0));
60   CHECK_EQ(0, r.Call(-1001, 0));
61   CHECK_EQ(0, r.Call(kMin, 0));
62 }
63 
WASM_EXEC_TEST(Int32AsmjsDivU)64 WASM_EXEC_TEST(Int32AsmjsDivU) {
65   WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
66                         MachineType::Int32());
67   BUILD(r, WASM_BINOP(kExprI32AsmjsDivU, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
68   const int32_t kMin = std::numeric_limits<int32_t>::min();
69   CHECK_EQ(0, r.Call(0, 100));
70   CHECK_EQ(0, r.Call(kMin, -1));
71   CHECK_EQ(0, r.Call(100, 0));
72   CHECK_EQ(0, r.Call(-1001, 0));
73   CHECK_EQ(0, r.Call(kMin, 0));
74 }
75 
WASM_EXEC_TEST(Int32AsmjsRemU)76 WASM_EXEC_TEST(Int32AsmjsRemU) {
77   WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
78                         MachineType::Int32());
79   BUILD(r, WASM_BINOP(kExprI32AsmjsRemU, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
80   const int32_t kMin = std::numeric_limits<int32_t>::min();
81   CHECK_EQ(17, r.Call(217, 100));
82   CHECK_EQ(0, r.Call(100, 0));
83   CHECK_EQ(0, r.Call(-1001, 0));
84   CHECK_EQ(0, r.Call(kMin, 0));
85   CHECK_EQ(kMin, r.Call(kMin, -1));
86 }
87 
WASM_EXEC_TEST(I32AsmjsSConvertF32)88 WASM_EXEC_TEST(I32AsmjsSConvertF32) {
89   WasmRunner<int32_t> r(execution_mode, MachineType::Float32());
90   BUILD(r, WASM_UNOP(kExprI32AsmjsSConvertF32, WASM_GET_LOCAL(0)));
91 
92   FOR_FLOAT32_INPUTS(i) {
93     int32_t expected = DoubleToInt32(*i);
94     CHECK_EQ(expected, r.Call(*i));
95   }
96 }
97 
WASM_EXEC_TEST(I32AsmjsSConvertF64)98 WASM_EXEC_TEST(I32AsmjsSConvertF64) {
99   WasmRunner<int32_t> r(execution_mode, MachineType::Float64());
100   BUILD(r, WASM_UNOP(kExprI32AsmjsSConvertF64, WASM_GET_LOCAL(0)));
101 
102   FOR_FLOAT64_INPUTS(i) {
103     int32_t expected = DoubleToInt32(*i);
104     CHECK_EQ(expected, r.Call(*i));
105   }
106 }
107 
WASM_EXEC_TEST(I32AsmjsUConvertF32)108 WASM_EXEC_TEST(I32AsmjsUConvertF32) {
109   WasmRunner<uint32_t> r(execution_mode, MachineType::Float32());
110   BUILD(r, WASM_UNOP(kExprI32AsmjsUConvertF32, WASM_GET_LOCAL(0)));
111 
112   FOR_FLOAT32_INPUTS(i) {
113     uint32_t expected = DoubleToUint32(*i);
114     CHECK_EQ(expected, r.Call(*i));
115   }
116 }
117 
WASM_EXEC_TEST(I32AsmjsUConvertF64)118 WASM_EXEC_TEST(I32AsmjsUConvertF64) {
119   WasmRunner<uint32_t> r(execution_mode, MachineType::Float64());
120   BUILD(r, WASM_UNOP(kExprI32AsmjsUConvertF64, WASM_GET_LOCAL(0)));
121 
122   FOR_FLOAT64_INPUTS(i) {
123     uint32_t expected = DoubleToUint32(*i);
124     CHECK_EQ(expected, r.Call(*i));
125   }
126 }
127 
WASM_EXEC_TEST(LoadMemI32_oob_asm)128 WASM_EXEC_TEST(LoadMemI32_oob_asm) {
129   TestingModule module(execution_mode);
130   int32_t* memory = module.AddMemoryElems<int32_t>(8);
131   WasmRunner<int32_t> r(&module, MachineType::Uint32());
132   module.RandomizeMemory(1112);
133 
134   BUILD(r, WASM_UNOP(kExprI32AsmjsLoadMem, WASM_GET_LOCAL(0)));
135 
136   memory[0] = 999999;
137   CHECK_EQ(999999, r.Call(0u));
138   // TODO(titzer): offset 29-31 should also be OOB.
139   for (uint32_t offset = 32; offset < 40; offset++) {
140     CHECK_EQ(0, r.Call(offset));
141   }
142 
143   for (uint32_t offset = 0x80000000; offset < 0x80000010; offset++) {
144     CHECK_EQ(0, r.Call(offset));
145   }
146 }
147 
WASM_EXEC_TEST(LoadMemF32_oob_asm)148 WASM_EXEC_TEST(LoadMemF32_oob_asm) {
149   TestingModule module(execution_mode);
150   float* memory = module.AddMemoryElems<float>(8);
151   WasmRunner<float> r(&module, MachineType::Uint32());
152   module.RandomizeMemory(1112);
153 
154   BUILD(r, WASM_UNOP(kExprF32AsmjsLoadMem, WASM_GET_LOCAL(0)));
155 
156   memory[0] = 9999.5f;
157   CHECK_EQ(9999.5f, r.Call(0u));
158   // TODO(titzer): offset 29-31 should also be OOB.
159   for (uint32_t offset = 32; offset < 40; offset++) {
160     CHECK(std::isnan(r.Call(offset)));
161   }
162 
163   for (uint32_t offset = 0x80000000; offset < 0x80000010; offset++) {
164     CHECK(std::isnan(r.Call(offset)));
165   }
166 }
167 
WASM_EXEC_TEST(LoadMemF64_oob_asm)168 WASM_EXEC_TEST(LoadMemF64_oob_asm) {
169   TestingModule module(execution_mode);
170   double* memory = module.AddMemoryElems<double>(8);
171   WasmRunner<double> r(&module, MachineType::Uint32());
172   module.RandomizeMemory(1112);
173 
174   BUILD(r, WASM_UNOP(kExprF64AsmjsLoadMem, WASM_GET_LOCAL(0)));
175 
176   memory[0] = 9799.5;
177   CHECK_EQ(9799.5, r.Call(0u));
178   memory[1] = 11799.25;
179   CHECK_EQ(11799.25, r.Call(8u));
180   // TODO(titzer): offset 57-63 should also be OOB.
181   for (uint32_t offset = 64; offset < 80; offset++) {
182     CHECK(std::isnan(r.Call(offset)));
183   }
184 
185   for (uint32_t offset = 0x80000000; offset < 0x80000010; offset++) {
186     CHECK(std::isnan(r.Call(offset)));
187   }
188 }
189 
WASM_EXEC_TEST(StoreMemI32_oob_asm)190 WASM_EXEC_TEST(StoreMemI32_oob_asm) {
191   TestingModule module(execution_mode);
192   int32_t* memory = module.AddMemoryElems<int32_t>(8);
193   WasmRunner<int32_t> r(&module, MachineType::Uint32(), MachineType::Uint32());
194   module.RandomizeMemory(1112);
195 
196   BUILD(r, WASM_BINOP(kExprI32AsmjsStoreMem, WASM_GET_LOCAL(0),
197                       WASM_GET_LOCAL(1)));
198 
199   memory[0] = 7777;
200   CHECK_EQ(999999, r.Call(0u, 999999));
201   CHECK_EQ(999999, memory[0]);
202   // TODO(titzer): offset 29-31 should also be OOB.
203   for (uint32_t offset = 32; offset < 40; offset++) {
204     CHECK_EQ(8888, r.Call(offset, 8888));
205   }
206 
207   for (uint32_t offset = 0x10000000; offset < 0xF0000000; offset += 0x1000000) {
208     CHECK_EQ(7777, r.Call(offset, 7777));
209   }
210 }
211 
212 #define FOREACH_INT_CHECKED_LOAD_OP(TEST_BODY) \
213   TEST_BODY(kExprI32AsmjsLoadMem8S)            \
214   TEST_BODY(kExprI32AsmjsLoadMem8U)            \
215   TEST_BODY(kExprI32AsmjsLoadMem16S)           \
216   TEST_BODY(kExprI32AsmjsLoadMem16U)           \
217   TEST_BODY(kExprI32AsmjsLoadMem)
218 
219 #define FOREACH_INT_CHECKED_STORE_OP(TEST_BODY) \
220   TEST_BODY(kExprI32AsmjsStoreMem8)             \
221   TEST_BODY(kExprI32AsmjsStoreMem16)            \
222   TEST_BODY(kExprI32AsmjsStoreMem)
223 
224 #define INT_LOAD_TEST(OP_TYPE)                                                \
225   TEST(RunWasm_AsmCheckedRelocInfo##OP_TYPE) {                                \
226     TestingModule module(kExecuteCompiled);                                   \
227     WasmRunner<int32_t> r(&module, MachineType::Uint32());                    \
228     BUILD(r, WASM_UNOP(OP_TYPE, WASM_GET_LOCAL(0)));                          \
229     CHECK_EQ(1, GetMatchingRelocInfoCount(module.instance->function_code[0],  \
230                                           RelocInfo::WASM_MEMORY_REFERENCE)); \
231     CHECK_NE(                                                                 \
232         0, GetMatchingRelocInfoCount(module.instance->function_code[0],       \
233                                      RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); \
234   }
235 
236 FOREACH_INT_CHECKED_LOAD_OP(INT_LOAD_TEST)
237 
238 #define INT_STORE_TEST(OP_TYPE)                                               \
239   TEST(RunWasm_AsmCheckedRelocInfo##OP_TYPE) {                                \
240     TestingModule module(kExecuteCompiled);                                   \
241     WasmRunner<int32_t> r(&module, MachineType::Uint32(),                     \
242                           MachineType::Uint32());                             \
243     BUILD(r, WASM_BINOP(OP_TYPE, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));      \
244     CHECK_EQ(1, GetMatchingRelocInfoCount(module.instance->function_code[0],  \
245                                           RelocInfo::WASM_MEMORY_REFERENCE)); \
246     CHECK_NE(                                                                 \
247         0, GetMatchingRelocInfoCount(module.instance->function_code[0],       \
248                                      RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); \
249   }
250 
FOREACH_INT_CHECKED_STORE_OP(INT_STORE_TEST)251 FOREACH_INT_CHECKED_STORE_OP(INT_STORE_TEST)
252 
253 TEST(RunWasm_AsmCheckedLoadFloat32RelocInfo) {
254   TestingModule module(kExecuteCompiled);
255   WasmRunner<float> r(&module, MachineType::Uint32());
256   BUILD(r, WASM_UNOP(kExprF32AsmjsLoadMem, WASM_GET_LOCAL(0)));
257 
258   CHECK_EQ(1, GetMatchingRelocInfoCount(module.instance->function_code[0],
259                                         RelocInfo::WASM_MEMORY_REFERENCE));
260   CHECK_NE(0, GetMatchingRelocInfoCount(module.instance->function_code[0],
261                                         RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
262 }
263 
TEST(RunWasm_AsmCheckedStoreFloat32RelocInfo)264 TEST(RunWasm_AsmCheckedStoreFloat32RelocInfo) {
265   TestingModule module(kExecuteCompiled);
266   WasmRunner<float> r(&module, MachineType::Uint32(), MachineType::Float32());
267   BUILD(r, WASM_BINOP(kExprF32AsmjsStoreMem, WASM_GET_LOCAL(0),
268                       WASM_GET_LOCAL(1)));
269 
270   CHECK_EQ(1, GetMatchingRelocInfoCount(module.instance->function_code[0],
271                                         RelocInfo::WASM_MEMORY_REFERENCE));
272   CHECK_NE(0, GetMatchingRelocInfoCount(module.instance->function_code[0],
273                                         RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
274 }
275 
TEST(RunWasm_AsmCheckedLoadFloat64RelocInfo)276 TEST(RunWasm_AsmCheckedLoadFloat64RelocInfo) {
277   TestingModule module(kExecuteCompiled);
278   WasmRunner<double> r(&module, MachineType::Uint32());
279   BUILD(r, WASM_UNOP(kExprF64AsmjsLoadMem, WASM_GET_LOCAL(0)));
280 
281   CHECK_EQ(1, GetMatchingRelocInfoCount(module.instance->function_code[0],
282                                         RelocInfo::WASM_MEMORY_REFERENCE));
283   CHECK_NE(0, GetMatchingRelocInfoCount(module.instance->function_code[0],
284                                         RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
285 }
286 
TEST(RunWasm_AsmCheckedStoreFloat64RelocInfo)287 TEST(RunWasm_AsmCheckedStoreFloat64RelocInfo) {
288   TestingModule module(kExecuteCompiled);
289   WasmRunner<double> r(&module, MachineType::Uint32(), MachineType::Float64());
290   BUILD(r, WASM_BINOP(kExprF64AsmjsStoreMem, WASM_GET_LOCAL(0),
291                       WASM_GET_LOCAL(1)));
292 
293   CHECK_EQ(1, GetMatchingRelocInfoCount(module.instance->function_code[0],
294                                         RelocInfo::WASM_MEMORY_REFERENCE));
295   CHECK_NE(0, GetMatchingRelocInfoCount(module.instance->function_code[0],
296                                         RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
297 }
298