| 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/access-builder.h" | 10 #include "src/compiler/access-builder.h" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 case IrOpcode::kJSCallWithArrayLike: | 33 case IrOpcode::kJSCallWithArrayLike: |
| 34 return ReduceJSCallWithArrayLike(node); | 34 return ReduceJSCallWithArrayLike(node); |
| 35 case IrOpcode::kJSCallWithSpread: | 35 case IrOpcode::kJSCallWithSpread: |
| 36 return ReduceJSCallWithSpread(node); | 36 return ReduceJSCallWithSpread(node); |
| 37 default: | 37 default: |
| 38 break; | 38 break; |
| 39 } | 39 } |
| 40 return NoChange(); | 40 return NoChange(); |
| 41 } | 41 } |
| 42 | 42 |
| 43 void JSCallReducer::Finalize() { |
| 44 std::set<Node*> const waitlist = std::move(waitlist_); |
| 45 for (Node* node : waitlist) { |
| 46 if (!node->IsDead()) { |
| 47 Reduction const reduction = Reduce(node); |
| 48 if (reduction.Changed()) { |
| 49 Node* replacement = reduction.replacement(); |
| 50 if (replacement != node) { |
| 51 Replace(node, replacement); |
| 52 } |
| 53 } |
| 54 } |
| 55 } |
| 56 } |
| 43 | 57 |
| 44 // ES6 section 22.1.1 The Array Constructor | 58 // ES6 section 22.1.1 The Array Constructor |
| 45 Reduction JSCallReducer::ReduceArrayConstructor(Node* node) { | 59 Reduction JSCallReducer::ReduceArrayConstructor(Node* node) { |
| 46 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); | 60 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); |
| 47 Node* target = NodeProperties::GetValueInput(node, 0); | 61 Node* target = NodeProperties::GetValueInput(node, 0); |
| 48 CallParameters const& p = CallParametersOf(node->op()); | 62 CallParameters const& p = CallParametersOf(node->op()); |
| 49 | 63 |
| 50 // Check if we have an allocation site from the CallIC. | 64 // Check if we have an allocation site from the CallIC. |
| 51 Handle<AllocationSite> site; | 65 Handle<AllocationSite> site; |
| 52 if (p.feedback().IsValid()) { | 66 if (p.feedback().IsValid()) { |
| (...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 !isolate()->initial_array_iterator_prototype_map()->is_stable()) { | 714 !isolate()->initial_array_iterator_prototype_map()->is_stable()) { |
| 701 return NoChange(); | 715 return NoChange(); |
| 702 } | 716 } |
| 703 | 717 |
| 704 // Check if {arguments_list} is an arguments object, and {node} is the only | 718 // Check if {arguments_list} is an arguments object, and {node} is the only |
| 705 // value user of {arguments_list} (except for value uses in frame states). | 719 // value user of {arguments_list} (except for value uses in frame states). |
| 706 Node* arguments_list = NodeProperties::GetValueInput(node, arity); | 720 Node* arguments_list = NodeProperties::GetValueInput(node, arity); |
| 707 if (arguments_list->opcode() != IrOpcode::kJSCreateArguments) | 721 if (arguments_list->opcode() != IrOpcode::kJSCreateArguments) |
| 708 return NoChange(); | 722 return NoChange(); |
| 709 for (Edge edge : arguments_list->use_edges()) { | 723 for (Edge edge : arguments_list->use_edges()) { |
| 724 if (!NodeProperties::IsValueEdge(edge)) continue; |
| 710 Node* const user = edge.from(); | 725 Node* const user = edge.from(); |
| 711 if (user == node) continue; | 726 switch (user->opcode()) { |
| 712 // Ignore uses as frame state's locals or parameters. | 727 case IrOpcode::kStateValues: |
| 713 if (user->opcode() == IrOpcode::kStateValues) continue; | 728 // Ignore uses as frame state's locals or parameters. |
| 714 // Ignore uses as frame state's accumulator. | 729 continue; |
| 715 if (user->opcode() == IrOpcode::kFrameState && | 730 case IrOpcode::kFrameState: |
| 716 user->InputAt(2) == arguments_list) { | 731 // Ignore uses as frame state's accumulator. |
| 717 continue; | 732 if (user->InputAt(2) == arguments_list) continue; |
| 733 break; |
| 734 case IrOpcode::kReferenceEqual: |
| 735 // Ignore uses for comparisons. |
| 736 continue; |
| 737 case IrOpcode::kJSCallWithArrayLike: |
| 738 // Ignore uses as argumentsList input to calls with array like. |
| 739 if (user->InputAt(2) == arguments_list) continue; |
| 740 break; |
| 741 case IrOpcode::kJSCallWithSpread: { |
| 742 // Ignore uses as spread input to calls with spread. |
| 743 SpreadWithArityParameter p = SpreadWithArityParameterOf(user->op()); |
| 744 int const arity = static_cast<int>(p.arity() - 1); |
| 745 if (user->InputAt(arity) == arguments_list) continue; |
| 746 break; |
| 747 } |
| 748 case IrOpcode::kJSConstructWithSpread: { |
| 749 // Ignore uses as spread input to construct with spread. |
| 750 SpreadWithArityParameter p = SpreadWithArityParameterOf(user->op()); |
| 751 int const arity = static_cast<int>(p.arity() - 2); |
| 752 if (user->InputAt(arity) == arguments_list) continue; |
| 753 break; |
| 754 } |
| 755 default: |
| 756 break; |
| 718 } | 757 } |
| 719 if (!NodeProperties::IsValueEdge(edge)) continue; | 758 // We currently reduce the {node} to something better than what |
| 759 // it already is, but we might be able to do something about the |
| 760 // {node} later, so put it onto the waitlist and try again during |
| 761 // the finalization phase. |
| 762 waitlist_.insert(node); |
| 720 return NoChange(); | 763 return NoChange(); |
| 721 } | 764 } |
| 722 | 765 |
| 723 // Get to the actual frame state from which to extract the arguments; | 766 // Get to the actual frame state from which to extract the arguments; |
| 724 // we can only optimize this in case the {node} was already inlined into | 767 // we can only optimize this in case the {node} was already inlined into |
| 725 // some other function (and same for the {arguments_list}). | 768 // some other function (and same for the {arguments_list}). |
| 726 CreateArgumentsType const type = CreateArgumentsTypeOf(arguments_list->op()); | 769 CreateArgumentsType const type = CreateArgumentsTypeOf(arguments_list->op()); |
| 727 Node* frame_state = NodeProperties::GetFrameStateInput(arguments_list); | 770 Node* frame_state = NodeProperties::GetFrameStateInput(arguments_list); |
| 728 FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state); | 771 FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state); |
| 729 int start_index = 0; | 772 int start_index = 0; |
| (...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1191 return jsgraph()->javascript(); | 1234 return jsgraph()->javascript(); |
| 1192 } | 1235 } |
| 1193 | 1236 |
| 1194 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { | 1237 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { |
| 1195 return jsgraph()->simplified(); | 1238 return jsgraph()->simplified(); |
| 1196 } | 1239 } |
| 1197 | 1240 |
| 1198 } // namespace compiler | 1241 } // namespace compiler |
| 1199 } // namespace internal | 1242 } // namespace internal |
| 1200 } // namespace v8 | 1243 } // namespace v8 |
| OLD | NEW |