OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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-call-reducer.h" | 5 #include "src/compiler/js-call-reducer.h" |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
10 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/js-graph.h" |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 if (node->opcode() == IrOpcode::kJSCallWithSpread) { | 478 if (node->opcode() == IrOpcode::kJSCallWithSpread) { |
479 NodeProperties::ChangeOp( | 479 NodeProperties::ChangeOp( |
480 node, javascript()->Call(arity + 1, 7, VectorSlotPair())); | 480 node, javascript()->Call(arity + 1, 7, VectorSlotPair())); |
481 } else { | 481 } else { |
482 NodeProperties::ChangeOp( | 482 NodeProperties::ChangeOp( |
483 node, javascript()->Construct(arity + 2, 7, VectorSlotPair())); | 483 node, javascript()->Construct(arity + 2, 7, VectorSlotPair())); |
484 } | 484 } |
485 return Changed(node); | 485 return Changed(node); |
486 } | 486 } |
487 | 487 |
| 488 namespace { |
| 489 |
| 490 bool ShouldUseCallICFeedback(Node* node) { |
| 491 HeapObjectMatcher m(node); |
| 492 if (m.HasValue() || m.IsJSCreateClosure()) { |
| 493 // Don't use CallIC feedback when we know the function |
| 494 // being called, i.e. either know the closure itself or |
| 495 // at least the SharedFunctionInfo. |
| 496 return false; |
| 497 } else if (m.IsPhi()) { |
| 498 // Protect against endless loops here. |
| 499 Node* control = NodeProperties::GetControlInput(node); |
| 500 if (control->opcode() == IrOpcode::kLoop) return false; |
| 501 // Check if {node} is a Phi of nodes which shouldn't |
| 502 // use CallIC feedback (not looking through loops). |
| 503 int const value_input_count = m.node()->op()->ValueInputCount(); |
| 504 for (int n = 0; n < value_input_count; ++n) { |
| 505 if (ShouldUseCallICFeedback(node->InputAt(n))) return true; |
| 506 } |
| 507 return false; |
| 508 } |
| 509 return true; |
| 510 } |
| 511 |
| 512 } // namespace |
| 513 |
488 Reduction JSCallReducer::ReduceJSCall(Node* node) { | 514 Reduction JSCallReducer::ReduceJSCall(Node* node) { |
489 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); | 515 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); |
490 CallParameters const& p = CallParametersOf(node->op()); | 516 CallParameters const& p = CallParametersOf(node->op()); |
491 Node* target = NodeProperties::GetValueInput(node, 0); | 517 Node* target = NodeProperties::GetValueInput(node, 0); |
492 Node* control = NodeProperties::GetControlInput(node); | 518 Node* control = NodeProperties::GetControlInput(node); |
493 Node* effect = NodeProperties::GetEffectInput(node); | 519 Node* effect = NodeProperties::GetEffectInput(node); |
494 | 520 |
495 // Try to specialize JSCall {node}s with constant {target}s. | 521 // Try to specialize JSCall {node}s with constant {target}s. |
496 HeapObjectMatcher m(target); | 522 HeapObjectMatcher m(target); |
497 if (m.HasValue()) { | 523 if (m.HasValue()) { |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 // Check that the {target} is still the {array_function}. | 643 // Check that the {target} is still the {array_function}. |
618 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target, | 644 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target, |
619 array_function); | 645 array_function); |
620 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control); | 646 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control); |
621 | 647 |
622 // Turn the {node} into a {JSCreateArray} call. | 648 // Turn the {node} into a {JSCreateArray} call. |
623 NodeProperties::ReplaceValueInput(node, array_function, 0); | 649 NodeProperties::ReplaceValueInput(node, array_function, 0); |
624 NodeProperties::ReplaceEffectInput(node, effect); | 650 NodeProperties::ReplaceEffectInput(node, effect); |
625 return ReduceArrayConstructor(node); | 651 return ReduceArrayConstructor(node); |
626 } else if (feedback->IsWeakCell()) { | 652 } else if (feedback->IsWeakCell()) { |
| 653 // Check if we want to use CallIC feedback here. |
| 654 if (!ShouldUseCallICFeedback(target)) return NoChange(); |
| 655 |
627 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); | 656 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); |
628 if (cell->value()->IsJSFunction()) { | 657 if (cell->value()->IsJSFunction()) { |
629 Node* target_function = | 658 Node* target_function = |
630 jsgraph()->Constant(handle(cell->value(), isolate())); | 659 jsgraph()->Constant(handle(cell->value(), isolate())); |
631 | 660 |
632 // Check that the {target} is still the {target_function}. | 661 // Check that the {target} is still the {target_function}. |
633 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target, | 662 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target, |
634 target_function); | 663 target_function); |
635 effect = | 664 effect = |
636 graph()->NewNode(simplified()->CheckIf(), check, effect, control); | 665 graph()->NewNode(simplified()->CheckIf(), check, effect, control); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 // Turn the {node} into a {JSCreateArray} call. | 766 // Turn the {node} into a {JSCreateArray} call. |
738 NodeProperties::ReplaceEffectInput(node, effect); | 767 NodeProperties::ReplaceEffectInput(node, effect); |
739 for (int i = arity; i > 0; --i) { | 768 for (int i = arity; i > 0; --i) { |
740 NodeProperties::ReplaceValueInput( | 769 NodeProperties::ReplaceValueInput( |
741 node, NodeProperties::GetValueInput(node, i), i + 1); | 770 node, NodeProperties::GetValueInput(node, i), i + 1); |
742 } | 771 } |
743 NodeProperties::ReplaceValueInput(node, new_target, 1); | 772 NodeProperties::ReplaceValueInput(node, new_target, 1); |
744 NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site)); | 773 NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site)); |
745 return Changed(node); | 774 return Changed(node); |
746 } else if (feedback->IsWeakCell()) { | 775 } else if (feedback->IsWeakCell()) { |
| 776 // Check if we want to use CallIC feedback here. |
| 777 if (!ShouldUseCallICFeedback(target)) return NoChange(); |
| 778 |
747 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); | 779 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); |
748 if (cell->value()->IsJSFunction()) { | 780 if (cell->value()->IsJSFunction()) { |
749 Node* target_function = | 781 Node* target_function = |
750 jsgraph()->Constant(handle(cell->value(), isolate())); | 782 jsgraph()->Constant(handle(cell->value(), isolate())); |
751 | 783 |
752 // Check that the {target} is still the {target_function}. | 784 // Check that the {target} is still the {target_function}. |
753 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target, | 785 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target, |
754 target_function); | 786 target_function); |
755 effect = | 787 effect = |
756 graph()->NewNode(simplified()->CheckIf(), check, effect, control); | 788 graph()->NewNode(simplified()->CheckIf(), check, effect, control); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
795 return jsgraph()->javascript(); | 827 return jsgraph()->javascript(); |
796 } | 828 } |
797 | 829 |
798 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { | 830 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { |
799 return jsgraph()->simplified(); | 831 return jsgraph()->simplified(); |
800 } | 832 } |
801 | 833 |
802 } // namespace compiler | 834 } // namespace compiler |
803 } // namespace internal | 835 } // namespace internal |
804 } // namespace v8 | 836 } // namespace v8 |
OLD | NEW |