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/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 // Check if argArray is an arguments object, and {node} is the only value | 97 // Check if argArray is an arguments object, and {node} is the only value |
98 // user of argArray (except for value uses in frame states). | 98 // user of argArray (except for value uses in frame states). |
99 Node* arg_array = NodeProperties::GetValueInput(node, 3); | 99 Node* arg_array = NodeProperties::GetValueInput(node, 3); |
100 if (arg_array->opcode() != IrOpcode::kJSCreateArguments) return NoChange(); | 100 if (arg_array->opcode() != IrOpcode::kJSCreateArguments) return NoChange(); |
101 for (Edge edge : arg_array->use_edges()) { | 101 for (Edge edge : arg_array->use_edges()) { |
102 if (edge.from()->opcode() == IrOpcode::kStateValues) continue; | 102 if (edge.from()->opcode() == IrOpcode::kStateValues) continue; |
103 if (!NodeProperties::IsValueEdge(edge)) continue; | 103 if (!NodeProperties::IsValueEdge(edge)) continue; |
104 if (edge.from() == node) continue; | 104 if (edge.from() == node) continue; |
105 return NoChange(); | 105 return NoChange(); |
106 } | 106 } |
107 // Get to the actual frame state from which to extract the arguments; | 107 // Check if the arguments can be handled in the fast case (i.e. we don't |
108 // we can only optimize this in case the {node} was already inlined into | 108 // have aliased sloppy arguments), and compute the {start_index} for |
109 // some other function (and same for the {arg_array}). | 109 // rest parameters. |
110 CreateArgumentsType type = CreateArgumentsTypeOf(arg_array->op()); | 110 CreateArgumentsType const type = CreateArgumentsTypeOf(arg_array->op()); |
111 Node* frame_state = NodeProperties::GetFrameStateInput(arg_array); | 111 Node* frame_state = NodeProperties::GetFrameStateInput(arg_array); |
112 Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput); | |
113 if (outer_state->opcode() != IrOpcode::kFrameState) return NoChange(); | |
114 FrameStateInfo outer_info = OpParameter<FrameStateInfo>(outer_state); | |
115 if (outer_info.type() == FrameStateType::kArgumentsAdaptor) { | |
116 // Need to take the parameters from the arguments adaptor. | |
117 frame_state = outer_state; | |
118 } | |
119 FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state); | 112 FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state); |
120 int start_index = 0; | 113 int start_index = 0; |
121 if (type == CreateArgumentsType::kMappedArguments) { | 114 if (type == CreateArgumentsType::kMappedArguments) { |
122 // Mapped arguments (sloppy mode) cannot be handled if they are aliased. | 115 // Mapped arguments (sloppy mode) cannot be handled if they are aliased. |
123 Handle<SharedFunctionInfo> shared; | 116 Handle<SharedFunctionInfo> shared; |
124 if (!state_info.shared_info().ToHandle(&shared)) return NoChange(); | 117 if (!state_info.shared_info().ToHandle(&shared)) return NoChange(); |
125 if (shared->internal_formal_parameter_count() != 0) return NoChange(); | 118 if (shared->internal_formal_parameter_count() != 0) return NoChange(); |
126 } else if (type == CreateArgumentsType::kRestParameter) { | 119 } else if (type == CreateArgumentsType::kRestParameter) { |
127 Handle<SharedFunctionInfo> shared; | 120 Handle<SharedFunctionInfo> shared; |
128 if (!state_info.shared_info().ToHandle(&shared)) return NoChange(); | 121 if (!state_info.shared_info().ToHandle(&shared)) return NoChange(); |
129 start_index = shared->internal_formal_parameter_count(); | 122 start_index = shared->internal_formal_parameter_count(); |
130 } | 123 } |
| 124 // Check if are applying to inlined arguments or to the arguments of |
| 125 // the outermost function. |
| 126 Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput); |
| 127 if (outer_state->opcode() != IrOpcode::kFrameState) { |
| 128 // TODO(jarin,bmeurer): Support the NewUnmappedArgumentsElement and |
| 129 // NewRestParameterElements in the EscapeAnalysis and Deoptimizer |
| 130 // instead, then we don't need this hack. |
| 131 if (type != CreateArgumentsType::kRestParameter) { |
| 132 // There are no other uses of the {arg_array} except in StateValues, |
| 133 // so we just replace {arg_array} with a marker for the Deoptimizer |
| 134 // that this refers to the arguments object. |
| 135 Node* arguments = graph()->NewNode(common()->ArgumentsObjectState()); |
| 136 ReplaceWithValue(arg_array, arguments); |
| 137 } |
| 138 |
| 139 // Reduce {node} to a JSCallForwardVarargs operation, which just |
| 140 // re-pushes the incoming arguments and calls the {target}. |
| 141 node->RemoveInput(0); // Function.prototype.apply |
| 142 node->RemoveInput(2); // arguments |
| 143 NodeProperties::ChangeOp(node, javascript()->CallForwardVarargs( |
| 144 start_index, p.tail_call_mode())); |
| 145 return Changed(node); |
| 146 } |
| 147 // Get to the actual frame state from which to extract the arguments; |
| 148 // we can only optimize this in case the {node} was already inlined into |
| 149 // some other function (and same for the {arg_array}). |
| 150 FrameStateInfo outer_info = OpParameter<FrameStateInfo>(outer_state); |
| 151 if (outer_info.type() == FrameStateType::kArgumentsAdaptor) { |
| 152 // Need to take the parameters from the arguments adaptor. |
| 153 frame_state = outer_state; |
| 154 } |
131 // Remove the argArray input from the {node}. | 155 // Remove the argArray input from the {node}. |
132 node->RemoveInput(static_cast<int>(--arity)); | 156 node->RemoveInput(static_cast<int>(--arity)); |
133 // Add the actual parameters to the {node}, skipping the receiver. | 157 // Add the actual parameters to the {node}, skipping the receiver, |
| 158 // starting from {start_index}. |
134 Node* const parameters = frame_state->InputAt(kFrameStateParametersInput); | 159 Node* const parameters = frame_state->InputAt(kFrameStateParametersInput); |
135 for (int i = start_index + 1; i < state_info.parameter_count(); ++i) { | 160 for (int i = start_index + 1; i < parameters->InputCount(); ++i) { |
136 node->InsertInput(graph()->zone(), static_cast<int>(arity), | 161 node->InsertInput(graph()->zone(), static_cast<int>(arity), |
137 parameters->InputAt(i)); | 162 parameters->InputAt(i)); |
138 ++arity; | 163 ++arity; |
139 } | 164 } |
140 // Drop the {target} from the {node}. | 165 // Drop the {target} from the {node}. |
141 node->RemoveInput(0); | 166 node->RemoveInput(0); |
142 --arity; | 167 --arity; |
143 } else { | 168 } else { |
144 return NoChange(); | 169 return NoChange(); |
145 } | 170 } |
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
674 return jsgraph()->javascript(); | 699 return jsgraph()->javascript(); |
675 } | 700 } |
676 | 701 |
677 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { | 702 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { |
678 return jsgraph()->simplified(); | 703 return jsgraph()->simplified(); |
679 } | 704 } |
680 | 705 |
681 } // namespace compiler | 706 } // namespace compiler |
682 } // namespace internal | 707 } // namespace internal |
683 } // namespace v8 | 708 } // namespace v8 |
OLD | NEW |