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 | |
Michael Starzinger
2016/07/06 14:34:00
nit: We could DCHECK(arity > 1) here.
mvstanton
2016/07/06 14:48:45
Done.
| |
628 ArrayNArgumentsConstructorStub stub(isolate()); | |
629 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | |
630 isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), arity + 1, | |
631 CallDescriptor::kNeedsFrameState); | |
632 node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode())); | |
633 node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site)); | |
634 node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(arity)); | |
635 node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant()); | |
636 NodeProperties::ChangeOp(node, common()->Call(desc)); | |
637 return Changed(node); | |
638 } | |
639 | |
512 Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) { | 640 Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) { |
513 DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode()); | 641 DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode()); |
514 CreateArrayParameters const& p = CreateArrayParametersOf(node->op()); | 642 CreateArrayParameters const& p = CreateArrayParametersOf(node->op()); |
515 Node* target = NodeProperties::GetValueInput(node, 0); | 643 Node* target = NodeProperties::GetValueInput(node, 0); |
516 Node* new_target = NodeProperties::GetValueInput(node, 1); | 644 Node* new_target = NodeProperties::GetValueInput(node, 1); |
517 | 645 |
646 // TODO(mstarzinger): Array constructor can throw. Hook up exceptional edges. | |
647 if (NodeProperties::IsExceptionalCall(node)) return NoChange(); | |
648 | |
518 // TODO(bmeurer): Optimize the subclassing case. | 649 // TODO(bmeurer): Optimize the subclassing case. |
519 if (target != new_target) return NoChange(); | 650 if (target != new_target) return NoChange(); |
520 | 651 |
521 // Check if we have a feedback {site} on the {node}. | 652 // Check if we have a feedback {site} on the {node}. |
522 Handle<AllocationSite> site = p.site(); | 653 Handle<AllocationSite> site = p.site(); |
523 if (p.site().is_null()) return NoChange(); | 654 if (p.site().is_null()) return NoChange(); |
524 | 655 |
525 // Attempt to inline calls to the Array constructor for the relevant cases | 656 // Attempt to inline calls to the Array constructor for the relevant cases |
526 // where either no arguments are provided, or exactly one unsigned number | 657 // where either no arguments are provided, or exactly one unsigned number |
527 // argument is given. | 658 // argument is given. |
528 if (site->CanInlineCall()) { | 659 if (site->CanInlineCall()) { |
529 if (p.arity() == 0) { | 660 if (p.arity() == 0) { |
530 Node* length = jsgraph()->ZeroConstant(); | 661 Node* length = jsgraph()->ZeroConstant(); |
531 int capacity = JSArray::kPreallocatedArrayElements; | 662 int capacity = JSArray::kPreallocatedArrayElements; |
532 return ReduceNewArray(node, length, capacity, site); | 663 return ReduceNewArray(node, length, capacity, site); |
533 } else if (p.arity() == 1) { | 664 } else if (p.arity() == 1) { |
534 Node* length = NodeProperties::GetValueInput(node, 2); | 665 Node* length = NodeProperties::GetValueInput(node, 2); |
535 Type* length_type = NodeProperties::GetType(length); | 666 Type* length_type = NodeProperties::GetType(length); |
536 if (length_type->Is(Type::SignedSmall()) && | 667 if (length_type->Is(Type::SignedSmall()) && length_type->Min() >= 0 && |
537 length_type->Min() >= 0 && | 668 length_type->Max() <= kElementLoopUnrollLimit && |
538 length_type->Max() <= kElementLoopUnrollLimit) { | 669 length_type->Min() == length_type->Max()) { |
539 int capacity = static_cast<int>(length_type->Max()); | 670 int capacity = static_cast<int>(length_type->Max()); |
540 return ReduceNewArray(node, length, capacity, site); | 671 return ReduceNewArray(node, length, capacity, site); |
541 } | 672 } |
542 } | 673 } |
543 } | 674 } |
544 | 675 |
545 return NoChange(); | 676 return ReduceNewArrayToStubCall(node, site); |
546 } | 677 } |
547 | 678 |
548 Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) { | 679 Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) { |
549 DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode()); | 680 DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode()); |
550 CreateClosureParameters const& p = CreateClosureParametersOf(node->op()); | 681 CreateClosureParameters const& p = CreateClosureParametersOf(node->op()); |
551 Handle<SharedFunctionInfo> shared = p.shared_info(); | 682 Handle<SharedFunctionInfo> shared = p.shared_info(); |
552 | 683 |
553 Node* effect = NodeProperties::GetEffectInput(node); | 684 Node* effect = NodeProperties::GetEffectInput(node); |
554 Node* control = NodeProperties::GetControlInput(node); | 685 Node* control = NodeProperties::GetControlInput(node); |
555 Node* context = NodeProperties::GetContextInput(node); | 686 Node* context = NodeProperties::GetContextInput(node); |
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1130 return jsgraph()->simplified(); | 1261 return jsgraph()->simplified(); |
1131 } | 1262 } |
1132 | 1263 |
1133 MachineOperatorBuilder* JSCreateLowering::machine() const { | 1264 MachineOperatorBuilder* JSCreateLowering::machine() const { |
1134 return jsgraph()->machine(); | 1265 return jsgraph()->machine(); |
1135 } | 1266 } |
1136 | 1267 |
1137 } // namespace compiler | 1268 } // namespace compiler |
1138 } // namespace internal | 1269 } // namespace internal |
1139 } // namespace v8 | 1270 } // namespace v8 |
OLD | NEW |