Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: test/cctest/compiler/test-run-load-store.cc

Issue 1858323003: [turbofan] Length and index2 are unsigned in CheckedLoad/CheckedStore. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: git cl try Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/cctest/cctest.gyp ('k') | test/cctest/compiler/test-run-machops.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 the V8 project authors. All rights reserved. Use of this
2 // source code is governed by a BSD-style license that can be found in the
3 // LICENSE file.
4
5 #include <cmath>
6 #include <functional>
7 #include <limits>
8
9 #include "src/base/bits.h"
10 #include "src/base/utils/random-number-generator.h"
11 #include "src/codegen.h"
12 #include "test/cctest/cctest.h"
13 #include "test/cctest/compiler/codegen-tester.h"
14 #include "test/cctest/compiler/graph-builder-tester.h"
15 #include "test/cctest/compiler/value-helper.h"
16
17 using namespace v8::base;
18
19 namespace {
20 template <typename Type>
21 void CheckOobValue(Type val) {
22 UNREACHABLE();
23 }
24
25 template <>
26 void CheckOobValue(int32_t val) {
27 CHECK_EQ(0, val);
28 }
29
30 template <>
31 void CheckOobValue(int64_t val) {
32 CHECK_EQ(0, val);
33 }
34
35 template <>
36 void CheckOobValue(float val) {
37 CHECK(std::isnan(val));
38 }
39
40 template <>
41 void CheckOobValue(double val) {
42 CHECK(std::isnan(val));
43 }
44 } // namespace
45
46 namespace v8 {
47 namespace internal {
48 namespace compiler {
49
50 // This is a America!
51 #define A_BILLION 1000000000ULL
52 #define A_GIG (1024ULL * 1024ULL * 1024ULL)
53
54 TEST(RunLoadInt32) {
55 RawMachineAssemblerTester<int32_t> m;
56
57 int32_t p1 = 0; // loads directly from this location.
58 m.Return(m.LoadFromPointer(&p1, MachineType::Int32()));
59
60 FOR_INT32_INPUTS(i) {
61 p1 = *i;
62 CHECK_EQ(p1, m.Call());
63 }
64 }
65
66 TEST(RunLoadInt32Offset) {
67 int32_t p1 = 0; // loads directly from this location.
68
69 int32_t offsets[] = {-2000000, -100, -101, 1, 3,
70 7, 120, 2000, 2000000000, 0xff};
71
72 for (size_t i = 0; i < arraysize(offsets); i++) {
73 RawMachineAssemblerTester<int32_t> m;
74 int32_t offset = offsets[i];
75 byte* pointer = reinterpret_cast<byte*>(&p1) - offset;
76 // generate load [#base + #index]
77 m.Return(m.LoadFromPointer(pointer, MachineType::Int32(), offset));
78
79 FOR_INT32_INPUTS(j) {
80 p1 = *j;
81 CHECK_EQ(p1, m.Call());
82 }
83 }
84 }
85
86 TEST(RunLoadStoreFloat32Offset) {
87 float p1 = 0.0f; // loads directly from this location.
88 float p2 = 0.0f; // and stores directly into this location.
89
90 FOR_INT32_INPUTS(i) {
91 int32_t magic = 0x2342aabb + *i * 3;
92 RawMachineAssemblerTester<int32_t> m;
93 int32_t offset = *i;
94 byte* from = reinterpret_cast<byte*>(&p1) - offset;
95 byte* to = reinterpret_cast<byte*>(&p2) - offset;
96 // generate load [#base + #index]
97 Node* load = m.Load(MachineType::Float32(), m.PointerConstant(from),
98 m.IntPtrConstant(offset));
99 m.Store(MachineRepresentation::kFloat32, m.PointerConstant(to),
100 m.IntPtrConstant(offset), load, kNoWriteBarrier);
101 m.Return(m.Int32Constant(magic));
102
103 FOR_FLOAT32_INPUTS(j) {
104 p1 = *j;
105 p2 = *j - 5;
106 CHECK_EQ(magic, m.Call());
107 CheckDoubleEq(p1, p2);
108 }
109 }
110 }
111
112 TEST(RunLoadStoreFloat64Offset) {
113 double p1 = 0; // loads directly from this location.
114 double p2 = 0; // and stores directly into this location.
115
116 FOR_INT32_INPUTS(i) {
117 int32_t magic = 0x2342aabb + *i * 3;
118 RawMachineAssemblerTester<int32_t> m;
119 int32_t offset = *i;
120 byte* from = reinterpret_cast<byte*>(&p1) - offset;
121 byte* to = reinterpret_cast<byte*>(&p2) - offset;
122 // generate load [#base + #index]
123 Node* load = m.Load(MachineType::Float64(), m.PointerConstant(from),
124 m.IntPtrConstant(offset));
125 m.Store(MachineRepresentation::kFloat64, m.PointerConstant(to),
126 m.IntPtrConstant(offset), load, kNoWriteBarrier);
127 m.Return(m.Int32Constant(magic));
128
129 FOR_FLOAT64_INPUTS(j) {
130 p1 = *j;
131 p2 = *j - 5;
132 CHECK_EQ(magic, m.Call());
133 CheckDoubleEq(p1, p2);
134 }
135 }
136 }
137
138 namespace {
139 template <typename Type>
140 void RunLoadImmIndex(MachineType rep) {
141 const int kNumElems = 3;
142 Type buffer[kNumElems];
143
144 // initialize the buffer with some raw data.
145 byte* raw = reinterpret_cast<byte*>(buffer);
146 for (size_t i = 0; i < sizeof(buffer); i++) {
147 raw[i] = static_cast<byte>((i + sizeof(buffer)) ^ 0xAA);
148 }
149
150 // Test with various large and small offsets.
151 for (int offset = -1; offset <= 200000; offset *= -5) {
152 for (int i = 0; i < kNumElems; i++) {
153 BufferedRawMachineAssemblerTester<Type> m;
154 Node* base = m.PointerConstant(buffer - offset);
155 Node* index = m.Int32Constant((offset + i) * sizeof(buffer[0]));
156 m.Return(m.Load(rep, base, index));
157
158 volatile Type expected = buffer[i];
159 volatile Type actual = m.Call();
160 CHECK_EQ(expected, actual);
161 }
162 }
163 }
164
165 template <typename CType>
166 void RunLoadStore(MachineType rep) {
167 const int kNumElems = 4;
168 CType buffer[kNumElems];
169
170 for (int32_t x = 0; x < kNumElems; x++) {
171 int32_t y = kNumElems - x - 1;
172 // initialize the buffer with raw data.
173 byte* raw = reinterpret_cast<byte*>(buffer);
174 for (size_t i = 0; i < sizeof(buffer); i++) {
175 raw[i] = static_cast<byte>((i + sizeof(buffer)) ^ 0xAA);
176 }
177
178 RawMachineAssemblerTester<int32_t> m;
179 int32_t OK = 0x29000 + x;
180 Node* base = m.PointerConstant(buffer);
181 Node* index0 = m.IntPtrConstant(x * sizeof(buffer[0]));
182 Node* load = m.Load(rep, base, index0);
183 Node* index1 = m.IntPtrConstant(y * sizeof(buffer[0]));
184 m.Store(rep.representation(), base, index1, load, kNoWriteBarrier);
185 m.Return(m.Int32Constant(OK));
186
187 CHECK(buffer[x] != buffer[y]);
188 CHECK_EQ(OK, m.Call());
189 CHECK(buffer[x] == buffer[y]);
190 }
191 }
192 } // namespace
193
194 TEST(RunLoadImmIndex) {
195 RunLoadImmIndex<int8_t>(MachineType::Int8());
196 RunLoadImmIndex<uint8_t>(MachineType::Uint8());
197 RunLoadImmIndex<int16_t>(MachineType::Int16());
198 RunLoadImmIndex<uint16_t>(MachineType::Uint16());
199 RunLoadImmIndex<int32_t>(MachineType::Int32());
200 RunLoadImmIndex<uint32_t>(MachineType::Uint32());
201 RunLoadImmIndex<int32_t*>(MachineType::AnyTagged());
202 RunLoadImmIndex<float>(MachineType::Float32());
203 RunLoadImmIndex<double>(MachineType::Float64());
204 #if V8_TARGET_ARCH_64_BIT
205 RunLoadImmIndex<int64_t>(MachineType::Int64());
206 #endif
207 // TODO(titzer): test various indexing modes.
208 }
209
210 TEST(RunLoadStore) {
211 RunLoadStore<int8_t>(MachineType::Int8());
212 RunLoadStore<uint8_t>(MachineType::Uint8());
213 RunLoadStore<int16_t>(MachineType::Int16());
214 RunLoadStore<uint16_t>(MachineType::Uint16());
215 RunLoadStore<int32_t>(MachineType::Int32());
216 RunLoadStore<uint32_t>(MachineType::Uint32());
217 RunLoadStore<void*>(MachineType::AnyTagged());
218 RunLoadStore<float>(MachineType::Float32());
219 RunLoadStore<double>(MachineType::Float64());
220 #if V8_TARGET_ARCH_64_BIT
221 RunLoadStore<int64_t>(MachineType::Int64());
222 #endif
223 }
224
225 TEST(RunLoadStoreSignExtend32) {
226 int32_t buffer[4];
227 RawMachineAssemblerTester<int32_t> m;
228 Node* load8 = m.LoadFromPointer(&buffer[0], MachineType::Int8());
229 Node* load16 = m.LoadFromPointer(&buffer[0], MachineType::Int16());
230 Node* load32 = m.LoadFromPointer(&buffer[0], MachineType::Int32());
231 m.StoreToPointer(&buffer[1], MachineRepresentation::kWord32, load8);
232 m.StoreToPointer(&buffer[2], MachineRepresentation::kWord32, load16);
233 m.StoreToPointer(&buffer[3], MachineRepresentation::kWord32, load32);
234 m.Return(load8);
235
236 FOR_INT32_INPUTS(i) {
237 buffer[0] = *i;
238
239 CHECK_EQ(static_cast<int8_t>(*i & 0xff), m.Call());
240 CHECK_EQ(static_cast<int8_t>(*i & 0xff), buffer[1]);
241 CHECK_EQ(static_cast<int16_t>(*i & 0xffff), buffer[2]);
242 CHECK_EQ(*i, buffer[3]);
243 }
244 }
245
246 TEST(RunLoadStoreZeroExtend32) {
247 uint32_t buffer[4];
248 RawMachineAssemblerTester<uint32_t> m;
249 Node* load8 = m.LoadFromPointer(&buffer[0], MachineType::Uint8());
250 Node* load16 = m.LoadFromPointer(&buffer[0], MachineType::Uint16());
251 Node* load32 = m.LoadFromPointer(&buffer[0], MachineType::Uint32());
252 m.StoreToPointer(&buffer[1], MachineRepresentation::kWord32, load8);
253 m.StoreToPointer(&buffer[2], MachineRepresentation::kWord32, load16);
254 m.StoreToPointer(&buffer[3], MachineRepresentation::kWord32, load32);
255 m.Return(load8);
256
257 FOR_UINT32_INPUTS(i) {
258 buffer[0] = *i;
259
260 CHECK_EQ((*i & 0xff), m.Call());
261 CHECK_EQ((*i & 0xff), buffer[1]);
262 CHECK_EQ((*i & 0xffff), buffer[2]);
263 CHECK_EQ(*i, buffer[3]);
264 }
265 }
266
267 #if V8_TARGET_ARCH_64_BIT
268 TEST(RunCheckedLoadInt64) {
269 int64_t buffer[] = {0x66bbccddeeff0011LL, 0x1122334455667788LL};
270 RawMachineAssemblerTester<int64_t> m(MachineType::Int32());
271 Node* base = m.PointerConstant(buffer);
272 Node* index = m.Parameter(0);
273 Node* length = m.Int32Constant(16);
274 Node* load = m.AddNode(m.machine()->CheckedLoad(MachineType::Int64()), base,
275 index, length);
276 m.Return(load);
277
278 CHECK_EQ(buffer[0], m.Call(0));
279 CHECK_EQ(buffer[1], m.Call(8));
280 CheckOobValue(m.Call(16));
281 }
282
283 TEST(RunLoadStoreSignExtend64) {
284 if (true) return; // TODO(titzer): sign extension of loads to 64-bit.
285 int64_t buffer[5];
286 RawMachineAssemblerTester<int64_t> m;
287 Node* load8 = m.LoadFromPointer(&buffer[0], MachineType::Int8());
288 Node* load16 = m.LoadFromPointer(&buffer[0], MachineType::Int16());
289 Node* load32 = m.LoadFromPointer(&buffer[0], MachineType::Int32());
290 Node* load64 = m.LoadFromPointer(&buffer[0], MachineType::Int64());
291 m.StoreToPointer(&buffer[1], MachineRepresentation::kWord64, load8);
292 m.StoreToPointer(&buffer[2], MachineRepresentation::kWord64, load16);
293 m.StoreToPointer(&buffer[3], MachineRepresentation::kWord64, load32);
294 m.StoreToPointer(&buffer[4], MachineRepresentation::kWord64, load64);
295 m.Return(load8);
296
297 FOR_INT64_INPUTS(i) {
298 buffer[0] = *i;
299
300 CHECK_EQ(static_cast<int8_t>(*i & 0xff), m.Call());
301 CHECK_EQ(static_cast<int8_t>(*i & 0xff), buffer[1]);
302 CHECK_EQ(static_cast<int16_t>(*i & 0xffff), buffer[2]);
303 CHECK_EQ(static_cast<int32_t>(*i & 0xffffffff), buffer[3]);
304 CHECK_EQ(*i, buffer[4]);
305 }
306 }
307
308 TEST(RunLoadStoreZeroExtend64) {
309 if (kPointerSize < 8) return;
310 uint64_t buffer[5];
311 RawMachineAssemblerTester<int64_t> m;
312 Node* load8 = m.LoadFromPointer(&buffer[0], MachineType::Uint8());
313 Node* load16 = m.LoadFromPointer(&buffer[0], MachineType::Uint16());
314 Node* load32 = m.LoadFromPointer(&buffer[0], MachineType::Uint32());
315 Node* load64 = m.LoadFromPointer(&buffer[0], MachineType::Uint64());
316 m.StoreToPointer(&buffer[1], MachineRepresentation::kWord64, load8);
317 m.StoreToPointer(&buffer[2], MachineRepresentation::kWord64, load16);
318 m.StoreToPointer(&buffer[3], MachineRepresentation::kWord64, load32);
319 m.StoreToPointer(&buffer[4], MachineRepresentation::kWord64, load64);
320 m.Return(load8);
321
322 FOR_UINT64_INPUTS(i) {
323 buffer[0] = *i;
324
325 CHECK_EQ((*i & 0xff), m.Call());
326 CHECK_EQ((*i & 0xff), buffer[1]);
327 CHECK_EQ((*i & 0xffff), buffer[2]);
328 CHECK_EQ((*i & 0xffffffff), buffer[3]);
329 CHECK_EQ(*i, buffer[4]);
330 }
331 }
332
333 TEST(RunCheckedStoreInt64) {
334 const int64_t write = 0x5566778899aabbLL;
335 const int64_t before = 0x33bbccddeeff0011LL;
336 int64_t buffer[] = {before, before};
337 RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
338 Node* base = m.PointerConstant(buffer);
339 Node* index = m.Parameter(0);
340 Node* length = m.Int32Constant(16);
341 Node* value = m.Int64Constant(write);
342 Node* store =
343 m.AddNode(m.machine()->CheckedStore(MachineRepresentation::kWord64), base,
344 index, length, value);
345 USE(store);
346 m.Return(m.Int32Constant(11));
347
348 CHECK_EQ(11, m.Call(16));
349 CHECK_EQ(before, buffer[0]);
350 CHECK_EQ(before, buffer[1]);
351
352 CHECK_EQ(11, m.Call(0));
353 CHECK_EQ(write, buffer[0]);
354 CHECK_EQ(before, buffer[1]);
355
356 CHECK_EQ(11, m.Call(8));
357 CHECK_EQ(write, buffer[0]);
358 CHECK_EQ(write, buffer[1]);
359 }
360 #endif
361
362 namespace {
363 template <typename IntType>
364 void LoadStoreTruncation(MachineType kRepresentation) {
365 IntType input;
366
367 RawMachineAssemblerTester<int32_t> m;
368 Node* a = m.LoadFromPointer(&input, kRepresentation);
369 Node* ap1 = m.Int32Add(a, m.Int32Constant(1));
370 m.StoreToPointer(&input, kRepresentation.representation(), ap1);
371 m.Return(ap1);
372
373 const IntType max = std::numeric_limits<IntType>::max();
374 const IntType min = std::numeric_limits<IntType>::min();
375
376 // Test upper bound.
377 input = max;
378 CHECK_EQ(max + 1, m.Call());
379 CHECK_EQ(min, input);
380
381 // Test lower bound.
382 input = min;
383 CHECK_EQ(static_cast<IntType>(max + 2), m.Call());
384 CHECK_EQ(min + 1, input);
385
386 // Test all one byte values that are not one byte bounds.
387 for (int i = -127; i < 127; i++) {
388 input = i;
389 int expected = i >= 0 ? i + 1 : max + (i - min) + 2;
390 CHECK_EQ(static_cast<IntType>(expected), m.Call());
391 CHECK_EQ(static_cast<IntType>(i + 1), input);
392 }
393 }
394 } // namespace
395
396 TEST(RunLoadStoreTruncation) {
397 LoadStoreTruncation<int8_t>(MachineType::Int8());
398 LoadStoreTruncation<int16_t>(MachineType::Int16());
399 }
400
401 void TestRunOobCheckedLoad(bool length_is_immediate) {
402 USE(CheckOobValue<int32_t>);
403 USE(CheckOobValue<int64_t>);
404 USE(CheckOobValue<float>);
405 USE(CheckOobValue<double>);
406
407 RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
408 MachineType::Int32());
409 MachineOperatorBuilder machine(m.zone());
410 const int32_t kNumElems = 27;
411 const int32_t kLength = kNumElems * 4;
412
413 int32_t buffer[kNumElems];
414 Node* base = m.PointerConstant(buffer);
415 Node* offset = m.Parameter(0);
416 Node* len = length_is_immediate ? m.Int32Constant(kLength) : m.Parameter(1);
417 Node* node =
418 m.AddNode(machine.CheckedLoad(MachineType::Int32()), base, offset, len);
419 m.Return(node);
420
421 {
422 // randomize memory.
423 v8::base::RandomNumberGenerator rng;
424 rng.SetSeed(100);
425 rng.NextBytes(&buffer[0], sizeof(buffer));
426 }
427
428 // in-bounds accesses.
429 for (int32_t i = 0; i < kNumElems; i++) {
430 int32_t offset = static_cast<int32_t>(i * sizeof(int32_t));
431 int32_t expected = buffer[i];
432 CHECK_EQ(expected, m.Call(offset, kLength));
433 }
434
435 // slightly out-of-bounds accesses.
436 for (int32_t i = kLength; i < kNumElems + 30; i++) {
437 int32_t offset = static_cast<int32_t>(i * sizeof(int32_t));
438 CheckOobValue(m.Call(offset, kLength));
439 }
440
441 // way out-of-bounds accesses.
442 for (int32_t offset = -2000000000; offset <= 2000000000;
443 offset += 100000000) {
444 if (offset == 0) continue;
445 CheckOobValue(m.Call(offset, kLength));
446 }
447 }
448
449 TEST(RunOobCheckedLoad) { TestRunOobCheckedLoad(false); }
450
451 TEST(RunOobCheckedLoadImm) { TestRunOobCheckedLoad(true); }
452
453 void TestRunOobCheckedStore(bool length_is_immediate) {
454 RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
455 MachineType::Int32());
456 MachineOperatorBuilder machine(m.zone());
457 const int32_t kNumElems = 29;
458 const int32_t kValue = -78227234;
459 const int32_t kLength = kNumElems * 4;
460
461 int32_t buffer[kNumElems + kNumElems];
462 Node* base = m.PointerConstant(buffer);
463 Node* offset = m.Parameter(0);
464 Node* len = length_is_immediate ? m.Int32Constant(kLength) : m.Parameter(1);
465 Node* val = m.Int32Constant(kValue);
466 m.AddNode(machine.CheckedStore(MachineRepresentation::kWord32), base, offset,
467 len, val);
468 m.Return(val);
469
470 // in-bounds accesses.
471 for (int32_t i = 0; i < kNumElems; i++) {
472 memset(buffer, 0, sizeof(buffer));
473 int32_t offset = static_cast<int32_t>(i * sizeof(int32_t));
474 CHECK_EQ(kValue, m.Call(offset, kLength));
475 for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
476 if (i == j) {
477 CHECK_EQ(kValue, buffer[j]);
478 } else {
479 CHECK_EQ(0, buffer[j]);
480 }
481 }
482 }
483
484 memset(buffer, 0, sizeof(buffer));
485
486 // slightly out-of-bounds accesses.
487 for (int32_t i = kLength; i < kNumElems + 30; i++) {
488 int32_t offset = static_cast<int32_t>(i * sizeof(int32_t));
489 CHECK_EQ(kValue, m.Call(offset, kLength));
490 for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
491 CHECK_EQ(0, buffer[j]);
492 }
493 }
494
495 // way out-of-bounds accesses.
496 for (int32_t offset = -2000000000; offset <= 2000000000;
497 offset += 100000000) {
498 if (offset == 0) continue;
499 CHECK_EQ(kValue, m.Call(offset, kLength));
500 for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
501 CHECK_EQ(0, buffer[j]);
502 }
503 }
504 }
505
506 TEST(RunOobCheckedStore) { TestRunOobCheckedStore(false); }
507
508 TEST(RunOobCheckedStoreImm) { TestRunOobCheckedStore(true); }
509
510 // TODO(titzer): CheckedLoad/CheckedStore don't support 64-bit offsets.
511 #define ALLOW_64_BIT_OFFSETS 0
512
513 #if V8_TARGET_ARCH_64_BIT && ALLOW_64_BIT_OFFSETS
514
515 void TestRunOobCheckedLoad64(uint32_t pseudo_base, bool length_is_immediate) {
516 RawMachineAssemblerTester<int32_t> m(MachineType::Uint64(),
517 MachineType::Uint64());
518 MachineOperatorBuilder machine(m.zone());
519 const uint32_t kNumElems = 25;
520 const uint32_t kLength = kNumElems * 4;
521 int32_t real_buffer[kNumElems];
522
523 // Simulate the end of a large buffer.
524 int32_t* buffer = real_buffer - (pseudo_base / 4);
525 uint64_t length = kLength + pseudo_base;
526
527 Node* base = m.PointerConstant(buffer);
528 Node* offset = m.Parameter(0);
529 Node* len = length_is_immediate ? m.Int64Constant(length) : m.Parameter(1);
530 Node* node =
531 m.AddNode(machine.CheckedLoad(MachineType::Int32()), base, offset, len);
532 m.Return(node);
533
534 {
535 // randomize memory.
536 v8::base::RandomNumberGenerator rng;
537 rng.SetSeed(100);
538 rng.NextBytes(&real_buffer[0], sizeof(real_buffer));
539 }
540
541 // in-bounds accesses.
542 for (uint32_t i = 0; i < kNumElems; i++) {
543 uint64_t offset = pseudo_base + i * 4;
544 int32_t expected = real_buffer[i];
545 CHECK_EQ(expected, m.Call(offset, length));
546 }
547
548 // in-bounds accesses w.r.t lower 32-bits, but upper bits set.
549 for (uint64_t i = 0x100000000ULL; i != 0; i <<= 1) {
550 uint64_t offset = pseudo_base + i;
551 CheckOobValue(m.Call(offset, length));
552 }
553
554 // slightly out-of-bounds accesses.
555 for (uint32_t i = kLength; i < kNumElems + 30; i++) {
556 uint64_t offset = pseudo_base + i * 4;
557 CheckOobValue(0, m.Call(offset, length));
558 }
559
560 // way out-of-bounds accesses.
561 for (uint64_t offset = length; offset < 100 * A_BILLION; offset += A_GIG) {
562 if (offset < length) continue;
563 CheckOobValue(0, m.Call(offset, length));
564 }
565 }
566
567 TEST(RunOobCheckedLoad64_0) {
568 TestRunOobCheckedLoad64(0, false);
569 TestRunOobCheckedLoad64(0, true);
570 }
571
572 TEST(RunOobCheckedLoad64_1) {
573 TestRunOobCheckedLoad64(1 * A_BILLION, false);
574 TestRunOobCheckedLoad64(1 * A_BILLION, true);
575 }
576
577 TEST(RunOobCheckedLoad64_2) {
578 TestRunOobCheckedLoad64(2 * A_BILLION, false);
579 TestRunOobCheckedLoad64(2 * A_BILLION, true);
580 }
581
582 TEST(RunOobCheckedLoad64_3) {
583 TestRunOobCheckedLoad64(3 * A_BILLION, false);
584 TestRunOobCheckedLoad64(3 * A_BILLION, true);
585 }
586
587 TEST(RunOobCheckedLoad64_4) {
588 TestRunOobCheckedLoad64(4 * A_BILLION, false);
589 TestRunOobCheckedLoad64(4 * A_BILLION, true);
590 }
591
592 void TestRunOobCheckedStore64(uint32_t pseudo_base, bool length_is_immediate) {
593 RawMachineAssemblerTester<int32_t> m(MachineType::Uint64(),
594 MachineType::Uint64());
595 MachineOperatorBuilder machine(m.zone());
596 const uint32_t kNumElems = 21;
597 const uint32_t kLength = kNumElems * 4;
598 const uint32_t kValue = 897234987;
599 int32_t real_buffer[kNumElems + kNumElems];
600
601 // Simulate the end of a large buffer.
602 int32_t* buffer = real_buffer - (pseudo_base / 4);
603 uint64_t length = kLength + pseudo_base;
604
605 Node* base = m.PointerConstant(buffer);
606 Node* offset = m.Parameter(0);
607 Node* len = length_is_immediate ? m.Int64Constant(length) : m.Parameter(1);
608 Node* val = m.Int32Constant(kValue);
609 m.AddNode(machine.CheckedStore(MachineRepresentation::kWord32), base, offset,
610 len, val);
611 m.Return(val);
612
613 // in-bounds accesses.
614 for (uint32_t i = 0; i < kNumElems; i++) {
615 memset(real_buffer, 0, sizeof(real_buffer));
616 uint64_t offset = pseudo_base + i * 4;
617 CHECK_EQ(kValue, m.Call(offset, length));
618 for (uint32_t j = 0; j < kNumElems + kNumElems; j++) {
619 if (i == j) {
620 CHECK_EQ(kValue, real_buffer[j]);
621 } else {
622 CHECK_EQ(0, real_buffer[j]);
623 }
624 }
625 }
626
627 memset(real_buffer, 0, sizeof(real_buffer));
628
629 // in-bounds accesses w.r.t lower 32-bits, but upper bits set.
630 for (uint64_t i = 0x100000000ULL; i != 0; i <<= 1) {
631 uint64_t offset = pseudo_base + i;
632 CHECK_EQ(kValue, m.Call(offset, length));
633 for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
634 CHECK_EQ(0, real_buffer[j]);
635 }
636 }
637
638 // slightly out-of-bounds accesses.
639 for (uint32_t i = kLength; i < kNumElems + 30; i++) {
640 uint64_t offset = pseudo_base + i * 4;
641 CHECK_EQ(kValue, m.Call(offset, length));
642 for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
643 CHECK_EQ(0, real_buffer[j]);
644 }
645 }
646
647 // way out-of-bounds accesses.
648 for (uint64_t offset = length; offset < 100 * A_BILLION; offset += A_GIG) {
649 if (offset < length) continue;
650 CHECK_EQ(kValue, m.Call(offset, length));
651 for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
652 CHECK_EQ(0, real_buffer[j]);
653 }
654 }
655 }
656
657 TEST(RunOobCheckedStore64_0) {
658 TestRunOobCheckedStore64(0, false);
659 TestRunOobCheckedStore64(0, true);
660 }
661
662 TEST(RunOobCheckedStore64_1) {
663 TestRunOobCheckedStore64(1 * A_BILLION, false);
664 TestRunOobCheckedStore64(1 * A_BILLION, true);
665 }
666
667 TEST(RunOobCheckedStore64_2) {
668 TestRunOobCheckedStore64(2 * A_BILLION, false);
669 TestRunOobCheckedStore64(2 * A_BILLION, true);
670 }
671
672 TEST(RunOobCheckedStore64_3) {
673 TestRunOobCheckedStore64(3 * A_BILLION, false);
674 TestRunOobCheckedStore64(3 * A_BILLION, true);
675 }
676
677 TEST(RunOobCheckedStore64_4) {
678 TestRunOobCheckedStore64(4 * A_BILLION, false);
679 TestRunOobCheckedStore64(4 * A_BILLION, true);
680 }
681
682 #endif
683
684 void TestRunOobCheckedLoad_pseudo(uint64_t x, bool length_is_immediate) {
685 RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
686 MachineType::Uint32());
687
688 uint32_t pseudo_base = static_cast<uint32_t>(x);
689 MachineOperatorBuilder machine(m.zone());
690 const uint32_t kNumElems = 29;
691 const uint32_t kLength = pseudo_base + kNumElems * 4;
692
693 int32_t buffer[kNumElems];
694 Node* base = m.PointerConstant(reinterpret_cast<byte*>(buffer) - pseudo_base);
695 Node* offset = m.Parameter(0);
696 Node* len = length_is_immediate ? m.Int32Constant(kLength) : m.Parameter(1);
697 Node* node =
698 m.AddNode(machine.CheckedLoad(MachineType::Int32()), base, offset, len);
699 m.Return(node);
700
701 {
702 // randomize memory.
703 v8::base::RandomNumberGenerator rng;
704 rng.SetSeed(100);
705 rng.NextBytes(&buffer[0], sizeof(buffer));
706 }
707
708 // in-bounds accesses.
709 for (uint32_t i = 0; i < kNumElems; i++) {
710 uint32_t offset = static_cast<uint32_t>(i * sizeof(int32_t));
711 uint32_t expected = buffer[i];
712 CHECK_EQ(expected, m.Call(offset + pseudo_base, kLength));
713 }
714
715 // slightly out-of-bounds accesses.
716 for (int32_t i = kNumElems; i < kNumElems + 30; i++) {
717 uint32_t offset = static_cast<uint32_t>(i * sizeof(int32_t));
718 CheckOobValue(m.Call(offset + pseudo_base, kLength));
719 }
720
721 // way out-of-bounds accesses.
722 for (uint64_t i = pseudo_base + sizeof(buffer); i < 0xFFFFFFFF;
723 i += A_BILLION) {
724 uint32_t offset = static_cast<uint32_t>(i);
725 CheckOobValue(m.Call(offset, kLength));
726 }
727 }
728
729 TEST(RunOobCheckedLoad_pseudo0) {
730 TestRunOobCheckedLoad_pseudo(0, false);
731 TestRunOobCheckedLoad_pseudo(0, true);
732 }
733
734 TEST(RunOobCheckedLoad_pseudo1) {
735 TestRunOobCheckedLoad_pseudo(100000, false);
736 TestRunOobCheckedLoad_pseudo(100000, true);
737 }
738
739 TEST(RunOobCheckedLoad_pseudo2) {
740 TestRunOobCheckedLoad_pseudo(A_BILLION, false);
741 TestRunOobCheckedLoad_pseudo(A_BILLION, true);
742 }
743
744 TEST(RunOobCheckedLoad_pseudo3) {
745 TestRunOobCheckedLoad_pseudo(A_GIG, false);
746 TestRunOobCheckedLoad_pseudo(A_GIG, true);
747 }
748
749 TEST(RunOobCheckedLoad_pseudo4) {
750 TestRunOobCheckedLoad_pseudo(2 * A_BILLION, false);
751 TestRunOobCheckedLoad_pseudo(2 * A_BILLION, true);
752 }
753
754 TEST(RunOobCheckedLoad_pseudo5) {
755 TestRunOobCheckedLoad_pseudo(2 * A_GIG, false);
756 TestRunOobCheckedLoad_pseudo(2 * A_GIG, true);
757 }
758
759 TEST(RunOobCheckedLoad_pseudo6) {
760 TestRunOobCheckedLoad_pseudo(3 * A_BILLION, false);
761 TestRunOobCheckedLoad_pseudo(3 * A_BILLION, true);
762 }
763
764 TEST(RunOobCheckedLoad_pseudo7) {
765 TestRunOobCheckedLoad_pseudo(3 * A_GIG, false);
766 TestRunOobCheckedLoad_pseudo(3 * A_GIG, true);
767 }
768
769 TEST(RunOobCheckedLoad_pseudo8) {
770 TestRunOobCheckedLoad_pseudo(4 * A_BILLION, false);
771 TestRunOobCheckedLoad_pseudo(4 * A_BILLION, true);
772 }
773
774 template <typename MemType>
775 void TestRunOobCheckedLoadT_pseudo(uint64_t x, bool length_is_immediate) {
776 const int32_t kReturn = 11999;
777 const uint32_t kNumElems = 29;
778 MemType buffer[kNumElems];
779 uint32_t pseudo_base = static_cast<uint32_t>(x);
780 const uint32_t kLength = static_cast<uint32_t>(pseudo_base + sizeof(buffer));
781
782 MemType result;
783
784 RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
785 MachineType::Uint32());
786 MachineOperatorBuilder machine(m.zone());
787 Node* base = m.PointerConstant(reinterpret_cast<byte*>(buffer) - pseudo_base);
788 Node* offset = m.Parameter(0);
789 Node* len = length_is_immediate ? m.Int32Constant(kLength) : m.Parameter(1);
790 Node* node = m.AddNode(machine.CheckedLoad(MachineTypeForC<MemType>()), base,
791 offset, len);
792 Node* store = m.StoreToPointer(
793 &result, MachineTypeForC<MemType>().representation(), node);
794 USE(store);
795 m.Return(m.Int32Constant(kReturn));
796
797 {
798 // randomize memory.
799 v8::base::RandomNumberGenerator rng;
800 rng.SetSeed(103);
801 rng.NextBytes(&buffer[0], sizeof(buffer));
802 }
803
804 // in-bounds accesses.
805 for (uint32_t i = 0; i < kNumElems; i++) {
806 uint32_t offset = static_cast<uint32_t>(i * sizeof(MemType));
807 MemType expected = buffer[i];
808 CHECK_EQ(kReturn, m.Call(offset + pseudo_base, kLength));
809 CHECK_EQ(expected, result);
810 }
811
812 // slightly out-of-bounds accesses.
813 for (int32_t i = kNumElems; i < kNumElems + 30; i++) {
814 uint32_t offset = static_cast<uint32_t>(i * sizeof(MemType));
815 CHECK_EQ(kReturn, m.Call(offset + pseudo_base, kLength));
816 CheckOobValue(result);
817 }
818
819 // way out-of-bounds accesses.
820 for (uint64_t i = pseudo_base + sizeof(buffer); i < 0xFFFFFFFF;
821 i += A_BILLION) {
822 uint32_t offset = static_cast<uint32_t>(i);
823 CHECK_EQ(kReturn, m.Call(offset, kLength));
824 CheckOobValue(result);
825 }
826 }
827
828 TEST(RunOobCheckedLoadT_pseudo0) {
829 TestRunOobCheckedLoadT_pseudo<int32_t>(0, false);
830 TestRunOobCheckedLoadT_pseudo<int32_t>(0, true);
831 TestRunOobCheckedLoadT_pseudo<float>(0, false);
832 TestRunOobCheckedLoadT_pseudo<float>(0, true);
833 TestRunOobCheckedLoadT_pseudo<double>(0, false);
834 TestRunOobCheckedLoadT_pseudo<double>(0, true);
835 }
836
837 TEST(RunOobCheckedLoadT_pseudo1) {
838 TestRunOobCheckedLoadT_pseudo<int32_t>(100000, false);
839 TestRunOobCheckedLoadT_pseudo<int32_t>(100000, true);
840 TestRunOobCheckedLoadT_pseudo<float>(100000, false);
841 TestRunOobCheckedLoadT_pseudo<float>(100000, true);
842 TestRunOobCheckedLoadT_pseudo<double>(100000, false);
843 TestRunOobCheckedLoadT_pseudo<double>(100000, true);
844 }
845
846 TEST(RunOobCheckedLoadT_pseudo2) {
847 TestRunOobCheckedLoadT_pseudo<int32_t>(A_BILLION, false);
848 TestRunOobCheckedLoadT_pseudo<int32_t>(A_BILLION, true);
849 TestRunOobCheckedLoadT_pseudo<float>(A_BILLION, false);
850 TestRunOobCheckedLoadT_pseudo<float>(A_BILLION, true);
851 TestRunOobCheckedLoadT_pseudo<double>(A_BILLION, false);
852 TestRunOobCheckedLoadT_pseudo<double>(A_BILLION, true);
853 }
854
855 TEST(RunOobCheckedLoadT_pseudo3) {
856 TestRunOobCheckedLoadT_pseudo<int32_t>(A_GIG, false);
857 TestRunOobCheckedLoadT_pseudo<int32_t>(A_GIG, true);
858 TestRunOobCheckedLoadT_pseudo<float>(A_GIG, false);
859 TestRunOobCheckedLoadT_pseudo<float>(A_GIG, true);
860 TestRunOobCheckedLoadT_pseudo<double>(A_GIG, false);
861 TestRunOobCheckedLoadT_pseudo<double>(A_GIG, true);
862 }
863
864 TEST(RunOobCheckedLoadT_pseudo4) {
865 TestRunOobCheckedLoadT_pseudo<int32_t>(2 * A_BILLION, false);
866 TestRunOobCheckedLoadT_pseudo<int32_t>(2 * A_BILLION, true);
867 TestRunOobCheckedLoadT_pseudo<float>(2 * A_BILLION, false);
868 TestRunOobCheckedLoadT_pseudo<float>(2 * A_BILLION, true);
869 TestRunOobCheckedLoadT_pseudo<double>(2 * A_BILLION, false);
870 TestRunOobCheckedLoadT_pseudo<double>(2 * A_BILLION, true);
871 }
872
873 TEST(RunOobCheckedLoadT_pseudo5) {
874 TestRunOobCheckedLoadT_pseudo<int32_t>(2 * A_GIG, false);
875 TestRunOobCheckedLoadT_pseudo<int32_t>(2 * A_GIG, true);
876 TestRunOobCheckedLoadT_pseudo<float>(2 * A_GIG, false);
877 TestRunOobCheckedLoadT_pseudo<float>(2 * A_GIG, true);
878 TestRunOobCheckedLoadT_pseudo<double>(2 * A_GIG, false);
879 TestRunOobCheckedLoadT_pseudo<double>(2 * A_GIG, true);
880 }
881
882 TEST(RunOobCheckedLoadT_pseudo6) {
883 TestRunOobCheckedLoadT_pseudo<int32_t>(3 * A_BILLION, false);
884 TestRunOobCheckedLoadT_pseudo<int32_t>(3 * A_BILLION, true);
885 TestRunOobCheckedLoadT_pseudo<float>(3 * A_BILLION, false);
886 TestRunOobCheckedLoadT_pseudo<float>(3 * A_BILLION, true);
887 TestRunOobCheckedLoadT_pseudo<double>(3 * A_BILLION, false);
888 TestRunOobCheckedLoadT_pseudo<double>(3 * A_BILLION, true);
889 }
890
891 TEST(RunOobCheckedLoadT_pseudo7) {
892 TestRunOobCheckedLoadT_pseudo<int32_t>(3 * A_GIG, false);
893 TestRunOobCheckedLoadT_pseudo<int32_t>(3 * A_GIG, true);
894 TestRunOobCheckedLoadT_pseudo<float>(3 * A_GIG, false);
895 TestRunOobCheckedLoadT_pseudo<float>(3 * A_GIG, true);
896 TestRunOobCheckedLoadT_pseudo<double>(3 * A_GIG, false);
897 TestRunOobCheckedLoadT_pseudo<double>(3 * A_GIG, true);
898 }
899
900 TEST(RunOobCheckedLoadT_pseudo8) {
901 TestRunOobCheckedLoadT_pseudo<int32_t>(4 * A_BILLION, false);
902 TestRunOobCheckedLoadT_pseudo<int32_t>(4 * A_BILLION, true);
903 TestRunOobCheckedLoadT_pseudo<float>(4 * A_BILLION, false);
904 TestRunOobCheckedLoadT_pseudo<float>(4 * A_BILLION, true);
905 TestRunOobCheckedLoadT_pseudo<double>(4 * A_BILLION, false);
906 TestRunOobCheckedLoadT_pseudo<double>(4 * A_BILLION, true);
907 }
908
909 } // namespace compiler
910 } // namespace internal
911 } // namespace v8
OLDNEW
« no previous file with comments | « test/cctest/cctest.gyp ('k') | test/cctest/compiler/test-run-machops.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698