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/change-lowering.h" | 8 #include "src/compiler/change-lowering.h" |
9 #include "src/compiler/control-builders.h" | 9 #include "src/compiler/control-builders.h" |
10 #include "src/compiler/generic-node-inl.h" | 10 #include "src/compiler/generic-node-inl.h" |
(...skipping 1306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1317 t.machine()->Float64LessThan(), | 1317 t.machine()->Float64LessThan(), |
1318 t.machine()->Float64LessThanOrEqual()}; | 1318 t.machine()->Float64LessThanOrEqual()}; |
1319 | 1319 |
1320 for (size_t i = 0; i < arraysize(ops); i++) { | 1320 for (size_t i = 0; i < arraysize(ops); i++) { |
1321 CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToFloat64, | 1321 CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToFloat64, |
1322 IrOpcode::kChangeBitToBool); | 1322 IrOpcode::kChangeBitToBool); |
1323 } | 1323 } |
1324 } | 1324 } |
1325 | 1325 |
1326 | 1326 |
| 1327 namespace { |
| 1328 |
1327 void CheckFieldAccessArithmetic(FieldAccess access, Node* load_or_store) { | 1329 void CheckFieldAccessArithmetic(FieldAccess access, Node* load_or_store) { |
1328 Int32Matcher index = Int32Matcher(load_or_store->InputAt(1)); | 1330 IntPtrMatcher mindex(load_or_store->InputAt(1)); |
1329 CHECK(index.Is(access.offset - access.tag())); | 1331 CHECK(mindex.Is(access.offset - access.tag())); |
1330 } | 1332 } |
1331 | 1333 |
1332 | 1334 |
1333 Node* CheckElementAccessArithmetic(ElementAccess access, Node* load_or_store) { | 1335 Node* CheckElementAccessArithmetic(ElementAccess access, Node* load_or_store) { |
1334 Int32BinopMatcher index(load_or_store->InputAt(1)); | 1336 Node* index = load_or_store->InputAt(1); |
1335 CHECK_EQ(IrOpcode::kInt32Add, index.node()->opcode()); | 1337 if (kPointerSize == 8) { |
1336 CHECK(index.right().Is(access.header_size - access.tag())); | 1338 CHECK_EQ(IrOpcode::kChangeUint32ToUint64, index->opcode()); |
| 1339 index = index->InputAt(0); |
| 1340 } |
1337 | 1341 |
1338 int element_size = ElementSizeOf(access.machine_type); | 1342 Int32BinopMatcher mindex(index); |
| 1343 CHECK_EQ(IrOpcode::kInt32Add, mindex.node()->opcode()); |
| 1344 CHECK(mindex.right().Is(access.header_size - access.tag())); |
1339 | 1345 |
1340 if (element_size != 1) { | 1346 const int element_size_shift = ElementSizeLog2Of(access.machine_type); |
1341 Int32BinopMatcher mul(index.left().node()); | 1347 if (element_size_shift) { |
1342 CHECK_EQ(IrOpcode::kInt32Mul, mul.node()->opcode()); | 1348 Int32BinopMatcher shl(mindex.left().node()); |
1343 CHECK(mul.right().Is(element_size)); | 1349 CHECK_EQ(IrOpcode::kWord32Shl, shl.node()->opcode()); |
1344 return mul.left().node(); | 1350 CHECK(shl.right().Is(element_size_shift)); |
| 1351 return shl.left().node(); |
1345 } else { | 1352 } else { |
1346 return index.left().node(); | 1353 return mindex.left().node(); |
1347 } | 1354 } |
1348 } | 1355 } |
1349 | 1356 |
1350 | 1357 |
1351 static const MachineType machine_reps[] = { | 1358 const MachineType kMachineReps[] = {kRepBit, kMachInt8, kMachInt16, |
1352 kRepBit, kMachInt8, kMachInt16, kMachInt32, | 1359 kMachInt32, kMachInt64, kMachFloat64, |
1353 kMachInt64, kMachFloat64, kMachAnyTagged}; | 1360 kMachAnyTagged}; |
| 1361 |
| 1362 } // namespace |
1354 | 1363 |
1355 | 1364 |
1356 TEST(LowerLoadField_to_load) { | 1365 TEST(LowerLoadField_to_load) { |
1357 TestingGraph t(Type::Any(), Type::Signed32()); | 1366 TestingGraph t(Type::Any(), Type::Signed32()); |
1358 | 1367 |
1359 for (size_t i = 0; i < arraysize(machine_reps); i++) { | 1368 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
1360 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1369 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
1361 Handle<Name>::null(), Type::Any(), machine_reps[i]}; | 1370 Handle<Name>::null(), Type::Any(), kMachineReps[i]}; |
1362 | 1371 |
1363 Node* load = | 1372 Node* load = |
1364 t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, t.start); | 1373 t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, t.start); |
1365 Node* use = t.Use(load, machine_reps[i]); | 1374 Node* use = t.Use(load, kMachineReps[i]); |
1366 t.Return(use); | 1375 t.Return(use); |
1367 t.Lower(); | 1376 t.Lower(); |
1368 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1377 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
1369 CHECK_EQ(t.p0, load->InputAt(0)); | 1378 CHECK_EQ(t.p0, load->InputAt(0)); |
1370 CheckFieldAccessArithmetic(access, load); | 1379 CheckFieldAccessArithmetic(access, load); |
1371 | 1380 |
1372 MachineType rep = OpParameter<MachineType>(load); | 1381 MachineType rep = OpParameter<MachineType>(load); |
1373 CHECK_EQ(machine_reps[i], rep); | 1382 CHECK_EQ(kMachineReps[i], rep); |
1374 } | 1383 } |
1375 } | 1384 } |
1376 | 1385 |
1377 | 1386 |
1378 TEST(LowerStoreField_to_store) { | 1387 TEST(LowerStoreField_to_store) { |
1379 TestingGraph t(Type::Any(), Type::Signed32()); | 1388 TestingGraph t(Type::Any(), Type::Signed32()); |
1380 | 1389 |
1381 for (size_t i = 0; i < arraysize(machine_reps); i++) { | 1390 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
1382 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1391 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
1383 Handle<Name>::null(), Type::Any(), machine_reps[i]}; | 1392 Handle<Name>::null(), Type::Any(), kMachineReps[i]}; |
1384 | 1393 |
1385 | 1394 |
1386 Node* val = t.ExampleWithOutput(machine_reps[i]); | 1395 Node* val = t.ExampleWithOutput(kMachineReps[i]); |
1387 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, | 1396 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, |
1388 val, t.start, t.start); | 1397 val, t.start, t.start); |
1389 t.Effect(store); | 1398 t.Effect(store); |
1390 t.Lower(); | 1399 t.Lower(); |
1391 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1400 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
1392 CHECK_EQ(val, store->InputAt(2)); | 1401 CHECK_EQ(val, store->InputAt(2)); |
1393 CheckFieldAccessArithmetic(access, store); | 1402 CheckFieldAccessArithmetic(access, store); |
1394 | 1403 |
1395 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); | 1404 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); |
1396 if (machine_reps[i] & kRepTagged) { | 1405 if (kMachineReps[i] & kRepTagged) { |
1397 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); | 1406 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); |
1398 } | 1407 } |
1399 CHECK_EQ(machine_reps[i], rep.machine_type()); | 1408 CHECK_EQ(kMachineReps[i], rep.machine_type()); |
1400 } | 1409 } |
1401 } | 1410 } |
1402 | 1411 |
1403 | 1412 |
1404 TEST(LowerLoadElement_to_load) { | 1413 TEST(LowerLoadElement_to_load) { |
1405 TestingGraph t(Type::Any(), Type::Signed32()); | 1414 TestingGraph t(Type::Any(), Type::Signed32()); |
1406 | 1415 |
1407 for (size_t i = 0; i < arraysize(machine_reps); i++) { | 1416 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
1408 ElementAccess access = {kNoBoundsCheck, kTaggedBase, | 1417 ElementAccess access = {kNoBoundsCheck, kTaggedBase, |
1409 FixedArrayBase::kHeaderSize, Type::Any(), | 1418 FixedArrayBase::kHeaderSize, Type::Any(), |
1410 machine_reps[i]}; | 1419 kMachineReps[i]}; |
1411 | 1420 |
1412 Node* load = | 1421 Node* load = |
1413 t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, t.p1, | 1422 t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, t.p1, |
1414 t.jsgraph.Int32Constant(1024), t.start, t.start); | 1423 t.jsgraph.Int32Constant(1024), t.start, t.start); |
1415 Node* use = t.Use(load, machine_reps[i]); | 1424 Node* use = t.Use(load, kMachineReps[i]); |
1416 t.Return(use); | 1425 t.Return(use); |
1417 t.Lower(); | 1426 t.Lower(); |
1418 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1427 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
1419 CHECK_EQ(t.p0, load->InputAt(0)); | 1428 CHECK_EQ(t.p0, load->InputAt(0)); |
1420 CheckElementAccessArithmetic(access, load); | 1429 CheckElementAccessArithmetic(access, load); |
1421 | 1430 |
1422 MachineType rep = OpParameter<MachineType>(load); | 1431 MachineType rep = OpParameter<MachineType>(load); |
1423 CHECK_EQ(machine_reps[i], rep); | 1432 CHECK_EQ(kMachineReps[i], rep); |
1424 } | 1433 } |
1425 } | 1434 } |
1426 | 1435 |
1427 | 1436 |
1428 TEST(LowerStoreElement_to_store) { | 1437 TEST(LowerStoreElement_to_store) { |
1429 TestingGraph t(Type::Any(), Type::Signed32()); | 1438 TestingGraph t(Type::Any(), Type::Signed32()); |
1430 | 1439 |
1431 for (size_t i = 0; i < arraysize(machine_reps); i++) { | 1440 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
1432 ElementAccess access = {kNoBoundsCheck, kTaggedBase, | 1441 ElementAccess access = {kNoBoundsCheck, kTaggedBase, |
1433 FixedArrayBase::kHeaderSize, Type::Any(), | 1442 FixedArrayBase::kHeaderSize, Type::Any(), |
1434 machine_reps[i]}; | 1443 kMachineReps[i]}; |
1435 | 1444 |
1436 Node* val = t.ExampleWithOutput(machine_reps[i]); | 1445 Node* val = t.ExampleWithOutput(kMachineReps[i]); |
1437 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, | 1446 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, |
1438 t.p1, t.jsgraph.Int32Constant(1024), val, | 1447 t.p1, t.jsgraph.Int32Constant(1024), val, |
1439 t.start, t.start); | 1448 t.start, t.start); |
1440 t.Effect(store); | 1449 t.Effect(store); |
1441 t.Lower(); | 1450 t.Lower(); |
1442 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1451 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
1443 CHECK_EQ(val, store->InputAt(2)); | 1452 CHECK_EQ(val, store->InputAt(2)); |
1444 CheckElementAccessArithmetic(access, store); | 1453 CheckElementAccessArithmetic(access, store); |
1445 | 1454 |
1446 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); | 1455 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); |
1447 if (machine_reps[i] & kRepTagged) { | 1456 if (kMachineReps[i] & kRepTagged) { |
1448 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); | 1457 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); |
1449 } | 1458 } |
1450 CHECK_EQ(machine_reps[i], rep.machine_type()); | 1459 CHECK_EQ(kMachineReps[i], rep.machine_type()); |
1451 } | 1460 } |
1452 } | 1461 } |
1453 | 1462 |
1454 | 1463 |
1455 TEST(InsertChangeForLoadElementIndex) { | 1464 TEST(InsertChangeForLoadElementIndex) { |
1456 // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length) => | 1465 // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length) => |
1457 // Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k)) | 1466 // Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k)) |
1458 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); | 1467 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); |
1459 ElementAccess access = {kNoBoundsCheck, kTaggedBase, | 1468 ElementAccess access = {kNoBoundsCheck, kTaggedBase, |
1460 FixedArrayBase::kHeaderSize, Type::Any(), | 1469 FixedArrayBase::kHeaderSize, Type::Any(), |
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1920 for (size_t i = 0; i < arraysize(constants); i++) { | 1929 for (size_t i = 0; i < arraysize(constants); i++) { |
1921 TestingGraph t(Type::Signed32()); | 1930 TestingGraph t(Type::Signed32()); |
1922 Node* k = t.jsgraph.Constant(constants[i]); | 1931 Node* k = t.jsgraph.Constant(constants[i]); |
1923 Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); | 1932 Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); |
1924 t.Return(mod); | 1933 t.Return(mod); |
1925 t.Lower(); | 1934 t.Lower(); |
1926 | 1935 |
1927 CHECK_EQ(IrOpcode::kFloat64Mod, mod->opcode()); // Pesky -0 behavior. | 1936 CHECK_EQ(IrOpcode::kFloat64Mod, mod->opcode()); // Pesky -0 behavior. |
1928 } | 1937 } |
1929 } | 1938 } |
OLD | NEW |