| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. Use of this | 1 // Copyright 2014 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 | 2 // source code is governed by a BSD-style license that can be found in the |
| 3 // LICENSE file. | 3 // LICENSE file. |
| 4 | 4 |
| 5 #include <cmath> | 5 #include <cmath> |
| 6 #include <functional> | 6 #include <functional> |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/base/utils/random-number-generator.h" | 10 #include "src/base/utils/random-number-generator.h" |
| (...skipping 1189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1200 m.AddNode(m.common()->Phi(MachineRepresentation::kWord32, num_results), | 1200 m.AddNode(m.common()->Phi(MachineRepresentation::kWord32, num_results), |
| 1201 num_results, results); | 1201 num_results, results); |
| 1202 m.Return(phi); | 1202 m.Return(phi); |
| 1203 | 1203 |
| 1204 for (size_t i = 0; i < kNumValues; ++i) { | 1204 for (size_t i = 0; i < kNumValues; ++i) { |
| 1205 CHECK_EQ(values[i], m.Call(static_cast<int>(i))); | 1205 CHECK_EQ(values[i], m.Call(static_cast<int>(i))); |
| 1206 } | 1206 } |
| 1207 } | 1207 } |
| 1208 | 1208 |
| 1209 | 1209 |
| 1210 TEST(RunLoadInt32) { | |
| 1211 RawMachineAssemblerTester<int32_t> m; | |
| 1212 | |
| 1213 int32_t p1 = 0; // loads directly from this location. | |
| 1214 m.Return(m.LoadFromPointer(&p1, MachineType::Int32())); | |
| 1215 | |
| 1216 FOR_INT32_INPUTS(i) { | |
| 1217 p1 = *i; | |
| 1218 CHECK_EQ(p1, m.Call()); | |
| 1219 } | |
| 1220 } | |
| 1221 | |
| 1222 | |
| 1223 TEST(RunLoadInt32Offset) { | |
| 1224 int32_t p1 = 0; // loads directly from this location. | |
| 1225 | |
| 1226 int32_t offsets[] = {-2000000, -100, -101, 1, 3, | |
| 1227 7, 120, 2000, 2000000000, 0xff}; | |
| 1228 | |
| 1229 for (size_t i = 0; i < arraysize(offsets); i++) { | |
| 1230 RawMachineAssemblerTester<int32_t> m; | |
| 1231 int32_t offset = offsets[i]; | |
| 1232 byte* pointer = reinterpret_cast<byte*>(&p1) - offset; | |
| 1233 // generate load [#base + #index] | |
| 1234 m.Return(m.LoadFromPointer(pointer, MachineType::Int32(), offset)); | |
| 1235 | |
| 1236 FOR_INT32_INPUTS(j) { | |
| 1237 p1 = *j; | |
| 1238 CHECK_EQ(p1, m.Call()); | |
| 1239 } | |
| 1240 } | |
| 1241 } | |
| 1242 | |
| 1243 | |
| 1244 TEST(RunLoadStoreFloat32Offset) { | |
| 1245 float p1 = 0.0f; // loads directly from this location. | |
| 1246 float p2 = 0.0f; // and stores directly into this location. | |
| 1247 | |
| 1248 FOR_INT32_INPUTS(i) { | |
| 1249 int32_t magic = 0x2342aabb + *i * 3; | |
| 1250 RawMachineAssemblerTester<int32_t> m; | |
| 1251 int32_t offset = *i; | |
| 1252 byte* from = reinterpret_cast<byte*>(&p1) - offset; | |
| 1253 byte* to = reinterpret_cast<byte*>(&p2) - offset; | |
| 1254 // generate load [#base + #index] | |
| 1255 Node* load = m.Load(MachineType::Float32(), m.PointerConstant(from), | |
| 1256 m.IntPtrConstant(offset)); | |
| 1257 m.Store(MachineRepresentation::kFloat32, m.PointerConstant(to), | |
| 1258 m.IntPtrConstant(offset), load, kNoWriteBarrier); | |
| 1259 m.Return(m.Int32Constant(magic)); | |
| 1260 | |
| 1261 FOR_FLOAT32_INPUTS(j) { | |
| 1262 p1 = *j; | |
| 1263 p2 = *j - 5; | |
| 1264 CHECK_EQ(magic, m.Call()); | |
| 1265 CHECK_DOUBLE_EQ(p1, p2); | |
| 1266 } | |
| 1267 } | |
| 1268 } | |
| 1269 | |
| 1270 | |
| 1271 TEST(RunLoadStoreFloat64Offset) { | |
| 1272 double p1 = 0; // loads directly from this location. | |
| 1273 double p2 = 0; // and stores directly into this location. | |
| 1274 | |
| 1275 FOR_INT32_INPUTS(i) { | |
| 1276 int32_t magic = 0x2342aabb + *i * 3; | |
| 1277 RawMachineAssemblerTester<int32_t> m; | |
| 1278 int32_t offset = *i; | |
| 1279 byte* from = reinterpret_cast<byte*>(&p1) - offset; | |
| 1280 byte* to = reinterpret_cast<byte*>(&p2) - offset; | |
| 1281 // generate load [#base + #index] | |
| 1282 Node* load = m.Load(MachineType::Float64(), m.PointerConstant(from), | |
| 1283 m.IntPtrConstant(offset)); | |
| 1284 m.Store(MachineRepresentation::kFloat64, m.PointerConstant(to), | |
| 1285 m.IntPtrConstant(offset), load, kNoWriteBarrier); | |
| 1286 m.Return(m.Int32Constant(magic)); | |
| 1287 | |
| 1288 FOR_FLOAT64_INPUTS(j) { | |
| 1289 p1 = *j; | |
| 1290 p2 = *j - 5; | |
| 1291 CHECK_EQ(magic, m.Call()); | |
| 1292 CHECK_DOUBLE_EQ(p1, p2); | |
| 1293 } | |
| 1294 } | |
| 1295 } | |
| 1296 | |
| 1297 | |
| 1298 TEST(RunInt32AddP) { | 1210 TEST(RunInt32AddP) { |
| 1299 RawMachineAssemblerTester<int32_t> m; | 1211 RawMachineAssemblerTester<int32_t> m; |
| 1300 Int32BinopTester bt(&m); | 1212 Int32BinopTester bt(&m); |
| 1301 | 1213 |
| 1302 bt.AddReturn(m.Int32Add(bt.param0, bt.param1)); | 1214 bt.AddReturn(m.Int32Add(bt.param0, bt.param1)); |
| 1303 | 1215 |
| 1304 FOR_INT32_INPUTS(i) { | 1216 FOR_INT32_INPUTS(i) { |
| 1305 FOR_INT32_INPUTS(j) { | 1217 FOR_INT32_INPUTS(j) { |
| 1306 // Use uint32_t because signed overflow is UB in C. | 1218 // Use uint32_t because signed overflow is UB in C. |
| 1307 int expected = static_cast<int32_t>(*i + *j); | 1219 int expected = static_cast<int32_t>(*i + *j); |
| (...skipping 2320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3628 MachineType::Int32()); | 3540 MachineType::Int32()); |
| 3629 int32_t constant = static_cast<int32_t>(0x55555 + i); | 3541 int32_t constant = static_cast<int32_t>(0x55555 + i); |
| 3630 m.AddNode(kOps[i], m.Parameter(0), m.Parameter(1)); | 3542 m.AddNode(kOps[i], m.Parameter(0), m.Parameter(1)); |
| 3631 m.Return(m.Int32Constant(constant)); | 3543 m.Return(m.Int32Constant(constant)); |
| 3632 | 3544 |
| 3633 CHECK_EQ(constant, m.Call(1, 1)); | 3545 CHECK_EQ(constant, m.Call(1, 1)); |
| 3634 } | 3546 } |
| 3635 } | 3547 } |
| 3636 | 3548 |
| 3637 | 3549 |
| 3638 template <typename Type> | |
| 3639 static void RunLoadImmIndex(MachineType rep) { | |
| 3640 const int kNumElems = 3; | |
| 3641 Type buffer[kNumElems]; | |
| 3642 | |
| 3643 // initialize the buffer with some raw data. | |
| 3644 byte* raw = reinterpret_cast<byte*>(buffer); | |
| 3645 for (size_t i = 0; i < sizeof(buffer); i++) { | |
| 3646 raw[i] = static_cast<byte>((i + sizeof(buffer)) ^ 0xAA); | |
| 3647 } | |
| 3648 | |
| 3649 // Test with various large and small offsets. | |
| 3650 for (int offset = -1; offset <= 200000; offset *= -5) { | |
| 3651 for (int i = 0; i < kNumElems; i++) { | |
| 3652 BufferedRawMachineAssemblerTester<Type> m; | |
| 3653 Node* base = m.PointerConstant(buffer - offset); | |
| 3654 Node* index = m.Int32Constant((offset + i) * sizeof(buffer[0])); | |
| 3655 m.Return(m.Load(rep, base, index)); | |
| 3656 | |
| 3657 volatile Type expected = buffer[i]; | |
| 3658 volatile Type actual = m.Call(); | |
| 3659 CHECK_EQ(expected, actual); | |
| 3660 } | |
| 3661 } | |
| 3662 } | |
| 3663 | |
| 3664 | |
| 3665 TEST(RunLoadImmIndex) { | |
| 3666 RunLoadImmIndex<int8_t>(MachineType::Int8()); | |
| 3667 RunLoadImmIndex<uint8_t>(MachineType::Uint8()); | |
| 3668 RunLoadImmIndex<int16_t>(MachineType::Int16()); | |
| 3669 RunLoadImmIndex<uint16_t>(MachineType::Uint16()); | |
| 3670 RunLoadImmIndex<int32_t>(MachineType::Int32()); | |
| 3671 RunLoadImmIndex<uint32_t>(MachineType::Uint32()); | |
| 3672 RunLoadImmIndex<int32_t*>(MachineType::AnyTagged()); | |
| 3673 RunLoadImmIndex<float>(MachineType::Float32()); | |
| 3674 RunLoadImmIndex<double>(MachineType::Float64()); | |
| 3675 if (kPointerSize == 8) { | |
| 3676 RunLoadImmIndex<int64_t>(MachineType::Int64()); | |
| 3677 } | |
| 3678 // TODO(titzer): test various indexing modes. | |
| 3679 } | |
| 3680 | |
| 3681 | |
| 3682 template <typename CType> | |
| 3683 static void RunLoadStore(MachineType rep) { | |
| 3684 const int kNumElems = 4; | |
| 3685 CType buffer[kNumElems]; | |
| 3686 | |
| 3687 for (int32_t x = 0; x < kNumElems; x++) { | |
| 3688 int32_t y = kNumElems - x - 1; | |
| 3689 // initialize the buffer with raw data. | |
| 3690 byte* raw = reinterpret_cast<byte*>(buffer); | |
| 3691 for (size_t i = 0; i < sizeof(buffer); i++) { | |
| 3692 raw[i] = static_cast<byte>((i + sizeof(buffer)) ^ 0xAA); | |
| 3693 } | |
| 3694 | |
| 3695 RawMachineAssemblerTester<int32_t> m; | |
| 3696 int32_t OK = 0x29000 + x; | |
| 3697 Node* base = m.PointerConstant(buffer); | |
| 3698 Node* index0 = m.IntPtrConstant(x * sizeof(buffer[0])); | |
| 3699 Node* load = m.Load(rep, base, index0); | |
| 3700 Node* index1 = m.IntPtrConstant(y * sizeof(buffer[0])); | |
| 3701 m.Store(rep.representation(), base, index1, load, kNoWriteBarrier); | |
| 3702 m.Return(m.Int32Constant(OK)); | |
| 3703 | |
| 3704 CHECK(buffer[x] != buffer[y]); | |
| 3705 CHECK_EQ(OK, m.Call()); | |
| 3706 CHECK(buffer[x] == buffer[y]); | |
| 3707 } | |
| 3708 } | |
| 3709 | |
| 3710 | |
| 3711 TEST(RunLoadStore) { | |
| 3712 RunLoadStore<int8_t>(MachineType::Int8()); | |
| 3713 RunLoadStore<uint8_t>(MachineType::Uint8()); | |
| 3714 RunLoadStore<int16_t>(MachineType::Int16()); | |
| 3715 RunLoadStore<uint16_t>(MachineType::Uint16()); | |
| 3716 RunLoadStore<int32_t>(MachineType::Int32()); | |
| 3717 RunLoadStore<uint32_t>(MachineType::Uint32()); | |
| 3718 RunLoadStore<void*>(MachineType::AnyTagged()); | |
| 3719 RunLoadStore<float>(MachineType::Float32()); | |
| 3720 RunLoadStore<double>(MachineType::Float64()); | |
| 3721 } | |
| 3722 | |
| 3723 | |
| 3724 TEST(RunFloat32Add) { | 3550 TEST(RunFloat32Add) { |
| 3725 BufferedRawMachineAssemblerTester<float> m(MachineType::Float32(), | 3551 BufferedRawMachineAssemblerTester<float> m(MachineType::Float32(), |
| 3726 MachineType::Float32()); | 3552 MachineType::Float32()); |
| 3727 m.Return(m.Float32Add(m.Parameter(0), m.Parameter(1))); | 3553 m.Return(m.Float32Add(m.Parameter(0), m.Parameter(1))); |
| 3728 | 3554 |
| 3729 FOR_FLOAT32_INPUTS(i) { | 3555 FOR_FLOAT32_INPUTS(i) { |
| 3730 FOR_FLOAT32_INPUTS(j) { CHECK_FLOAT_EQ(*i + *j, m.Call(*i, *j)); } | 3556 FOR_FLOAT32_INPUTS(j) { CHECK_FLOAT_EQ(*i + *j, m.Call(*i, *j)); } |
| 3731 } | 3557 } |
| 3732 } | 3558 } |
| 3733 | 3559 |
| (...skipping 1346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5080 FOR_FLOAT64_INPUTS(pr) { | 4906 FOR_FLOAT64_INPUTS(pr) { |
| 5081 input_a = *pl; | 4907 input_a = *pl; |
| 5082 input_b = *pr; | 4908 input_b = *pr; |
| 5083 int32_t expected = cmp.Float64Compare(input_a, input_b) ? 1 : 0; | 4909 int32_t expected = cmp.Float64Compare(input_a, input_b) ? 1 : 0; |
| 5084 CHECK_EQ(expected, m.Call()); | 4910 CHECK_EQ(expected, m.Call()); |
| 5085 } | 4911 } |
| 5086 } | 4912 } |
| 5087 } | 4913 } |
| 5088 | 4914 |
| 5089 | 4915 |
| 5090 template <typename IntType> | |
| 5091 static void LoadStoreTruncation(MachineType kRepresentation) { | |
| 5092 IntType input; | |
| 5093 | |
| 5094 RawMachineAssemblerTester<int32_t> m; | |
| 5095 Node* a = m.LoadFromPointer(&input, kRepresentation); | |
| 5096 Node* ap1 = m.Int32Add(a, m.Int32Constant(1)); | |
| 5097 m.StoreToPointer(&input, kRepresentation.representation(), ap1); | |
| 5098 m.Return(ap1); | |
| 5099 | |
| 5100 const IntType max = std::numeric_limits<IntType>::max(); | |
| 5101 const IntType min = std::numeric_limits<IntType>::min(); | |
| 5102 | |
| 5103 // Test upper bound. | |
| 5104 input = max; | |
| 5105 CHECK_EQ(max + 1, m.Call()); | |
| 5106 CHECK_EQ(min, input); | |
| 5107 | |
| 5108 // Test lower bound. | |
| 5109 input = min; | |
| 5110 CHECK_EQ(static_cast<IntType>(max + 2), m.Call()); | |
| 5111 CHECK_EQ(min + 1, input); | |
| 5112 | |
| 5113 // Test all one byte values that are not one byte bounds. | |
| 5114 for (int i = -127; i < 127; i++) { | |
| 5115 input = i; | |
| 5116 int expected = i >= 0 ? i + 1 : max + (i - min) + 2; | |
| 5117 CHECK_EQ(static_cast<IntType>(expected), m.Call()); | |
| 5118 CHECK_EQ(static_cast<IntType>(i + 1), input); | |
| 5119 } | |
| 5120 } | |
| 5121 | |
| 5122 | |
| 5123 TEST(RunLoadStoreTruncation) { | |
| 5124 LoadStoreTruncation<int8_t>(MachineType::Int8()); | |
| 5125 LoadStoreTruncation<int16_t>(MachineType::Int16()); | |
| 5126 } | |
| 5127 | |
| 5128 | |
| 5129 static void IntPtrCompare(intptr_t left, intptr_t right) { | 4916 static void IntPtrCompare(intptr_t left, intptr_t right) { |
| 5130 for (int test = 0; test < 7; test++) { | 4917 for (int test = 0; test < 7; test++) { |
| 5131 RawMachineAssemblerTester<bool> m(MachineType::Pointer(), | 4918 RawMachineAssemblerTester<bool> m(MachineType::Pointer(), |
| 5132 MachineType::Pointer()); | 4919 MachineType::Pointer()); |
| 5133 Node* p0 = m.Parameter(0); | 4920 Node* p0 = m.Parameter(0); |
| 5134 Node* p1 = m.Parameter(1); | 4921 Node* p1 = m.Parameter(1); |
| 5135 Node* res = NULL; | 4922 Node* res = NULL; |
| 5136 bool expected = false; | 4923 bool expected = false; |
| 5137 switch (test) { | 4924 switch (test) { |
| 5138 case 0: | 4925 case 0: |
| (...skipping 827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5966 function, param, param, param, param, param, param, param, param)); | 5753 function, param, param, param, param, param, param, param, param)); |
| 5967 FOR_INT32_INPUTS(i) { | 5754 FOR_INT32_INPUTS(i) { |
| 5968 int32_t const x = *i; | 5755 int32_t const x = *i; |
| 5969 CHECK_EQ(x * 8, m.Call(x)); | 5756 CHECK_EQ(x * 8, m.Call(x)); |
| 5970 } | 5757 } |
| 5971 } | 5758 } |
| 5972 #endif // USE_SIMULATOR | 5759 #endif // USE_SIMULATOR |
| 5973 | 5760 |
| 5974 #if V8_TARGET_ARCH_64_BIT | 5761 #if V8_TARGET_ARCH_64_BIT |
| 5975 // TODO(titzer): run int64 tests on all platforms when supported. | 5762 // TODO(titzer): run int64 tests on all platforms when supported. |
| 5976 TEST(RunCheckedLoadInt64) { | |
| 5977 int64_t buffer[] = {0x66bbccddeeff0011LL, 0x1122334455667788LL}; | |
| 5978 RawMachineAssemblerTester<int64_t> m(MachineType::Int32()); | |
| 5979 Node* base = m.PointerConstant(buffer); | |
| 5980 Node* index = m.Parameter(0); | |
| 5981 Node* length = m.Int32Constant(16); | |
| 5982 Node* load = m.AddNode(m.machine()->CheckedLoad(MachineType::Int64()), base, | |
| 5983 index, length); | |
| 5984 m.Return(load); | |
| 5985 | |
| 5986 CHECK_EQ(buffer[0], m.Call(0)); | |
| 5987 CHECK_EQ(buffer[1], m.Call(8)); | |
| 5988 CHECK_EQ(0, m.Call(16)); | |
| 5989 } | |
| 5990 | |
| 5991 | |
| 5992 TEST(RunCheckedStoreInt64) { | |
| 5993 const int64_t write = 0x5566778899aabbLL; | |
| 5994 const int64_t before = 0x33bbccddeeff0011LL; | |
| 5995 int64_t buffer[] = {before, before}; | |
| 5996 RawMachineAssemblerTester<int32_t> m(MachineType::Int32()); | |
| 5997 Node* base = m.PointerConstant(buffer); | |
| 5998 Node* index = m.Parameter(0); | |
| 5999 Node* length = m.Int32Constant(16); | |
| 6000 Node* value = m.Int64Constant(write); | |
| 6001 Node* store = | |
| 6002 m.AddNode(m.machine()->CheckedStore(MachineRepresentation::kWord64), base, | |
| 6003 index, length, value); | |
| 6004 USE(store); | |
| 6005 m.Return(m.Int32Constant(11)); | |
| 6006 | |
| 6007 CHECK_EQ(11, m.Call(16)); | |
| 6008 CHECK_EQ(before, buffer[0]); | |
| 6009 CHECK_EQ(before, buffer[1]); | |
| 6010 | |
| 6011 CHECK_EQ(11, m.Call(0)); | |
| 6012 CHECK_EQ(write, buffer[0]); | |
| 6013 CHECK_EQ(before, buffer[1]); | |
| 6014 | |
| 6015 CHECK_EQ(11, m.Call(8)); | |
| 6016 CHECK_EQ(write, buffer[0]); | |
| 6017 CHECK_EQ(write, buffer[1]); | |
| 6018 } | |
| 6019 | |
| 6020 | 5763 |
| 6021 TEST(RunBitcastInt64ToFloat64) { | 5764 TEST(RunBitcastInt64ToFloat64) { |
| 6022 int64_t input = 1; | 5765 int64_t input = 1; |
| 6023 double output = 0.0; | 5766 double output = 0.0; |
| 6024 RawMachineAssemblerTester<int32_t> m; | 5767 RawMachineAssemblerTester<int32_t> m; |
| 6025 m.StoreToPointer( | 5768 m.StoreToPointer( |
| 6026 &output, MachineRepresentation::kFloat64, | 5769 &output, MachineRepresentation::kFloat64, |
| 6027 m.BitcastInt64ToFloat64(m.LoadFromPointer(&input, MachineType::Int64()))); | 5770 m.BitcastInt64ToFloat64(m.LoadFromPointer(&input, MachineType::Int64()))); |
| 6028 m.Return(m.Int32Constant(11)); | 5771 m.Return(m.Int32Constant(11)); |
| 6029 FOR_INT64_INPUTS(i) { | 5772 FOR_INT64_INPUTS(i) { |
| (...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6499 r.Goto(&merge); | 6242 r.Goto(&merge); |
| 6500 r.Bind(&merge); | 6243 r.Bind(&merge); |
| 6501 Node* phi = r.Phi(MachineRepresentation::kWord32, fa, fb); | 6244 Node* phi = r.Phi(MachineRepresentation::kWord32, fa, fb); |
| 6502 r.Return(phi); | 6245 r.Return(phi); |
| 6503 CHECK_EQ(1, r.Call(1)); | 6246 CHECK_EQ(1, r.Call(1)); |
| 6504 } | 6247 } |
| 6505 | 6248 |
| 6506 } // namespace compiler | 6249 } // namespace compiler |
| 6507 } // namespace internal | 6250 } // namespace internal |
| 6508 } // namespace v8 | 6251 } // namespace v8 |
| OLD | NEW |