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/access-builder.h" | 7 #include "src/compiler/access-builder.h" |
8 #include "src/compiler/control-builders.h" | 8 #include "src/compiler/control-builders.h" |
9 #include "src/compiler/generic-node-inl.h" | 9 #include "src/compiler/generic-node-inl.h" |
10 #include "src/compiler/graph-visualizer.h" | 10 #include "src/compiler/graph-visualizer.h" |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 } | 318 } |
319 | 319 |
320 | 320 |
321 TEST(RunLoadElementFromUntaggedBase) { | 321 TEST(RunLoadElementFromUntaggedBase) { |
322 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), | 322 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), |
323 Smi::FromInt(4), Smi::FromInt(5)}; | 323 Smi::FromInt(4), Smi::FromInt(5)}; |
324 | 324 |
325 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes | 325 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes |
326 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index | 326 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index |
327 int offset = static_cast<int>(i * sizeof(Smi*)); | 327 int offset = static_cast<int>(i * sizeof(Smi*)); |
328 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), | 328 ElementAccess access = {kNoBoundsCheck, kUntaggedBase, offset, |
329 kMachAnyTagged}; | 329 Type::Integral32(), kMachAnyTagged}; |
330 | 330 |
331 SimplifiedLoweringTester<Object*> t; | 331 SimplifiedLoweringTester<Object*> t; |
332 Node* load = t.LoadElement( | 332 Node* load = t.LoadElement( |
333 access, t.PointerConstant(smis), t.Int32Constant(static_cast<int>(j)), | 333 access, t.PointerConstant(smis), t.Int32Constant(static_cast<int>(j)), |
334 t.Int32Constant(static_cast<int>(arraysize(smis)))); | 334 t.Int32Constant(static_cast<int>(arraysize(smis)))); |
335 t.Return(load); | 335 t.Return(load); |
336 t.LowerAllNodes(); | 336 t.LowerAllNodes(); |
337 | 337 |
338 if (!Pipeline::SupportedTarget()) continue; | 338 if (!Pipeline::SupportedTarget()) continue; |
339 | 339 |
340 for (int k = -5; k <= 5; k++) { | 340 for (int k = -5; k <= 5; k++) { |
341 Smi* expected = Smi::FromInt(k); | 341 Smi* expected = Smi::FromInt(k); |
342 smis[i + j] = expected; | 342 smis[i + j] = expected; |
343 CHECK_EQ(expected, t.Call()); | 343 CHECK_EQ(expected, t.Call()); |
344 } | 344 } |
345 } | 345 } |
346 } | 346 } |
347 } | 347 } |
348 | 348 |
349 | 349 |
350 TEST(RunStoreElementFromUntaggedBase) { | 350 TEST(RunStoreElementFromUntaggedBase) { |
351 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), | 351 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), |
352 Smi::FromInt(4), Smi::FromInt(5)}; | 352 Smi::FromInt(4), Smi::FromInt(5)}; |
353 | 353 |
354 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes | 354 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes |
355 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index | 355 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index |
356 int offset = static_cast<int>(i * sizeof(Smi*)); | 356 int offset = static_cast<int>(i * sizeof(Smi*)); |
357 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), | 357 ElementAccess access = {kNoBoundsCheck, kUntaggedBase, offset, |
358 kMachAnyTagged}; | 358 Type::Integral32(), kMachAnyTagged}; |
359 | 359 |
360 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 360 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
361 Node* p0 = t.Parameter(0); | 361 Node* p0 = t.Parameter(0); |
362 t.StoreElement(access, t.PointerConstant(smis), | 362 t.StoreElement(access, t.PointerConstant(smis), |
363 t.Int32Constant(static_cast<int>(j)), | 363 t.Int32Constant(static_cast<int>(j)), |
364 t.Int32Constant(static_cast<int>(arraysize(smis))), p0); | 364 t.Int32Constant(static_cast<int>(arraysize(smis))), p0); |
365 t.Return(p0); | 365 t.Return(p0); |
366 t.LowerAllNodes(); | 366 t.LowerAllNodes(); |
367 | 367 |
368 if (!Pipeline::SupportedTarget()) continue; | 368 if (!Pipeline::SupportedTarget()) continue; |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 if (tagged) { | 510 if (tagged) { |
511 E* raw = reinterpret_cast<E*>(tagged_array->GetDataStartAddress()); | 511 E* raw = reinterpret_cast<E*>(tagged_array->GetDataStartAddress()); |
512 return raw[index]; | 512 return raw[index]; |
513 } else { | 513 } else { |
514 return untagged_array[index]; | 514 return untagged_array[index]; |
515 } | 515 } |
516 } | 516 } |
517 | 517 |
518 private: | 518 private: |
519 ElementAccess GetElementAccess() { | 519 ElementAccess GetElementAccess() { |
520 ElementAccess access = {tagged ? kTaggedBase : kUntaggedBase, | 520 ElementAccess access = { |
521 tagged ? FixedArrayBase::kHeaderSize : 0, | 521 kNoBoundsCheck, tagged ? kTaggedBase : kUntaggedBase, |
522 Type::Any(), rep}; | 522 tagged ? FixedArrayBase::kHeaderSize : 0, Type::Any(), rep}; |
523 return access; | 523 return access; |
524 } | 524 } |
525 | 525 |
526 FieldAccess GetFieldAccess(int field) { | 526 FieldAccess GetFieldAccess(int field) { |
527 int offset = field * sizeof(E); | 527 int offset = field * sizeof(E); |
528 FieldAccess access = {tagged ? kTaggedBase : kUntaggedBase, | 528 FieldAccess access = {tagged ? kTaggedBase : kUntaggedBase, |
529 offset + (tagged ? FixedArrayBase::kHeaderSize : 0), | 529 offset + (tagged ? FixedArrayBase::kHeaderSize : 0), |
530 Handle<Name>(), Type::Any(), rep}; | 530 Handle<Name>(), Type::Any(), rep}; |
531 return access; | 531 return access; |
532 } | 532 } |
(...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1342 } | 1342 } |
1343 CHECK_EQ(machine_reps[i], rep.machine_type()); | 1343 CHECK_EQ(machine_reps[i], rep.machine_type()); |
1344 } | 1344 } |
1345 } | 1345 } |
1346 | 1346 |
1347 | 1347 |
1348 TEST(LowerLoadElement_to_load) { | 1348 TEST(LowerLoadElement_to_load) { |
1349 TestingGraph t(Type::Any(), Type::Signed32()); | 1349 TestingGraph t(Type::Any(), Type::Signed32()); |
1350 | 1350 |
1351 for (size_t i = 0; i < arraysize(machine_reps); i++) { | 1351 for (size_t i = 0; i < arraysize(machine_reps); i++) { |
1352 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1352 ElementAccess access = {kNoBoundsCheck, kTaggedBase, |
1353 Type::Any(), machine_reps[i]}; | 1353 FixedArrayBase::kHeaderSize, Type::Any(), |
| 1354 machine_reps[i]}; |
1354 | 1355 |
1355 Node* load = | 1356 Node* load = |
1356 t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, t.p1, | 1357 t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, t.p1, |
1357 t.jsgraph.Int32Constant(1024), t.start); | 1358 t.jsgraph.Int32Constant(1024), t.start); |
1358 Node* use = t.Use(load, machine_reps[i]); | 1359 Node* use = t.Use(load, machine_reps[i]); |
1359 t.Return(use); | 1360 t.Return(use); |
1360 t.Lower(); | 1361 t.Lower(); |
1361 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1362 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
1362 CHECK_EQ(t.p0, load->InputAt(0)); | 1363 CHECK_EQ(t.p0, load->InputAt(0)); |
1363 CheckElementAccessArithmetic(access, load); | 1364 CheckElementAccessArithmetic(access, load); |
1364 | 1365 |
1365 MachineType rep = OpParameter<MachineType>(load); | 1366 MachineType rep = OpParameter<MachineType>(load); |
1366 CHECK_EQ(machine_reps[i], rep); | 1367 CHECK_EQ(machine_reps[i], rep); |
1367 } | 1368 } |
1368 } | 1369 } |
1369 | 1370 |
1370 | 1371 |
1371 TEST(LowerStoreElement_to_store) { | 1372 TEST(LowerStoreElement_to_store) { |
1372 TestingGraph t(Type::Any(), Type::Signed32()); | 1373 TestingGraph t(Type::Any(), Type::Signed32()); |
1373 | 1374 |
1374 for (size_t i = 0; i < arraysize(machine_reps); i++) { | 1375 for (size_t i = 0; i < arraysize(machine_reps); i++) { |
1375 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1376 ElementAccess access = {kNoBoundsCheck, kTaggedBase, |
1376 Type::Any(), machine_reps[i]}; | 1377 FixedArrayBase::kHeaderSize, Type::Any(), |
| 1378 machine_reps[i]}; |
1377 | 1379 |
1378 Node* val = t.ExampleWithOutput(machine_reps[i]); | 1380 Node* val = t.ExampleWithOutput(machine_reps[i]); |
1379 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, | 1381 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, |
1380 t.p1, t.jsgraph.Int32Constant(1024), val, | 1382 t.p1, t.jsgraph.Int32Constant(1024), val, |
1381 t.start, t.start); | 1383 t.start, t.start); |
1382 t.Effect(store); | 1384 t.Effect(store); |
1383 t.Lower(); | 1385 t.Lower(); |
1384 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1386 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
1385 CHECK_EQ(val, store->InputAt(2)); | 1387 CHECK_EQ(val, store->InputAt(2)); |
1386 CheckElementAccessArithmetic(access, store); | 1388 CheckElementAccessArithmetic(access, store); |
1387 | 1389 |
1388 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); | 1390 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); |
1389 if (machine_reps[i] & kRepTagged) { | 1391 if (machine_reps[i] & kRepTagged) { |
1390 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); | 1392 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); |
1391 } | 1393 } |
1392 CHECK_EQ(machine_reps[i], rep.machine_type()); | 1394 CHECK_EQ(machine_reps[i], rep.machine_type()); |
1393 } | 1395 } |
1394 } | 1396 } |
1395 | 1397 |
1396 | 1398 |
1397 TEST(InsertChangeForLoadElementIndex) { | 1399 TEST(InsertChangeForLoadElementIndex) { |
1398 // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length) => | 1400 // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length) => |
1399 // Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k)) | 1401 // Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k)) |
1400 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); | 1402 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); |
1401 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | 1403 ElementAccess access = {kNoBoundsCheck, kTaggedBase, |
| 1404 FixedArrayBase::kHeaderSize, Type::Any(), |
1402 kMachAnyTagged}; | 1405 kMachAnyTagged}; |
1403 | 1406 |
1404 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, | 1407 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, |
1405 t.p1, t.p2, t.start); | 1408 t.p1, t.p2, t.start); |
1406 t.Return(load); | 1409 t.Return(load); |
1407 t.Lower(); | 1410 t.Lower(); |
1408 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1411 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
1409 CHECK_EQ(t.p0, load->InputAt(0)); | 1412 CHECK_EQ(t.p0, load->InputAt(0)); |
1410 | 1413 |
1411 Node* index = CheckElementAccessArithmetic(access, load); | 1414 Node* index = CheckElementAccessArithmetic(access, load); |
1412 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, index); | 1415 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, index); |
1413 } | 1416 } |
1414 | 1417 |
1415 | 1418 |
1416 TEST(InsertChangeForStoreElementIndex) { | 1419 TEST(InsertChangeForStoreElementIndex) { |
1417 // StoreElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length, val) => | 1420 // StoreElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length, val) => |
1418 // Store(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k), val) | 1421 // Store(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k), val) |
1419 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); | 1422 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); |
1420 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | 1423 ElementAccess access = {kNoBoundsCheck, kTaggedBase, |
| 1424 FixedArrayBase::kHeaderSize, Type::Any(), |
1421 kMachAnyTagged}; | 1425 kMachAnyTagged}; |
1422 | 1426 |
1423 Node* store = | 1427 Node* store = |
1424 t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, t.p1, t.p2, | 1428 t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, t.p1, t.p2, |
1425 t.jsgraph.TrueConstant(), t.start, t.start); | 1429 t.jsgraph.TrueConstant(), t.start, t.start); |
1426 t.Effect(store); | 1430 t.Effect(store); |
1427 t.Lower(); | 1431 t.Lower(); |
1428 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1432 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
1429 CHECK_EQ(t.p0, store->InputAt(0)); | 1433 CHECK_EQ(t.p0, store->InputAt(0)); |
1430 | 1434 |
1431 Node* index = CheckElementAccessArithmetic(access, store); | 1435 Node* index = CheckElementAccessArithmetic(access, store); |
1432 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, index); | 1436 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, index); |
1433 } | 1437 } |
1434 | 1438 |
1435 | 1439 |
1436 TEST(InsertChangeForLoadElement) { | 1440 TEST(InsertChangeForLoadElement) { |
1437 // TODO(titzer): test all load/store representation change insertions. | 1441 // TODO(titzer): test all load/store representation change insertions. |
1438 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); | 1442 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); |
1439 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | 1443 ElementAccess access = {kNoBoundsCheck, kTaggedBase, |
| 1444 FixedArrayBase::kHeaderSize, Type::Any(), |
1440 kMachFloat64}; | 1445 kMachFloat64}; |
1441 | 1446 |
1442 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, | 1447 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, |
1443 t.p1, t.p1, t.start); | 1448 t.p1, t.p1, t.start); |
1444 t.Return(load); | 1449 t.Return(load); |
1445 t.Lower(); | 1450 t.Lower(); |
1446 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1451 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
1447 CHECK_EQ(t.p0, load->InputAt(0)); | 1452 CHECK_EQ(t.p0, load->InputAt(0)); |
1448 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); | 1453 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); |
1449 } | 1454 } |
(...skipping 11 matching lines...) Expand all Loading... |
1461 t.Lower(); | 1466 t.Lower(); |
1462 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1467 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
1463 CHECK_EQ(t.p0, load->InputAt(0)); | 1468 CHECK_EQ(t.p0, load->InputAt(0)); |
1464 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); | 1469 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); |
1465 } | 1470 } |
1466 | 1471 |
1467 | 1472 |
1468 TEST(InsertChangeForStoreElement) { | 1473 TEST(InsertChangeForStoreElement) { |
1469 // TODO(titzer): test all load/store representation change insertions. | 1474 // TODO(titzer): test all load/store representation change insertions. |
1470 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); | 1475 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); |
1471 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | 1476 ElementAccess access = {kNoBoundsCheck, kTaggedBase, |
| 1477 FixedArrayBase::kHeaderSize, Type::Any(), |
1472 kMachFloat64}; | 1478 kMachFloat64}; |
1473 | 1479 |
1474 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, | 1480 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, |
1475 t.jsgraph.Int32Constant(0), t.p2, t.p1, | 1481 t.jsgraph.Int32Constant(0), t.p2, t.p1, |
1476 t.start, t.start); | 1482 t.start, t.start); |
1477 t.Effect(store); | 1483 t.Effect(store); |
1478 t.Lower(); | 1484 t.Lower(); |
1479 | 1485 |
1480 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1486 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
1481 CHECK_EQ(t.p0, store->InputAt(0)); | 1487 CHECK_EQ(t.p0, store->InputAt(0)); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1516 Node* phi = t.graph()->NewNode(t.common()->Phi(kMachAnyTagged, 2), load0, | 1522 Node* phi = t.graph()->NewNode(t.common()->Phi(kMachAnyTagged, 2), load0, |
1517 load1, t.start); | 1523 load1, t.start); |
1518 t.Return(t.Use(phi, kMachineTypes[i])); | 1524 t.Return(t.Use(phi, kMachineTypes[i])); |
1519 t.Lower(); | 1525 t.Lower(); |
1520 | 1526 |
1521 CHECK_EQ(IrOpcode::kPhi, phi->opcode()); | 1527 CHECK_EQ(IrOpcode::kPhi, phi->opcode()); |
1522 CHECK_EQ(RepresentationOf(kMachineTypes[i]), | 1528 CHECK_EQ(RepresentationOf(kMachineTypes[i]), |
1523 RepresentationOf(OpParameter<MachineType>(phi))); | 1529 RepresentationOf(OpParameter<MachineType>(phi))); |
1524 } | 1530 } |
1525 } | 1531 } |
OLD | NEW |