OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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 "src/compiler/js-create-lowering.h" | 5 #include "src/compiler/js-create-lowering.h" |
6 | 6 |
7 #include "src/allocation-site-scopes.h" | 7 #include "src/allocation-site-scopes.h" |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
10 #include "src/compiler/access-builder.h" | 10 #include "src/compiler/access-builder.h" |
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 a.Allocate(JSArray::kSize, pretenure); | 502 a.Allocate(JSArray::kSize, pretenure); |
503 a.Store(AccessBuilder::ForMap(), js_array_map); | 503 a.Store(AccessBuilder::ForMap(), js_array_map); |
504 a.Store(AccessBuilder::ForJSObjectProperties(), properties); | 504 a.Store(AccessBuilder::ForJSObjectProperties(), properties); |
505 a.Store(AccessBuilder::ForJSObjectElements(), elements); | 505 a.Store(AccessBuilder::ForJSObjectElements(), elements); |
506 a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length); | 506 a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length); |
507 RelaxControls(node); | 507 RelaxControls(node); |
508 a.FinishAndChange(node); | 508 a.FinishAndChange(node); |
509 return Changed(node); | 509 return Changed(node); |
510 } | 510 } |
511 | 511 |
| 512 Reduction JSCreateLowering::ReduceNewArrayToStubCall( |
| 513 Node* node, Handle<AllocationSite> site) { |
| 514 CreateArrayParameters const& p = CreateArrayParametersOf(node->op()); |
| 515 int const arity = static_cast<int>(p.arity()); |
| 516 |
| 517 ElementsKind elements_kind = site->GetElementsKind(); |
| 518 AllocationSiteOverrideMode override_mode = |
| 519 (AllocationSite::GetMode(elements_kind) == TRACK_ALLOCATION_SITE) |
| 520 ? DISABLE_ALLOCATION_SITES |
| 521 : DONT_OVERRIDE; |
| 522 |
| 523 if (arity == 0) { |
| 524 ArrayNoArgumentConstructorStub stub(isolate(), elements_kind, |
| 525 override_mode); |
| 526 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 527 isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 1, |
| 528 CallDescriptor::kNeedsFrameState); |
| 529 node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode())); |
| 530 node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site)); |
| 531 node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(0)); |
| 532 node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant()); |
| 533 NodeProperties::ChangeOp(node, common()->Call(desc)); |
| 534 return Changed(node); |
| 535 } else if (arity == 1) { |
| 536 AllocationSiteOverrideMode override_mode = |
| 537 (AllocationSite::GetMode(elements_kind) == TRACK_ALLOCATION_SITE) |
| 538 ? DISABLE_ALLOCATION_SITES |
| 539 : DONT_OVERRIDE; |
| 540 |
| 541 if (IsHoleyElementsKind(elements_kind)) { |
| 542 ArraySingleArgumentConstructorStub stub(isolate(), elements_kind, |
| 543 override_mode); |
| 544 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 545 isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 2, |
| 546 CallDescriptor::kNeedsFrameState); |
| 547 node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode())); |
| 548 node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site)); |
| 549 node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(1)); |
| 550 node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant()); |
| 551 NodeProperties::ChangeOp(node, common()->Call(desc)); |
| 552 return Changed(node); |
| 553 } |
| 554 |
| 555 Node* effect = NodeProperties::GetEffectInput(node); |
| 556 Node* control = NodeProperties::GetControlInput(node); |
| 557 Node* length = NodeProperties::GetValueInput(node, 2); |
| 558 Node* equal = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), |
| 559 length, jsgraph()->ZeroConstant()); |
| 560 |
| 561 Node* branch = |
| 562 graph()->NewNode(common()->Branch(BranchHint::kFalse), equal, control); |
| 563 Node* call_holey; |
| 564 Node* call_packed; |
| 565 Node* if_success_packed; |
| 566 Node* if_success_holey; |
| 567 Node* context = NodeProperties::GetContextInput(node); |
| 568 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0); |
| 569 Node* if_equal = graph()->NewNode(common()->IfTrue(), branch); |
| 570 { |
| 571 ArraySingleArgumentConstructorStub stub(isolate(), elements_kind, |
| 572 override_mode); |
| 573 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 574 isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 2, |
| 575 CallDescriptor::kNeedsFrameState); |
| 576 |
| 577 Node* inputs[] = {jsgraph()->HeapConstant(stub.GetCode()), |
| 578 node->InputAt(1), |
| 579 jsgraph()->HeapConstant(site), |
| 580 jsgraph()->Int32Constant(1), |
| 581 jsgraph()->UndefinedConstant(), |
| 582 length, |
| 583 context, |
| 584 frame_state, |
| 585 effect, |
| 586 if_equal}; |
| 587 |
| 588 call_holey = |
| 589 graph()->NewNode(common()->Call(desc), arraysize(inputs), inputs); |
| 590 if_success_holey = graph()->NewNode(common()->IfSuccess(), call_holey); |
| 591 } |
| 592 Node* if_not_equal = graph()->NewNode(common()->IfFalse(), branch); |
| 593 { |
| 594 // Require elements kind to "go holey." |
| 595 ArraySingleArgumentConstructorStub stub( |
| 596 isolate(), GetHoleyElementsKind(elements_kind), override_mode); |
| 597 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 598 isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 2, |
| 599 CallDescriptor::kNeedsFrameState); |
| 600 |
| 601 Node* inputs[] = {jsgraph()->HeapConstant(stub.GetCode()), |
| 602 node->InputAt(1), |
| 603 jsgraph()->HeapConstant(site), |
| 604 jsgraph()->Int32Constant(1), |
| 605 jsgraph()->UndefinedConstant(), |
| 606 length, |
| 607 context, |
| 608 frame_state, |
| 609 effect, |
| 610 if_not_equal}; |
| 611 |
| 612 call_packed = |
| 613 graph()->NewNode(common()->Call(desc), arraysize(inputs), inputs); |
| 614 if_success_packed = graph()->NewNode(common()->IfSuccess(), call_packed); |
| 615 } |
| 616 Node* merge = graph()->NewNode(common()->Merge(2), if_success_holey, |
| 617 if_success_packed); |
| 618 Node* effect_phi = graph()->NewNode(common()->EffectPhi(2), call_holey, |
| 619 call_packed, merge); |
| 620 Node* phi = |
| 621 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), |
| 622 call_holey, call_packed, merge); |
| 623 |
| 624 ReplaceWithValue(node, phi, effect_phi, merge); |
| 625 return Changed(node); |
| 626 } |
| 627 |
| 628 DCHECK(arity > 1); |
| 629 ArrayNArgumentsConstructorStub stub(isolate()); |
| 630 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 631 isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), arity + 1, |
| 632 CallDescriptor::kNeedsFrameState); |
| 633 node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode())); |
| 634 node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site)); |
| 635 node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(arity)); |
| 636 node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant()); |
| 637 NodeProperties::ChangeOp(node, common()->Call(desc)); |
| 638 return Changed(node); |
| 639 } |
| 640 |
512 Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) { | 641 Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) { |
513 DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode()); | 642 DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode()); |
514 CreateArrayParameters const& p = CreateArrayParametersOf(node->op()); | 643 CreateArrayParameters const& p = CreateArrayParametersOf(node->op()); |
515 Node* target = NodeProperties::GetValueInput(node, 0); | 644 Node* target = NodeProperties::GetValueInput(node, 0); |
516 Node* new_target = NodeProperties::GetValueInput(node, 1); | 645 Node* new_target = NodeProperties::GetValueInput(node, 1); |
517 | 646 |
| 647 // TODO(mstarzinger): Array constructor can throw. Hook up exceptional edges. |
| 648 if (NodeProperties::IsExceptionalCall(node)) return NoChange(); |
| 649 |
518 // TODO(bmeurer): Optimize the subclassing case. | 650 // TODO(bmeurer): Optimize the subclassing case. |
519 if (target != new_target) return NoChange(); | 651 if (target != new_target) return NoChange(); |
520 | 652 |
521 // Check if we have a feedback {site} on the {node}. | 653 // Check if we have a feedback {site} on the {node}. |
522 Handle<AllocationSite> site = p.site(); | 654 Handle<AllocationSite> site = p.site(); |
523 if (p.site().is_null()) return NoChange(); | 655 if (p.site().is_null()) return NoChange(); |
524 | 656 |
525 // Attempt to inline calls to the Array constructor for the relevant cases | 657 // Attempt to inline calls to the Array constructor for the relevant cases |
526 // where either no arguments are provided, or exactly one unsigned number | 658 // where either no arguments are provided, or exactly one unsigned number |
527 // argument is given. | 659 // argument is given. |
528 if (site->CanInlineCall()) { | 660 if (site->CanInlineCall()) { |
529 if (p.arity() == 0) { | 661 if (p.arity() == 0) { |
530 Node* length = jsgraph()->ZeroConstant(); | 662 Node* length = jsgraph()->ZeroConstant(); |
531 int capacity = JSArray::kPreallocatedArrayElements; | 663 int capacity = JSArray::kPreallocatedArrayElements; |
532 return ReduceNewArray(node, length, capacity, site); | 664 return ReduceNewArray(node, length, capacity, site); |
533 } else if (p.arity() == 1) { | 665 } else if (p.arity() == 1) { |
534 Node* length = NodeProperties::GetValueInput(node, 2); | 666 Node* length = NodeProperties::GetValueInput(node, 2); |
535 Type* length_type = NodeProperties::GetType(length); | 667 Type* length_type = NodeProperties::GetType(length); |
536 if (length_type->Is(Type::SignedSmall()) && | 668 if (length_type->Is(Type::SignedSmall()) && length_type->Min() >= 0 && |
537 length_type->Min() >= 0 && | 669 length_type->Max() <= kElementLoopUnrollLimit && |
538 length_type->Max() <= kElementLoopUnrollLimit) { | 670 length_type->Min() == length_type->Max()) { |
539 int capacity = static_cast<int>(length_type->Max()); | 671 int capacity = static_cast<int>(length_type->Max()); |
540 return ReduceNewArray(node, length, capacity, site); | 672 return ReduceNewArray(node, length, capacity, site); |
541 } | 673 } |
542 } | 674 } |
543 } | 675 } |
544 | 676 |
545 return NoChange(); | 677 return ReduceNewArrayToStubCall(node, site); |
546 } | 678 } |
547 | 679 |
548 Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) { | 680 Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) { |
549 DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode()); | 681 DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode()); |
550 CreateClosureParameters const& p = CreateClosureParametersOf(node->op()); | 682 CreateClosureParameters const& p = CreateClosureParametersOf(node->op()); |
551 Handle<SharedFunctionInfo> shared = p.shared_info(); | 683 Handle<SharedFunctionInfo> shared = p.shared_info(); |
552 | 684 |
553 Node* effect = NodeProperties::GetEffectInput(node); | 685 Node* effect = NodeProperties::GetEffectInput(node); |
554 Node* control = NodeProperties::GetControlInput(node); | 686 Node* control = NodeProperties::GetControlInput(node); |
555 Node* context = NodeProperties::GetContextInput(node); | 687 Node* context = NodeProperties::GetContextInput(node); |
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1130 return jsgraph()->simplified(); | 1262 return jsgraph()->simplified(); |
1131 } | 1263 } |
1132 | 1264 |
1133 MachineOperatorBuilder* JSCreateLowering::machine() const { | 1265 MachineOperatorBuilder* JSCreateLowering::machine() const { |
1134 return jsgraph()->machine(); | 1266 return jsgraph()->machine(); |
1135 } | 1267 } |
1136 | 1268 |
1137 } // namespace compiler | 1269 } // namespace compiler |
1138 } // namespace internal | 1270 } // namespace internal |
1139 } // namespace v8 | 1271 } // namespace v8 |
OLD | NEW |