LCOV - code coverage report
Current view: top level - test/cctest/compiler - test-run-load-store.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 566 574 98.6 %
Date: 2017-10-20 Functions: 96 96 100.0 %

          Line data    Source code
       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 "src/objects-inl.h"
      13             : #include "test/cctest/cctest.h"
      14             : #include "test/cctest/compiler/codegen-tester.h"
      15             : #include "test/cctest/compiler/graph-builder-tester.h"
      16             : #include "test/cctest/compiler/value-helper.h"
      17             : 
      18             : 
      19             : namespace {
      20             : template <typename Type>
      21             : void CheckOobValue(Type val) {
      22             :   UNREACHABLE();
      23             : }
      24             : 
      25             : template <>
      26        7656 : void CheckOobValue(int32_t val) {
      27        7656 :   CHECK_EQ(0, val);
      28        7656 : }
      29             : 
      30             : template <>
      31           6 : void CheckOobValue(int64_t val) {
      32           6 :   CHECK_EQ(0, val);
      33           6 : }
      34             : 
      35             : template <>
      36        3588 : void CheckOobValue(float val) {
      37        3588 :   CHECK(std::isnan(val));
      38        3588 : }
      39             : 
      40             : template <>
      41        3588 : void CheckOobValue(double val) {
      42        3588 :   CHECK(std::isnan(val));
      43        3588 : }
      44             : }  // namespace
      45             : 
      46             : namespace v8 {
      47             : namespace internal {
      48             : namespace compiler {
      49             : 
      50             : enum TestAlignment {
      51             :   kAligned,
      52             :   kUnaligned,
      53             : };
      54             : 
      55             : // This is a America!
      56             : #define A_BILLION 1000000000ULL
      57             : #define A_GIG (1024ULL * 1024ULL * 1024ULL)
      58             : 
      59             : namespace {
      60          12 : void RunLoadInt32(const TestAlignment t) {
      61          12 :   RawMachineAssemblerTester<int32_t> m;
      62             : 
      63          12 :   int32_t p1 = 0;  // loads directly from this location.
      64             : 
      65          12 :   if (t == TestAlignment::kAligned) {
      66           6 :     m.Return(m.LoadFromPointer(&p1, MachineType::Int32()));
      67           6 :   } else if (t == TestAlignment::kUnaligned) {
      68           6 :     m.Return(m.UnalignedLoadFromPointer(&p1, MachineType::Int32()));
      69             :   } else {
      70           0 :     UNREACHABLE();
      71             :   }
      72             : 
      73         708 :   FOR_INT32_INPUTS(i) {
      74         696 :     p1 = *i;
      75         696 :     CHECK_EQ(p1, m.Call());
      76             :   }
      77          12 : }
      78             : 
      79          12 : void RunLoadInt32Offset(TestAlignment t) {
      80          12 :   int32_t p1 = 0;  // loads directly from this location.
      81             : 
      82             :   int32_t offsets[] = {-2000000, -100, -101, 1,          3,
      83          12 :                        7,        120,  2000, 2000000000, 0xff};
      84             : 
      85         132 :   for (size_t i = 0; i < arraysize(offsets); i++) {
      86         120 :     RawMachineAssemblerTester<int32_t> m;
      87         120 :     int32_t offset = offsets[i];
      88         120 :     byte* pointer = reinterpret_cast<byte*>(&p1) - offset;
      89             : 
      90             :     // generate load [#base + #index]
      91         120 :     if (t == TestAlignment::kAligned) {
      92          60 :       m.Return(m.LoadFromPointer(pointer, MachineType::Int32(), offset));
      93          60 :     } else if (t == TestAlignment::kUnaligned) {
      94             :       m.Return(
      95          60 :           m.UnalignedLoadFromPointer(pointer, MachineType::Int32(), offset));
      96             :     } else {
      97           0 :       UNREACHABLE();
      98             :     }
      99             : 
     100        7080 :     FOR_INT32_INPUTS(j) {
     101        6960 :       p1 = *j;
     102        6960 :       CHECK_EQ(p1, m.Call());
     103             :     }
     104             :   }
     105          12 : }
     106             : 
     107          12 : void RunLoadStoreFloat32Offset(TestAlignment t) {
     108          12 :   float p1 = 0.0f;  // loads directly from this location.
     109          12 :   float p2 = 0.0f;  // and stores directly into this location.
     110             : 
     111         708 :   FOR_INT32_INPUTS(i) {
     112         696 :     int32_t magic = 0x2342aabb + *i * 3;
     113         696 :     RawMachineAssemblerTester<int32_t> m;
     114         696 :     int32_t offset = *i;
     115         696 :     byte* from = reinterpret_cast<byte*>(&p1) - offset;
     116         696 :     byte* to = reinterpret_cast<byte*>(&p2) - offset;
     117             :     // generate load [#base + #index]
     118         696 :     if (t == TestAlignment::kAligned) {
     119             :       Node* load = m.Load(MachineType::Float32(), m.PointerConstant(from),
     120         696 :                           m.IntPtrConstant(offset));
     121             :       m.Store(MachineRepresentation::kFloat32, m.PointerConstant(to),
     122         348 :               m.IntPtrConstant(offset), load, kNoWriteBarrier);
     123         348 :     } else if (t == TestAlignment::kUnaligned) {
     124             :       Node* load =
     125             :           m.UnalignedLoad(MachineType::Float32(), m.PointerConstant(from),
     126         696 :                           m.IntPtrConstant(offset));
     127             :       m.UnalignedStore(MachineRepresentation::kFloat32, m.PointerConstant(to),
     128         348 :                        m.IntPtrConstant(offset), load);
     129             : 
     130             :     } else {
     131           0 :       UNREACHABLE();
     132             :     }
     133         696 :     m.Return(m.Int32Constant(magic));
     134             : 
     135       80736 :     FOR_FLOAT32_INPUTS(j) {
     136       80040 :       p1 = *j;
     137       80040 :       p2 = *j - 5;
     138       80040 :       CHECK_EQ(magic, m.Call());
     139       80040 :       CheckDoubleEq(p1, p2);
     140             :     }
     141             :   }
     142          12 : }
     143             : 
     144          12 : void RunLoadStoreFloat64Offset(TestAlignment t) {
     145          12 :   double p1 = 0;  // loads directly from this location.
     146          12 :   double p2 = 0;  // and stores directly into this location.
     147             : 
     148         708 :   FOR_INT32_INPUTS(i) {
     149         696 :     int32_t magic = 0x2342aabb + *i * 3;
     150         696 :     RawMachineAssemblerTester<int32_t> m;
     151         696 :     int32_t offset = *i;
     152         696 :     byte* from = reinterpret_cast<byte*>(&p1) - offset;
     153         696 :     byte* to = reinterpret_cast<byte*>(&p2) - offset;
     154             :     // generate load [#base + #index]
     155         696 :     if (t == TestAlignment::kAligned) {
     156             :       Node* load = m.Load(MachineType::Float64(), m.PointerConstant(from),
     157         696 :                           m.IntPtrConstant(offset));
     158             :       m.Store(MachineRepresentation::kFloat64, m.PointerConstant(to),
     159         348 :               m.IntPtrConstant(offset), load, kNoWriteBarrier);
     160         348 :     } else if (t == TestAlignment::kUnaligned) {
     161             :       Node* load =
     162             :           m.UnalignedLoad(MachineType::Float64(), m.PointerConstant(from),
     163         696 :                           m.IntPtrConstant(offset));
     164             :       m.UnalignedStore(MachineRepresentation::kFloat64, m.PointerConstant(to),
     165         348 :                        m.IntPtrConstant(offset), load);
     166             :     } else {
     167           0 :       UNREACHABLE();
     168             :     }
     169         696 :     m.Return(m.Int32Constant(magic));
     170             : 
     171       34800 :     FOR_FLOAT64_INPUTS(j) {
     172       34104 :       p1 = *j;
     173       34104 :       p2 = *j - 5;
     174       34104 :       CHECK_EQ(magic, m.Call());
     175       34104 :       CheckDoubleEq(p1, p2);
     176             :     }
     177             :   }
     178          12 : }
     179             : }  // namespace
     180             : 
     181       23724 : TEST(RunLoadInt32) { RunLoadInt32(TestAlignment::kAligned); }
     182             : 
     183       23724 : TEST(RunUnalignedLoadInt32) { RunLoadInt32(TestAlignment::kUnaligned); }
     184             : 
     185       23724 : TEST(RunLoadInt32Offset) { RunLoadInt32Offset(TestAlignment::kAligned); }
     186             : 
     187       23724 : TEST(RunUnalignedLoadInt32Offset) {
     188           6 :   RunLoadInt32Offset(TestAlignment::kUnaligned);
     189           6 : }
     190             : 
     191       23724 : TEST(RunLoadStoreFloat32Offset) {
     192           6 :   RunLoadStoreFloat32Offset(TestAlignment::kAligned);
     193           6 : }
     194             : 
     195       23724 : TEST(RunUnalignedLoadStoreFloat32Offset) {
     196           6 :   RunLoadStoreFloat32Offset(TestAlignment::kUnaligned);
     197           6 : }
     198             : 
     199       23724 : TEST(RunLoadStoreFloat64Offset) {
     200           6 :   RunLoadStoreFloat64Offset(TestAlignment::kAligned);
     201           6 : }
     202             : 
     203       23724 : TEST(RunUnalignedLoadStoreFloat64Offset) {
     204           6 :   RunLoadStoreFloat64Offset(TestAlignment::kUnaligned);
     205           6 : }
     206             : 
     207             : namespace {
     208             : template <typename Type>
     209         108 : void RunLoadImmIndex(MachineType rep, TestAlignment t) {
     210             :   const int kNumElems = 3;
     211             :   Type buffer[kNumElems];
     212             : 
     213             :   // initialize the buffer with some raw data.
     214             :   byte* raw = reinterpret_cast<byte*>(buffer);
     215        1584 :   for (size_t i = 0; i < sizeof(buffer); i++) {
     216        1476 :     raw[i] = static_cast<byte>((i + sizeof(buffer)) ^ 0xAA);
     217             :   }
     218             : 
     219             :   // Test with various large and small offsets.
     220         972 :   for (int offset = -1; offset <= 200000; offset *= -5) {
     221        2916 :     for (int i = 0; i < kNumElems; i++) {
     222        2916 :       BufferedRawMachineAssemblerTester<Type> m;
     223        2916 :       Node* base = m.PointerConstant(buffer - offset);
     224        2916 :       Node* index = m.Int32Constant((offset + i) * sizeof(buffer[0]));
     225        2916 :       if (t == TestAlignment::kAligned) {
     226        1620 :         m.Return(m.Load(rep, base, index));
     227        1296 :       } else if (t == TestAlignment::kUnaligned) {
     228        1296 :         m.Return(m.UnalignedLoad(rep, base, index));
     229             :       } else {
     230           0 :         UNREACHABLE();
     231             :       }
     232             : 
     233        2916 :       volatile Type expected = buffer[i];
     234        2916 :       volatile Type actual = m.Call();
     235        2916 :       CHECK_EQ(expected, actual);
     236             :     }
     237             :   }
     238         108 : }
     239             : 
     240             : template <typename CType>
     241         108 : void RunLoadStore(MachineType rep, TestAlignment t) {
     242             :   const int kNumElems = 4;
     243             :   CType buffer[kNumElems];
     244             : 
     245         540 :   for (int32_t x = 0; x < kNumElems; x++) {
     246         432 :     int32_t y = kNumElems - x - 1;
     247             :     // initialize the buffer with raw data.
     248             :     byte* raw = reinterpret_cast<byte*>(buffer);
     249        8304 :     for (size_t i = 0; i < sizeof(buffer); i++) {
     250        7872 :       raw[i] = static_cast<byte>((i + sizeof(buffer)) ^ 0xAA);
     251             :     }
     252             : 
     253         432 :     RawMachineAssemblerTester<int32_t> m;
     254         432 :     int32_t OK = 0x29000 + x;
     255             :     Node* base = m.PointerConstant(buffer);
     256         432 :     Node* index0 = m.IntPtrConstant(x * sizeof(buffer[0]));
     257         432 :     Node* index1 = m.IntPtrConstant(y * sizeof(buffer[0]));
     258         432 :     if (t == TestAlignment::kAligned) {
     259         240 :       Node* load = m.Load(rep, base, index0);
     260         240 :       m.Store(rep.representation(), base, index1, load, kNoWriteBarrier);
     261         192 :     } else if (t == TestAlignment::kUnaligned) {
     262         192 :       Node* load = m.UnalignedLoad(rep, base, index0);
     263         192 :       m.UnalignedStore(rep.representation(), base, index1, load);
     264             :     }
     265             : 
     266         432 :     m.Return(m.Int32Constant(OK));
     267             : 
     268         432 :     CHECK(buffer[x] != buffer[y]);
     269         432 :     CHECK_EQ(OK, m.Call());
     270         432 :     CHECK(buffer[x] == buffer[y]);
     271             :   }
     272         108 : }
     273             : 
     274             : template <typename CType>
     275          48 : void RunUnalignedLoadStoreUnalignedAccess(MachineType rep) {
     276             :   CType in, out;
     277             :   CType in_buffer[2];
     278             :   CType out_buffer[2];
     279             :   byte* raw;
     280             : 
     281         288 :   for (int x = 0; x < static_cast<int>(sizeof(CType)); x++) {
     282         240 :     int y = sizeof(CType) - x;
     283             : 
     284             :     raw = reinterpret_cast<byte*>(&in);
     285        1728 :     for (size_t i = 0; i < sizeof(CType); i++) {
     286        1488 :       raw[i] = static_cast<byte>((i + sizeof(CType)) ^ 0xAA);
     287             :     }
     288             : 
     289             :     raw = reinterpret_cast<byte*>(in_buffer);
     290         240 :     MemCopy(raw + x, &in, sizeof(CType));
     291             : 
     292         240 :     RawMachineAssemblerTester<int32_t> m;
     293         240 :     int32_t OK = 0x29000 + x;
     294             : 
     295             :     Node* base0 = m.PointerConstant(in_buffer);
     296             :     Node* base1 = m.PointerConstant(out_buffer);
     297         240 :     Node* index0 = m.IntPtrConstant(x);
     298         240 :     Node* index1 = m.IntPtrConstant(y);
     299         240 :     Node* load = m.UnalignedLoad(rep, base0, index0);
     300         240 :     m.UnalignedStore(rep.representation(), base1, index1, load);
     301             : 
     302         240 :     m.Return(m.Int32Constant(OK));
     303             : 
     304         240 :     CHECK_EQ(OK, m.Call());
     305             : 
     306             :     raw = reinterpret_cast<byte*>(&out_buffer);
     307         240 :     MemCopy(&out, raw + y, sizeof(CType));
     308         240 :     CHECK(in == out);
     309             :   }
     310          48 : }
     311             : }  // namespace
     312             : 
     313       23724 : TEST(RunLoadImmIndex) {
     314           6 :   RunLoadImmIndex<int8_t>(MachineType::Int8(), TestAlignment::kAligned);
     315           6 :   RunLoadImmIndex<uint8_t>(MachineType::Uint8(), TestAlignment::kAligned);
     316           6 :   RunLoadImmIndex<int16_t>(MachineType::Int16(), TestAlignment::kAligned);
     317           6 :   RunLoadImmIndex<uint16_t>(MachineType::Uint16(), TestAlignment::kAligned);
     318           6 :   RunLoadImmIndex<int32_t>(MachineType::Int32(), TestAlignment::kAligned);
     319           6 :   RunLoadImmIndex<uint32_t>(MachineType::Uint32(), TestAlignment::kAligned);
     320           6 :   RunLoadImmIndex<int32_t*>(MachineType::AnyTagged(), TestAlignment::kAligned);
     321           6 :   RunLoadImmIndex<float>(MachineType::Float32(), TestAlignment::kAligned);
     322           6 :   RunLoadImmIndex<double>(MachineType::Float64(), TestAlignment::kAligned);
     323             : #if V8_TARGET_ARCH_64_BIT
     324           6 :   RunLoadImmIndex<int64_t>(MachineType::Int64(), TestAlignment::kAligned);
     325             : #endif
     326             :   // TODO(titzer): test various indexing modes.
     327           6 : }
     328             : 
     329       23724 : TEST(RunUnalignedLoadImmIndex) {
     330           6 :   RunLoadImmIndex<int16_t>(MachineType::Int16(), TestAlignment::kUnaligned);
     331           6 :   RunLoadImmIndex<uint16_t>(MachineType::Uint16(), TestAlignment::kUnaligned);
     332           6 :   RunLoadImmIndex<int32_t>(MachineType::Int32(), TestAlignment::kUnaligned);
     333           6 :   RunLoadImmIndex<uint32_t>(MachineType::Uint32(), TestAlignment::kUnaligned);
     334             :   RunLoadImmIndex<int32_t*>(MachineType::AnyTagged(),
     335           6 :                             TestAlignment::kUnaligned);
     336           6 :   RunLoadImmIndex<float>(MachineType::Float32(), TestAlignment::kUnaligned);
     337           6 :   RunLoadImmIndex<double>(MachineType::Float64(), TestAlignment::kUnaligned);
     338             : #if V8_TARGET_ARCH_64_BIT
     339           6 :   RunLoadImmIndex<int64_t>(MachineType::Int64(), TestAlignment::kUnaligned);
     340             : #endif
     341             :   // TODO(titzer): test various indexing modes.
     342           6 : }
     343             : 
     344       23724 : TEST(RunLoadStore) {
     345           6 :   RunLoadStore<int8_t>(MachineType::Int8(), TestAlignment::kAligned);
     346           6 :   RunLoadStore<uint8_t>(MachineType::Uint8(), TestAlignment::kAligned);
     347           6 :   RunLoadStore<int16_t>(MachineType::Int16(), TestAlignment::kAligned);
     348           6 :   RunLoadStore<uint16_t>(MachineType::Uint16(), TestAlignment::kAligned);
     349           6 :   RunLoadStore<int32_t>(MachineType::Int32(), TestAlignment::kAligned);
     350           6 :   RunLoadStore<uint32_t>(MachineType::Uint32(), TestAlignment::kAligned);
     351           6 :   RunLoadStore<void*>(MachineType::AnyTagged(), TestAlignment::kAligned);
     352           6 :   RunLoadStore<float>(MachineType::Float32(), TestAlignment::kAligned);
     353           6 :   RunLoadStore<double>(MachineType::Float64(), TestAlignment::kAligned);
     354             : #if V8_TARGET_ARCH_64_BIT
     355           6 :   RunLoadStore<int64_t>(MachineType::Int64(), TestAlignment::kAligned);
     356             : #endif
     357           6 : }
     358             : 
     359       23724 : TEST(RunUnalignedLoadStore) {
     360           6 :   RunLoadStore<int16_t>(MachineType::Int16(), TestAlignment::kUnaligned);
     361           6 :   RunLoadStore<uint16_t>(MachineType::Uint16(), TestAlignment::kUnaligned);
     362           6 :   RunLoadStore<int32_t>(MachineType::Int32(), TestAlignment::kUnaligned);
     363           6 :   RunLoadStore<uint32_t>(MachineType::Uint32(), TestAlignment::kUnaligned);
     364           6 :   RunLoadStore<void*>(MachineType::AnyTagged(), TestAlignment::kUnaligned);
     365           6 :   RunLoadStore<float>(MachineType::Float32(), TestAlignment::kUnaligned);
     366           6 :   RunLoadStore<double>(MachineType::Float64(), TestAlignment::kUnaligned);
     367             : #if V8_TARGET_ARCH_64_BIT
     368           6 :   RunLoadStore<int64_t>(MachineType::Int64(), TestAlignment::kUnaligned);
     369             : #endif
     370           6 : }
     371             : 
     372       23724 : TEST(RunUnalignedLoadStoreUnalignedAccess) {
     373           6 :   RunUnalignedLoadStoreUnalignedAccess<int16_t>(MachineType::Int16());
     374           6 :   RunUnalignedLoadStoreUnalignedAccess<uint16_t>(MachineType::Uint16());
     375           6 :   RunUnalignedLoadStoreUnalignedAccess<int32_t>(MachineType::Int32());
     376           6 :   RunUnalignedLoadStoreUnalignedAccess<uint32_t>(MachineType::Uint32());
     377           6 :   RunUnalignedLoadStoreUnalignedAccess<void*>(MachineType::AnyTagged());
     378           6 :   RunUnalignedLoadStoreUnalignedAccess<float>(MachineType::Float32());
     379           6 :   RunUnalignedLoadStoreUnalignedAccess<double>(MachineType::Float64());
     380             : #if V8_TARGET_ARCH_64_BIT
     381           6 :   RunUnalignedLoadStoreUnalignedAccess<int64_t>(MachineType::Int64());
     382             : #endif
     383           6 : }
     384             : 
     385             : #if V8_TARGET_LITTLE_ENDIAN
     386             : #define LSB(addr, bytes) addr
     387             : #elif V8_TARGET_BIG_ENDIAN
     388             : #define LSB(addr, bytes) reinterpret_cast<byte*>(addr + 1) - bytes
     389             : #else
     390             : #error "Unknown Architecture"
     391             : #endif
     392             : 
     393             : namespace {
     394          12 : void RunLoadStoreSignExtend32(TestAlignment t) {
     395             :   int32_t buffer[4];
     396          12 :   RawMachineAssemblerTester<int32_t> m;
     397          12 :   Node* load8 = m.LoadFromPointer(LSB(&buffer[0], 1), MachineType::Int8());
     398          12 :   if (t == TestAlignment::kAligned) {
     399           6 :     Node* load16 = m.LoadFromPointer(LSB(&buffer[0], 2), MachineType::Int16());
     400           6 :     Node* load32 = m.LoadFromPointer(&buffer[0], MachineType::Int32());
     401           6 :     m.StoreToPointer(&buffer[1], MachineRepresentation::kWord32, load8);
     402           6 :     m.StoreToPointer(&buffer[2], MachineRepresentation::kWord32, load16);
     403           6 :     m.StoreToPointer(&buffer[3], MachineRepresentation::kWord32, load32);
     404           6 :   } else if (t == TestAlignment::kUnaligned) {
     405             :     Node* load16 =
     406           6 :         m.UnalignedLoadFromPointer(LSB(&buffer[0], 2), MachineType::Int16());
     407           6 :     Node* load32 = m.UnalignedLoadFromPointer(&buffer[0], MachineType::Int32());
     408           6 :     m.StoreToPointer(&buffer[1], MachineRepresentation::kWord32, load8);
     409             :     m.UnalignedStoreToPointer(&buffer[2], MachineRepresentation::kWord32,
     410           6 :                               load16);
     411             :     m.UnalignedStoreToPointer(&buffer[3], MachineRepresentation::kWord32,
     412           6 :                               load32);
     413             :   } else {
     414           0 :     UNREACHABLE();
     415             :   }
     416          12 :   m.Return(load8);
     417             : 
     418         708 :   FOR_INT32_INPUTS(i) {
     419         696 :     buffer[0] = *i;
     420             : 
     421        1392 :     CHECK_EQ(static_cast<int8_t>(*i & 0xff), m.Call());
     422         696 :     CHECK_EQ(static_cast<int8_t>(*i & 0xff), buffer[1]);
     423        1392 :     CHECK_EQ(static_cast<int16_t>(*i & 0xffff), buffer[2]);
     424         696 :     CHECK_EQ(*i, buffer[3]);
     425             :   }
     426          12 : }
     427             : 
     428          12 : void RunLoadStoreZeroExtend32(TestAlignment t) {
     429             :   uint32_t buffer[4];
     430          12 :   RawMachineAssemblerTester<uint32_t> m;
     431          12 :   Node* load8 = m.LoadFromPointer(LSB(&buffer[0], 1), MachineType::Uint8());
     432          12 :   if (t == TestAlignment::kAligned) {
     433           6 :     Node* load16 = m.LoadFromPointer(LSB(&buffer[0], 2), MachineType::Uint16());
     434           6 :     Node* load32 = m.LoadFromPointer(&buffer[0], MachineType::Uint32());
     435           6 :     m.StoreToPointer(&buffer[1], MachineRepresentation::kWord32, load8);
     436           6 :     m.StoreToPointer(&buffer[2], MachineRepresentation::kWord32, load16);
     437           6 :     m.StoreToPointer(&buffer[3], MachineRepresentation::kWord32, load32);
     438           6 :   } else if (t == TestAlignment::kUnaligned) {
     439             :     Node* load16 =
     440           6 :         m.UnalignedLoadFromPointer(LSB(&buffer[0], 2), MachineType::Uint16());
     441             :     Node* load32 =
     442           6 :         m.UnalignedLoadFromPointer(&buffer[0], MachineType::Uint32());
     443           6 :     m.StoreToPointer(&buffer[1], MachineRepresentation::kWord32, load8);
     444             :     m.UnalignedStoreToPointer(&buffer[2], MachineRepresentation::kWord32,
     445           6 :                               load16);
     446             :     m.UnalignedStoreToPointer(&buffer[3], MachineRepresentation::kWord32,
     447           6 :                               load32);
     448             :   }
     449          12 :   m.Return(load8);
     450             : 
     451         708 :   FOR_UINT32_INPUTS(i) {
     452         696 :     buffer[0] = *i;
     453             : 
     454         696 :     CHECK_EQ((*i & 0xff), m.Call());
     455         696 :     CHECK_EQ((*i & 0xff), buffer[1]);
     456         696 :     CHECK_EQ((*i & 0xffff), buffer[2]);
     457         696 :     CHECK_EQ(*i, buffer[3]);
     458             :   }
     459          12 : }
     460             : }  // namespace
     461             : 
     462       23724 : TEST(RunLoadStoreSignExtend32) {
     463           6 :   RunLoadStoreSignExtend32(TestAlignment::kAligned);
     464           6 : }
     465             : 
     466       23724 : TEST(RunUnalignedLoadStoreSignExtend32) {
     467           6 :   RunLoadStoreSignExtend32(TestAlignment::kUnaligned);
     468           6 : }
     469             : 
     470       23724 : TEST(RunLoadStoreZeroExtend32) {
     471           6 :   RunLoadStoreZeroExtend32(TestAlignment::kAligned);
     472           6 : }
     473             : 
     474       23724 : TEST(RunUnalignedLoadStoreZeroExtend32) {
     475           6 :   RunLoadStoreZeroExtend32(TestAlignment::kUnaligned);
     476           6 : }
     477             : 
     478             : #if V8_TARGET_ARCH_64_BIT
     479             : 
     480             : namespace {
     481             : void RunLoadStoreSignExtend64(TestAlignment t) {
     482             :   if (true) return;  // TODO(titzer): sign extension of loads to 64-bit.
     483             :   int64_t buffer[5];
     484             :   RawMachineAssemblerTester<int64_t> m;
     485             :   Node* load8 = m.LoadFromPointer(LSB(&buffer[0], 1), MachineType::Int8());
     486             :   if (t == TestAlignment::kAligned) {
     487             :     Node* load16 = m.LoadFromPointer(LSB(&buffer[0], 2), MachineType::Int16());
     488             :     Node* load32 = m.LoadFromPointer(LSB(&buffer[0], 4), MachineType::Int32());
     489             :     Node* load64 = m.LoadFromPointer(&buffer[0], MachineType::Int64());
     490             :     m.StoreToPointer(&buffer[1], MachineRepresentation::kWord64, load8);
     491             :     m.StoreToPointer(&buffer[2], MachineRepresentation::kWord64, load16);
     492             :     m.StoreToPointer(&buffer[3], MachineRepresentation::kWord64, load32);
     493             :     m.StoreToPointer(&buffer[4], MachineRepresentation::kWord64, load64);
     494             :   } else if (t == TestAlignment::kUnaligned) {
     495             :     Node* load16 =
     496             :         m.UnalignedLoadFromPointer(LSB(&buffer[0], 2), MachineType::Int16());
     497             :     Node* load32 =
     498             :         m.UnalignedLoadFromPointer(LSB(&buffer[0], 4), MachineType::Int32());
     499             :     Node* load64 = m.UnalignedLoadFromPointer(&buffer[0], MachineType::Int64());
     500             :     m.StoreToPointer(&buffer[1], MachineRepresentation::kWord64, load8);
     501             :     m.UnalignedStoreToPointer(&buffer[2], MachineRepresentation::kWord64,
     502             :                               load16);
     503             :     m.UnalignedStoreToPointer(&buffer[3], MachineRepresentation::kWord64,
     504             :                               load32);
     505             :     m.UnalignedStoreToPointer(&buffer[4], MachineRepresentation::kWord64,
     506             :                               load64);
     507             :   } else {
     508             :     UNREACHABLE();
     509             :   }
     510             :   m.Return(load8);
     511             : 
     512             :   FOR_INT64_INPUTS(i) {
     513             :     buffer[0] = *i;
     514             : 
     515             :     CHECK_EQ(static_cast<int8_t>(*i & 0xff), m.Call());
     516             :     CHECK_EQ(static_cast<int8_t>(*i & 0xff), buffer[1]);
     517             :     CHECK_EQ(static_cast<int16_t>(*i & 0xffff), buffer[2]);
     518             :     CHECK_EQ(static_cast<int32_t>(*i & 0xffffffff), buffer[3]);
     519             :     CHECK_EQ(*i, buffer[4]);
     520             :   }
     521             : }
     522             : 
     523          12 : void RunLoadStoreZeroExtend64(TestAlignment t) {
     524          12 :   if (kPointerSize < 8) return;
     525             :   uint64_t buffer[5];
     526          12 :   RawMachineAssemblerTester<uint64_t> m;
     527          12 :   Node* load8 = m.LoadFromPointer(LSB(&buffer[0], 1), MachineType::Uint8());
     528          12 :   if (t == TestAlignment::kAligned) {
     529           6 :     Node* load16 = m.LoadFromPointer(LSB(&buffer[0], 2), MachineType::Uint16());
     530           6 :     Node* load32 = m.LoadFromPointer(LSB(&buffer[0], 4), MachineType::Uint32());
     531           6 :     Node* load64 = m.LoadFromPointer(&buffer[0], MachineType::Uint64());
     532           6 :     m.StoreToPointer(&buffer[1], MachineRepresentation::kWord64, load8);
     533           6 :     m.StoreToPointer(&buffer[2], MachineRepresentation::kWord64, load16);
     534           6 :     m.StoreToPointer(&buffer[3], MachineRepresentation::kWord64, load32);
     535           6 :     m.StoreToPointer(&buffer[4], MachineRepresentation::kWord64, load64);
     536           6 :   } else if (t == TestAlignment::kUnaligned) {
     537             :     Node* load16 =
     538           6 :         m.UnalignedLoadFromPointer(LSB(&buffer[0], 2), MachineType::Uint16());
     539             :     Node* load32 =
     540           6 :         m.UnalignedLoadFromPointer(LSB(&buffer[0], 4), MachineType::Uint32());
     541             :     Node* load64 =
     542           6 :         m.UnalignedLoadFromPointer(&buffer[0], MachineType::Uint64());
     543           6 :     m.StoreToPointer(&buffer[1], MachineRepresentation::kWord64, load8);
     544             :     m.UnalignedStoreToPointer(&buffer[2], MachineRepresentation::kWord64,
     545           6 :                               load16);
     546             :     m.UnalignedStoreToPointer(&buffer[3], MachineRepresentation::kWord64,
     547           6 :                               load32);
     548             :     m.UnalignedStoreToPointer(&buffer[4], MachineRepresentation::kWord64,
     549           6 :                               load64);
     550             :   } else {
     551           0 :     UNREACHABLE();
     552             :   }
     553          12 :   m.Return(load8);
     554             : 
     555         984 :   FOR_UINT64_INPUTS(i) {
     556         972 :     buffer[0] = *i;
     557             : 
     558         972 :     CHECK_EQ((*i & 0xff), m.Call());
     559         972 :     CHECK_EQ((*i & 0xff), buffer[1]);
     560         972 :     CHECK_EQ((*i & 0xffff), buffer[2]);
     561         972 :     CHECK_EQ((*i & 0xffffffff), buffer[3]);
     562         972 :     CHECK_EQ(*i, buffer[4]);
     563             :   }
     564             : }
     565             : 
     566             : }  // namespace
     567             : 
     568       23724 : TEST(RunCheckedLoadInt64) {
     569           6 :   int64_t buffer[] = {0x66bbccddeeff0011LL, 0x1122334455667788LL};
     570           6 :   RawMachineAssemblerTester<int64_t> m(MachineType::Int32());
     571             :   Node* base = m.PointerConstant(buffer);
     572           6 :   Node* index = m.Parameter(0);
     573           6 :   Node* length = m.Int32Constant(16);
     574             :   Node* load = m.AddNode(m.machine()->CheckedLoad(MachineType::Int64()), base,
     575           6 :                          index, length);
     576           6 :   m.Return(load);
     577             : 
     578           6 :   CHECK_EQ(buffer[0], m.Call(0));
     579           6 :   CHECK_EQ(buffer[1], m.Call(8));
     580           6 :   CheckOobValue(m.Call(16));
     581           6 : }
     582             : 
     583       23724 : TEST(RunLoadStoreSignExtend64) {
     584             :   RunLoadStoreSignExtend64(TestAlignment::kAligned);
     585           6 : }
     586             : 
     587       23724 : TEST(RunUnalignedLoadStoreSignExtend64) {
     588             :   RunLoadStoreSignExtend64(TestAlignment::kUnaligned);
     589           6 : }
     590             : 
     591       23724 : TEST(RunLoadStoreZeroExtend64) {
     592           6 :   RunLoadStoreZeroExtend64(TestAlignment::kAligned);
     593           6 : }
     594             : 
     595       23724 : TEST(RunUnalignedLoadStoreZeroExtend64) {
     596           6 :   RunLoadStoreZeroExtend64(TestAlignment::kUnaligned);
     597           6 : }
     598             : 
     599       23724 : TEST(RunCheckedStoreInt64) {
     600             :   const int64_t write = 0x5566778899aabbLL;
     601             :   const int64_t before = 0x33bbccddeeff0011LL;
     602           6 :   int64_t buffer[] = {before, before};
     603           6 :   RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
     604             :   Node* base = m.PointerConstant(buffer);
     605           6 :   Node* index = m.Parameter(0);
     606           6 :   Node* length = m.Int32Constant(16);
     607           6 :   Node* value = m.Int64Constant(write);
     608             :   Node* store =
     609             :       m.AddNode(m.machine()->CheckedStore(MachineRepresentation::kWord64), base,
     610           6 :                 index, length, value);
     611             :   USE(store);
     612           6 :   m.Return(m.Int32Constant(11));
     613             : 
     614           6 :   CHECK_EQ(11, m.Call(16));
     615           6 :   CHECK_EQ(before, buffer[0]);
     616           6 :   CHECK_EQ(before, buffer[1]);
     617             : 
     618           6 :   CHECK_EQ(11, m.Call(0));
     619           6 :   CHECK_EQ(write, buffer[0]);
     620           6 :   CHECK_EQ(before, buffer[1]);
     621             : 
     622           6 :   CHECK_EQ(11, m.Call(8));
     623           6 :   CHECK_EQ(write, buffer[0]);
     624           6 :   CHECK_EQ(write, buffer[1]);
     625           6 : }
     626             : #endif
     627             : 
     628             : namespace {
     629             : template <typename IntType>
     630          18 : void LoadStoreTruncation(MachineType kRepresentation, TestAlignment t) {
     631             :   IntType input;
     632             : 
     633          18 :   RawMachineAssemblerTester<int32_t> m;
     634             :   Node* ap1;
     635          18 :   if (t == TestAlignment::kAligned) {
     636          12 :     Node* a = m.LoadFromPointer(&input, kRepresentation);
     637          12 :     ap1 = m.Int32Add(a, m.Int32Constant(1));
     638          12 :     m.StoreToPointer(&input, kRepresentation.representation(), ap1);
     639           6 :   } else if (t == TestAlignment::kUnaligned) {
     640           6 :     Node* a = m.UnalignedLoadFromPointer(&input, kRepresentation);
     641           6 :     ap1 = m.Int32Add(a, m.Int32Constant(1));
     642           6 :     m.UnalignedStoreToPointer(&input, kRepresentation.representation(), ap1);
     643             :   } else {
     644           0 :     UNREACHABLE();
     645             :   }
     646          18 :   m.Return(ap1);
     647             : 
     648             :   const IntType max = std::numeric_limits<IntType>::max();
     649             :   const IntType min = std::numeric_limits<IntType>::min();
     650             : 
     651             :   // Test upper bound.
     652          18 :   input = max;
     653          18 :   CHECK_EQ(max + 1, m.Call());
     654          18 :   CHECK_EQ(min, input);
     655             : 
     656             :   // Test lower bound.
     657          18 :   input = min;
     658          18 :   CHECK_EQ(static_cast<IntType>(max + 2), m.Call());
     659          18 :   CHECK_EQ(min + 1, input);
     660             : 
     661             :   // Test all one byte values that are not one byte bounds.
     662        4572 :   for (int i = -127; i < 127; i++) {
     663        4572 :     input = i;
     664        4572 :     int expected = i >= 0 ? i + 1 : max + (i - min) + 2;
     665        9144 :     CHECK_EQ(static_cast<IntType>(expected), m.Call());
     666        4572 :     CHECK_EQ(static_cast<IntType>(i + 1), input);
     667             :   }
     668          18 : }
     669             : }  // namespace
     670             : 
     671       23724 : TEST(RunLoadStoreTruncation) {
     672           6 :   LoadStoreTruncation<int8_t>(MachineType::Int8(), TestAlignment::kAligned);
     673           6 :   LoadStoreTruncation<int16_t>(MachineType::Int16(), TestAlignment::kAligned);
     674           6 : }
     675             : 
     676       23724 : TEST(RunUnalignedLoadStoreTruncation) {
     677           6 :   LoadStoreTruncation<int16_t>(MachineType::Int16(), TestAlignment::kUnaligned);
     678           6 : }
     679             : 
     680          12 : void TestRunOobCheckedLoad(bool length_is_immediate) {
     681             :   USE(CheckOobValue<int32_t>);
     682             :   USE(CheckOobValue<int64_t>);
     683             :   USE(CheckOobValue<float>);
     684             :   USE(CheckOobValue<double>);
     685             : 
     686             :   RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
     687          12 :                                        MachineType::Int32());
     688          12 :   MachineOperatorBuilder machine(m.zone());
     689             :   const int32_t kNumElems = 27;
     690             :   const int32_t kLength = kNumElems * 4;
     691             : 
     692             :   int32_t buffer[kNumElems];
     693             :   Node* base = m.PointerConstant(buffer);
     694          12 :   Node* offset = m.Parameter(0);
     695          12 :   Node* len = length_is_immediate ? m.Int32Constant(kLength) : m.Parameter(1);
     696             :   Node* node =
     697          12 :       m.AddNode(machine.CheckedLoad(MachineType::Int32()), base, offset, len);
     698          12 :   m.Return(node);
     699             : 
     700             :   {
     701             :     // randomize memory.
     702          12 :     v8::base::RandomNumberGenerator rng;
     703          12 :     rng.SetSeed(100);
     704          12 :     rng.NextBytes(&buffer[0], sizeof(buffer));
     705             :   }
     706             : 
     707             :   // in-bounds accesses.
     708         336 :   for (int32_t i = 0; i < kNumElems; i++) {
     709         324 :     int32_t offset = static_cast<int32_t>(i * sizeof(int32_t));
     710         324 :     int32_t expected = buffer[i];
     711         324 :     CHECK_EQ(expected, m.Call(offset, kLength));
     712             :   }
     713             : 
     714             :   // slightly out-of-bounds accesses.
     715             :   for (int32_t i = kLength; i < kNumElems + 30; i++) {
     716             :     int32_t offset = static_cast<int32_t>(i * sizeof(int32_t));
     717             :     CheckOobValue(m.Call(offset, kLength));
     718             :   }
     719             : 
     720             :   // way out-of-bounds accesses.
     721         492 :   for (int32_t offset = -2000000000; offset <= 2000000000;
     722             :        offset += 100000000) {
     723         492 :     if (offset == 0) continue;
     724         480 :     CheckOobValue(m.Call(offset, kLength));
     725             :   }
     726          12 : }
     727             : 
     728       23724 : TEST(RunOobCheckedLoad) { TestRunOobCheckedLoad(false); }
     729             : 
     730       23724 : TEST(RunOobCheckedLoadImm) { TestRunOobCheckedLoad(true); }
     731             : 
     732          12 : void TestRunOobCheckedStore(bool length_is_immediate) {
     733             :   RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
     734          12 :                                        MachineType::Int32());
     735          12 :   MachineOperatorBuilder machine(m.zone());
     736             :   const int32_t kNumElems = 29;
     737             :   const int32_t kValue = -78227234;
     738             :   const int32_t kLength = kNumElems * 4;
     739             : 
     740             :   int32_t buffer[kNumElems + kNumElems];
     741             :   Node* base = m.PointerConstant(buffer);
     742          12 :   Node* offset = m.Parameter(0);
     743          12 :   Node* len = length_is_immediate ? m.Int32Constant(kLength) : m.Parameter(1);
     744          12 :   Node* val = m.Int32Constant(kValue);
     745             :   m.AddNode(machine.CheckedStore(MachineRepresentation::kWord32), base, offset,
     746          12 :             len, val);
     747          12 :   m.Return(val);
     748             : 
     749             :   // in-bounds accesses.
     750         360 :   for (int32_t i = 0; i < kNumElems; i++) {
     751             :     memset(buffer, 0, sizeof(buffer));
     752         348 :     int32_t offset = static_cast<int32_t>(i * sizeof(int32_t));
     753         348 :     CHECK_EQ(kValue, m.Call(offset, kLength));
     754       20184 :     for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
     755       20184 :       if (i == j) {
     756         348 :         CHECK_EQ(kValue, buffer[j]);
     757             :       } else {
     758       19836 :         CHECK_EQ(0, buffer[j]);
     759             :       }
     760             :     }
     761             :   }
     762             : 
     763             :   memset(buffer, 0, sizeof(buffer));
     764             : 
     765             :   // slightly out-of-bounds accesses.
     766             :   for (int32_t i = kLength; i < kNumElems + 30; i++) {
     767             :     int32_t offset = static_cast<int32_t>(i * sizeof(int32_t));
     768             :     CHECK_EQ(kValue, m.Call(offset, kLength));
     769             :     for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
     770             :       CHECK_EQ(0, buffer[j]);
     771             :     }
     772             :   }
     773             : 
     774             :   // way out-of-bounds accesses.
     775         504 :   for (int32_t offset = -2000000000; offset <= 2000000000;
     776             :        offset += 100000000) {
     777         492 :     if (offset == 0) continue;
     778         480 :     CHECK_EQ(kValue, m.Call(offset, kLength));
     779       27840 :     for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
     780       27840 :       CHECK_EQ(0, buffer[j]);
     781             :     }
     782             :   }
     783          12 : }
     784             : 
     785       23724 : TEST(RunOobCheckedStore) { TestRunOobCheckedStore(false); }
     786             : 
     787       23724 : TEST(RunOobCheckedStoreImm) { TestRunOobCheckedStore(true); }
     788             : 
     789             : // TODO(titzer): CheckedLoad/CheckedStore don't support 64-bit offsets.
     790             : #define ALLOW_64_BIT_OFFSETS 0
     791             : 
     792             : #if V8_TARGET_ARCH_64_BIT && ALLOW_64_BIT_OFFSETS
     793             : 
     794             : void TestRunOobCheckedLoad64(uint32_t pseudo_base, bool length_is_immediate) {
     795             :   RawMachineAssemblerTester<int32_t> m(MachineType::Uint64(),
     796             :                                        MachineType::Uint64());
     797             :   MachineOperatorBuilder machine(m.zone());
     798             :   const uint32_t kNumElems = 25;
     799             :   const uint32_t kLength = kNumElems * 4;
     800             :   int32_t real_buffer[kNumElems];
     801             : 
     802             :   // Simulate the end of a large buffer.
     803             :   int32_t* buffer = real_buffer - (pseudo_base / 4);
     804             :   uint64_t length = kLength + pseudo_base;
     805             : 
     806             :   Node* base = m.PointerConstant(buffer);
     807             :   Node* offset = m.Parameter(0);
     808             :   Node* len = length_is_immediate ? m.Int64Constant(length) : m.Parameter(1);
     809             :   Node* node =
     810             :       m.AddNode(machine.CheckedLoad(MachineType::Int32()), base, offset, len);
     811             :   m.Return(node);
     812             : 
     813             :   {
     814             :     // randomize memory.
     815             :     v8::base::RandomNumberGenerator rng;
     816             :     rng.SetSeed(100);
     817             :     rng.NextBytes(&real_buffer[0], sizeof(real_buffer));
     818             :   }
     819             : 
     820             :   // in-bounds accesses.
     821             :   for (uint32_t i = 0; i < kNumElems; i++) {
     822             :     uint64_t offset = pseudo_base + i * 4;
     823             :     int32_t expected = real_buffer[i];
     824             :     CHECK_EQ(expected, m.Call(offset, length));
     825             :   }
     826             : 
     827             :   // in-bounds accesses w.r.t lower 32-bits, but upper bits set.
     828             :   for (uint64_t i = 0x100000000ULL; i != 0; i <<= 1) {
     829             :     uint64_t offset = pseudo_base + i;
     830             :     CheckOobValue(m.Call(offset, length));
     831             :   }
     832             : 
     833             :   // slightly out-of-bounds accesses.
     834             :   for (uint32_t i = kLength; i < kNumElems + 30; i++) {
     835             :     uint64_t offset = pseudo_base + i * 4;
     836             :     CheckOobValue(0, m.Call(offset, length));
     837             :   }
     838             : 
     839             :   // way out-of-bounds accesses.
     840             :   for (uint64_t offset = length; offset < 100 * A_BILLION; offset += A_GIG) {
     841             :     if (offset < length) continue;
     842             :     CheckOobValue(0, m.Call(offset, length));
     843             :   }
     844             : }
     845             : 
     846             : TEST(RunOobCheckedLoad64_0) {
     847             :   TestRunOobCheckedLoad64(0, false);
     848             :   TestRunOobCheckedLoad64(0, true);
     849             : }
     850             : 
     851             : TEST(RunOobCheckedLoad64_1) {
     852             :   TestRunOobCheckedLoad64(1 * A_BILLION, false);
     853             :   TestRunOobCheckedLoad64(1 * A_BILLION, true);
     854             : }
     855             : 
     856             : TEST(RunOobCheckedLoad64_2) {
     857             :   TestRunOobCheckedLoad64(2 * A_BILLION, false);
     858             :   TestRunOobCheckedLoad64(2 * A_BILLION, true);
     859             : }
     860             : 
     861             : TEST(RunOobCheckedLoad64_3) {
     862             :   TestRunOobCheckedLoad64(3 * A_BILLION, false);
     863             :   TestRunOobCheckedLoad64(3 * A_BILLION, true);
     864             : }
     865             : 
     866             : TEST(RunOobCheckedLoad64_4) {
     867             :   TestRunOobCheckedLoad64(4 * A_BILLION, false);
     868             :   TestRunOobCheckedLoad64(4 * A_BILLION, true);
     869             : }
     870             : 
     871             : void TestRunOobCheckedStore64(uint32_t pseudo_base, bool length_is_immediate) {
     872             :   RawMachineAssemblerTester<int32_t> m(MachineType::Uint64(),
     873             :                                        MachineType::Uint64());
     874             :   MachineOperatorBuilder machine(m.zone());
     875             :   const uint32_t kNumElems = 21;
     876             :   const uint32_t kLength = kNumElems * 4;
     877             :   const uint32_t kValue = 897234987;
     878             :   int32_t real_buffer[kNumElems + kNumElems];
     879             : 
     880             :   // Simulate the end of a large buffer.
     881             :   int32_t* buffer = real_buffer - (pseudo_base / 4);
     882             :   uint64_t length = kLength + pseudo_base;
     883             : 
     884             :   Node* base = m.PointerConstant(buffer);
     885             :   Node* offset = m.Parameter(0);
     886             :   Node* len = length_is_immediate ? m.Int64Constant(length) : m.Parameter(1);
     887             :   Node* val = m.Int32Constant(kValue);
     888             :   m.AddNode(machine.CheckedStore(MachineRepresentation::kWord32), base, offset,
     889             :             len, val);
     890             :   m.Return(val);
     891             : 
     892             :   // in-bounds accesses.
     893             :   for (uint32_t i = 0; i < kNumElems; i++) {
     894             :     memset(real_buffer, 0, sizeof(real_buffer));
     895             :     uint64_t offset = pseudo_base + i * 4;
     896             :     CHECK_EQ(kValue, m.Call(offset, length));
     897             :     for (uint32_t j = 0; j < kNumElems + kNumElems; j++) {
     898             :       if (i == j) {
     899             :         CHECK_EQ(kValue, real_buffer[j]);
     900             :       } else {
     901             :         CHECK_EQ(0, real_buffer[j]);
     902             :       }
     903             :     }
     904             :   }
     905             : 
     906             :   memset(real_buffer, 0, sizeof(real_buffer));
     907             : 
     908             :   // in-bounds accesses w.r.t lower 32-bits, but upper bits set.
     909             :   for (uint64_t i = 0x100000000ULL; i != 0; i <<= 1) {
     910             :     uint64_t offset = pseudo_base + i;
     911             :     CHECK_EQ(kValue, m.Call(offset, length));
     912             :     for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
     913             :       CHECK_EQ(0, real_buffer[j]);
     914             :     }
     915             :   }
     916             : 
     917             :   // slightly out-of-bounds accesses.
     918             :   for (uint32_t i = kLength; i < kNumElems + 30; i++) {
     919             :     uint64_t offset = pseudo_base + i * 4;
     920             :     CHECK_EQ(kValue, m.Call(offset, length));
     921             :     for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
     922             :       CHECK_EQ(0, real_buffer[j]);
     923             :     }
     924             :   }
     925             : 
     926             :   // way out-of-bounds accesses.
     927             :   for (uint64_t offset = length; offset < 100 * A_BILLION; offset += A_GIG) {
     928             :     if (offset < length) continue;
     929             :     CHECK_EQ(kValue, m.Call(offset, length));
     930             :     for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
     931             :       CHECK_EQ(0, real_buffer[j]);
     932             :     }
     933             :   }
     934             : }
     935             : 
     936             : TEST(RunOobCheckedStore64_0) {
     937             :   TestRunOobCheckedStore64(0, false);
     938             :   TestRunOobCheckedStore64(0, true);
     939             : }
     940             : 
     941             : TEST(RunOobCheckedStore64_1) {
     942             :   TestRunOobCheckedStore64(1 * A_BILLION, false);
     943             :   TestRunOobCheckedStore64(1 * A_BILLION, true);
     944             : }
     945             : 
     946             : TEST(RunOobCheckedStore64_2) {
     947             :   TestRunOobCheckedStore64(2 * A_BILLION, false);
     948             :   TestRunOobCheckedStore64(2 * A_BILLION, true);
     949             : }
     950             : 
     951             : TEST(RunOobCheckedStore64_3) {
     952             :   TestRunOobCheckedStore64(3 * A_BILLION, false);
     953             :   TestRunOobCheckedStore64(3 * A_BILLION, true);
     954             : }
     955             : 
     956             : TEST(RunOobCheckedStore64_4) {
     957             :   TestRunOobCheckedStore64(4 * A_BILLION, false);
     958             :   TestRunOobCheckedStore64(4 * A_BILLION, true);
     959             : }
     960             : 
     961             : #endif
     962             : 
     963         108 : void TestRunOobCheckedLoad_pseudo(uint64_t x, bool length_is_immediate) {
     964             :   RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
     965         108 :                                        MachineType::Uint32());
     966             : 
     967         108 :   uint32_t pseudo_base = static_cast<uint32_t>(x);
     968         108 :   MachineOperatorBuilder machine(m.zone());
     969             :   const uint32_t kNumElems = 29;
     970         108 :   const uint32_t kLength = pseudo_base + kNumElems * 4;
     971             : 
     972             :   int32_t buffer[kNumElems];
     973         108 :   Node* base = m.PointerConstant(reinterpret_cast<byte*>(buffer) - pseudo_base);
     974         108 :   Node* offset = m.Parameter(0);
     975         108 :   Node* len = length_is_immediate ? m.Int32Constant(kLength) : m.Parameter(1);
     976             :   Node* node =
     977         108 :       m.AddNode(machine.CheckedLoad(MachineType::Int32()), base, offset, len);
     978         108 :   m.Return(node);
     979             : 
     980             :   {
     981             :     // randomize memory.
     982         108 :     v8::base::RandomNumberGenerator rng;
     983         108 :     rng.SetSeed(100);
     984         108 :     rng.NextBytes(&buffer[0], sizeof(buffer));
     985             :   }
     986             : 
     987             :   // in-bounds accesses.
     988        3240 :   for (uint32_t i = 0; i < kNumElems; i++) {
     989        3132 :     uint32_t offset = static_cast<uint32_t>(i * sizeof(int32_t));
     990        3132 :     uint32_t expected = buffer[i];
     991        3132 :     CHECK_EQ(expected,
     992             :              static_cast<uint32_t>(m.Call(offset + pseudo_base, kLength)));
     993             :   }
     994             : 
     995             :   // slightly out-of-bounds accesses.
     996        3240 :   for (uint32_t i = kNumElems; i < kNumElems + 30; i++) {
     997        3240 :     uint32_t offset = i * sizeof(int32_t);
     998        3240 :     CheckOobValue(m.Call(offset + pseudo_base, kLength));
     999             :   }
    1000             : 
    1001             :   // way out-of-bounds accesses.
    1002         456 :   for (uint64_t i = pseudo_base + sizeof(buffer); i < 0xFFFFFFFF;
    1003             :        i += A_BILLION) {
    1004         348 :     uint32_t offset = static_cast<uint32_t>(i);
    1005         348 :     CheckOobValue(m.Call(offset, kLength));
    1006             :   }
    1007         108 : }
    1008             : 
    1009       23724 : TEST(RunOobCheckedLoad_pseudo0) {
    1010           6 :   TestRunOobCheckedLoad_pseudo(0, false);
    1011           6 :   TestRunOobCheckedLoad_pseudo(0, true);
    1012           6 : }
    1013             : 
    1014       23724 : TEST(RunOobCheckedLoad_pseudo1) {
    1015           6 :   TestRunOobCheckedLoad_pseudo(100000, false);
    1016           6 :   TestRunOobCheckedLoad_pseudo(100000, true);
    1017           6 : }
    1018             : 
    1019       23724 : TEST(RunOobCheckedLoad_pseudo2) {
    1020           6 :   TestRunOobCheckedLoad_pseudo(A_BILLION, false);
    1021           6 :   TestRunOobCheckedLoad_pseudo(A_BILLION, true);
    1022           6 : }
    1023             : 
    1024       23724 : TEST(RunOobCheckedLoad_pseudo3) {
    1025           6 :   TestRunOobCheckedLoad_pseudo(A_GIG, false);
    1026           6 :   TestRunOobCheckedLoad_pseudo(A_GIG, true);
    1027           6 : }
    1028             : 
    1029       23724 : TEST(RunOobCheckedLoad_pseudo4) {
    1030           6 :   TestRunOobCheckedLoad_pseudo(2 * A_BILLION, false);
    1031           6 :   TestRunOobCheckedLoad_pseudo(2 * A_BILLION, true);
    1032           6 : }
    1033             : 
    1034       23724 : TEST(RunOobCheckedLoad_pseudo5) {
    1035           6 :   TestRunOobCheckedLoad_pseudo(2 * A_GIG, false);
    1036           6 :   TestRunOobCheckedLoad_pseudo(2 * A_GIG, true);
    1037           6 : }
    1038             : 
    1039       23724 : TEST(RunOobCheckedLoad_pseudo6) {
    1040           6 :   TestRunOobCheckedLoad_pseudo(3 * A_BILLION, false);
    1041           6 :   TestRunOobCheckedLoad_pseudo(3 * A_BILLION, true);
    1042           6 : }
    1043             : 
    1044       23724 : TEST(RunOobCheckedLoad_pseudo7) {
    1045           6 :   TestRunOobCheckedLoad_pseudo(3 * A_GIG, false);
    1046           6 :   TestRunOobCheckedLoad_pseudo(3 * A_GIG, true);
    1047           6 : }
    1048             : 
    1049       23724 : TEST(RunOobCheckedLoad_pseudo8) {
    1050           6 :   TestRunOobCheckedLoad_pseudo(4 * A_BILLION, false);
    1051           6 :   TestRunOobCheckedLoad_pseudo(4 * A_BILLION, true);
    1052           6 : }
    1053             : 
    1054             : template <typename MemType>
    1055         324 : void TestRunOobCheckedLoadT_pseudo(uint64_t x, bool length_is_immediate) {
    1056             :   const int32_t kReturn = 11999;
    1057             :   const uint32_t kNumElems = 29;
    1058             :   MemType buffer[kNumElems];
    1059         324 :   uint32_t pseudo_base = static_cast<uint32_t>(x);
    1060         324 :   const uint32_t kLength = static_cast<uint32_t>(pseudo_base + sizeof(buffer));
    1061             : 
    1062             :   MemType result;
    1063             : 
    1064             :   RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
    1065         324 :                                        MachineType::Uint32());
    1066         324 :   MachineOperatorBuilder machine(m.zone());
    1067         324 :   Node* base = m.PointerConstant(reinterpret_cast<byte*>(buffer) - pseudo_base);
    1068         324 :   Node* offset = m.Parameter(0);
    1069         324 :   Node* len = length_is_immediate ? m.Int32Constant(kLength) : m.Parameter(1);
    1070             :   Node* node = m.AddNode(machine.CheckedLoad(MachineTypeForC<MemType>()), base,
    1071         324 :                          offset, len);
    1072             :   Node* store = m.StoreToPointer(
    1073         324 :       &result, MachineTypeForC<MemType>().representation(), node);
    1074             :   USE(store);
    1075         324 :   m.Return(m.Int32Constant(kReturn));
    1076             : 
    1077             :   {
    1078             :     // randomize memory.
    1079         324 :     v8::base::RandomNumberGenerator rng;
    1080         324 :     rng.SetSeed(103);
    1081         324 :     rng.NextBytes(&buffer[0], sizeof(buffer));
    1082             :   }
    1083             : 
    1084             :   // in-bounds accesses.
    1085        9720 :   for (uint32_t i = 0; i < kNumElems; i++) {
    1086        9396 :     uint32_t offset = static_cast<uint32_t>(i * sizeof(MemType));
    1087        9396 :     MemType expected = buffer[i];
    1088        9396 :     CHECK_EQ(kReturn, m.Call(offset + pseudo_base, kLength));
    1089        9396 :     CHECK_EQ(expected, result);
    1090             :   }
    1091             : 
    1092             :   // slightly out-of-bounds accesses.
    1093        9720 :   for (uint32_t i = kNumElems; i < kNumElems + 30; i++) {
    1094        9720 :     uint32_t offset = static_cast<uint32_t>(i * sizeof(MemType));
    1095        9720 :     CHECK_EQ(kReturn, m.Call(offset + pseudo_base, kLength));
    1096        9720 :     CheckOobValue(result);
    1097             :   }
    1098             : 
    1099             :   // way out-of-bounds accesses.
    1100        1368 :   for (uint64_t i = pseudo_base + sizeof(buffer); i < 0xFFFFFFFF;
    1101             :        i += A_BILLION) {
    1102        1044 :     uint32_t offset = static_cast<uint32_t>(i);
    1103        1044 :     CHECK_EQ(kReturn, m.Call(offset, kLength));
    1104        1044 :     CheckOobValue(result);
    1105             :   }
    1106         324 : }
    1107             : 
    1108       23724 : TEST(RunOobCheckedLoadT_pseudo0) {
    1109           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(0, false);
    1110           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(0, true);
    1111           6 :   TestRunOobCheckedLoadT_pseudo<float>(0, false);
    1112           6 :   TestRunOobCheckedLoadT_pseudo<float>(0, true);
    1113           6 :   TestRunOobCheckedLoadT_pseudo<double>(0, false);
    1114           6 :   TestRunOobCheckedLoadT_pseudo<double>(0, true);
    1115           6 : }
    1116             : 
    1117       23724 : TEST(RunOobCheckedLoadT_pseudo1) {
    1118           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(100000, false);
    1119           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(100000, true);
    1120           6 :   TestRunOobCheckedLoadT_pseudo<float>(100000, false);
    1121           6 :   TestRunOobCheckedLoadT_pseudo<float>(100000, true);
    1122           6 :   TestRunOobCheckedLoadT_pseudo<double>(100000, false);
    1123           6 :   TestRunOobCheckedLoadT_pseudo<double>(100000, true);
    1124           6 : }
    1125             : 
    1126       23724 : TEST(RunOobCheckedLoadT_pseudo2) {
    1127           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(A_BILLION, false);
    1128           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(A_BILLION, true);
    1129           6 :   TestRunOobCheckedLoadT_pseudo<float>(A_BILLION, false);
    1130           6 :   TestRunOobCheckedLoadT_pseudo<float>(A_BILLION, true);
    1131           6 :   TestRunOobCheckedLoadT_pseudo<double>(A_BILLION, false);
    1132           6 :   TestRunOobCheckedLoadT_pseudo<double>(A_BILLION, true);
    1133           6 : }
    1134             : 
    1135       23724 : TEST(RunOobCheckedLoadT_pseudo3) {
    1136           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(A_GIG, false);
    1137           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(A_GIG, true);
    1138           6 :   TestRunOobCheckedLoadT_pseudo<float>(A_GIG, false);
    1139           6 :   TestRunOobCheckedLoadT_pseudo<float>(A_GIG, true);
    1140           6 :   TestRunOobCheckedLoadT_pseudo<double>(A_GIG, false);
    1141           6 :   TestRunOobCheckedLoadT_pseudo<double>(A_GIG, true);
    1142           6 : }
    1143             : 
    1144       23724 : TEST(RunOobCheckedLoadT_pseudo4) {
    1145           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(2 * A_BILLION, false);
    1146           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(2 * A_BILLION, true);
    1147           6 :   TestRunOobCheckedLoadT_pseudo<float>(2 * A_BILLION, false);
    1148           6 :   TestRunOobCheckedLoadT_pseudo<float>(2 * A_BILLION, true);
    1149           6 :   TestRunOobCheckedLoadT_pseudo<double>(2 * A_BILLION, false);
    1150           6 :   TestRunOobCheckedLoadT_pseudo<double>(2 * A_BILLION, true);
    1151           6 : }
    1152             : 
    1153       23724 : TEST(RunOobCheckedLoadT_pseudo5) {
    1154           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(2 * A_GIG, false);
    1155           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(2 * A_GIG, true);
    1156           6 :   TestRunOobCheckedLoadT_pseudo<float>(2 * A_GIG, false);
    1157           6 :   TestRunOobCheckedLoadT_pseudo<float>(2 * A_GIG, true);
    1158           6 :   TestRunOobCheckedLoadT_pseudo<double>(2 * A_GIG, false);
    1159           6 :   TestRunOobCheckedLoadT_pseudo<double>(2 * A_GIG, true);
    1160           6 : }
    1161             : 
    1162       23724 : TEST(RunOobCheckedLoadT_pseudo6) {
    1163           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(3 * A_BILLION, false);
    1164           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(3 * A_BILLION, true);
    1165           6 :   TestRunOobCheckedLoadT_pseudo<float>(3 * A_BILLION, false);
    1166           6 :   TestRunOobCheckedLoadT_pseudo<float>(3 * A_BILLION, true);
    1167           6 :   TestRunOobCheckedLoadT_pseudo<double>(3 * A_BILLION, false);
    1168           6 :   TestRunOobCheckedLoadT_pseudo<double>(3 * A_BILLION, true);
    1169           6 : }
    1170             : 
    1171       23724 : TEST(RunOobCheckedLoadT_pseudo7) {
    1172           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(3 * A_GIG, false);
    1173           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(3 * A_GIG, true);
    1174           6 :   TestRunOobCheckedLoadT_pseudo<float>(3 * A_GIG, false);
    1175           6 :   TestRunOobCheckedLoadT_pseudo<float>(3 * A_GIG, true);
    1176           6 :   TestRunOobCheckedLoadT_pseudo<double>(3 * A_GIG, false);
    1177           6 :   TestRunOobCheckedLoadT_pseudo<double>(3 * A_GIG, true);
    1178           6 : }
    1179             : 
    1180       23724 : TEST(RunOobCheckedLoadT_pseudo8) {
    1181           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(4 * A_BILLION, false);
    1182           6 :   TestRunOobCheckedLoadT_pseudo<int32_t>(4 * A_BILLION, true);
    1183           6 :   TestRunOobCheckedLoadT_pseudo<float>(4 * A_BILLION, false);
    1184           6 :   TestRunOobCheckedLoadT_pseudo<float>(4 * A_BILLION, true);
    1185           6 :   TestRunOobCheckedLoadT_pseudo<double>(4 * A_BILLION, false);
    1186           6 :   TestRunOobCheckedLoadT_pseudo<double>(4 * A_BILLION, true);
    1187           6 : }
    1188             : 
    1189             : }  // namespace compiler
    1190             : }  // namespace internal
    1191       71154 : }  // namespace v8

Generated by: LCOV version 1.10