| 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/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
| 8 #include "src/compiler/access-builder.h" | 8 #include "src/compiler/access-builder.h" |
| 9 #include "src/compiler/change-lowering.h" | 9 #include "src/compiler/change-lowering.h" |
| 10 #include "src/compiler/control-builders.h" | 10 #include "src/compiler/control-builders.h" |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 }; | 99 }; |
| 100 | 100 |
| 101 | 101 |
| 102 // TODO(titzer): factor these tests out to test-run-simplifiedops.cc. | 102 // TODO(titzer): factor these tests out to test-run-simplifiedops.cc. |
| 103 // TODO(titzer): test tagged representation for input to NumberToInt32. | 103 // TODO(titzer): test tagged representation for input to NumberToInt32. |
| 104 TEST(RunNumberToInt32_float64) { | 104 TEST(RunNumberToInt32_float64) { |
| 105 // TODO(titzer): explicit load/stores here are only because of representations | 105 // TODO(titzer): explicit load/stores here are only because of representations |
| 106 double input; | 106 double input; |
| 107 int32_t result; | 107 int32_t result; |
| 108 SimplifiedLoweringTester<Object*> t; | 108 SimplifiedLoweringTester<Object*> t; |
| 109 FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(), | 109 FieldAccess load = {kUntaggedBase, 0, |
| 110 MachineType::Float64()}; | 110 Handle<Name>(), Type::Number(), |
| 111 MachineType::Float64(), kNoWriteBarrier}; |
| 111 Node* loaded = t.LoadField(load, t.PointerConstant(&input)); | 112 Node* loaded = t.LoadField(load, t.PointerConstant(&input)); |
| 112 NodeProperties::SetType(loaded, Type::Number()); | 113 NodeProperties::SetType(loaded, Type::Number()); |
| 113 Node* convert = t.NumberToInt32(loaded); | 114 Node* convert = t.NumberToInt32(loaded); |
| 114 FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Signed32(), | 115 FieldAccess store = {kUntaggedBase, 0, |
| 115 MachineType::Int32()}; | 116 Handle<Name>(), Type::Signed32(), |
| 117 MachineType::Int32(), kNoWriteBarrier}; |
| 116 t.StoreField(store, t.PointerConstant(&result), convert); | 118 t.StoreField(store, t.PointerConstant(&result), convert); |
| 117 t.Return(t.jsgraph.TrueConstant()); | 119 t.Return(t.jsgraph.TrueConstant()); |
| 118 t.LowerAllNodesAndLowerChanges(); | 120 t.LowerAllNodesAndLowerChanges(); |
| 119 t.GenerateCode(); | 121 t.GenerateCode(); |
| 120 | 122 |
| 121 FOR_FLOAT64_INPUTS(i) { | 123 FOR_FLOAT64_INPUTS(i) { |
| 122 input = *i; | 124 input = *i; |
| 123 int32_t expected = DoubleToInt32(*i); | 125 int32_t expected = DoubleToInt32(*i); |
| 124 t.Call(); | 126 t.Call(); |
| 125 CHECK_EQ(expected, result); | 127 CHECK_EQ(expected, result); |
| 126 } | 128 } |
| 127 } | 129 } |
| 128 | 130 |
| 129 | 131 |
| 130 // TODO(titzer): test tagged representation for input to NumberToUint32. | 132 // TODO(titzer): test tagged representation for input to NumberToUint32. |
| 131 TEST(RunNumberToUint32_float64) { | 133 TEST(RunNumberToUint32_float64) { |
| 132 // TODO(titzer): explicit load/stores here are only because of representations | 134 // TODO(titzer): explicit load/stores here are only because of representations |
| 133 double input; | 135 double input; |
| 134 uint32_t result; | 136 uint32_t result; |
| 135 SimplifiedLoweringTester<Object*> t; | 137 SimplifiedLoweringTester<Object*> t; |
| 136 FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(), | 138 FieldAccess load = {kUntaggedBase, 0, |
| 137 MachineType::Float64()}; | 139 Handle<Name>(), Type::Number(), |
| 140 MachineType::Float64(), kNoWriteBarrier}; |
| 138 Node* loaded = t.LoadField(load, t.PointerConstant(&input)); | 141 Node* loaded = t.LoadField(load, t.PointerConstant(&input)); |
| 139 NodeProperties::SetType(loaded, Type::Number()); | 142 NodeProperties::SetType(loaded, Type::Number()); |
| 140 Node* convert = t.NumberToUint32(loaded); | 143 Node* convert = t.NumberToUint32(loaded); |
| 141 FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Unsigned32(), | 144 FieldAccess store = {kUntaggedBase, 0, |
| 142 MachineType::Uint32()}; | 145 Handle<Name>(), Type::Unsigned32(), |
| 146 MachineType::Uint32(), kNoWriteBarrier}; |
| 143 t.StoreField(store, t.PointerConstant(&result), convert); | 147 t.StoreField(store, t.PointerConstant(&result), convert); |
| 144 t.Return(t.jsgraph.TrueConstant()); | 148 t.Return(t.jsgraph.TrueConstant()); |
| 145 t.LowerAllNodesAndLowerChanges(); | 149 t.LowerAllNodesAndLowerChanges(); |
| 146 t.GenerateCode(); | 150 t.GenerateCode(); |
| 147 | 151 |
| 148 FOR_FLOAT64_INPUTS(i) { | 152 FOR_FLOAT64_INPUTS(i) { |
| 149 input = *i; | 153 input = *i; |
| 150 uint32_t expected = DoubleToUint32(*i); | 154 uint32_t expected = DoubleToUint32(*i); |
| 151 t.Call(); | 155 t.Call(); |
| 152 CHECK_EQ(static_cast<int32_t>(expected), static_cast<int32_t>(result)); | 156 CHECK_EQ(static_cast<int32_t>(expected), static_cast<int32_t>(result)); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 CHECK_EQ(data[i], expected); | 295 CHECK_EQ(data[i], expected); |
| 292 } | 296 } |
| 293 } | 297 } |
| 294 | 298 |
| 295 | 299 |
| 296 TEST(RunLoadFieldFromUntaggedBase) { | 300 TEST(RunLoadFieldFromUntaggedBase) { |
| 297 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)}; | 301 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)}; |
| 298 | 302 |
| 299 for (size_t i = 0; i < arraysize(smis); i++) { | 303 for (size_t i = 0; i < arraysize(smis); i++) { |
| 300 int offset = static_cast<int>(i * sizeof(Smi*)); | 304 int offset = static_cast<int>(i * sizeof(Smi*)); |
| 301 FieldAccess access = {kUntaggedBase, offset, Handle<Name>(), | 305 FieldAccess access = {kUntaggedBase, |
| 302 Type::Integral32(), MachineType::AnyTagged()}; | 306 offset, |
| 307 Handle<Name>(), |
| 308 Type::Integral32(), |
| 309 MachineType::AnyTagged(), |
| 310 kNoWriteBarrier}; |
| 303 | 311 |
| 304 SimplifiedLoweringTester<Object*> t; | 312 SimplifiedLoweringTester<Object*> t; |
| 305 Node* load = t.LoadField(access, t.PointerConstant(smis)); | 313 Node* load = t.LoadField(access, t.PointerConstant(smis)); |
| 306 t.Return(load); | 314 t.Return(load); |
| 307 t.LowerAllNodesAndLowerChanges(); | 315 t.LowerAllNodesAndLowerChanges(); |
| 308 | 316 |
| 309 for (int j = -5; j <= 5; j++) { | 317 for (int j = -5; j <= 5; j++) { |
| 310 Smi* expected = Smi::FromInt(j); | 318 Smi* expected = Smi::FromInt(j); |
| 311 smis[i] = expected; | 319 smis[i] = expected; |
| 312 CHECK_EQ(expected, t.Call()); | 320 CHECK_EQ(expected, t.Call()); |
| 313 } | 321 } |
| 314 } | 322 } |
| 315 } | 323 } |
| 316 | 324 |
| 317 | 325 |
| 318 TEST(RunStoreFieldToUntaggedBase) { | 326 TEST(RunStoreFieldToUntaggedBase) { |
| 319 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)}; | 327 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)}; |
| 320 | 328 |
| 321 for (size_t i = 0; i < arraysize(smis); i++) { | 329 for (size_t i = 0; i < arraysize(smis); i++) { |
| 322 int offset = static_cast<int>(i * sizeof(Smi*)); | 330 int offset = static_cast<int>(i * sizeof(Smi*)); |
| 323 FieldAccess access = {kUntaggedBase, offset, Handle<Name>(), | 331 FieldAccess access = {kUntaggedBase, |
| 324 Type::Integral32(), MachineType::AnyTagged()}; | 332 offset, |
| 333 Handle<Name>(), |
| 334 Type::Integral32(), |
| 335 MachineType::AnyTagged(), |
| 336 kNoWriteBarrier}; |
| 325 | 337 |
| 326 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged()); | 338 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged()); |
| 327 Node* p0 = t.Parameter(0); | 339 Node* p0 = t.Parameter(0); |
| 328 t.StoreField(access, t.PointerConstant(smis), p0); | 340 t.StoreField(access, t.PointerConstant(smis), p0); |
| 329 t.Return(p0); | 341 t.Return(p0); |
| 330 t.LowerAllNodesAndLowerChanges(); | 342 t.LowerAllNodesAndLowerChanges(); |
| 331 | 343 |
| 332 for (int j = -5; j <= 5; j++) { | 344 for (int j = -5; j <= 5; j++) { |
| 333 Smi* expected = Smi::FromInt(j); | 345 Smi* expected = Smi::FromInt(j); |
| 334 smis[i] = Smi::FromInt(-100); | 346 smis[i] = Smi::FromInt(-100); |
| 335 CHECK_EQ(expected, t.Call(expected)); | 347 CHECK_EQ(expected, t.Call(expected)); |
| 336 CHECK_EQ(expected, smis[i]); | 348 CHECK_EQ(expected, smis[i]); |
| 337 } | 349 } |
| 338 } | 350 } |
| 339 } | 351 } |
| 340 | 352 |
| 341 | 353 |
| 342 TEST(RunLoadElementFromUntaggedBase) { | 354 TEST(RunLoadElementFromUntaggedBase) { |
| 343 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), | 355 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), |
| 344 Smi::FromInt(4), Smi::FromInt(5)}; | 356 Smi::FromInt(4), Smi::FromInt(5)}; |
| 345 | 357 |
| 346 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes | 358 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes |
| 347 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index | 359 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index |
| 348 int offset = static_cast<int>(i * sizeof(Smi*)); | 360 int offset = static_cast<int>(i * sizeof(Smi*)); |
| 349 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), | 361 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), |
| 350 MachineType::AnyTagged()}; | 362 MachineType::AnyTagged(), kNoWriteBarrier}; |
| 351 | 363 |
| 352 SimplifiedLoweringTester<Object*> t; | 364 SimplifiedLoweringTester<Object*> t; |
| 353 Node* load = t.LoadElement(access, t.PointerConstant(smis), | 365 Node* load = t.LoadElement(access, t.PointerConstant(smis), |
| 354 t.Int32Constant(static_cast<int>(j))); | 366 t.Int32Constant(static_cast<int>(j))); |
| 355 t.Return(load); | 367 t.Return(load); |
| 356 t.LowerAllNodesAndLowerChanges(); | 368 t.LowerAllNodesAndLowerChanges(); |
| 357 | 369 |
| 358 for (int k = -5; k <= 5; k++) { | 370 for (int k = -5; k <= 5; k++) { |
| 359 Smi* expected = Smi::FromInt(k); | 371 Smi* expected = Smi::FromInt(k); |
| 360 smis[i + j] = expected; | 372 smis[i + j] = expected; |
| 361 CHECK_EQ(expected, t.Call()); | 373 CHECK_EQ(expected, t.Call()); |
| 362 } | 374 } |
| 363 } | 375 } |
| 364 } | 376 } |
| 365 } | 377 } |
| 366 | 378 |
| 367 | 379 |
| 368 TEST(RunStoreElementFromUntaggedBase) { | 380 TEST(RunStoreElementFromUntaggedBase) { |
| 369 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), | 381 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), |
| 370 Smi::FromInt(4), Smi::FromInt(5)}; | 382 Smi::FromInt(4), Smi::FromInt(5)}; |
| 371 | 383 |
| 372 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes | 384 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes |
| 373 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index | 385 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index |
| 374 int offset = static_cast<int>(i * sizeof(Smi*)); | 386 int offset = static_cast<int>(i * sizeof(Smi*)); |
| 375 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), | 387 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), |
| 376 MachineType::AnyTagged()}; | 388 MachineType::AnyTagged(), kNoWriteBarrier}; |
| 377 | 389 |
| 378 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged()); | 390 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged()); |
| 379 Node* p0 = t.Parameter(0); | 391 Node* p0 = t.Parameter(0); |
| 380 t.StoreElement(access, t.PointerConstant(smis), | 392 t.StoreElement(access, t.PointerConstant(smis), |
| 381 t.Int32Constant(static_cast<int>(j)), p0); | 393 t.Int32Constant(static_cast<int>(j)), p0); |
| 382 t.Return(p0); | 394 t.Return(p0); |
| 383 t.LowerAllNodesAndLowerChanges(); | 395 t.LowerAllNodesAndLowerChanges(); |
| 384 | 396 |
| 385 for (int k = -5; k <= 5; k++) { | 397 for (int k = -5; k <= 5; k++) { |
| 386 Smi* expected = Smi::FromInt(k); | 398 Smi* expected = Smi::FromInt(k); |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 518 return GetTaggedElement(index); | 530 return GetTaggedElement(index); |
| 519 } else { | 531 } else { |
| 520 return untagged_array[index]; | 532 return untagged_array[index]; |
| 521 } | 533 } |
| 522 } | 534 } |
| 523 | 535 |
| 524 private: | 536 private: |
| 525 ElementAccess GetElementAccess() { | 537 ElementAccess GetElementAccess() { |
| 526 ElementAccess access = {tagged ? kTaggedBase : kUntaggedBase, | 538 ElementAccess access = {tagged ? kTaggedBase : kUntaggedBase, |
| 527 tagged ? FixedArrayBase::kHeaderSize : 0, | 539 tagged ? FixedArrayBase::kHeaderSize : 0, |
| 528 Type::Any(), rep}; | 540 Type::Any(), rep, kFullWriteBarrier}; |
| 529 return access; | 541 return access; |
| 530 } | 542 } |
| 531 | 543 |
| 532 FieldAccess GetFieldAccess(int field) { | 544 FieldAccess GetFieldAccess(int field) { |
| 533 int offset = field * sizeof(E); | 545 int offset = field * sizeof(E); |
| 534 FieldAccess access = {tagged ? kTaggedBase : kUntaggedBase, | 546 FieldAccess access = {tagged ? kTaggedBase : kUntaggedBase, |
| 535 offset + (tagged ? FixedArrayBase::kHeaderSize : 0), | 547 offset + (tagged ? FixedArrayBase::kHeaderSize : 0), |
| 536 Handle<Name>(), Type::Any(), rep}; | 548 Handle<Name>(), |
| 549 Type::Any(), |
| 550 rep, |
| 551 kFullWriteBarrier}; |
| 537 return access; | 552 return access; |
| 538 } | 553 } |
| 539 | 554 |
| 540 template <typename T> | 555 template <typename T> |
| 541 Node* GetBaseNode(SimplifiedLoweringTester<T>* t) { | 556 Node* GetBaseNode(SimplifiedLoweringTester<T>* t) { |
| 542 return tagged ? t->HeapConstant(tagged_array) | 557 return tagged ? t->HeapConstant(tagged_array) |
| 543 : t->PointerConstant(untagged_array); | 558 : t->PointerConstant(untagged_array); |
| 544 } | 559 } |
| 545 | 560 |
| 546 void BoundsCheck(int index) { | 561 void BoundsCheck(int index) { |
| (...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1305 MachineType::Int8(), MachineType::Int16(), MachineType::Int32(), | 1320 MachineType::Int8(), MachineType::Int16(), MachineType::Int32(), |
| 1306 MachineType::Uint32(), MachineType::Int64(), MachineType::Float64(), | 1321 MachineType::Uint32(), MachineType::Int64(), MachineType::Float64(), |
| 1307 MachineType::AnyTagged()}; | 1322 MachineType::AnyTagged()}; |
| 1308 | 1323 |
| 1309 } // namespace | 1324 } // namespace |
| 1310 | 1325 |
| 1311 | 1326 |
| 1312 TEST(LowerLoadField_to_load) { | 1327 TEST(LowerLoadField_to_load) { |
| 1313 for (size_t i = 0; i < arraysize(kMachineReps); i++) { | 1328 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
| 1314 TestingGraph t(Type::Any(), Type::Signed32()); | 1329 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1315 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1330 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1316 Handle<Name>::null(), Type::Any(), kMachineReps[i]}; | 1331 Handle<Name>::null(), Type::Any(), |
| 1332 kMachineReps[i], kNoWriteBarrier}; |
| 1317 | 1333 |
| 1318 Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, | 1334 Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, |
| 1319 t.start, t.start); | 1335 t.start, t.start); |
| 1320 Node* use = t.Use(load, kMachineReps[i]); | 1336 Node* use = t.Use(load, kMachineReps[i]); |
| 1321 t.Return(use); | 1337 t.Return(use); |
| 1322 t.LowerAllNodesAndLowerChanges(); | 1338 t.LowerAllNodesAndLowerChanges(); |
| 1323 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1339 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
| 1324 CHECK_EQ(t.p0, load->InputAt(0)); | 1340 CHECK_EQ(t.p0, load->InputAt(0)); |
| 1325 CheckFieldAccessArithmetic(access, load); | 1341 CheckFieldAccessArithmetic(access, load); |
| 1326 | 1342 |
| 1327 MachineType rep = LoadRepresentationOf(load->op()); | 1343 MachineType rep = LoadRepresentationOf(load->op()); |
| 1328 CHECK_EQ(kMachineReps[i], rep); | 1344 CHECK_EQ(kMachineReps[i], rep); |
| 1329 } | 1345 } |
| 1330 } | 1346 } |
| 1331 | 1347 |
| 1332 | 1348 |
| 1333 TEST(LowerStoreField_to_store) { | 1349 TEST(LowerStoreField_to_store) { |
| 1334 { | 1350 { |
| 1335 TestingGraph t(Type::Any(), Type::Signed32()); | 1351 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1336 | 1352 |
| 1337 for (size_t i = 0; i < arraysize(kMachineReps); i++) { | 1353 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
| 1338 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1354 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1339 Handle<Name>::null(), Type::Any(), kMachineReps[i]}; | 1355 Handle<Name>::null(), Type::Any(), |
| 1340 | 1356 kMachineReps[i], kNoWriteBarrier}; |
| 1341 | 1357 |
| 1342 Node* val = t.ExampleWithOutput(kMachineReps[i]); | 1358 Node* val = t.ExampleWithOutput(kMachineReps[i]); |
| 1343 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, | 1359 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, |
| 1344 val, t.start, t.start); | 1360 val, t.start, t.start); |
| 1345 t.Effect(store); | 1361 t.Effect(store); |
| 1346 t.LowerAllNodesAndLowerChanges(); | 1362 t.LowerAllNodesAndLowerChanges(); |
| 1347 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1363 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
| 1348 CHECK_EQ(val, store->InputAt(2)); | 1364 CHECK_EQ(val, store->InputAt(2)); |
| 1349 CheckFieldAccessArithmetic(access, store); | 1365 CheckFieldAccessArithmetic(access, store); |
| 1350 | 1366 |
| 1351 StoreRepresentation rep = StoreRepresentationOf(store->op()); | 1367 StoreRepresentation rep = StoreRepresentationOf(store->op()); |
| 1352 if (kMachineReps[i].representation() == MachineRepresentation::kTagged) { | 1368 if (kMachineReps[i].representation() == MachineRepresentation::kTagged) { |
| 1353 CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind()); | 1369 CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind()); |
| 1354 } | 1370 } |
| 1355 CHECK_EQ(kMachineReps[i].representation(), rep.representation()); | 1371 CHECK_EQ(kMachineReps[i].representation(), rep.representation()); |
| 1356 } | 1372 } |
| 1357 } | 1373 } |
| 1358 { | 1374 { |
| 1359 HandleAndZoneScope scope; | 1375 HandleAndZoneScope scope; |
| 1360 Zone* z = scope.main_zone(); | 1376 Zone* z = scope.main_zone(); |
| 1361 TestingGraph t(Type::Any(), Type::Intersect(Type::SignedSmall(), | 1377 TestingGraph t(Type::Any(), Type::Intersect(Type::SignedSmall(), |
| 1362 Type::TaggedSigned(), z)); | 1378 Type::TaggedSigned(), z)); |
| 1363 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1379 FieldAccess access = { |
| 1364 Handle<Name>::null(), Type::Any(), | 1380 kTaggedBase, FixedArrayBase::kHeaderSize, Handle<Name>::null(), |
| 1365 MachineType::AnyTagged()}; | 1381 Type::Any(), MachineType::AnyTagged(), kNoWriteBarrier}; |
| 1366 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, | 1382 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, |
| 1367 t.p1, t.start, t.start); | 1383 t.p1, t.start, t.start); |
| 1368 t.Effect(store); | 1384 t.Effect(store); |
| 1369 t.LowerAllNodesAndLowerChanges(); | 1385 t.LowerAllNodesAndLowerChanges(); |
| 1370 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1386 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
| 1371 CHECK_EQ(t.p1, store->InputAt(2)); | 1387 CHECK_EQ(t.p1, store->InputAt(2)); |
| 1372 StoreRepresentation rep = StoreRepresentationOf(store->op()); | 1388 StoreRepresentation rep = StoreRepresentationOf(store->op()); |
| 1373 CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind()); | 1389 CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind()); |
| 1374 } | 1390 } |
| 1375 } | 1391 } |
| 1376 | 1392 |
| 1377 | 1393 |
| 1378 TEST(LowerLoadElement_to_load) { | 1394 TEST(LowerLoadElement_to_load) { |
| 1379 for (size_t i = 0; i < arraysize(kMachineReps); i++) { | 1395 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
| 1380 TestingGraph t(Type::Any(), Type::Signed32()); | 1396 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1381 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1397 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1382 Type::Any(), kMachineReps[i]}; | 1398 Type::Any(), kMachineReps[i], kNoWriteBarrier}; |
| 1383 | 1399 |
| 1384 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, | 1400 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, |
| 1385 t.p1, t.start, t.start); | 1401 t.p1, t.start, t.start); |
| 1386 Node* use = t.Use(load, kMachineReps[i]); | 1402 Node* use = t.Use(load, kMachineReps[i]); |
| 1387 t.Return(use); | 1403 t.Return(use); |
| 1388 t.LowerAllNodesAndLowerChanges(); | 1404 t.LowerAllNodesAndLowerChanges(); |
| 1389 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1405 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
| 1390 CHECK_EQ(t.p0, load->InputAt(0)); | 1406 CHECK_EQ(t.p0, load->InputAt(0)); |
| 1391 CheckElementAccessArithmetic(access, load); | 1407 CheckElementAccessArithmetic(access, load); |
| 1392 | 1408 |
| 1393 MachineType rep = LoadRepresentationOf(load->op()); | 1409 MachineType rep = LoadRepresentationOf(load->op()); |
| 1394 CHECK_EQ(kMachineReps[i], rep); | 1410 CHECK_EQ(kMachineReps[i], rep); |
| 1395 } | 1411 } |
| 1396 } | 1412 } |
| 1397 | 1413 |
| 1398 | 1414 |
| 1399 TEST(LowerStoreElement_to_store) { | 1415 TEST(LowerStoreElement_to_store) { |
| 1400 { | 1416 { |
| 1401 for (size_t i = 0; i < arraysize(kMachineReps); i++) { | 1417 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
| 1402 TestingGraph t(Type::Any(), Type::Signed32()); | 1418 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1403 | 1419 |
| 1404 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1420 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1405 Type::Any(), kMachineReps[i]}; | 1421 Type::Any(), kMachineReps[i], kNoWriteBarrier}; |
| 1406 | 1422 |
| 1407 Node* val = t.ExampleWithOutput(kMachineReps[i]); | 1423 Node* val = t.ExampleWithOutput(kMachineReps[i]); |
| 1408 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), | 1424 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), |
| 1409 t.p0, t.p1, val, t.start, t.start); | 1425 t.p0, t.p1, val, t.start, t.start); |
| 1410 t.Effect(store); | 1426 t.Effect(store); |
| 1411 t.LowerAllNodesAndLowerChanges(); | 1427 t.LowerAllNodesAndLowerChanges(); |
| 1412 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1428 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
| 1413 CHECK_EQ(val, store->InputAt(2)); | 1429 CHECK_EQ(val, store->InputAt(2)); |
| 1414 CheckElementAccessArithmetic(access, store); | 1430 CheckElementAccessArithmetic(access, store); |
| 1415 | 1431 |
| 1416 StoreRepresentation rep = StoreRepresentationOf(store->op()); | 1432 StoreRepresentation rep = StoreRepresentationOf(store->op()); |
| 1417 if (kMachineReps[i].representation() == MachineRepresentation::kTagged) { | 1433 if (kMachineReps[i].representation() == MachineRepresentation::kTagged) { |
| 1418 CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind()); | 1434 CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind()); |
| 1419 } | 1435 } |
| 1420 CHECK_EQ(kMachineReps[i].representation(), rep.representation()); | 1436 CHECK_EQ(kMachineReps[i].representation(), rep.representation()); |
| 1421 } | 1437 } |
| 1422 } | 1438 } |
| 1423 { | 1439 { |
| 1424 HandleAndZoneScope scope; | 1440 HandleAndZoneScope scope; |
| 1425 Zone* z = scope.main_zone(); | 1441 Zone* z = scope.main_zone(); |
| 1426 TestingGraph t( | 1442 TestingGraph t( |
| 1427 Type::Any(), Type::Signed32(), | 1443 Type::Any(), Type::Signed32(), |
| 1428 Type::Intersect(Type::SignedSmall(), Type::TaggedSigned(), z)); | 1444 Type::Intersect(Type::SignedSmall(), Type::TaggedSigned(), z)); |
| 1429 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1445 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1430 Type::Any(), MachineType::AnyTagged()}; | 1446 Type::Any(), MachineType::AnyTagged(), |
| 1447 kNoWriteBarrier}; |
| 1431 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, | 1448 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, |
| 1432 t.p1, t.p2, t.start, t.start); | 1449 t.p1, t.p2, t.start, t.start); |
| 1433 t.Effect(store); | 1450 t.Effect(store); |
| 1434 t.LowerAllNodesAndLowerChanges(); | 1451 t.LowerAllNodesAndLowerChanges(); |
| 1435 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1452 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
| 1436 CHECK_EQ(t.p2, store->InputAt(2)); | 1453 CHECK_EQ(t.p2, store->InputAt(2)); |
| 1437 StoreRepresentation rep = StoreRepresentationOf(store->op()); | 1454 StoreRepresentation rep = StoreRepresentationOf(store->op()); |
| 1438 CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind()); | 1455 CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind()); |
| 1439 } | 1456 } |
| 1440 } | 1457 } |
| 1441 | 1458 |
| 1442 | 1459 |
| 1443 TEST(InsertChangeForLoadElementIndex) { | 1460 TEST(InsertChangeForLoadElementIndex) { |
| 1444 // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length) => | 1461 // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length) => |
| 1445 // Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k)) | 1462 // Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k)) |
| 1446 TestingGraph t(Type::Any(), Type::Signed32()); | 1463 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1447 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | 1464 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), |
| 1448 MachineType::AnyTagged()}; | 1465 MachineType::AnyTagged(), kNoWriteBarrier}; |
| 1449 | 1466 |
| 1450 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, | 1467 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, |
| 1451 t.p1, t.start, t.start); | 1468 t.p1, t.start, t.start); |
| 1452 t.Return(load); | 1469 t.Return(load); |
| 1453 t.Lower(); | 1470 t.Lower(); |
| 1454 CHECK_EQ(IrOpcode::kLoadElement, load->opcode()); | 1471 CHECK_EQ(IrOpcode::kLoadElement, load->opcode()); |
| 1455 CHECK_EQ(t.p0, load->InputAt(0)); | 1472 CHECK_EQ(t.p0, load->InputAt(0)); |
| 1456 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, load->InputAt(1)); | 1473 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, load->InputAt(1)); |
| 1457 } | 1474 } |
| 1458 | 1475 |
| 1459 | 1476 |
| 1460 TEST(InsertChangeForStoreElementIndex) { | 1477 TEST(InsertChangeForStoreElementIndex) { |
| 1461 // StoreElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length, val) => | 1478 // StoreElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length, val) => |
| 1462 // Store(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k), val) | 1479 // Store(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k), val) |
| 1463 TestingGraph t(Type::Any(), Type::Signed32()); | 1480 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1464 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | 1481 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), |
| 1465 MachineType::AnyTagged()}; | 1482 MachineType::AnyTagged(), kFullWriteBarrier}; |
| 1466 | 1483 |
| 1467 Node* store = | 1484 Node* store = |
| 1468 t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, t.p1, | 1485 t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, t.p1, |
| 1469 t.jsgraph.TrueConstant(), t.start, t.start); | 1486 t.jsgraph.TrueConstant(), t.start, t.start); |
| 1470 t.Effect(store); | 1487 t.Effect(store); |
| 1471 t.Lower(); | 1488 t.Lower(); |
| 1472 CHECK_EQ(IrOpcode::kStoreElement, store->opcode()); | 1489 CHECK_EQ(IrOpcode::kStoreElement, store->opcode()); |
| 1473 CHECK_EQ(t.p0, store->InputAt(0)); | 1490 CHECK_EQ(t.p0, store->InputAt(0)); |
| 1474 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, store->InputAt(1)); | 1491 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, store->InputAt(1)); |
| 1475 } | 1492 } |
| 1476 | 1493 |
| 1477 | 1494 |
| 1478 TEST(InsertChangeForLoadElement) { | 1495 TEST(InsertChangeForLoadElement) { |
| 1479 // TODO(titzer): test all load/store representation change insertions. | 1496 // TODO(titzer): test all load/store representation change insertions. |
| 1480 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); | 1497 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); |
| 1481 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | 1498 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), |
| 1482 MachineType::Float64()}; | 1499 MachineType::Float64(), kNoWriteBarrier}; |
| 1483 | 1500 |
| 1484 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, | 1501 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, |
| 1485 t.p1, t.start, t.start); | 1502 t.p1, t.start, t.start); |
| 1486 t.Return(load); | 1503 t.Return(load); |
| 1487 t.Lower(); | 1504 t.Lower(); |
| 1488 CHECK_EQ(IrOpcode::kLoadElement, load->opcode()); | 1505 CHECK_EQ(IrOpcode::kLoadElement, load->opcode()); |
| 1489 CHECK_EQ(t.p0, load->InputAt(0)); | 1506 CHECK_EQ(t.p0, load->InputAt(0)); |
| 1490 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); | 1507 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); |
| 1491 } | 1508 } |
| 1492 | 1509 |
| 1493 | 1510 |
| 1494 TEST(InsertChangeForLoadField) { | 1511 TEST(InsertChangeForLoadField) { |
| 1495 // TODO(titzer): test all load/store representation change insertions. | 1512 // TODO(titzer): test all load/store representation change insertions. |
| 1496 TestingGraph t(Type::Any(), Type::Signed32()); | 1513 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1497 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1514 FieldAccess access = { |
| 1498 Handle<Name>::null(), Type::Any(), | 1515 kTaggedBase, FixedArrayBase::kHeaderSize, Handle<Name>::null(), |
| 1499 MachineType::Float64()}; | 1516 Type::Any(), MachineType::Float64(), kNoWriteBarrier}; |
| 1500 | 1517 |
| 1501 Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, | 1518 Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, |
| 1502 t.start, t.start); | 1519 t.start, t.start); |
| 1503 t.Return(load); | 1520 t.Return(load); |
| 1504 t.Lower(); | 1521 t.Lower(); |
| 1505 CHECK_EQ(IrOpcode::kLoadField, load->opcode()); | 1522 CHECK_EQ(IrOpcode::kLoadField, load->opcode()); |
| 1506 CHECK_EQ(t.p0, load->InputAt(0)); | 1523 CHECK_EQ(t.p0, load->InputAt(0)); |
| 1507 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); | 1524 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); |
| 1508 } | 1525 } |
| 1509 | 1526 |
| 1510 | 1527 |
| 1511 TEST(InsertChangeForStoreElement) { | 1528 TEST(InsertChangeForStoreElement) { |
| 1512 // TODO(titzer): test all load/store representation change insertions. | 1529 // TODO(titzer): test all load/store representation change insertions. |
| 1513 TestingGraph t(Type::Any(), Type::Signed32()); | 1530 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1514 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | 1531 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), |
| 1515 MachineType::Float64()}; | 1532 MachineType::Float64(), kFullWriteBarrier}; |
| 1516 | 1533 |
| 1517 Node* store = | 1534 Node* store = |
| 1518 t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, | 1535 t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, |
| 1519 t.jsgraph.Int32Constant(0), t.p1, t.start, t.start); | 1536 t.jsgraph.Int32Constant(0), t.p1, t.start, t.start); |
| 1520 t.Effect(store); | 1537 t.Effect(store); |
| 1521 t.Lower(); | 1538 t.Lower(); |
| 1522 | 1539 |
| 1523 CHECK_EQ(IrOpcode::kStoreElement, store->opcode()); | 1540 CHECK_EQ(IrOpcode::kStoreElement, store->opcode()); |
| 1524 CHECK_EQ(t.p0, store->InputAt(0)); | 1541 CHECK_EQ(t.p0, store->InputAt(0)); |
| 1525 CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(2)); | 1542 CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(2)); |
| 1526 } | 1543 } |
| 1527 | 1544 |
| 1528 | 1545 |
| 1529 TEST(InsertChangeForStoreField) { | 1546 TEST(InsertChangeForStoreField) { |
| 1530 // TODO(titzer): test all load/store representation change insertions. | 1547 // TODO(titzer): test all load/store representation change insertions. |
| 1531 TestingGraph t(Type::Any(), Type::Signed32()); | 1548 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1532 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1549 FieldAccess access = { |
| 1533 Handle<Name>::null(), Type::Any(), | 1550 kTaggedBase, FixedArrayBase::kHeaderSize, Handle<Name>::null(), |
| 1534 MachineType::Float64()}; | 1551 Type::Any(), MachineType::Float64(), kNoWriteBarrier}; |
| 1535 | 1552 |
| 1536 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, | 1553 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, |
| 1537 t.p1, t.start, t.start); | 1554 t.p1, t.start, t.start); |
| 1538 t.Effect(store); | 1555 t.Effect(store); |
| 1539 t.Lower(); | 1556 t.Lower(); |
| 1540 | 1557 |
| 1541 CHECK_EQ(IrOpcode::kStoreField, store->opcode()); | 1558 CHECK_EQ(IrOpcode::kStoreField, store->opcode()); |
| 1542 CHECK_EQ(t.p0, store->InputAt(0)); | 1559 CHECK_EQ(t.p0, store->InputAt(0)); |
| 1543 CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(1)); | 1560 CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(1)); |
| 1544 } | 1561 } |
| 1545 | 1562 |
| 1546 | 1563 |
| 1547 TEST(UpdatePhi) { | 1564 TEST(UpdatePhi) { |
| 1548 TestingGraph t(Type::Any(), Type::Signed32()); | 1565 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1549 static const MachineType kMachineTypes[] = { | 1566 static const MachineType kMachineTypes[] = { |
| 1550 MachineType::Int32(), MachineType::Uint32(), MachineType::Float64()}; | 1567 MachineType::Int32(), MachineType::Uint32(), MachineType::Float64()}; |
| 1551 Type* kTypes[] = {Type::Signed32(), Type::Unsigned32(), Type::Number()}; | 1568 Type* kTypes[] = {Type::Signed32(), Type::Unsigned32(), Type::Number()}; |
| 1552 | 1569 |
| 1553 for (size_t i = 0; i < arraysize(kMachineTypes); i++) { | 1570 for (size_t i = 0; i < arraysize(kMachineTypes); i++) { |
| 1554 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1571 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1555 Handle<Name>::null(), kTypes[i], kMachineTypes[i]}; | 1572 Handle<Name>::null(), kTypes[i], |
| 1573 kMachineTypes[i], kFullWriteBarrier}; |
| 1556 | 1574 |
| 1557 Node* load0 = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, | 1575 Node* load0 = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, |
| 1558 t.start, t.start); | 1576 t.start, t.start); |
| 1559 Node* load1 = t.graph()->NewNode(t.simplified()->LoadField(access), t.p1, | 1577 Node* load1 = t.graph()->NewNode(t.simplified()->LoadField(access), t.p1, |
| 1560 t.start, t.start); | 1578 t.start, t.start); |
| 1561 Node* phi = | 1579 Node* phi = |
| 1562 t.graph()->NewNode(t.common()->Phi(MachineRepresentation::kTagged, 2), | 1580 t.graph()->NewNode(t.common()->Phi(MachineRepresentation::kTagged, 2), |
| 1563 load0, load1, t.start); | 1581 load0, load1, t.start); |
| 1564 t.Return(t.Use(phi, kMachineTypes[i])); | 1582 t.Return(t.Use(phi, kMachineTypes[i])); |
| 1565 t.Lower(); | 1583 t.Lower(); |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1939 t.Return(use); | 1957 t.Return(use); |
| 1940 t.Lower(); | 1958 t.Lower(); |
| 1941 | 1959 |
| 1942 CHECK_EQ(d.expected, PhiRepresentationOf(phi->op())); | 1960 CHECK_EQ(d.expected, PhiRepresentationOf(phi->op())); |
| 1943 } | 1961 } |
| 1944 } | 1962 } |
| 1945 | 1963 |
| 1946 } // namespace compiler | 1964 } // namespace compiler |
| 1947 } // namespace internal | 1965 } // namespace internal |
| 1948 } // namespace v8 | 1966 } // namespace v8 |
| OLD | NEW |