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 |