Line data Source code
1 : // Copyright 2018 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 "test/cctest/wasm/wasm-atomics-utils.h"
6 : #include "test/common/wasm/wasm-macro-gen.h"
7 :
8 : namespace v8 {
9 : namespace internal {
10 : namespace wasm {
11 : namespace test_run_wasm_atomics_64 {
12 :
13 72 : void RunU64BinOp(ExecutionTier execution_tier, WasmOpcode wasm_op,
14 : Uint64BinOp expected_op) {
15 : EXPERIMENTAL_FLAG_SCOPE(threads);
16 144 : WasmRunner<uint64_t, uint64_t> r(execution_tier);
17 : uint64_t* memory =
18 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
19 : r.builder().SetHasSharedMemory();
20 :
21 72 : BUILD(r, WASM_ATOMICS_BINOP(wasm_op, WASM_I32V_1(0), WASM_GET_LOCAL(0),
22 : MachineRepresentation::kWord64));
23 :
24 11736 : FOR_UINT64_INPUTS(i) {
25 : uint64_t initial = i;
26 950616 : FOR_UINT64_INPUTS(j) {
27 : r.builder().WriteMemory(&memory[0], initial);
28 472392 : CHECK_EQ(initial, r.Call(j));
29 472392 : uint64_t expected = expected_op(i, j);
30 472392 : CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
31 : }
32 : }
33 72 : }
34 :
35 : #define TEST_OPERATION(Name) \
36 : WASM_EXEC_TEST(I64Atomic##Name) { \
37 : RunU64BinOp(execution_tier, kExprI64Atomic##Name, Name); \
38 : }
39 26135 : OPERATION_LIST(TEST_OPERATION)
40 : #undef TEST_OPERATION
41 :
42 72 : void RunU32BinOp(ExecutionTier execution_tier, WasmOpcode wasm_op,
43 : Uint32BinOp expected_op) {
44 : EXPERIMENTAL_FLAG_SCOPE(threads);
45 144 : WasmRunner<uint64_t, uint64_t> r(execution_tier);
46 : uint32_t* memory =
47 : r.builder().AddMemoryElems<uint32_t>(kWasmPageSize / sizeof(uint32_t));
48 : r.builder().SetHasSharedMemory();
49 :
50 72 : BUILD(r, WASM_ATOMICS_BINOP(wasm_op, WASM_I32V_1(0), WASM_GET_LOCAL(0),
51 : MachineRepresentation::kWord32));
52 :
53 8424 : FOR_UINT32_INPUTS(i) {
54 : uint32_t initial = i;
55 488592 : FOR_UINT32_INPUTS(j) {
56 : r.builder().WriteMemory(&memory[0], initial);
57 484416 : CHECK_EQ(initial, r.Call(j));
58 242208 : uint32_t expected = expected_op(i, j);
59 242208 : CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
60 : }
61 : }
62 72 : }
63 :
64 : #define TEST_OPERATION(Name) \
65 : WASM_EXEC_TEST(I64Atomic##Name##32U) { \
66 : RunU32BinOp(execution_tier, kExprI64Atomic##Name##32U, Name); \
67 : }
68 26135 : OPERATION_LIST(TEST_OPERATION)
69 : #undef TEST_OPERATION
70 :
71 72 : void RunU16BinOp(ExecutionTier tier, WasmOpcode wasm_op,
72 : Uint16BinOp expected_op) {
73 : EXPERIMENTAL_FLAG_SCOPE(threads);
74 144 : WasmRunner<uint64_t, uint64_t> r(tier);
75 : r.builder().SetHasSharedMemory();
76 : uint16_t* memory =
77 : r.builder().AddMemoryElems<uint16_t>(kWasmPageSize / sizeof(uint16_t));
78 :
79 72 : BUILD(r, WASM_ATOMICS_BINOP(wasm_op, WASM_I32V_1(0), WASM_GET_LOCAL(0),
80 : MachineRepresentation::kWord16));
81 :
82 1368 : FOR_UINT16_INPUTS(i) {
83 : uint16_t initial = i;
84 12312 : FOR_UINT16_INPUTS(j) {
85 : r.builder().WriteMemory(&memory[0], initial);
86 11664 : CHECK_EQ(initial, r.Call(j));
87 5832 : uint16_t expected = expected_op(i, j);
88 5832 : CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
89 : }
90 : }
91 72 : }
92 :
93 : #define TEST_OPERATION(Name) \
94 : WASM_EXEC_TEST(I64Atomic##Name##16U) { \
95 : RunU16BinOp(execution_tier, kExprI64Atomic##Name##16U, Name); \
96 : }
97 26135 : OPERATION_LIST(TEST_OPERATION)
98 : #undef TEST_OPERATION
99 :
100 72 : void RunU8BinOp(ExecutionTier execution_tier, WasmOpcode wasm_op,
101 : Uint8BinOp expected_op) {
102 : EXPERIMENTAL_FLAG_SCOPE(threads);
103 144 : WasmRunner<uint64_t, uint64_t> r(execution_tier);
104 : r.builder().SetHasSharedMemory();
105 : uint8_t* memory = r.builder().AddMemoryElems<uint8_t>(kWasmPageSize);
106 :
107 72 : BUILD(r, WASM_ATOMICS_BINOP(wasm_op, WASM_I32V_1(0), WASM_GET_LOCAL(0),
108 : MachineRepresentation::kWord8));
109 :
110 1368 : FOR_UINT8_INPUTS(i) {
111 : uint8_t initial = i;
112 12312 : FOR_UINT8_INPUTS(j) {
113 : r.builder().WriteMemory(&memory[0], initial);
114 11664 : CHECK_EQ(initial, r.Call(j));
115 5832 : uint8_t expected = expected_op(i, j);
116 5832 : CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
117 : }
118 : }
119 72 : }
120 :
121 : #define TEST_OPERATION(Name) \
122 : WASM_EXEC_TEST(I64Atomic##Name##8U) { \
123 : RunU8BinOp(execution_tier, kExprI64Atomic##Name##8U, Name); \
124 : }
125 26135 : OPERATION_LIST(TEST_OPERATION)
126 : #undef TEST_OPERATION
127 :
128 26087 : WASM_EXEC_TEST(I64AtomicCompareExchange) {
129 : EXPERIMENTAL_FLAG_SCOPE(threads);
130 24 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_tier);
131 : r.builder().SetHasSharedMemory();
132 : uint64_t* memory =
133 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
134 12 : BUILD(r, WASM_ATOMICS_TERNARY_OP(
135 : kExprI64AtomicCompareExchange, WASM_I32V_1(0), WASM_GET_LOCAL(0),
136 : WASM_GET_LOCAL(1), MachineRepresentation::kWord64));
137 :
138 1956 : FOR_UINT64_INPUTS(i) {
139 : uint64_t initial = i;
140 158436 : FOR_UINT64_INPUTS(j) {
141 : r.builder().WriteMemory(&memory[0], initial);
142 78732 : CHECK_EQ(initial, r.Call(i, j));
143 : uint64_t expected = CompareExchange(initial, i, j);
144 78732 : CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
145 : }
146 : }
147 12 : }
148 :
149 26087 : WASM_EXEC_TEST(I64AtomicCompareExchange32U) {
150 : EXPERIMENTAL_FLAG_SCOPE(threads);
151 24 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_tier);
152 : r.builder().SetHasSharedMemory();
153 : uint32_t* memory =
154 : r.builder().AddMemoryElems<uint32_t>(kWasmPageSize / sizeof(uint32_t));
155 12 : BUILD(r, WASM_ATOMICS_TERNARY_OP(kExprI64AtomicCompareExchange32U,
156 : WASM_I32V_1(0), WASM_GET_LOCAL(0),
157 : WASM_GET_LOCAL(1),
158 : MachineRepresentation::kWord32));
159 :
160 1404 : FOR_UINT32_INPUTS(i) {
161 : uint32_t initial = i;
162 81432 : FOR_UINT32_INPUTS(j) {
163 : r.builder().WriteMemory(&memory[0], initial);
164 40368 : CHECK_EQ(initial, r.Call(i, j));
165 : uint32_t expected = CompareExchange(initial, i, j);
166 40368 : CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
167 : }
168 : }
169 12 : }
170 :
171 26087 : WASM_EXEC_TEST(I64AtomicCompareExchange16U) {
172 : EXPERIMENTAL_FLAG_SCOPE(threads);
173 24 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_tier);
174 : r.builder().SetHasSharedMemory();
175 : uint16_t* memory =
176 : r.builder().AddMemoryElems<uint16_t>(kWasmPageSize / sizeof(uint16_t));
177 12 : BUILD(r, WASM_ATOMICS_TERNARY_OP(kExprI64AtomicCompareExchange16U,
178 : WASM_I32V_1(0), WASM_GET_LOCAL(0),
179 : WASM_GET_LOCAL(1),
180 : MachineRepresentation::kWord16));
181 :
182 228 : FOR_UINT16_INPUTS(i) {
183 : uint16_t initial = i;
184 2052 : FOR_UINT16_INPUTS(j) {
185 : r.builder().WriteMemory(&memory[0], initial);
186 972 : CHECK_EQ(initial, r.Call(i, j));
187 : uint16_t expected = CompareExchange(initial, i, j);
188 972 : CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
189 : }
190 : }
191 12 : }
192 :
193 26087 : WASM_EXEC_TEST(I32AtomicCompareExchange8U) {
194 : EXPERIMENTAL_FLAG_SCOPE(threads);
195 24 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_tier);
196 : r.builder().SetHasSharedMemory();
197 : uint8_t* memory = r.builder().AddMemoryElems<uint8_t>(kWasmPageSize);
198 12 : BUILD(r,
199 : WASM_ATOMICS_TERNARY_OP(kExprI64AtomicCompareExchange8U, WASM_I32V_1(0),
200 : WASM_GET_LOCAL(0), WASM_GET_LOCAL(1),
201 : MachineRepresentation::kWord8));
202 228 : FOR_UINT8_INPUTS(i) {
203 : uint8_t initial = i;
204 2052 : FOR_UINT8_INPUTS(j) {
205 : r.builder().WriteMemory(&memory[0], initial);
206 972 : CHECK_EQ(initial, r.Call(i, j));
207 : uint8_t expected = CompareExchange(initial, i, j);
208 972 : CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
209 : }
210 : }
211 12 : }
212 :
213 26087 : WASM_EXEC_TEST(I64AtomicLoad) {
214 : EXPERIMENTAL_FLAG_SCOPE(threads);
215 24 : WasmRunner<uint64_t> r(execution_tier);
216 : r.builder().SetHasSharedMemory();
217 : uint64_t* memory =
218 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
219 12 : BUILD(r, WASM_ATOMICS_LOAD_OP(kExprI64AtomicLoad, WASM_ZERO,
220 : MachineRepresentation::kWord64));
221 :
222 1956 : FOR_UINT64_INPUTS(i) {
223 : uint64_t expected = i;
224 : r.builder().WriteMemory(&memory[0], expected);
225 972 : CHECK_EQ(expected, r.Call());
226 : }
227 12 : }
228 :
229 26087 : WASM_EXEC_TEST(I64AtomicLoad32U) {
230 : EXPERIMENTAL_FLAG_SCOPE(threads);
231 24 : WasmRunner<uint64_t> r(execution_tier);
232 : r.builder().SetHasSharedMemory();
233 : uint32_t* memory =
234 : r.builder().AddMemoryElems<uint32_t>(kWasmPageSize / sizeof(uint32_t));
235 12 : BUILD(r, WASM_ATOMICS_LOAD_OP(kExprI64AtomicLoad32U, WASM_ZERO,
236 : MachineRepresentation::kWord32));
237 :
238 1404 : FOR_UINT32_INPUTS(i) {
239 : uint32_t expected = i;
240 : r.builder().WriteMemory(&memory[0], expected);
241 1392 : CHECK_EQ(expected, r.Call());
242 : }
243 12 : }
244 :
245 26087 : WASM_EXEC_TEST(I64AtomicLoad16U) {
246 : EXPERIMENTAL_FLAG_SCOPE(threads);
247 24 : WasmRunner<uint64_t> r(execution_tier);
248 : r.builder().SetHasSharedMemory();
249 : uint16_t* memory =
250 : r.builder().AddMemoryElems<uint16_t>(kWasmPageSize / sizeof(uint16_t));
251 12 : BUILD(r, WASM_ATOMICS_LOAD_OP(kExprI64AtomicLoad16U, WASM_ZERO,
252 : MachineRepresentation::kWord16));
253 :
254 228 : FOR_UINT16_INPUTS(i) {
255 : uint16_t expected = i;
256 : r.builder().WriteMemory(&memory[0], expected);
257 216 : CHECK_EQ(expected, r.Call());
258 : }
259 12 : }
260 :
261 26087 : WASM_EXEC_TEST(I64AtomicLoad8U) {
262 : EXPERIMENTAL_FLAG_SCOPE(threads);
263 24 : WasmRunner<uint64_t> r(execution_tier);
264 : r.builder().SetHasSharedMemory();
265 : uint8_t* memory = r.builder().AddMemoryElems<uint8_t>(kWasmPageSize);
266 12 : BUILD(r, WASM_ATOMICS_LOAD_OP(kExprI64AtomicLoad8U, WASM_ZERO,
267 : MachineRepresentation::kWord8));
268 :
269 228 : FOR_UINT8_INPUTS(i) {
270 : uint8_t expected = i;
271 : r.builder().WriteMemory(&memory[0], expected);
272 216 : CHECK_EQ(expected, r.Call());
273 : }
274 12 : }
275 :
276 26087 : WASM_EXEC_TEST(I64AtomicStoreLoad) {
277 : EXPERIMENTAL_FLAG_SCOPE(threads);
278 24 : WasmRunner<uint64_t, uint64_t> r(execution_tier);
279 : r.builder().SetHasSharedMemory();
280 : uint64_t* memory =
281 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
282 :
283 12 : BUILD(r,
284 : WASM_ATOMICS_STORE_OP(kExprI64AtomicStore, WASM_ZERO, WASM_GET_LOCAL(0),
285 : MachineRepresentation::kWord64),
286 : WASM_ATOMICS_LOAD_OP(kExprI64AtomicLoad, WASM_ZERO,
287 : MachineRepresentation::kWord64));
288 :
289 1956 : FOR_UINT64_INPUTS(i) {
290 : uint64_t expected = i;
291 972 : CHECK_EQ(expected, r.Call(i));
292 972 : CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
293 : }
294 12 : }
295 :
296 26087 : WASM_EXEC_TEST(I64AtomicStoreLoad32U) {
297 : EXPERIMENTAL_FLAG_SCOPE(threads);
298 24 : WasmRunner<uint64_t, uint64_t> r(execution_tier);
299 : r.builder().SetHasSharedMemory();
300 : uint32_t* memory =
301 : r.builder().AddMemoryElems<uint32_t>(kWasmPageSize / sizeof(uint32_t));
302 :
303 12 : BUILD(
304 : r,
305 : WASM_ATOMICS_STORE_OP(kExprI64AtomicStore32U, WASM_ZERO,
306 : WASM_GET_LOCAL(0), MachineRepresentation::kWord32),
307 : WASM_ATOMICS_LOAD_OP(kExprI64AtomicLoad32U, WASM_ZERO,
308 : MachineRepresentation::kWord32));
309 :
310 1404 : FOR_UINT32_INPUTS(i) {
311 : uint32_t expected = i;
312 696 : CHECK_EQ(expected, r.Call(i));
313 696 : CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
314 : }
315 12 : }
316 :
317 26087 : WASM_EXEC_TEST(I64AtomicStoreLoad16U) {
318 : EXPERIMENTAL_FLAG_SCOPE(threads);
319 24 : WasmRunner<uint64_t, uint64_t> r(execution_tier);
320 : r.builder().SetHasSharedMemory();
321 : uint16_t* memory =
322 : r.builder().AddMemoryElems<uint16_t>(kWasmPageSize / sizeof(uint16_t));
323 :
324 12 : BUILD(
325 : r,
326 : WASM_ATOMICS_STORE_OP(kExprI64AtomicStore16U, WASM_ZERO,
327 : WASM_GET_LOCAL(0), MachineRepresentation::kWord16),
328 : WASM_ATOMICS_LOAD_OP(kExprI64AtomicLoad16U, WASM_ZERO,
329 : MachineRepresentation::kWord16));
330 :
331 228 : FOR_UINT16_INPUTS(i) {
332 : uint16_t expected = i;
333 108 : CHECK_EQ(expected, r.Call(i));
334 108 : CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
335 : }
336 12 : }
337 :
338 26087 : WASM_EXEC_TEST(I64AtomicStoreLoad8U) {
339 : EXPERIMENTAL_FLAG_SCOPE(threads);
340 24 : WasmRunner<uint64_t, uint64_t> r(execution_tier);
341 : r.builder().SetHasSharedMemory();
342 : uint8_t* memory = r.builder().AddMemoryElems<uint8_t>(kWasmPageSize);
343 :
344 12 : BUILD(r,
345 : WASM_ATOMICS_STORE_OP(kExprI64AtomicStore8U, WASM_ZERO,
346 : WASM_GET_LOCAL(0), MachineRepresentation::kWord8),
347 : WASM_ATOMICS_LOAD_OP(kExprI64AtomicLoad8U, WASM_ZERO,
348 : MachineRepresentation::kWord8));
349 :
350 228 : FOR_UINT8_INPUTS(i) {
351 : uint8_t expected = i;
352 108 : CHECK_EQ(expected, r.Call(i));
353 108 : CHECK_EQ(i, r.builder().ReadMemory(&memory[0]));
354 : }
355 12 : }
356 :
357 : // Drop tests verify atomic operations are run correctly when the
358 : // entire 64-bit output is optimized out
359 72 : void RunDropTest(ExecutionTier execution_tier, WasmOpcode wasm_op,
360 : Uint64BinOp op) {
361 : EXPERIMENTAL_FLAG_SCOPE(threads);
362 144 : WasmRunner<uint64_t, uint64_t> r(execution_tier);
363 : uint64_t* memory =
364 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
365 : r.builder().SetHasSharedMemory();
366 :
367 72 : BUILD(r,
368 : WASM_ATOMICS_BINOP(wasm_op, WASM_I32V_1(0), WASM_GET_LOCAL(0),
369 : MachineRepresentation::kWord64),
370 : WASM_DROP, WASM_GET_LOCAL(0));
371 :
372 : uint64_t initial = 0x1111222233334444, local = 0x1111111111111111;
373 : r.builder().WriteMemory(&memory[0], initial);
374 72 : CHECK_EQ(local, r.Call(local));
375 72 : uint64_t expected = op(initial, local);
376 72 : CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
377 72 : }
378 :
379 : #define TEST_OPERATION(Name) \
380 : WASM_EXEC_TEST(I64Atomic##Name##Drop) { \
381 : RunDropTest(execution_tier, kExprI64Atomic##Name, Name); \
382 : }
383 26135 : OPERATION_LIST(TEST_OPERATION)
384 : #undef TEST_OPERATION
385 :
386 26087 : WASM_EXEC_TEST(I64AtomicSub16UDrop) {
387 : EXPERIMENTAL_FLAG_SCOPE(threads);
388 24 : WasmRunner<uint64_t, uint64_t> r(execution_tier);
389 : uint16_t* memory =
390 : r.builder().AddMemoryElems<uint16_t>(kWasmPageSize / sizeof(uint16_t));
391 : r.builder().SetHasSharedMemory();
392 :
393 12 : BUILD(r,
394 : WASM_ATOMICS_BINOP(kExprI64AtomicSub16U, WASM_I32V_1(0),
395 : WASM_GET_LOCAL(0), MachineRepresentation::kWord16),
396 : WASM_DROP, WASM_GET_LOCAL(0));
397 :
398 : uint16_t initial = 0x7, local = 0xffe0;
399 : r.builder().WriteMemory(&memory[0], initial);
400 12 : CHECK_EQ(local, r.Call(local));
401 : uint16_t expected = Sub(initial, local);
402 12 : CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
403 12 : }
404 :
405 26087 : WASM_EXEC_TEST(I64AtomicCompareExchangeDrop) {
406 : EXPERIMENTAL_FLAG_SCOPE(threads);
407 24 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_tier);
408 : r.builder().SetHasSharedMemory();
409 : uint64_t* memory =
410 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
411 12 : BUILD(r,
412 : WASM_ATOMICS_TERNARY_OP(kExprI64AtomicCompareExchange, WASM_I32V_1(0),
413 : WASM_GET_LOCAL(0), WASM_GET_LOCAL(1),
414 : MachineRepresentation::kWord64),
415 : WASM_DROP, WASM_GET_LOCAL(1));
416 :
417 : uint64_t initial = 0x1111222233334444, local = 0x1111111111111111;
418 : r.builder().WriteMemory(&memory[0], initial);
419 12 : CHECK_EQ(local, r.Call(initial, local));
420 : uint64_t expected = CompareExchange(initial, initial, local);
421 12 : CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
422 12 : }
423 :
424 26087 : WASM_EXEC_TEST(I64AtomicStoreLoadDrop) {
425 : EXPERIMENTAL_FLAG_SCOPE(threads);
426 24 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_tier);
427 : r.builder().SetHasSharedMemory();
428 : uint64_t* memory =
429 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
430 :
431 12 : BUILD(r,
432 : WASM_ATOMICS_STORE_OP(kExprI64AtomicStore, WASM_ZERO, WASM_GET_LOCAL(0),
433 : MachineRepresentation::kWord64),
434 : WASM_ATOMICS_LOAD_OP(kExprI64AtomicLoad, WASM_ZERO,
435 : MachineRepresentation::kWord64),
436 : WASM_DROP, WASM_GET_LOCAL(1));
437 :
438 : uint64_t store_value = 0x1111111111111111, expected = 0xC0DE;
439 12 : CHECK_EQ(expected, r.Call(store_value, expected));
440 12 : CHECK_EQ(store_value, r.builder().ReadMemory(&memory[0]));
441 12 : }
442 :
443 26087 : WASM_EXEC_TEST(I64AtomicAddConvertDrop) {
444 : EXPERIMENTAL_FLAG_SCOPE(threads);
445 24 : WasmRunner<uint64_t, uint64_t> r(execution_tier);
446 : uint64_t* memory =
447 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
448 : r.builder().SetHasSharedMemory();
449 :
450 12 : BUILD(r,
451 : WASM_ATOMICS_BINOP(kExprI64AtomicAdd, WASM_I32V_1(0), WASM_GET_LOCAL(0),
452 : MachineRepresentation::kWord64),
453 : kExprI32ConvertI64, WASM_DROP, WASM_GET_LOCAL(0));
454 :
455 : uint64_t initial = 0x1111222233334444, local = 0x1111111111111111;
456 : r.builder().WriteMemory(&memory[0], initial);
457 12 : CHECK_EQ(local, r.Call(local));
458 : uint64_t expected = Add(initial, local);
459 12 : CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
460 12 : }
461 :
462 26087 : WASM_EXEC_TEST(I64AtomicLoadConvertDrop) {
463 : EXPERIMENTAL_FLAG_SCOPE(threads);
464 24 : WasmRunner<uint32_t, uint64_t> r(execution_tier);
465 : uint64_t* memory =
466 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
467 : r.builder().SetHasSharedMemory();
468 :
469 12 : BUILD(r, WASM_I32_CONVERT_I64(WASM_ATOMICS_LOAD_OP(
470 : kExprI64AtomicLoad, WASM_ZERO, MachineRepresentation::kWord64)));
471 :
472 : uint64_t initial = 0x1111222233334444;
473 : r.builder().WriteMemory(&memory[0], initial);
474 12 : CHECK_EQ(static_cast<uint32_t>(initial), r.Call(initial));
475 12 : }
476 :
477 : // Convert tests verify atomic operations are run correctly when the
478 : // upper half of the 64-bit output is optimized out
479 72 : void RunConvertTest(ExecutionTier execution_tier, WasmOpcode wasm_op,
480 : Uint64BinOp op) {
481 : EXPERIMENTAL_FLAG_SCOPE(threads);
482 144 : WasmRunner<uint32_t, uint64_t> r(execution_tier);
483 : uint64_t* memory =
484 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
485 : r.builder().SetHasSharedMemory();
486 :
487 72 : BUILD(r, WASM_I32_CONVERT_I64(
488 : WASM_ATOMICS_BINOP(wasm_op, WASM_ZERO, WASM_GET_LOCAL(0),
489 : MachineRepresentation::kWord64)));
490 :
491 : uint64_t initial = 0x1111222233334444, local = 0x1111111111111111;
492 : r.builder().WriteMemory(&memory[0], initial);
493 72 : CHECK_EQ(static_cast<uint32_t>(initial), r.Call(local));
494 72 : uint64_t expected = op(initial, local);
495 72 : CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
496 72 : }
497 :
498 : #define TEST_OPERATION(Name) \
499 : WASM_EXEC_TEST(I64AtomicConvert##Name) { \
500 : RunConvertTest(execution_tier, kExprI64Atomic##Name, Name); \
501 : }
502 26135 : OPERATION_LIST(TEST_OPERATION)
503 : #undef TEST_OPERATION
504 :
505 26087 : WASM_EXEC_TEST(I64AtomicConvertCompareExchange) {
506 : EXPERIMENTAL_FLAG_SCOPE(threads);
507 24 : WasmRunner<uint32_t, uint64_t, uint64_t> r(execution_tier);
508 : uint64_t* memory =
509 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
510 : r.builder().SetHasSharedMemory();
511 :
512 12 : BUILD(r, WASM_I32_CONVERT_I64(WASM_ATOMICS_TERNARY_OP(
513 : kExprI64AtomicCompareExchange, WASM_I32V_1(0), WASM_GET_LOCAL(0),
514 : WASM_GET_LOCAL(1), MachineRepresentation::kWord64)));
515 :
516 : uint64_t initial = 0x1111222233334444, local = 0x1111111111111111;
517 : r.builder().WriteMemory(&memory[0], initial);
518 12 : CHECK_EQ(static_cast<uint32_t>(initial), r.Call(initial, local));
519 : uint64_t expected = CompareExchange(initial, initial, local);
520 12 : CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
521 12 : }
522 :
523 : // The WASM_I64_EQ operation is used here to test that the index node
524 : // is lowered correctly.
525 72 : void RunNonConstIndexTest(ExecutionTier execution_tier, WasmOpcode wasm_op,
526 : Uint64BinOp op) {
527 : EXPERIMENTAL_FLAG_SCOPE(threads);
528 144 : WasmRunner<uint32_t, uint64_t> r(execution_tier);
529 : uint64_t* memory =
530 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
531 : r.builder().SetHasSharedMemory();
532 :
533 72 : BUILD(r, WASM_I32_CONVERT_I64(WASM_ATOMICS_BINOP(
534 : wasm_op, WASM_I64_EQ(WASM_I64V(1), WASM_I64V(0)),
535 : WASM_GET_LOCAL(0), MachineRepresentation::kWord32)));
536 :
537 : uint64_t initial = 0x1111222233334444, local = 0x5555666677778888;
538 : r.builder().WriteMemory(&memory[0], initial);
539 72 : CHECK_EQ(static_cast<uint32_t>(initial), r.Call(local));
540 72 : CHECK_EQ(static_cast<uint32_t>(op(initial, local)),
541 : static_cast<uint32_t>(r.builder().ReadMemory(&memory[0])));
542 72 : }
543 :
544 : #define TEST_OPERATION(Name) \
545 : WASM_EXEC_TEST(I64AtomicConstIndex##Name) { \
546 : RunNonConstIndexTest(execution_tier, kExprI64Atomic##Name##32U, Name); \
547 : }
548 26135 : OPERATION_LIST(TEST_OPERATION)
549 : #undef TEST_OPERATION
550 :
551 26087 : WASM_EXEC_TEST(I64AtomicNonConstIndexCompareExchange) {
552 : EXPERIMENTAL_FLAG_SCOPE(threads);
553 24 : WasmRunner<uint32_t, uint64_t, uint64_t> r(execution_tier);
554 : uint64_t* memory =
555 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
556 : r.builder().SetHasSharedMemory();
557 :
558 12 : BUILD(r, WASM_I32_CONVERT_I64(WASM_ATOMICS_TERNARY_OP(
559 : kExprI64AtomicCompareExchange16U,
560 : WASM_I64_EQ(WASM_I64V(1), WASM_I64V(0)), WASM_GET_LOCAL(0),
561 : WASM_GET_LOCAL(1), MachineRepresentation::kWord16)));
562 :
563 : uint64_t initial = 4444333322221111, local = 0x9999888877776666;
564 : r.builder().WriteMemory(&memory[0], initial);
565 12 : CHECK_EQ(static_cast<uint16_t>(initial), r.Call(initial, local));
566 12 : CHECK_EQ(static_cast<uint16_t>(CompareExchange(initial, initial, local)),
567 : static_cast<uint16_t>(r.builder().ReadMemory(&memory[0])));
568 12 : }
569 :
570 26087 : WASM_EXEC_TEST(I64AtomicNonConstIndexLoad8U) {
571 : EXPERIMENTAL_FLAG_SCOPE(threads);
572 24 : WasmRunner<uint32_t> r(execution_tier);
573 : r.builder().SetHasSharedMemory();
574 : uint64_t* memory =
575 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
576 12 : BUILD(r, WASM_I32_CONVERT_I64(WASM_ATOMICS_LOAD_OP(
577 : kExprI64AtomicLoad8U, WASM_I64_EQ(WASM_I64V(1), WASM_I64V(0)),
578 : MachineRepresentation::kWord8)));
579 :
580 : uint64_t expected = 0xffffeeeeddddcccc;
581 : r.builder().WriteMemory(&memory[0], expected);
582 12 : CHECK_EQ(static_cast<uint8_t>(expected), r.Call());
583 12 : }
584 :
585 26087 : WASM_EXEC_TEST(I64AtomicCompareExchangeFail) {
586 : EXPERIMENTAL_FLAG_SCOPE(threads);
587 24 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_tier);
588 : r.builder().SetHasSharedMemory();
589 : uint64_t* memory =
590 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
591 12 : BUILD(r, WASM_ATOMICS_TERNARY_OP(
592 : kExprI64AtomicCompareExchange, WASM_I32V_1(0), WASM_GET_LOCAL(0),
593 : WASM_GET_LOCAL(1), MachineRepresentation::kWord64));
594 :
595 : uint64_t initial = 0x1111222233334444, local = 0x1111111111111111,
596 : test = 0x2222222222222222;
597 : r.builder().WriteMemory(&memory[0], initial);
598 12 : CHECK_EQ(initial, r.Call(test, local));
599 : // No memory change on failed compare exchange
600 12 : CHECK_EQ(initial, r.builder().ReadMemory(&memory[0]));
601 12 : }
602 :
603 26087 : WASM_EXEC_TEST(I64AtomicCompareExchange32UFail) {
604 : EXPERIMENTAL_FLAG_SCOPE(threads);
605 24 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_tier);
606 : r.builder().SetHasSharedMemory();
607 : uint64_t* memory =
608 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
609 12 : BUILD(r, WASM_ATOMICS_TERNARY_OP(kExprI64AtomicCompareExchange32U,
610 : WASM_I32V_1(0), WASM_GET_LOCAL(0),
611 : WASM_GET_LOCAL(1),
612 : MachineRepresentation::kWord32));
613 :
614 : uint64_t initial = 0x1111222233334444, test = 0xffffffff, local = 0xeeeeeeee;
615 : r.builder().WriteMemory(&memory[0], initial);
616 12 : CHECK_EQ(static_cast<uint32_t>(initial), r.Call(test, local));
617 : // No memory change on failed compare exchange
618 12 : CHECK_EQ(initial, r.builder().ReadMemory(&memory[0]));
619 12 : }
620 :
621 : } // namespace test_run_wasm_atomics_64
622 : } // namespace wasm
623 : } // namespace internal
624 78189 : } // namespace v8
|