| 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/compiler/change-lowering.h" | 7 #include "src/compiler/change-lowering.h" |
| 8 #include "src/compiler/control-builders.h" | 8 #include "src/compiler/control-builders.h" |
| 9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
| 10 #include "src/compiler/node-properties.h" | 10 #include "src/compiler/node-properties.h" |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 Factory* factory() { return this->isolate()->factory(); } | 140 Factory* factory() { return this->isolate()->factory(); } |
| 141 Heap* heap() { return this->isolate()->heap(); } | 141 Heap* heap() { return this->isolate()->heap(); } |
| 142 }; | 142 }; |
| 143 | 143 |
| 144 | 144 |
| 145 TEST(RunChangeTaggedToInt32) { | 145 TEST(RunChangeTaggedToInt32) { |
| 146 // Build and lower a graph by hand. | 146 // Build and lower a graph by hand. |
| 147 ChangesLoweringTester<int32_t> t(kMachAnyTagged); | 147 ChangesLoweringTester<int32_t> t(kMachAnyTagged); |
| 148 t.BuildAndLower(t.simplified()->ChangeTaggedToInt32()); | 148 t.BuildAndLower(t.simplified()->ChangeTaggedToInt32()); |
| 149 | 149 |
| 150 if (Pipeline::SupportedTarget()) { | |
| 151 FOR_INT32_INPUTS(i) { | 150 FOR_INT32_INPUTS(i) { |
| 152 int32_t input = *i; | 151 int32_t input = *i; |
| 153 | 152 |
| 154 if (Smi::IsValid(input)) { | 153 if (Smi::IsValid(input)) { |
| 155 int32_t result = t.Call(Smi::FromInt(input)); | 154 int32_t result = t.Call(Smi::FromInt(input)); |
| 156 CHECK_EQ(input, result); | 155 CHECK_EQ(input, result); |
| 157 } | 156 } |
| 158 | 157 |
| 159 { | 158 { |
| 160 Handle<Object> number = t.factory()->NewNumber(input); | 159 Handle<Object> number = t.factory()->NewNumber(input); |
| 161 int32_t result = t.Call(*number); | 160 int32_t result = t.Call(*number); |
| 162 CHECK_EQ(input, result); | 161 CHECK_EQ(input, result); |
| 163 } | 162 } |
| 164 | 163 |
| 165 { | 164 { |
| 166 Handle<HeapNumber> number = t.factory()->NewHeapNumber(input); | 165 Handle<HeapNumber> number = t.factory()->NewHeapNumber(input); |
| 167 int32_t result = t.Call(*number); | 166 int32_t result = t.Call(*number); |
| 168 CHECK_EQ(input, result); | 167 CHECK_EQ(input, result); |
| 169 } | 168 } |
| 170 } | |
| 171 } | 169 } |
| 172 } | 170 } |
| 173 | 171 |
| 174 | 172 |
| 175 TEST(RunChangeTaggedToUint32) { | 173 TEST(RunChangeTaggedToUint32) { |
| 176 // Build and lower a graph by hand. | 174 // Build and lower a graph by hand. |
| 177 ChangesLoweringTester<uint32_t> t(kMachAnyTagged); | 175 ChangesLoweringTester<uint32_t> t(kMachAnyTagged); |
| 178 t.BuildAndLower(t.simplified()->ChangeTaggedToUint32()); | 176 t.BuildAndLower(t.simplified()->ChangeTaggedToUint32()); |
| 179 | 177 |
| 180 if (Pipeline::SupportedTarget()) { | |
| 181 FOR_UINT32_INPUTS(i) { | 178 FOR_UINT32_INPUTS(i) { |
| 182 uint32_t input = *i; | 179 uint32_t input = *i; |
| 183 | 180 |
| 184 if (Smi::IsValid(input)) { | 181 if (Smi::IsValid(input)) { |
| 185 uint32_t result = t.Call(Smi::FromInt(input)); | 182 uint32_t result = t.Call(Smi::FromInt(input)); |
| 186 CHECK_EQ(static_cast<int32_t>(input), static_cast<int32_t>(result)); | 183 CHECK_EQ(static_cast<int32_t>(input), static_cast<int32_t>(result)); |
| 187 } | 184 } |
| 188 | 185 |
| 189 { | 186 { |
| 190 Handle<Object> number = t.factory()->NewNumber(input); | 187 Handle<Object> number = t.factory()->NewNumber(input); |
| 191 uint32_t result = t.Call(*number); | 188 uint32_t result = t.Call(*number); |
| 192 CHECK_EQ(static_cast<int32_t>(input), static_cast<int32_t>(result)); | 189 CHECK_EQ(static_cast<int32_t>(input), static_cast<int32_t>(result)); |
| 193 } | 190 } |
| 194 | 191 |
| 195 { | 192 { |
| 196 Handle<HeapNumber> number = t.factory()->NewHeapNumber(input); | 193 Handle<HeapNumber> number = t.factory()->NewHeapNumber(input); |
| 197 uint32_t result = t.Call(*number); | 194 uint32_t result = t.Call(*number); |
| 198 CHECK_EQ(static_cast<int32_t>(input), static_cast<int32_t>(result)); | 195 CHECK_EQ(static_cast<int32_t>(input), static_cast<int32_t>(result)); |
| 199 } | 196 } |
| 200 } | 197 } |
| 201 } | |
| 202 } | 198 } |
| 203 | 199 |
| 204 | 200 |
| 205 TEST(RunChangeTaggedToFloat64) { | 201 TEST(RunChangeTaggedToFloat64) { |
| 206 ChangesLoweringTester<int32_t> t(kMachAnyTagged); | 202 ChangesLoweringTester<int32_t> t(kMachAnyTagged); |
| 207 double result; | 203 double result; |
| 208 | 204 |
| 209 t.BuildStoreAndLower( | 205 t.BuildStoreAndLower( |
| 210 t.simplified()->ChangeTaggedToFloat64(), | 206 t.simplified()->ChangeTaggedToFloat64(), |
| 211 t.machine()->Store(StoreRepresentation(kMachFloat64, kNoWriteBarrier)), | 207 t.machine()->Store(StoreRepresentation(kMachFloat64, kNoWriteBarrier)), |
| 212 &result); | 208 &result); |
| 213 | 209 |
| 214 if (Pipeline::SupportedTarget()) { | 210 { |
| 215 FOR_INT32_INPUTS(i) { | 211 FOR_INT32_INPUTS(i) { |
| 216 int32_t input = *i; | 212 int32_t input = *i; |
| 217 | 213 |
| 218 if (Smi::IsValid(input)) { | 214 if (Smi::IsValid(input)) { |
| 219 t.Call(Smi::FromInt(input)); | 215 t.Call(Smi::FromInt(input)); |
| 220 CHECK_EQ(input, static_cast<int32_t>(result)); | 216 CHECK_EQ(input, static_cast<int32_t>(result)); |
| 221 } | 217 } |
| 222 | 218 |
| 223 { | 219 { |
| 224 Handle<Object> number = t.factory()->NewNumber(input); | 220 Handle<Object> number = t.factory()->NewNumber(input); |
| 225 t.Call(*number); | 221 t.Call(*number); |
| 226 CHECK_EQ(input, static_cast<int32_t>(result)); | 222 CHECK_EQ(input, static_cast<int32_t>(result)); |
| 227 } | 223 } |
| 228 | 224 |
| 229 { | 225 { |
| 230 Handle<HeapNumber> number = t.factory()->NewHeapNumber(input); | 226 Handle<HeapNumber> number = t.factory()->NewHeapNumber(input); |
| 231 t.Call(*number); | 227 t.Call(*number); |
| 232 CHECK_EQ(input, static_cast<int32_t>(result)); | 228 CHECK_EQ(input, static_cast<int32_t>(result)); |
| 233 } | 229 } |
| 234 } | 230 } |
| 235 } | 231 } |
| 236 | 232 |
| 237 if (Pipeline::SupportedTarget()) { | 233 { |
| 238 FOR_FLOAT64_INPUTS(i) { | 234 FOR_FLOAT64_INPUTS(i) { |
| 239 double input = *i; | 235 double input = *i; |
| 240 { | 236 { |
| 241 Handle<Object> number = t.factory()->NewNumber(input); | 237 Handle<Object> number = t.factory()->NewNumber(input); |
| 242 t.Call(*number); | 238 t.Call(*number); |
| 243 CheckDoubleEq(input, result); | 239 CheckDoubleEq(input, result); |
| 244 } | 240 } |
| 245 | 241 |
| 246 { | 242 { |
| 247 Handle<HeapNumber> number = t.factory()->NewHeapNumber(input); | 243 Handle<HeapNumber> number = t.factory()->NewHeapNumber(input); |
| 248 t.Call(*number); | 244 t.Call(*number); |
| 249 CheckDoubleEq(input, result); | 245 CheckDoubleEq(input, result); |
| 250 } | 246 } |
| 251 } | 247 } |
| 252 } | 248 } |
| 253 } | 249 } |
| 254 | 250 |
| 255 | 251 |
| 256 TEST(RunChangeBoolToBit) { | 252 TEST(RunChangeBoolToBit) { |
| 257 ChangesLoweringTester<int32_t> t(kMachAnyTagged); | 253 ChangesLoweringTester<int32_t> t(kMachAnyTagged); |
| 258 t.BuildAndLower(t.simplified()->ChangeBoolToBit()); | 254 t.BuildAndLower(t.simplified()->ChangeBoolToBit()); |
| 259 | 255 |
| 260 if (Pipeline::SupportedTarget()) { | 256 { |
| 261 Object* true_obj = t.heap()->true_value(); | 257 Object* true_obj = t.heap()->true_value(); |
| 262 int32_t result = t.Call(true_obj); | 258 int32_t result = t.Call(true_obj); |
| 263 CHECK_EQ(1, result); | 259 CHECK_EQ(1, result); |
| 264 } | 260 } |
| 265 | 261 |
| 266 if (Pipeline::SupportedTarget()) { | 262 { |
| 267 Object* false_obj = t.heap()->false_value(); | 263 Object* false_obj = t.heap()->false_value(); |
| 268 int32_t result = t.Call(false_obj); | 264 int32_t result = t.Call(false_obj); |
| 269 CHECK_EQ(0, result); | 265 CHECK_EQ(0, result); |
| 270 } | 266 } |
| 271 } | 267 } |
| 272 | 268 |
| 273 | 269 |
| 274 TEST(RunChangeBitToBool) { | 270 TEST(RunChangeBitToBool) { |
| 275 ChangesLoweringTester<Object*> t(kMachInt32); | 271 ChangesLoweringTester<Object*> t(kMachInt32); |
| 276 t.BuildAndLower(t.simplified()->ChangeBitToBool()); | 272 t.BuildAndLower(t.simplified()->ChangeBitToBool()); |
| 277 | 273 |
| 278 if (Pipeline::SupportedTarget()) { | 274 { |
| 279 Object* result = t.Call(1); | 275 Object* result = t.Call(1); |
| 280 Object* true_obj = t.heap()->true_value(); | 276 Object* true_obj = t.heap()->true_value(); |
| 281 CHECK_EQ(true_obj, result); | 277 CHECK_EQ(true_obj, result); |
| 282 } | 278 } |
| 283 | 279 |
| 284 if (Pipeline::SupportedTarget()) { | 280 { |
| 285 Object* result = t.Call(0); | 281 Object* result = t.Call(0); |
| 286 Object* false_obj = t.heap()->false_value(); | 282 Object* false_obj = t.heap()->false_value(); |
| 287 CHECK_EQ(false_obj, result); | 283 CHECK_EQ(false_obj, result); |
| 288 } | 284 } |
| 289 } | 285 } |
| 290 | |
| 291 | |
| 292 #if V8_TURBOFAN_BACKEND | |
| 293 // TODO(titzer): disabled on ARM | |
| 294 | |
| 295 TEST(RunChangeInt32ToTaggedSmi) { | |
| 296 ChangesLoweringTester<Object*> t; | |
| 297 int32_t input; | |
| 298 t.BuildLoadAndLower(t.simplified()->ChangeInt32ToTagged(), | |
| 299 t.machine()->Load(kMachInt32), &input); | |
| 300 | |
| 301 if (Pipeline::SupportedTarget()) { | |
| 302 FOR_INT32_INPUTS(i) { | |
| 303 input = *i; | |
| 304 if (!Smi::IsValid(input)) continue; | |
| 305 Object* result = t.Call(); | |
| 306 t.CheckNumber(static_cast<double>(input), result); | |
| 307 } | |
| 308 } | |
| 309 } | |
| 310 | |
| 311 | |
| 312 TEST(RunChangeUint32ToTaggedSmi) { | |
| 313 ChangesLoweringTester<Object*> t; | |
| 314 uint32_t input; | |
| 315 t.BuildLoadAndLower(t.simplified()->ChangeUint32ToTagged(), | |
| 316 t.machine()->Load(kMachUint32), &input); | |
| 317 | |
| 318 if (Pipeline::SupportedTarget()) { | |
| 319 FOR_UINT32_INPUTS(i) { | |
| 320 input = *i; | |
| 321 if (input > static_cast<uint32_t>(Smi::kMaxValue)) continue; | |
| 322 Object* result = t.Call(); | |
| 323 double expected = static_cast<double>(input); | |
| 324 t.CheckNumber(expected, result); | |
| 325 } | |
| 326 } | |
| 327 } | |
| 328 | |
| 329 | |
| 330 TEST(RunChangeInt32ToTagged) { | |
| 331 ChangesLoweringTester<Object*> t; | |
| 332 int32_t input; | |
| 333 t.BuildLoadAndLower(t.simplified()->ChangeInt32ToTagged(), | |
| 334 t.machine()->Load(kMachInt32), &input); | |
| 335 | |
| 336 if (Pipeline::SupportedTarget()) { | |
| 337 for (int m = 0; m < 3; m++) { // Try 3 GC modes. | |
| 338 FOR_INT32_INPUTS(i) { | |
| 339 if (m == 0) CcTest::heap()->EnableInlineAllocation(); | |
| 340 if (m == 1) CcTest::heap()->DisableInlineAllocation(); | |
| 341 if (m == 2) SimulateFullSpace(CcTest::heap()->new_space()); | |
| 342 | |
| 343 input = *i; | |
| 344 Object* result = t.CallWithPotentialGC<Object>(); | |
| 345 t.CheckNumber(static_cast<double>(input), result); | |
| 346 } | |
| 347 } | |
| 348 } | |
| 349 } | |
| 350 | |
| 351 | |
| 352 TEST(RunChangeUint32ToTagged) { | |
| 353 ChangesLoweringTester<Object*> t; | |
| 354 uint32_t input; | |
| 355 t.BuildLoadAndLower(t.simplified()->ChangeUint32ToTagged(), | |
| 356 t.machine()->Load(kMachUint32), &input); | |
| 357 | |
| 358 if (Pipeline::SupportedTarget()) { | |
| 359 for (int m = 0; m < 3; m++) { // Try 3 GC modes. | |
| 360 FOR_UINT32_INPUTS(i) { | |
| 361 if (m == 0) CcTest::heap()->EnableInlineAllocation(); | |
| 362 if (m == 1) CcTest::heap()->DisableInlineAllocation(); | |
| 363 if (m == 2) SimulateFullSpace(CcTest::heap()->new_space()); | |
| 364 | |
| 365 input = *i; | |
| 366 Object* result = t.CallWithPotentialGC<Object>(); | |
| 367 double expected = static_cast<double>(input); | |
| 368 t.CheckNumber(expected, result); | |
| 369 } | |
| 370 } | |
| 371 } | |
| 372 } | |
| 373 | |
| 374 | |
| 375 TEST(RunChangeFloat64ToTagged) { | |
| 376 ChangesLoweringTester<Object*> t; | |
| 377 double input; | |
| 378 t.BuildLoadAndLower(t.simplified()->ChangeFloat64ToTagged(), | |
| 379 t.machine()->Load(kMachFloat64), &input); | |
| 380 | |
| 381 if (Pipeline::SupportedTarget()) { | |
| 382 for (int m = 0; m < 3; m++) { // Try 3 GC modes. | |
| 383 FOR_FLOAT64_INPUTS(i) { | |
| 384 if (m == 0) CcTest::heap()->EnableInlineAllocation(); | |
| 385 if (m == 1) CcTest::heap()->DisableInlineAllocation(); | |
| 386 if (m == 2) SimulateFullSpace(CcTest::heap()->new_space()); | |
| 387 | |
| 388 input = *i; | |
| 389 Object* result = t.CallWithPotentialGC<Object>(); | |
| 390 t.CheckNumber(input, result); | |
| 391 } | |
| 392 } | |
| 393 } | |
| 394 } | |
| 395 | |
| 396 #endif // V8_TURBOFAN_BACKEND | |
| OLD | NEW |