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 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 CHECK(result->IsMap()); | 200 CHECK(result->IsMap()); |
201 CHECK_EQ(*src_map, result); | 201 CHECK_EQ(*src_map, result); |
202 CHECK(*src_map == dst->map()); | 202 CHECK(*src_map == dst->map()); |
203 } | 203 } |
204 } | 204 } |
205 | 205 |
206 | 206 |
207 TEST(RunLoadStoreFixedArrayIndex) { | 207 TEST(RunLoadStoreFixedArrayIndex) { |
208 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 208 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
209 ElementAccess access = AccessBuilder::ForFixedArrayElement(); | 209 ElementAccess access = AccessBuilder::ForFixedArrayElement(); |
210 Node* load = t.LoadElement(access, t.Parameter(0), t.Int32Constant(0)); | 210 Node* load = t.LoadElement(access, t.Parameter(0), t.Int32Constant(0), |
211 t.StoreElement(access, t.Parameter(0), t.Int32Constant(1), load); | 211 t.Int32Constant(2)); |
| 212 t.StoreElement(access, t.Parameter(0), t.Int32Constant(1), t.Int32Constant(2), |
| 213 load); |
212 t.Return(load); | 214 t.Return(load); |
213 | 215 |
214 t.LowerAllNodes(); | 216 t.LowerAllNodes(); |
215 t.GenerateCode(); | 217 t.GenerateCode(); |
216 | 218 |
217 if (Pipeline::SupportedTarget()) { | 219 if (Pipeline::SupportedTarget()) { |
218 Handle<FixedArray> array = t.factory()->NewFixedArray(2); | 220 Handle<FixedArray> array = t.factory()->NewFixedArray(2); |
219 Handle<JSObject> src = TestObject(); | 221 Handle<JSObject> src = TestObject(); |
220 Handle<JSObject> dst = TestObject(); | 222 Handle<JSObject> dst = TestObject(); |
221 array->set(0, *src); | 223 array->set(0, *src); |
222 array->set(1, *dst); | 224 array->set(1, *dst); |
223 Object* result = t.Call(*array); | 225 Object* result = t.Call(*array); |
224 CHECK_EQ(*src, result); | 226 CHECK_EQ(*src, result); |
225 CHECK_EQ(*src, array->get(0)); | 227 CHECK_EQ(*src, array->get(0)); |
226 CHECK_EQ(*src, array->get(1)); | 228 CHECK_EQ(*src, array->get(1)); |
227 } | 229 } |
228 } | 230 } |
229 | 231 |
230 | 232 |
231 TEST(RunLoadStoreArrayBuffer) { | 233 TEST(RunLoadStoreArrayBuffer) { |
232 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 234 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
233 const int index = 12; | 235 const int index = 12; |
| 236 const int array_length = 2 * index; |
234 ElementAccess buffer_access = | 237 ElementAccess buffer_access = |
235 AccessBuilder::ForBackingStoreElement(kMachInt8); | 238 AccessBuilder::ForBackingStoreElement(kMachInt8); |
236 Node* backing_store = t.LoadField( | 239 Node* backing_store = t.LoadField( |
237 AccessBuilder::ForJSArrayBufferBackingStore(), t.Parameter(0)); | 240 AccessBuilder::ForJSArrayBufferBackingStore(), t.Parameter(0)); |
238 Node* load = | 241 Node* load = |
239 t.LoadElement(buffer_access, backing_store, t.Int32Constant(index)); | 242 t.LoadElement(buffer_access, backing_store, t.Int32Constant(index), |
| 243 t.Int32Constant(array_length)); |
240 t.StoreElement(buffer_access, backing_store, t.Int32Constant(index + 1), | 244 t.StoreElement(buffer_access, backing_store, t.Int32Constant(index + 1), |
241 load); | 245 t.Int32Constant(array_length), load); |
242 t.Return(t.jsgraph.TrueConstant()); | 246 t.Return(t.jsgraph.TrueConstant()); |
243 | 247 |
244 t.LowerAllNodes(); | 248 t.LowerAllNodes(); |
245 t.GenerateCode(); | 249 t.GenerateCode(); |
246 | 250 |
247 if (Pipeline::SupportedTarget()) { | 251 if (Pipeline::SupportedTarget()) { |
248 Handle<JSArrayBuffer> array = t.factory()->NewJSArrayBuffer(); | 252 Handle<JSArrayBuffer> array = t.factory()->NewJSArrayBuffer(); |
249 const int array_length = 2 * index; | |
250 Runtime::SetupArrayBufferAllocatingData(t.isolate(), array, array_length); | 253 Runtime::SetupArrayBufferAllocatingData(t.isolate(), array, array_length); |
251 uint8_t* data = reinterpret_cast<uint8_t*>(array->backing_store()); | 254 uint8_t* data = reinterpret_cast<uint8_t*>(array->backing_store()); |
252 for (int i = 0; i < array_length; i++) { | 255 for (int i = 0; i < array_length; i++) { |
253 data[i] = i; | 256 data[i] = i; |
254 } | 257 } |
255 | 258 |
256 // TODO(titzer): raw pointers in call | 259 // TODO(titzer): raw pointers in call |
257 Object* result = t.Call(*array); | 260 Object* result = t.Call(*array); |
258 CHECK_EQ(t.isolate()->heap()->true_value(), result); | 261 CHECK_EQ(t.isolate()->heap()->true_value(), result); |
259 for (int i = 0; i < array_length; i++) { | 262 for (int i = 0; i < array_length; i++) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), | 322 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), |
320 Smi::FromInt(4), Smi::FromInt(5)}; | 323 Smi::FromInt(4), Smi::FromInt(5)}; |
321 | 324 |
322 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 |
323 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 |
324 int offset = static_cast<int>(i * sizeof(Smi*)); | 327 int offset = static_cast<int>(i * sizeof(Smi*)); |
325 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), | 328 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), |
326 kMachAnyTagged}; | 329 kMachAnyTagged}; |
327 | 330 |
328 SimplifiedLoweringTester<Object*> t; | 331 SimplifiedLoweringTester<Object*> t; |
329 Node* load = t.LoadElement(access, t.PointerConstant(smis), | 332 Node* load = t.LoadElement( |
330 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)))); |
331 t.Return(load); | 335 t.Return(load); |
332 t.LowerAllNodes(); | 336 t.LowerAllNodes(); |
333 | 337 |
334 if (!Pipeline::SupportedTarget()) continue; | 338 if (!Pipeline::SupportedTarget()) continue; |
335 | 339 |
336 for (int k = -5; k <= 5; k++) { | 340 for (int k = -5; k <= 5; k++) { |
337 Smi* expected = Smi::FromInt(k); | 341 Smi* expected = Smi::FromInt(k); |
338 smis[i + j] = expected; | 342 smis[i + j] = expected; |
339 CHECK_EQ(expected, t.Call()); | 343 CHECK_EQ(expected, t.Call()); |
340 } | 344 } |
341 } | 345 } |
342 } | 346 } |
343 } | 347 } |
344 | 348 |
345 | 349 |
346 TEST(RunStoreElementFromUntaggedBase) { | 350 TEST(RunStoreElementFromUntaggedBase) { |
347 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), | 351 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), |
348 Smi::FromInt(4), Smi::FromInt(5)}; | 352 Smi::FromInt(4), Smi::FromInt(5)}; |
349 | 353 |
350 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 |
351 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 |
352 int offset = static_cast<int>(i * sizeof(Smi*)); | 356 int offset = static_cast<int>(i * sizeof(Smi*)); |
353 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), | 357 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), |
354 kMachAnyTagged}; | 358 kMachAnyTagged}; |
355 | 359 |
356 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 360 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
357 Node* p0 = t.Parameter(0); | 361 Node* p0 = t.Parameter(0); |
358 t.StoreElement(access, t.PointerConstant(smis), | 362 t.StoreElement(access, t.PointerConstant(smis), |
359 t.Int32Constant(static_cast<int>(j)), p0); | 363 t.Int32Constant(static_cast<int>(j)), |
| 364 t.Int32Constant(static_cast<int>(arraysize(smis))), p0); |
360 t.Return(p0); | 365 t.Return(p0); |
361 t.LowerAllNodes(); | 366 t.LowerAllNodes(); |
362 | 367 |
363 if (!Pipeline::SupportedTarget()) continue; | 368 if (!Pipeline::SupportedTarget()) continue; |
364 | 369 |
365 for (int k = -5; k <= 5; k++) { | 370 for (int k = -5; k <= 5; k++) { |
366 Smi* expected = Smi::FromInt(k); | 371 Smi* expected = Smi::FromInt(k); |
367 smis[i + j] = Smi::FromInt(-100); | 372 smis[i + j] = Smi::FromInt(-100); |
368 CHECK_EQ(expected, t.Call(expected)); | 373 CHECK_EQ(expected, t.Call(expected)); |
369 CHECK_EQ(expected, smis[i + j]); | 374 CHECK_EQ(expected, smis[i + j]); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 // or {tagged_array} at index {from_index} to index {to_index}. | 420 // or {tagged_array} at index {from_index} to index {to_index}. |
416 void RunCopyElement(int from_index, int to_index) { | 421 void RunCopyElement(int from_index, int to_index) { |
417 // TODO(titzer): test element and field accesses where the base is not | 422 // TODO(titzer): test element and field accesses where the base is not |
418 // a constant in the code. | 423 // a constant in the code. |
419 BoundsCheck(from_index); | 424 BoundsCheck(from_index); |
420 BoundsCheck(to_index); | 425 BoundsCheck(to_index); |
421 ElementAccess access = GetElementAccess(); | 426 ElementAccess access = GetElementAccess(); |
422 | 427 |
423 SimplifiedLoweringTester<Object*> t; | 428 SimplifiedLoweringTester<Object*> t; |
424 Node* ptr = GetBaseNode(&t); | 429 Node* ptr = GetBaseNode(&t); |
425 Node* load = t.LoadElement(access, ptr, t.Int32Constant(from_index)); | 430 Node* load = t.LoadElement(access, ptr, t.Int32Constant(from_index), |
426 t.StoreElement(access, ptr, t.Int32Constant(to_index), load); | 431 t.Int32Constant(num_elements)); |
| 432 t.StoreElement(access, ptr, t.Int32Constant(to_index), |
| 433 t.Int32Constant(num_elements), load); |
427 t.Return(t.jsgraph.TrueConstant()); | 434 t.Return(t.jsgraph.TrueConstant()); |
428 t.LowerAllNodes(); | 435 t.LowerAllNodes(); |
429 t.GenerateCode(); | 436 t.GenerateCode(); |
430 | 437 |
431 if (Pipeline::SupportedTarget()) { | 438 if (Pipeline::SupportedTarget()) { |
432 Object* result = t.Call(); | 439 Object* result = t.Call(); |
433 CHECK_EQ(t.isolate()->heap()->true_value(), result); | 440 CHECK_EQ(t.isolate()->heap()->true_value(), result); |
434 } | 441 } |
435 } | 442 } |
436 | 443 |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 | 633 |
627 | 634 |
628 // Fills in most of the nodes of the graph in order to make tests shorter. | 635 // Fills in most of the nodes of the graph in order to make tests shorter. |
629 class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders { | 636 class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders { |
630 public: | 637 public: |
631 Typer typer; | 638 Typer typer; |
632 JSOperatorBuilder javascript; | 639 JSOperatorBuilder javascript; |
633 JSGraph jsgraph; | 640 JSGraph jsgraph; |
634 Node* p0; | 641 Node* p0; |
635 Node* p1; | 642 Node* p1; |
| 643 Node* p2; |
636 Node* start; | 644 Node* start; |
637 Node* end; | 645 Node* end; |
638 Node* ret; | 646 Node* ret; |
639 | 647 |
640 explicit TestingGraph(Type* p0_type, Type* p1_type = Type::None()) | 648 explicit TestingGraph(Type* p0_type, Type* p1_type = Type::None(), |
| 649 Type* p2_type = Type::None()) |
641 : GraphAndBuilders(main_zone()), | 650 : GraphAndBuilders(main_zone()), |
642 typer(main_zone()), | 651 typer(main_zone()), |
643 javascript(main_zone()), | 652 javascript(main_zone()), |
644 jsgraph(graph(), common(), &javascript, &typer, machine()) { | 653 jsgraph(graph(), common(), &javascript, &typer, machine()) { |
645 start = graph()->NewNode(common()->Start(2)); | 654 start = graph()->NewNode(common()->Start(2)); |
646 graph()->SetStart(start); | 655 graph()->SetStart(start); |
647 ret = | 656 ret = |
648 graph()->NewNode(common()->Return(), jsgraph.Constant(0), start, start); | 657 graph()->NewNode(common()->Return(), jsgraph.Constant(0), start, start); |
649 end = graph()->NewNode(common()->End(), ret); | 658 end = graph()->NewNode(common()->End(), ret); |
650 graph()->SetEnd(end); | 659 graph()->SetEnd(end); |
651 p0 = graph()->NewNode(common()->Parameter(0), start); | 660 p0 = graph()->NewNode(common()->Parameter(0), start); |
652 p1 = graph()->NewNode(common()->Parameter(1), start); | 661 p1 = graph()->NewNode(common()->Parameter(1), start); |
| 662 p2 = graph()->NewNode(common()->Parameter(2), start); |
653 NodeProperties::SetBounds(p0, Bounds(p0_type)); | 663 NodeProperties::SetBounds(p0, Bounds(p0_type)); |
654 NodeProperties::SetBounds(p1, Bounds(p1_type)); | 664 NodeProperties::SetBounds(p1, Bounds(p1_type)); |
| 665 NodeProperties::SetBounds(p2, Bounds(p2_type)); |
655 } | 666 } |
656 | 667 |
657 void CheckLoweringBinop(IrOpcode::Value expected, const Operator* op) { | 668 void CheckLoweringBinop(IrOpcode::Value expected, const Operator* op) { |
658 Node* node = Return(graph()->NewNode(op, p0, p1)); | 669 Node* node = Return(graph()->NewNode(op, p0, p1)); |
659 Lower(); | 670 Lower(); |
660 CHECK_EQ(expected, node->opcode()); | 671 CHECK_EQ(expected, node->opcode()); |
661 } | 672 } |
662 | 673 |
663 void CheckLoweringTruncatedBinop(IrOpcode::Value expected, const Operator* op, | 674 void CheckLoweringTruncatedBinop(IrOpcode::Value expected, const Operator* op, |
664 const Operator* trunc) { | 675 const Operator* trunc) { |
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1334 } | 1345 } |
1335 | 1346 |
1336 | 1347 |
1337 TEST(LowerLoadElement_to_load) { | 1348 TEST(LowerLoadElement_to_load) { |
1338 TestingGraph t(Type::Any(), Type::Signed32()); | 1349 TestingGraph t(Type::Any(), Type::Signed32()); |
1339 | 1350 |
1340 for (size_t i = 0; i < arraysize(machine_reps); i++) { | 1351 for (size_t i = 0; i < arraysize(machine_reps); i++) { |
1341 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1352 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
1342 Type::Any(), machine_reps[i]}; | 1353 Type::Any(), machine_reps[i]}; |
1343 | 1354 |
1344 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, | 1355 Node* load = |
1345 t.p1, t.start); | 1356 t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, t.p1, |
| 1357 t.jsgraph.Int32Constant(1024), t.start); |
1346 Node* use = t.Use(load, machine_reps[i]); | 1358 Node* use = t.Use(load, machine_reps[i]); |
1347 t.Return(use); | 1359 t.Return(use); |
1348 t.Lower(); | 1360 t.Lower(); |
1349 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1361 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
1350 CHECK_EQ(t.p0, load->InputAt(0)); | 1362 CHECK_EQ(t.p0, load->InputAt(0)); |
1351 CheckElementAccessArithmetic(access, load); | 1363 CheckElementAccessArithmetic(access, load); |
1352 | 1364 |
1353 MachineType rep = OpParameter<MachineType>(load); | 1365 MachineType rep = OpParameter<MachineType>(load); |
1354 CHECK_EQ(machine_reps[i], rep); | 1366 CHECK_EQ(machine_reps[i], rep); |
1355 } | 1367 } |
1356 } | 1368 } |
1357 | 1369 |
1358 | 1370 |
1359 TEST(LowerStoreElement_to_store) { | 1371 TEST(LowerStoreElement_to_store) { |
1360 TestingGraph t(Type::Any(), Type::Signed32()); | 1372 TestingGraph t(Type::Any(), Type::Signed32()); |
1361 | 1373 |
1362 for (size_t i = 0; i < arraysize(machine_reps); i++) { | 1374 for (size_t i = 0; i < arraysize(machine_reps); i++) { |
1363 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1375 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
1364 Type::Any(), machine_reps[i]}; | 1376 Type::Any(), machine_reps[i]}; |
1365 | 1377 |
1366 Node* val = t.ExampleWithOutput(machine_reps[i]); | 1378 Node* val = t.ExampleWithOutput(machine_reps[i]); |
1367 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, | 1379 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, |
1368 t.p1, val, t.start, t.start); | 1380 t.p1, t.jsgraph.Int32Constant(1024), val, |
| 1381 t.start, t.start); |
1369 t.Effect(store); | 1382 t.Effect(store); |
1370 t.Lower(); | 1383 t.Lower(); |
1371 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1384 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
1372 CHECK_EQ(val, store->InputAt(2)); | 1385 CHECK_EQ(val, store->InputAt(2)); |
1373 CheckElementAccessArithmetic(access, store); | 1386 CheckElementAccessArithmetic(access, store); |
1374 | 1387 |
1375 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); | 1388 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); |
1376 if (machine_reps[i] & kRepTagged) { | 1389 if (machine_reps[i] & kRepTagged) { |
1377 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); | 1390 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); |
1378 } | 1391 } |
1379 CHECK_EQ(machine_reps[i], rep.machine_type()); | 1392 CHECK_EQ(machine_reps[i], rep.machine_type()); |
1380 } | 1393 } |
1381 } | 1394 } |
1382 | 1395 |
1383 | 1396 |
1384 TEST(InsertChangeForLoadElementIndex) { | 1397 TEST(InsertChangeForLoadElementIndex) { |
1385 // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged) => | 1398 // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length) => |
1386 // Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k)) | 1399 // Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k)) |
1387 TestingGraph t(Type::Any(), Type::Signed32()); | 1400 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); |
1388 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | 1401 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), |
1389 kMachAnyTagged}; | 1402 kMachAnyTagged}; |
1390 | 1403 |
1391 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, | 1404 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, |
1392 t.p1, t.start); | 1405 t.p1, t.p2, t.start); |
1393 t.Return(load); | 1406 t.Return(load); |
1394 t.Lower(); | 1407 t.Lower(); |
1395 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1408 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
1396 CHECK_EQ(t.p0, load->InputAt(0)); | 1409 CHECK_EQ(t.p0, load->InputAt(0)); |
1397 | 1410 |
1398 Node* index = CheckElementAccessArithmetic(access, load); | 1411 Node* index = CheckElementAccessArithmetic(access, load); |
1399 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, index); | 1412 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, index); |
1400 } | 1413 } |
1401 | 1414 |
1402 | 1415 |
1403 TEST(InsertChangeForStoreElementIndex) { | 1416 TEST(InsertChangeForStoreElementIndex) { |
1404 // StoreElement(obj: Tagged, index: kTypeInt32 | kRepTagged, val) => | 1417 // StoreElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length, val) => |
1405 // Store(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k), val) | 1418 // Store(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k), val) |
1406 TestingGraph t(Type::Any(), Type::Signed32()); | 1419 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); |
1407 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | 1420 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), |
1408 kMachAnyTagged}; | 1421 kMachAnyTagged}; |
1409 | 1422 |
1410 Node* store = | 1423 Node* store = |
1411 t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, t.p1, | 1424 t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, t.p1, t.p2, |
1412 t.jsgraph.TrueConstant(), t.start, t.start); | 1425 t.jsgraph.TrueConstant(), t.start, t.start); |
1413 t.Effect(store); | 1426 t.Effect(store); |
1414 t.Lower(); | 1427 t.Lower(); |
1415 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1428 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
1416 CHECK_EQ(t.p0, store->InputAt(0)); | 1429 CHECK_EQ(t.p0, store->InputAt(0)); |
1417 | 1430 |
1418 Node* index = CheckElementAccessArithmetic(access, store); | 1431 Node* index = CheckElementAccessArithmetic(access, store); |
1419 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, index); | 1432 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, index); |
1420 } | 1433 } |
1421 | 1434 |
1422 | 1435 |
1423 TEST(InsertChangeForLoadElement) { | 1436 TEST(InsertChangeForLoadElement) { |
1424 // TODO(titzer): test all load/store representation change insertions. | 1437 // TODO(titzer): test all load/store representation change insertions. |
1425 TestingGraph t(Type::Any(), Type::Signed32()); | 1438 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); |
1426 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | 1439 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), |
1427 kMachFloat64}; | 1440 kMachFloat64}; |
1428 | 1441 |
1429 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, | 1442 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, |
1430 t.p1, t.start); | 1443 t.p1, t.p1, t.start); |
1431 t.Return(load); | 1444 t.Return(load); |
1432 t.Lower(); | 1445 t.Lower(); |
1433 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1446 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
1434 CHECK_EQ(t.p0, load->InputAt(0)); | 1447 CHECK_EQ(t.p0, load->InputAt(0)); |
1435 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); | 1448 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); |
1436 } | 1449 } |
1437 | 1450 |
1438 | 1451 |
1439 TEST(InsertChangeForLoadField) { | 1452 TEST(InsertChangeForLoadField) { |
1440 // TODO(titzer): test all load/store representation change insertions. | 1453 // TODO(titzer): test all load/store representation change insertions. |
1441 TestingGraph t(Type::Any(), Type::Signed32()); | 1454 TestingGraph t(Type::Any(), Type::Signed32()); |
1442 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1455 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
1443 Handle<Name>::null(), Type::Any(), kMachFloat64}; | 1456 Handle<Name>::null(), Type::Any(), kMachFloat64}; |
1444 | 1457 |
1445 Node* load = | 1458 Node* load = |
1446 t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, t.start); | 1459 t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, t.start); |
1447 t.Return(load); | 1460 t.Return(load); |
1448 t.Lower(); | 1461 t.Lower(); |
1449 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1462 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
1450 CHECK_EQ(t.p0, load->InputAt(0)); | 1463 CHECK_EQ(t.p0, load->InputAt(0)); |
1451 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); | 1464 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); |
1452 } | 1465 } |
1453 | 1466 |
1454 | 1467 |
1455 TEST(InsertChangeForStoreElement) { | 1468 TEST(InsertChangeForStoreElement) { |
1456 // TODO(titzer): test all load/store representation change insertions. | 1469 // TODO(titzer): test all load/store representation change insertions. |
1457 TestingGraph t(Type::Any(), Type::Signed32()); | 1470 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); |
1458 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | 1471 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), |
1459 kMachFloat64}; | 1472 kMachFloat64}; |
1460 | 1473 |
1461 Node* store = | 1474 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, |
1462 t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, | 1475 t.jsgraph.Int32Constant(0), t.p2, t.p1, |
1463 t.jsgraph.Int32Constant(0), t.p1, t.start, t.start); | 1476 t.start, t.start); |
1464 t.Effect(store); | 1477 t.Effect(store); |
1465 t.Lower(); | 1478 t.Lower(); |
1466 | 1479 |
1467 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1480 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
1468 CHECK_EQ(t.p0, store->InputAt(0)); | 1481 CHECK_EQ(t.p0, store->InputAt(0)); |
1469 CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(2)); | 1482 CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(2)); |
1470 } | 1483 } |
1471 | 1484 |
1472 | 1485 |
1473 TEST(InsertChangeForStoreField) { | 1486 TEST(InsertChangeForStoreField) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1538 | 1551 |
1539 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, | 1552 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, |
1540 t.p1, t.start, t.start); | 1553 t.p1, t.start, t.start); |
1541 t.Effect(store); | 1554 t.Effect(store); |
1542 t.Lower(); | 1555 t.Lower(); |
1543 | 1556 |
1544 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1557 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
1545 CHECK_EQ(t.p0, store->InputAt(0)); | 1558 CHECK_EQ(t.p0, store->InputAt(0)); |
1546 CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(2)); | 1559 CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(2)); |
1547 } | 1560 } |
OLD | NEW |