| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <limits> | 5 #include <limits> |
| 6 | 6 |
| 7 #include "src/v8.h" | 7 #include "src/v8.h" |
| 8 #include "test/cctest/cctest.h" | 8 #include "test/cctest/cctest.h" |
| 9 #include "test/cctest/compiler/graph-builder-tester.h" | 9 #include "test/cctest/compiler/graph-builder-tester.h" |
| 10 | 10 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 ValueMatcher<double> m(n); | 58 ValueMatcher<double> m(n); |
| 59 CHECK_EQ(IrOpcode::kNumberConstant, n->opcode()); | 59 CHECK_EQ(IrOpcode::kNumberConstant, n->opcode()); |
| 60 CHECK(m.HasValue()); | 60 CHECK(m.HasValue()); |
| 61 CHECK_EQ(expected, m.Value()); | 61 CHECK_EQ(expected, m.Value()); |
| 62 } | 62 } |
| 63 | 63 |
| 64 Node* Parameter(int index = 0) { | 64 Node* Parameter(int index = 0) { |
| 65 return graph()->NewNode(common()->Parameter(index), graph()->start()); | 65 return graph()->NewNode(common()->Parameter(index), graph()->start()); |
| 66 } | 66 } |
| 67 | 67 |
| 68 void CheckTypeError(RepTypeUnion from, RepTypeUnion to) { | 68 void CheckTypeError(MachineTypeUnion from, MachineTypeUnion to) { |
| 69 changer()->testing_type_errors_ = true; | 69 changer()->testing_type_errors_ = true; |
| 70 changer()->type_error_ = false; | 70 changer()->type_error_ = false; |
| 71 Node* n = Parameter(0); | 71 Node* n = Parameter(0); |
| 72 Node* c = changer()->GetRepresentationFor(n, from, to); | 72 Node* c = changer()->GetRepresentationFor(n, from, to); |
| 73 CHECK(changer()->type_error_); |
| 73 CHECK_EQ(n, c); | 74 CHECK_EQ(n, c); |
| 74 CHECK(changer()->type_error_); | |
| 75 } | 75 } |
| 76 | 76 |
| 77 void CheckNop(RepTypeUnion from, RepTypeUnion to) { | 77 void CheckNop(MachineTypeUnion from, MachineTypeUnion to) { |
| 78 Node* n = Parameter(0); | 78 Node* n = Parameter(0); |
| 79 Node* c = changer()->GetRepresentationFor(n, from, to); | 79 Node* c = changer()->GetRepresentationFor(n, from, to); |
| 80 CHECK_EQ(n, c); | 80 CHECK_EQ(n, c); |
| 81 } | 81 } |
| 82 }; | 82 }; |
| 83 } | 83 } |
| 84 } | 84 } |
| 85 } // namespace v8::internal::compiler | 85 } // namespace v8::internal::compiler |
| 86 | 86 |
| 87 | 87 |
| 88 static const RepType all_reps[] = {rBit, rWord32, rWord64, rFloat64, rTagged}; | 88 static const MachineType all_reps[] = {kRepBit, kRepWord32, kRepWord64, |
| 89 kRepFloat64, kRepTagged}; |
| 89 | 90 |
| 90 | 91 |
| 91 // TODO(titzer): lift this to ValueHelper | 92 // TODO(titzer): lift this to ValueHelper |
| 92 static const double double_inputs[] = { | 93 static const double double_inputs[] = { |
| 93 0.0, -0.0, 1.0, -1.0, 0.1, 1.4, -1.7, | 94 0.0, -0.0, 1.0, -1.0, 0.1, 1.4, -1.7, |
| 94 2, 5, 6, 982983, 888, -999.8, 3.1e7, | 95 2, 5, 6, 982983, 888, -999.8, 3.1e7, |
| 95 -2e66, 2.3e124, -12e73, V8_INFINITY, -V8_INFINITY}; | 96 -2e66, 2.3e124, -12e73, V8_INFINITY, -V8_INFINITY}; |
| 96 | 97 |
| 97 | 98 |
| 98 static const int32_t int32_inputs[] = { | 99 static const int32_t int32_inputs[] = { |
| 99 0, 1, -1, | 100 0, 1, -1, |
| 100 2, 5, 6, | 101 2, 5, 6, |
| 101 982983, 888, -999, | 102 982983, 888, -999, |
| 102 65535, static_cast<int32_t>(0xFFFFFFFF), static_cast<int32_t>(0x80000000)}; | 103 65535, static_cast<int32_t>(0xFFFFFFFF), static_cast<int32_t>(0x80000000)}; |
| 103 | 104 |
| 104 | 105 |
| 105 static const uint32_t uint32_inputs[] = { | 106 static const uint32_t uint32_inputs[] = { |
| 106 0, 1, static_cast<uint32_t>(-1), 2, 5, 6, | 107 0, 1, static_cast<uint32_t>(-1), 2, 5, 6, |
| 107 982983, 888, static_cast<uint32_t>(-999), 65535, 0xFFFFFFFF, 0x80000000}; | 108 982983, 888, static_cast<uint32_t>(-999), 65535, 0xFFFFFFFF, 0x80000000}; |
| 108 | 109 |
| 109 | 110 |
| 110 TEST(BoolToBit_constant) { | 111 TEST(BoolToBit_constant) { |
| 111 RepresentationChangerTester r; | 112 RepresentationChangerTester r; |
| 112 | 113 |
| 113 Node* true_node = r.jsgraph()->TrueConstant(); | 114 Node* true_node = r.jsgraph()->TrueConstant(); |
| 114 Node* true_bit = r.changer()->GetRepresentationFor(true_node, rTagged, rBit); | 115 Node* true_bit = |
| 116 r.changer()->GetRepresentationFor(true_node, kRepTagged, kRepBit); |
| 115 r.CheckInt32Constant(true_bit, 1); | 117 r.CheckInt32Constant(true_bit, 1); |
| 116 | 118 |
| 117 Node* false_node = r.jsgraph()->FalseConstant(); | 119 Node* false_node = r.jsgraph()->FalseConstant(); |
| 118 Node* false_bit = | 120 Node* false_bit = |
| 119 r.changer()->GetRepresentationFor(false_node, rTagged, rBit); | 121 r.changer()->GetRepresentationFor(false_node, kRepTagged, kRepBit); |
| 120 r.CheckInt32Constant(false_bit, 0); | 122 r.CheckInt32Constant(false_bit, 0); |
| 121 } | 123 } |
| 122 | 124 |
| 123 | 125 |
| 124 TEST(BitToBool_constant) { | 126 TEST(BitToBool_constant) { |
| 125 RepresentationChangerTester r; | 127 RepresentationChangerTester r; |
| 126 | 128 |
| 127 for (int i = -5; i < 5; i++) { | 129 for (int i = -5; i < 5; i++) { |
| 128 Node* node = r.jsgraph()->Int32Constant(i); | 130 Node* node = r.jsgraph()->Int32Constant(i); |
| 129 Node* val = r.changer()->GetRepresentationFor(node, rBit, rTagged); | 131 Node* val = r.changer()->GetRepresentationFor(node, kRepBit, kRepTagged); |
| 130 r.CheckHeapConstant(val, i == 0 ? r.isolate()->heap()->false_value() | 132 r.CheckHeapConstant(val, i == 0 ? r.isolate()->heap()->false_value() |
| 131 : r.isolate()->heap()->true_value()); | 133 : r.isolate()->heap()->true_value()); |
| 132 } | 134 } |
| 133 } | 135 } |
| 134 | 136 |
| 135 | 137 |
| 136 TEST(ToTagged_constant) { | 138 TEST(ToTagged_constant) { |
| 137 RepresentationChangerTester r; | 139 RepresentationChangerTester r; |
| 138 | 140 |
| 139 for (size_t i = 0; i < ARRAY_SIZE(double_inputs); i++) { | 141 for (size_t i = 0; i < ARRAY_SIZE(double_inputs); i++) { |
| 140 Node* n = r.jsgraph()->Float64Constant(double_inputs[i]); | 142 Node* n = r.jsgraph()->Float64Constant(double_inputs[i]); |
| 141 Node* c = r.changer()->GetRepresentationFor(n, rFloat64, rTagged); | 143 Node* c = r.changer()->GetRepresentationFor(n, kRepFloat64, kRepTagged); |
| 142 r.CheckNumberConstant(c, double_inputs[i]); | 144 r.CheckNumberConstant(c, double_inputs[i]); |
| 143 } | 145 } |
| 144 | 146 |
| 145 for (size_t i = 0; i < ARRAY_SIZE(int32_inputs); i++) { | 147 for (size_t i = 0; i < ARRAY_SIZE(int32_inputs); i++) { |
| 146 Node* n = r.jsgraph()->Int32Constant(int32_inputs[i]); | 148 Node* n = r.jsgraph()->Int32Constant(int32_inputs[i]); |
| 147 Node* c = r.changer()->GetRepresentationFor(n, rWord32 | tInt32, rTagged); | 149 Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeInt32, |
| 150 kRepTagged); |
| 148 r.CheckNumberConstant(c, static_cast<double>(int32_inputs[i])); | 151 r.CheckNumberConstant(c, static_cast<double>(int32_inputs[i])); |
| 149 } | 152 } |
| 150 | 153 |
| 151 for (size_t i = 0; i < ARRAY_SIZE(uint32_inputs); i++) { | 154 for (size_t i = 0; i < ARRAY_SIZE(uint32_inputs); i++) { |
| 152 Node* n = r.jsgraph()->Int32Constant(uint32_inputs[i]); | 155 Node* n = r.jsgraph()->Int32Constant(uint32_inputs[i]); |
| 153 Node* c = r.changer()->GetRepresentationFor(n, rWord32 | tUint32, rTagged); | 156 Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeUint32, |
| 157 kRepTagged); |
| 154 r.CheckNumberConstant(c, static_cast<double>(uint32_inputs[i])); | 158 r.CheckNumberConstant(c, static_cast<double>(uint32_inputs[i])); |
| 155 } | 159 } |
| 156 } | 160 } |
| 157 | 161 |
| 158 | 162 |
| 159 static void CheckChange(IrOpcode::Value expected, RepTypeUnion from, | 163 static void CheckChange(IrOpcode::Value expected, MachineTypeUnion from, |
| 160 RepTypeUnion to) { | 164 MachineTypeUnion to) { |
| 161 RepresentationChangerTester r; | 165 RepresentationChangerTester r; |
| 162 | 166 |
| 163 Node* n = r.Parameter(); | 167 Node* n = r.Parameter(); |
| 164 Node* c = r.changer()->GetRepresentationFor(n, from, to); | 168 Node* c = r.changer()->GetRepresentationFor(n, from, to); |
| 165 | 169 |
| 166 CHECK_NE(c, n); | 170 CHECK_NE(c, n); |
| 167 CHECK_EQ(expected, c->opcode()); | 171 CHECK_EQ(expected, c->opcode()); |
| 168 CHECK_EQ(n, c->InputAt(0)); | 172 CHECK_EQ(n, c->InputAt(0)); |
| 169 } | 173 } |
| 170 | 174 |
| 171 | 175 |
| 172 TEST(SingleChanges) { | 176 TEST(SingleChanges) { |
| 173 CheckChange(IrOpcode::kChangeBoolToBit, rTagged, rBit); | 177 CheckChange(IrOpcode::kChangeBoolToBit, kRepTagged, kRepBit); |
| 174 CheckChange(IrOpcode::kChangeBitToBool, rBit, rTagged); | 178 CheckChange(IrOpcode::kChangeBitToBool, kRepBit, kRepTagged); |
| 175 | 179 |
| 176 CheckChange(IrOpcode::kChangeInt32ToTagged, rWord32 | tInt32, rTagged); | 180 CheckChange(IrOpcode::kChangeInt32ToTagged, kRepWord32 | kTypeInt32, |
| 177 CheckChange(IrOpcode::kChangeUint32ToTagged, rWord32 | tUint32, rTagged); | 181 kRepTagged); |
| 178 CheckChange(IrOpcode::kChangeFloat64ToTagged, rFloat64, rTagged); | 182 CheckChange(IrOpcode::kChangeUint32ToTagged, kRepWord32 | kTypeUint32, |
| 183 kRepTagged); |
| 184 CheckChange(IrOpcode::kChangeFloat64ToTagged, kRepFloat64, kRepTagged); |
| 179 | 185 |
| 180 CheckChange(IrOpcode::kChangeTaggedToInt32, rTagged | tInt32, rWord32); | 186 CheckChange(IrOpcode::kChangeTaggedToInt32, kRepTagged | kTypeInt32, |
| 181 CheckChange(IrOpcode::kChangeTaggedToUint32, rTagged | tUint32, rWord32); | 187 kRepWord32); |
| 182 CheckChange(IrOpcode::kChangeTaggedToFloat64, rTagged, rFloat64); | 188 CheckChange(IrOpcode::kChangeTaggedToUint32, kRepTagged | kTypeUint32, |
| 189 kRepWord32); |
| 190 CheckChange(IrOpcode::kChangeTaggedToFloat64, kRepTagged, kRepFloat64); |
| 183 | 191 |
| 184 // Int32,Uint32 <-> Float64 are actually machine conversions. | 192 // Int32,Uint32 <-> Float64 are actually machine conversions. |
| 185 CheckChange(IrOpcode::kChangeInt32ToFloat64, rWord32 | tInt32, rFloat64); | 193 CheckChange(IrOpcode::kChangeInt32ToFloat64, kRepWord32 | kTypeInt32, |
| 186 CheckChange(IrOpcode::kChangeUint32ToFloat64, rWord32 | tUint32, rFloat64); | 194 kRepFloat64); |
| 187 CheckChange(IrOpcode::kChangeFloat64ToInt32, rFloat64 | tInt32, rWord32); | 195 CheckChange(IrOpcode::kChangeUint32ToFloat64, kRepWord32 | kTypeUint32, |
| 188 CheckChange(IrOpcode::kChangeFloat64ToUint32, rFloat64 | tUint32, rWord32); | 196 kRepFloat64); |
| 197 CheckChange(IrOpcode::kChangeFloat64ToInt32, kRepFloat64 | kTypeInt32, |
| 198 kRepWord32); |
| 199 CheckChange(IrOpcode::kChangeFloat64ToUint32, kRepFloat64 | kTypeUint32, |
| 200 kRepWord32); |
| 189 } | 201 } |
| 190 | 202 |
| 191 | 203 |
| 192 TEST(SignednessInWord32) { | 204 TEST(SignednessInWord32) { |
| 193 RepresentationChangerTester r; | 205 RepresentationChangerTester r; |
| 194 | 206 |
| 195 // TODO(titzer): assume that uses of a word32 without a sign mean tInt32. | 207 // TODO(titzer): assume that uses of a word32 without a sign mean kTypeInt32. |
| 196 CheckChange(IrOpcode::kChangeTaggedToInt32, rTagged, rWord32 | tInt32); | 208 CheckChange(IrOpcode::kChangeTaggedToInt32, kRepTagged, |
| 197 CheckChange(IrOpcode::kChangeTaggedToUint32, rTagged, rWord32 | tUint32); | 209 kRepWord32 | kTypeInt32); |
| 198 CheckChange(IrOpcode::kChangeInt32ToFloat64, rWord32, rFloat64); | 210 CheckChange(IrOpcode::kChangeTaggedToUint32, kRepTagged, |
| 199 CheckChange(IrOpcode::kChangeFloat64ToInt32, rFloat64, rWord32); | 211 kRepWord32 | kTypeUint32); |
| 212 CheckChange(IrOpcode::kChangeInt32ToFloat64, kRepWord32, kRepFloat64); |
| 213 CheckChange(IrOpcode::kChangeFloat64ToInt32, kRepFloat64, kRepWord32); |
| 200 } | 214 } |
| 201 | 215 |
| 202 | 216 |
| 203 TEST(Nops) { | 217 TEST(Nops) { |
| 204 RepresentationChangerTester r; | 218 RepresentationChangerTester r; |
| 205 | 219 |
| 206 // X -> X is always a nop for any single representation X. | 220 // X -> X is always a nop for any single representation X. |
| 207 for (size_t i = 0; i < ARRAY_SIZE(all_reps); i++) { | 221 for (size_t i = 0; i < ARRAY_SIZE(all_reps); i++) { |
| 208 r.CheckNop(all_reps[i], all_reps[i]); | 222 r.CheckNop(all_reps[i], all_reps[i]); |
| 209 } | 223 } |
| 210 | 224 |
| 211 // 32-bit or 64-bit words can be used as branch conditions (rBit). | 225 // 32-bit or 64-bit words can be used as branch conditions (kRepBit). |
| 212 r.CheckNop(rWord32, rBit); | 226 r.CheckNop(kRepWord32, kRepBit); |
| 213 r.CheckNop(rWord32, rBit | tBool); | 227 r.CheckNop(kRepWord32, kRepBit | kTypeBool); |
| 214 r.CheckNop(rWord64, rBit); | 228 r.CheckNop(kRepWord64, kRepBit); |
| 215 r.CheckNop(rWord64, rBit | tBool); | 229 r.CheckNop(kRepWord64, kRepBit | kTypeBool); |
| 216 | 230 |
| 217 // rBit (result of comparison) is implicitly a wordish thing. | 231 // 32-bit words can be used as smaller word sizes and vice versa, because |
| 218 r.CheckNop(rBit, rWord32); | 232 // loads from memory implicitly sign or zero extend the value to the |
| 219 r.CheckNop(rBit | tBool, rWord32); | 233 // full machine word size, and stores implicitly truncate. |
| 220 r.CheckNop(rBit, rWord64); | 234 r.CheckNop(kRepWord32, kRepWord8); |
| 221 r.CheckNop(rBit | tBool, rWord64); | 235 r.CheckNop(kRepWord32, kRepWord16); |
| 236 r.CheckNop(kRepWord32, kRepWord32); |
| 237 r.CheckNop(kRepWord8, kRepWord32); |
| 238 r.CheckNop(kRepWord16, kRepWord32); |
| 239 |
| 240 // kRepBit (result of comparison) is implicitly a wordish thing. |
| 241 r.CheckNop(kRepBit, kRepWord8); |
| 242 r.CheckNop(kRepBit | kTypeBool, kRepWord8); |
| 243 r.CheckNop(kRepBit, kRepWord16); |
| 244 r.CheckNop(kRepBit | kTypeBool, kRepWord16); |
| 245 r.CheckNop(kRepBit, kRepWord32); |
| 246 r.CheckNop(kRepBit | kTypeBool, kRepWord32); |
| 247 r.CheckNop(kRepBit, kRepWord64); |
| 248 r.CheckNop(kRepBit | kTypeBool, kRepWord64); |
| 222 } | 249 } |
| 223 | 250 |
| 224 | 251 |
| 225 TEST(TypeErrors) { | 252 TEST(TypeErrors) { |
| 226 RepresentationChangerTester r; | 253 RepresentationChangerTester r; |
| 227 | 254 |
| 228 // Floats cannot be implicitly converted to/from comparison conditions. | 255 // Floats cannot be implicitly converted to/from comparison conditions. |
| 229 r.CheckTypeError(rFloat64, rBit); | 256 r.CheckTypeError(kRepFloat64, kRepBit); |
| 230 r.CheckTypeError(rFloat64, rBit | tBool); | 257 r.CheckTypeError(kRepFloat64, kRepBit | kTypeBool); |
| 231 r.CheckTypeError(rBit, rFloat64); | 258 r.CheckTypeError(kRepBit, kRepFloat64); |
| 232 r.CheckTypeError(rBit | tBool, rFloat64); | 259 r.CheckTypeError(kRepBit | kTypeBool, kRepFloat64); |
| 233 | 260 |
| 234 // Word64 is internal and shouldn't be implicitly converted. | 261 // Word64 is internal and shouldn't be implicitly converted. |
| 235 r.CheckTypeError(rWord64, rTagged | tBool); | 262 r.CheckTypeError(kRepWord64, kRepTagged | kTypeBool); |
| 236 r.CheckTypeError(rWord64, rTagged); | 263 r.CheckTypeError(kRepWord64, kRepTagged); |
| 237 r.CheckTypeError(rWord64, rTagged | tBool); | 264 r.CheckTypeError(kRepWord64, kRepTagged | kTypeBool); |
| 238 r.CheckTypeError(rTagged, rWord64); | 265 r.CheckTypeError(kRepTagged, kRepWord64); |
| 239 r.CheckTypeError(rTagged | tBool, rWord64); | 266 r.CheckTypeError(kRepTagged | kTypeBool, kRepWord64); |
| 240 | 267 |
| 241 // Word64 / Word32 shouldn't be implicitly converted. | 268 // Word64 / Word32 shouldn't be implicitly converted. |
| 242 r.CheckTypeError(rWord64, rWord32); | 269 r.CheckTypeError(kRepWord64, kRepWord32); |
| 243 r.CheckTypeError(rWord32, rWord64); | 270 r.CheckTypeError(kRepWord32, kRepWord64); |
| 244 r.CheckTypeError(rWord64, rWord32 | tInt32); | 271 r.CheckTypeError(kRepWord64, kRepWord32 | kTypeInt32); |
| 245 r.CheckTypeError(rWord32 | tInt32, rWord64); | 272 r.CheckTypeError(kRepWord32 | kTypeInt32, kRepWord64); |
| 246 r.CheckTypeError(rWord64, rWord32 | tUint32); | 273 r.CheckTypeError(kRepWord64, kRepWord32 | kTypeUint32); |
| 247 r.CheckTypeError(rWord32 | tUint32, rWord64); | 274 r.CheckTypeError(kRepWord32 | kTypeUint32, kRepWord64); |
| 248 | 275 |
| 249 for (size_t i = 0; i < ARRAY_SIZE(all_reps); i++) { | 276 for (size_t i = 0; i < ARRAY_SIZE(all_reps); i++) { |
| 250 for (size_t j = 0; j < ARRAY_SIZE(all_reps); j++) { | 277 for (size_t j = 0; j < ARRAY_SIZE(all_reps); j++) { |
| 251 if (i == j) continue; | 278 if (i == j) continue; |
| 252 // Only a single from representation is allowed. | 279 // Only a single from representation is allowed. |
| 253 r.CheckTypeError(all_reps[i] | all_reps[j], rTagged); | 280 r.CheckTypeError(all_reps[i] | all_reps[j], kRepTagged); |
| 254 } | 281 } |
| 255 } | 282 } |
| 256 } | 283 } |
| 257 | 284 |
| 258 | 285 |
| 259 TEST(CompleteMatrix) { | 286 TEST(CompleteMatrix) { |
| 260 // TODO(titzer): test all variants in the matrix. | 287 // TODO(titzer): test all variants in the matrix. |
| 261 // rB | 288 // rB |
| 262 // tBrB | 289 // tBrB |
| 263 // tBrT | 290 // tBrT |
| 264 // rW32 | 291 // rW32 |
| 265 // tIrW32 | 292 // tIrW32 |
| 266 // tUrW32 | 293 // tUrW32 |
| 267 // rW64 | 294 // rW64 |
| 268 // tIrW64 | 295 // tIrW64 |
| 269 // tUrW64 | 296 // tUrW64 |
| 270 // rF64 | 297 // rF64 |
| 271 // tIrF64 | 298 // tIrF64 |
| 272 // tUrF64 | 299 // tUrF64 |
| 273 // tArF64 | 300 // tArF64 |
| 274 // rT | 301 // rT |
| 275 // tArT | 302 // tArT |
| 276 } | 303 } |
| OLD | NEW |