| 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 |