| 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 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 CHECK(result->IsMap()); | 226 CHECK(result->IsMap()); |
| 227 CHECK_EQ(*src_map, result); | 227 CHECK_EQ(*src_map, result); |
| 228 CHECK(*src_map == dst->map()); | 228 CHECK(*src_map == dst->map()); |
| 229 } | 229 } |
| 230 } | 230 } |
| 231 | 231 |
| 232 | 232 |
| 233 TEST(RunLoadStoreFixedArrayIndex) { | 233 TEST(RunLoadStoreFixedArrayIndex) { |
| 234 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 234 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 235 ElementAccess access = AccessBuilder::ForFixedArrayElement(); | 235 ElementAccess access = AccessBuilder::ForFixedArrayElement(); |
| 236 Node* load = t.LoadElement(access, t.Parameter(0), t.Int32Constant(0), | 236 Node* load = t.LoadElement(access, t.Parameter(0), t.Int32Constant(0)); |
| 237 t.Int32Constant(2)); | 237 t.StoreElement(access, t.Parameter(0), t.Int32Constant(1), load); |
| 238 t.StoreElement(access, t.Parameter(0), t.Int32Constant(1), t.Int32Constant(2), | |
| 239 load); | |
| 240 t.Return(load); | 238 t.Return(load); |
| 241 | 239 |
| 242 t.LowerAllNodes(); | 240 t.LowerAllNodes(); |
| 243 t.GenerateCode(); | 241 t.GenerateCode(); |
| 244 | 242 |
| 245 if (Pipeline::SupportedTarget()) { | 243 if (Pipeline::SupportedTarget()) { |
| 246 Handle<FixedArray> array = t.factory()->NewFixedArray(2); | 244 Handle<FixedArray> array = t.factory()->NewFixedArray(2); |
| 247 Handle<JSObject> src = TestObject(); | 245 Handle<JSObject> src = TestObject(); |
| 248 Handle<JSObject> dst = TestObject(); | 246 Handle<JSObject> dst = TestObject(); |
| 249 array->set(0, *src); | 247 array->set(0, *src); |
| 250 array->set(1, *dst); | 248 array->set(1, *dst); |
| 251 Object* result = t.Call(*array); | 249 Object* result = t.Call(*array); |
| 252 CHECK_EQ(*src, result); | 250 CHECK_EQ(*src, result); |
| 253 CHECK_EQ(*src, array->get(0)); | 251 CHECK_EQ(*src, array->get(0)); |
| 254 CHECK_EQ(*src, array->get(1)); | 252 CHECK_EQ(*src, array->get(1)); |
| 255 } | 253 } |
| 256 } | 254 } |
| 257 | 255 |
| 258 | 256 |
| 259 TEST(RunLoadStoreArrayBuffer) { | 257 TEST(RunLoadStoreArrayBuffer) { |
| 260 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 258 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 261 const int index = 12; | 259 const int index = 12; |
| 262 const int array_length = 2 * index; | 260 const int array_length = 2 * index; |
| 263 ElementAccess buffer_access = | 261 ElementAccess buffer_access = |
| 264 AccessBuilder::ForTypedArrayElement(v8::kExternalInt8Array, true); | 262 AccessBuilder::ForTypedArrayElement(v8::kExternalInt8Array, true); |
| 265 Node* backing_store = t.LoadField( | 263 Node* backing_store = t.LoadField( |
| 266 AccessBuilder::ForJSArrayBufferBackingStore(), t.Parameter(0)); | 264 AccessBuilder::ForJSArrayBufferBackingStore(), t.Parameter(0)); |
| 267 Node* load = | 265 Node* load = |
| 268 t.LoadElement(buffer_access, backing_store, t.Int32Constant(index), | 266 t.LoadElement(buffer_access, backing_store, t.Int32Constant(index)); |
| 269 t.Int32Constant(array_length)); | |
| 270 t.StoreElement(buffer_access, backing_store, t.Int32Constant(index + 1), | 267 t.StoreElement(buffer_access, backing_store, t.Int32Constant(index + 1), |
| 271 t.Int32Constant(array_length), load); | 268 load); |
| 272 t.Return(t.jsgraph.TrueConstant()); | 269 t.Return(t.jsgraph.TrueConstant()); |
| 273 | 270 |
| 274 t.LowerAllNodes(); | 271 t.LowerAllNodes(); |
| 275 t.GenerateCode(); | 272 t.GenerateCode(); |
| 276 | 273 |
| 277 if (Pipeline::SupportedTarget()) { | 274 if (Pipeline::SupportedTarget()) { |
| 278 Handle<JSArrayBuffer> array = t.factory()->NewJSArrayBuffer(); | 275 Handle<JSArrayBuffer> array = t.factory()->NewJSArrayBuffer(); |
| 279 Runtime::SetupArrayBufferAllocatingData(t.isolate(), array, array_length); | 276 Runtime::SetupArrayBufferAllocatingData(t.isolate(), array, array_length); |
| 280 uint8_t* data = reinterpret_cast<uint8_t*>(array->backing_store()); | 277 uint8_t* data = reinterpret_cast<uint8_t*>(array->backing_store()); |
| 281 for (int i = 0; i < array_length; i++) { | 278 for (int i = 0; i < array_length; i++) { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 } | 341 } |
| 345 | 342 |
| 346 | 343 |
| 347 TEST(RunLoadElementFromUntaggedBase) { | 344 TEST(RunLoadElementFromUntaggedBase) { |
| 348 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), | 345 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), |
| 349 Smi::FromInt(4), Smi::FromInt(5)}; | 346 Smi::FromInt(4), Smi::FromInt(5)}; |
| 350 | 347 |
| 351 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes | 348 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes |
| 352 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index | 349 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index |
| 353 int offset = static_cast<int>(i * sizeof(Smi*)); | 350 int offset = static_cast<int>(i * sizeof(Smi*)); |
| 354 ElementAccess access = {kNoBoundsCheck, kUntaggedBase, offset, | 351 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), |
| 355 Type::Integral32(), kMachAnyTagged}; | 352 kMachAnyTagged}; |
| 356 | 353 |
| 357 SimplifiedLoweringTester<Object*> t; | 354 SimplifiedLoweringTester<Object*> t; |
| 358 Node* load = t.LoadElement( | 355 Node* load = t.LoadElement(access, t.PointerConstant(smis), |
| 359 access, t.PointerConstant(smis), t.Int32Constant(static_cast<int>(j)), | 356 t.Int32Constant(static_cast<int>(j))); |
| 360 t.Int32Constant(static_cast<int>(arraysize(smis)))); | |
| 361 t.Return(load); | 357 t.Return(load); |
| 362 t.LowerAllNodes(); | 358 t.LowerAllNodes(); |
| 363 | 359 |
| 364 if (!Pipeline::SupportedTarget()) continue; | 360 if (!Pipeline::SupportedTarget()) continue; |
| 365 | 361 |
| 366 for (int k = -5; k <= 5; k++) { | 362 for (int k = -5; k <= 5; k++) { |
| 367 Smi* expected = Smi::FromInt(k); | 363 Smi* expected = Smi::FromInt(k); |
| 368 smis[i + j] = expected; | 364 smis[i + j] = expected; |
| 369 CHECK_EQ(expected, t.Call()); | 365 CHECK_EQ(expected, t.Call()); |
| 370 } | 366 } |
| 371 } | 367 } |
| 372 } | 368 } |
| 373 } | 369 } |
| 374 | 370 |
| 375 | 371 |
| 376 TEST(RunStoreElementFromUntaggedBase) { | 372 TEST(RunStoreElementFromUntaggedBase) { |
| 377 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), | 373 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), |
| 378 Smi::FromInt(4), Smi::FromInt(5)}; | 374 Smi::FromInt(4), Smi::FromInt(5)}; |
| 379 | 375 |
| 380 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes | 376 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes |
| 381 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index | 377 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index |
| 382 int offset = static_cast<int>(i * sizeof(Smi*)); | 378 int offset = static_cast<int>(i * sizeof(Smi*)); |
| 383 ElementAccess access = {kNoBoundsCheck, kUntaggedBase, offset, | 379 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), |
| 384 Type::Integral32(), kMachAnyTagged}; | 380 kMachAnyTagged}; |
| 385 | 381 |
| 386 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 382 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 387 Node* p0 = t.Parameter(0); | 383 Node* p0 = t.Parameter(0); |
| 388 t.StoreElement(access, t.PointerConstant(smis), | 384 t.StoreElement(access, t.PointerConstant(smis), |
| 389 t.Int32Constant(static_cast<int>(j)), | 385 t.Int32Constant(static_cast<int>(j)), p0); |
| 390 t.Int32Constant(static_cast<int>(arraysize(smis))), p0); | |
| 391 t.Return(p0); | 386 t.Return(p0); |
| 392 t.LowerAllNodes(); | 387 t.LowerAllNodes(); |
| 393 | 388 |
| 394 if (!Pipeline::SupportedTarget()) continue; | 389 if (!Pipeline::SupportedTarget()) continue; |
| 395 | 390 |
| 396 for (int k = -5; k <= 5; k++) { | 391 for (int k = -5; k <= 5; k++) { |
| 397 Smi* expected = Smi::FromInt(k); | 392 Smi* expected = Smi::FromInt(k); |
| 398 smis[i + j] = Smi::FromInt(-100); | 393 smis[i + j] = Smi::FromInt(-100); |
| 399 CHECK_EQ(expected, t.Call(expected)); | 394 CHECK_EQ(expected, t.Call(expected)); |
| 400 CHECK_EQ(expected, smis[i + j]); | 395 CHECK_EQ(expected, smis[i + j]); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 // or {tagged_array} at index {from_index} to index {to_index}. | 441 // or {tagged_array} at index {from_index} to index {to_index}. |
| 447 void RunCopyElement(int from_index, int to_index) { | 442 void RunCopyElement(int from_index, int to_index) { |
| 448 // TODO(titzer): test element and field accesses where the base is not | 443 // TODO(titzer): test element and field accesses where the base is not |
| 449 // a constant in the code. | 444 // a constant in the code. |
| 450 BoundsCheck(from_index); | 445 BoundsCheck(from_index); |
| 451 BoundsCheck(to_index); | 446 BoundsCheck(to_index); |
| 452 ElementAccess access = GetElementAccess(); | 447 ElementAccess access = GetElementAccess(); |
| 453 | 448 |
| 454 SimplifiedLoweringTester<Object*> t; | 449 SimplifiedLoweringTester<Object*> t; |
| 455 Node* ptr = GetBaseNode(&t); | 450 Node* ptr = GetBaseNode(&t); |
| 456 Node* load = t.LoadElement(access, ptr, t.Int32Constant(from_index), | 451 Node* load = t.LoadElement(access, ptr, t.Int32Constant(from_index)); |
| 457 t.Int32Constant(static_cast<int>(num_elements))); | 452 t.StoreElement(access, ptr, t.Int32Constant(to_index), load); |
| 458 t.StoreElement(access, ptr, t.Int32Constant(to_index), | |
| 459 t.Int32Constant(static_cast<int>(num_elements)), load); | |
| 460 t.Return(t.jsgraph.TrueConstant()); | 453 t.Return(t.jsgraph.TrueConstant()); |
| 461 t.LowerAllNodes(); | 454 t.LowerAllNodes(); |
| 462 t.GenerateCode(); | 455 t.GenerateCode(); |
| 463 | 456 |
| 464 if (Pipeline::SupportedTarget()) { | 457 if (Pipeline::SupportedTarget()) { |
| 465 Object* result = t.Call(); | 458 Object* result = t.Call(); |
| 466 CHECK_EQ(t.isolate()->heap()->true_value(), result); | 459 CHECK_EQ(t.isolate()->heap()->true_value(), result); |
| 467 } | 460 } |
| 468 } | 461 } |
| 469 | 462 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 if (tagged) { | 529 if (tagged) { |
| 537 E* raw = reinterpret_cast<E*>(tagged_array->GetDataStartAddress()); | 530 E* raw = reinterpret_cast<E*>(tagged_array->GetDataStartAddress()); |
| 538 return raw[index]; | 531 return raw[index]; |
| 539 } else { | 532 } else { |
| 540 return untagged_array[index]; | 533 return untagged_array[index]; |
| 541 } | 534 } |
| 542 } | 535 } |
| 543 | 536 |
| 544 private: | 537 private: |
| 545 ElementAccess GetElementAccess() { | 538 ElementAccess GetElementAccess() { |
| 546 ElementAccess access = { | 539 ElementAccess access = {tagged ? kTaggedBase : kUntaggedBase, |
| 547 kNoBoundsCheck, tagged ? kTaggedBase : kUntaggedBase, | 540 tagged ? FixedArrayBase::kHeaderSize : 0, |
| 548 tagged ? FixedArrayBase::kHeaderSize : 0, Type::Any(), rep}; | 541 Type::Any(), rep}; |
| 549 return access; | 542 return access; |
| 550 } | 543 } |
| 551 | 544 |
| 552 FieldAccess GetFieldAccess(int field) { | 545 FieldAccess GetFieldAccess(int field) { |
| 553 int offset = field * sizeof(E); | 546 int offset = field * sizeof(E); |
| 554 FieldAccess access = {tagged ? kTaggedBase : kUntaggedBase, | 547 FieldAccess access = {tagged ? kTaggedBase : kUntaggedBase, |
| 555 offset + (tagged ? FixedArrayBase::kHeaderSize : 0), | 548 offset + (tagged ? FixedArrayBase::kHeaderSize : 0), |
| 556 Handle<Name>(), Type::Any(), rep}; | 549 Handle<Name>(), Type::Any(), rep}; |
| 557 return access; | 550 return access; |
| 558 } | 551 } |
| (...skipping 819 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1378 | 1371 |
| 1379 void CheckFieldAccessArithmetic(FieldAccess access, Node* load_or_store) { | 1372 void CheckFieldAccessArithmetic(FieldAccess access, Node* load_or_store) { |
| 1380 IntPtrMatcher mindex(load_or_store->InputAt(1)); | 1373 IntPtrMatcher mindex(load_or_store->InputAt(1)); |
| 1381 CHECK(mindex.Is(access.offset - access.tag())); | 1374 CHECK(mindex.Is(access.offset - access.tag())); |
| 1382 } | 1375 } |
| 1383 | 1376 |
| 1384 | 1377 |
| 1385 Node* CheckElementAccessArithmetic(ElementAccess access, Node* load_or_store) { | 1378 Node* CheckElementAccessArithmetic(ElementAccess access, Node* load_or_store) { |
| 1386 Node* index = load_or_store->InputAt(1); | 1379 Node* index = load_or_store->InputAt(1); |
| 1387 if (kPointerSize == 8) { | 1380 if (kPointerSize == 8) { |
| 1388 CHECK_EQ(IrOpcode::kChangeUint32ToUint64, index->opcode()); | 1381 CHECK_EQ(IrOpcode::kChangeInt32ToInt64, index->opcode()); |
| 1389 index = index->InputAt(0); | 1382 index = index->InputAt(0); |
| 1390 } | 1383 } |
| 1391 | 1384 |
| 1392 Int32BinopMatcher mindex(index); | 1385 Int32BinopMatcher mindex(index); |
| 1393 CHECK_EQ(IrOpcode::kInt32Add, mindex.node()->opcode()); | 1386 CHECK_EQ(IrOpcode::kInt32Add, mindex.node()->opcode()); |
| 1394 CHECK(mindex.right().Is(access.header_size - access.tag())); | 1387 CHECK(mindex.right().Is(access.header_size - access.tag())); |
| 1395 | 1388 |
| 1396 const int element_size_shift = ElementSizeLog2Of(access.machine_type); | 1389 const int element_size_shift = ElementSizeLog2Of(access.machine_type); |
| 1397 if (element_size_shift) { | 1390 if (element_size_shift) { |
| 1398 Int32BinopMatcher shl(mindex.left().node()); | 1391 Int32BinopMatcher shl(mindex.left().node()); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1457 } | 1450 } |
| 1458 CHECK_EQ(kMachineReps[i], rep.machine_type()); | 1451 CHECK_EQ(kMachineReps[i], rep.machine_type()); |
| 1459 } | 1452 } |
| 1460 } | 1453 } |
| 1461 | 1454 |
| 1462 | 1455 |
| 1463 TEST(LowerLoadElement_to_load) { | 1456 TEST(LowerLoadElement_to_load) { |
| 1464 TestingGraph t(Type::Any(), Type::Signed32()); | 1457 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1465 | 1458 |
| 1466 for (size_t i = 0; i < arraysize(kMachineReps); i++) { | 1459 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
| 1467 ElementAccess access = {kNoBoundsCheck, kTaggedBase, | 1460 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1468 FixedArrayBase::kHeaderSize, Type::Any(), | 1461 Type::Any(), kMachineReps[i]}; |
| 1469 kMachineReps[i]}; | |
| 1470 | 1462 |
| 1471 Node* load = | 1463 Node* load = |
| 1472 t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, t.p1, | 1464 t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, t.p1, |
| 1473 t.jsgraph.Int32Constant(1024), t.start, t.start); | 1465 t.jsgraph.Int32Constant(1024), t.start, t.start); |
| 1474 Node* use = t.Use(load, kMachineReps[i]); | 1466 Node* use = t.Use(load, kMachineReps[i]); |
| 1475 t.Return(use); | 1467 t.Return(use); |
| 1476 t.Lower(); | 1468 t.Lower(); |
| 1477 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1469 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
| 1478 CHECK_EQ(t.p0, load->InputAt(0)); | 1470 CHECK_EQ(t.p0, load->InputAt(0)); |
| 1479 CheckElementAccessArithmetic(access, load); | 1471 CheckElementAccessArithmetic(access, load); |
| 1480 | 1472 |
| 1481 MachineType rep = OpParameter<MachineType>(load); | 1473 MachineType rep = OpParameter<MachineType>(load); |
| 1482 CHECK_EQ(kMachineReps[i], rep); | 1474 CHECK_EQ(kMachineReps[i], rep); |
| 1483 } | 1475 } |
| 1484 } | 1476 } |
| 1485 | 1477 |
| 1486 | 1478 |
| 1487 TEST(LowerStoreElement_to_store) { | 1479 TEST(LowerStoreElement_to_store) { |
| 1488 TestingGraph t(Type::Any(), Type::Signed32()); | 1480 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1489 | 1481 |
| 1490 for (size_t i = 0; i < arraysize(kMachineReps); i++) { | 1482 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
| 1491 ElementAccess access = {kNoBoundsCheck, kTaggedBase, | 1483 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1492 FixedArrayBase::kHeaderSize, Type::Any(), | 1484 Type::Any(), kMachineReps[i]}; |
| 1493 kMachineReps[i]}; | |
| 1494 | 1485 |
| 1495 Node* val = t.ExampleWithOutput(kMachineReps[i]); | 1486 Node* val = t.ExampleWithOutput(kMachineReps[i]); |
| 1496 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, | 1487 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, |
| 1497 t.p1, t.jsgraph.Int32Constant(1024), val, | 1488 t.p1, val, t.start, t.start); |
| 1498 t.start, t.start); | |
| 1499 t.Effect(store); | 1489 t.Effect(store); |
| 1500 t.Lower(); | 1490 t.Lower(); |
| 1501 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1491 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
| 1502 CHECK_EQ(val, store->InputAt(2)); | 1492 CHECK_EQ(val, store->InputAt(2)); |
| 1503 CheckElementAccessArithmetic(access, store); | 1493 CheckElementAccessArithmetic(access, store); |
| 1504 | 1494 |
| 1505 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); | 1495 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); |
| 1506 if (kMachineReps[i] & kRepTagged) { | 1496 if (kMachineReps[i] & kRepTagged) { |
| 1507 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); | 1497 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); |
| 1508 } | 1498 } |
| 1509 CHECK_EQ(kMachineReps[i], rep.machine_type()); | 1499 CHECK_EQ(kMachineReps[i], rep.machine_type()); |
| 1510 } | 1500 } |
| 1511 } | 1501 } |
| 1512 | 1502 |
| 1513 | 1503 |
| 1514 TEST(InsertChangeForLoadElementIndex) { | 1504 TEST(InsertChangeForLoadElementIndex) { |
| 1515 // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length) => | 1505 // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length) => |
| 1516 // Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k)) | 1506 // Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k)) |
| 1517 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); | 1507 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); |
| 1518 ElementAccess access = {kNoBoundsCheck, kTaggedBase, | 1508 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), |
| 1519 FixedArrayBase::kHeaderSize, Type::Any(), | |
| 1520 kMachAnyTagged}; | 1509 kMachAnyTagged}; |
| 1521 | 1510 |
| 1522 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, | 1511 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, |
| 1523 t.p1, t.p2, t.start, t.start); | 1512 t.p1, t.p2, t.start, t.start); |
| 1524 t.Return(load); | 1513 t.Return(load); |
| 1525 t.Lower(); | 1514 t.Lower(); |
| 1526 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1515 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
| 1527 CHECK_EQ(t.p0, load->InputAt(0)); | 1516 CHECK_EQ(t.p0, load->InputAt(0)); |
| 1528 | 1517 |
| 1529 Node* index = CheckElementAccessArithmetic(access, load); | 1518 Node* index = CheckElementAccessArithmetic(access, load); |
| 1530 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, index); | 1519 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, index); |
| 1531 } | 1520 } |
| 1532 | 1521 |
| 1533 | 1522 |
| 1534 TEST(InsertChangeForStoreElementIndex) { | 1523 TEST(InsertChangeForStoreElementIndex) { |
| 1535 // StoreElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length, val) => | 1524 // StoreElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length, val) => |
| 1536 // Store(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k), val) | 1525 // Store(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k), val) |
| 1537 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); | 1526 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); |
| 1538 ElementAccess access = {kNoBoundsCheck, kTaggedBase, | 1527 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), |
| 1539 FixedArrayBase::kHeaderSize, Type::Any(), | |
| 1540 kMachAnyTagged}; | 1528 kMachAnyTagged}; |
| 1541 | 1529 |
| 1542 Node* store = | 1530 Node* store = |
| 1543 t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, t.p1, t.p2, | 1531 t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, t.p1, t.p2, |
| 1544 t.jsgraph.TrueConstant(), t.start, t.start); | 1532 t.jsgraph.TrueConstant(), t.start, t.start); |
| 1545 t.Effect(store); | 1533 t.Effect(store); |
| 1546 t.Lower(); | 1534 t.Lower(); |
| 1547 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1535 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
| 1548 CHECK_EQ(t.p0, store->InputAt(0)); | 1536 CHECK_EQ(t.p0, store->InputAt(0)); |
| 1549 | 1537 |
| 1550 Node* index = CheckElementAccessArithmetic(access, store); | 1538 Node* index = CheckElementAccessArithmetic(access, store); |
| 1551 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, index); | 1539 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, index); |
| 1552 } | 1540 } |
| 1553 | 1541 |
| 1554 | 1542 |
| 1555 TEST(InsertChangeForLoadElement) { | 1543 TEST(InsertChangeForLoadElement) { |
| 1556 // TODO(titzer): test all load/store representation change insertions. | 1544 // TODO(titzer): test all load/store representation change insertions. |
| 1557 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); | 1545 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); |
| 1558 ElementAccess access = {kNoBoundsCheck, kTaggedBase, | 1546 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), |
| 1559 FixedArrayBase::kHeaderSize, Type::Any(), | |
| 1560 kMachFloat64}; | 1547 kMachFloat64}; |
| 1561 | 1548 |
| 1562 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, | 1549 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, |
| 1563 t.p1, t.p1, t.start, t.start); | 1550 t.p1, t.p1, t.start, t.start); |
| 1564 t.Return(load); | 1551 t.Return(load); |
| 1565 t.Lower(); | 1552 t.Lower(); |
| 1566 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1553 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
| 1567 CHECK_EQ(t.p0, load->InputAt(0)); | 1554 CHECK_EQ(t.p0, load->InputAt(0)); |
| 1568 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); | 1555 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); |
| 1569 } | 1556 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1581 t.Lower(); | 1568 t.Lower(); |
| 1582 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1569 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
| 1583 CHECK_EQ(t.p0, load->InputAt(0)); | 1570 CHECK_EQ(t.p0, load->InputAt(0)); |
| 1584 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); | 1571 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); |
| 1585 } | 1572 } |
| 1586 | 1573 |
| 1587 | 1574 |
| 1588 TEST(InsertChangeForStoreElement) { | 1575 TEST(InsertChangeForStoreElement) { |
| 1589 // TODO(titzer): test all load/store representation change insertions. | 1576 // TODO(titzer): test all load/store representation change insertions. |
| 1590 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); | 1577 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); |
| 1591 ElementAccess access = {kNoBoundsCheck, kTaggedBase, | 1578 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), |
| 1592 FixedArrayBase::kHeaderSize, Type::Any(), | |
| 1593 kMachFloat64}; | 1579 kMachFloat64}; |
| 1594 | 1580 |
| 1595 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, | 1581 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, |
| 1596 t.jsgraph.Int32Constant(0), t.p2, t.p1, | 1582 t.p2, t.p1, t.start, t.start); |
| 1597 t.start, t.start); | |
| 1598 t.Effect(store); | 1583 t.Effect(store); |
| 1599 t.Lower(); | 1584 t.Lower(); |
| 1600 | 1585 |
| 1601 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1586 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
| 1602 CHECK_EQ(t.p0, store->InputAt(0)); | 1587 CHECK_EQ(t.p0, store->InputAt(0)); |
| 1603 CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(2)); | 1588 CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(2)); |
| 1604 } | 1589 } |
| 1605 | 1590 |
| 1606 | 1591 |
| 1607 TEST(InsertChangeForStoreField) { | 1592 TEST(InsertChangeForStoreField) { |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2046 Bounds phi_bounds = Bounds::Either(Bounds(d.arg1), Bounds(d.arg2), z); | 2031 Bounds phi_bounds = Bounds::Either(Bounds(d.arg1), Bounds(d.arg2), z); |
| 2047 NodeProperties::SetBounds(phi, phi_bounds); | 2032 NodeProperties::SetBounds(phi, phi_bounds); |
| 2048 | 2033 |
| 2049 Node* use = t.Use(phi, d.use); | 2034 Node* use = t.Use(phi, d.use); |
| 2050 t.Return(use); | 2035 t.Return(use); |
| 2051 t.Lower(); | 2036 t.Lower(); |
| 2052 | 2037 |
| 2053 CHECK_EQ(d.expected, OpParameter<MachineType>(phi)); | 2038 CHECK_EQ(d.expected, OpParameter<MachineType>(phi)); |
| 2054 } | 2039 } |
| 2055 } | 2040 } |
| OLD | NEW |