OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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-inlining.h" | 5 #include "src/compiler/js-inlining.h" |
6 | 6 |
7 #include "src/ast.h" | 7 #include "src/ast.h" |
8 #include "src/ast-numbering.h" | 8 #include "src/ast-numbering.h" |
9 #include "src/compiler/all-nodes.h" | 9 #include "src/compiler/all-nodes.h" |
10 #include "src/compiler/ast-graph-builder.h" | 10 #include "src/compiler/ast-graph-builder.h" |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 private: | 108 private: |
109 Operator const sentinel_op_; | 109 Operator const sentinel_op_; |
110 Node* const sentinel_; | 110 Node* const sentinel_; |
111 NodeVector copies_; | 111 NodeVector copies_; |
112 Graph* const source_graph_; | 112 Graph* const source_graph_; |
113 Graph* const target_graph_; | 113 Graph* const target_graph_; |
114 Zone* const temp_zone_; | 114 Zone* const temp_zone_; |
115 }; | 115 }; |
116 | 116 |
117 | 117 |
118 Reduction JSInliner::InlineCall(Node* call, Node* frame_state, Node* start, | 118 Reduction JSInliner::InlineCall(Node* call, Node* context, Node* frame_state, |
119 Node* end) { | 119 Node* start, Node* end) { |
120 // The scheduler is smart enough to place our code; we just ensure {control} | 120 // The scheduler is smart enough to place our code; we just ensure {control} |
121 // becomes the control input of the start of the inlinee, and {effect} becomes | 121 // becomes the control input of the start of the inlinee, and {effect} becomes |
122 // the effect input of the start of the inlinee. | 122 // the effect input of the start of the inlinee. |
123 Node* control = NodeProperties::GetControlInput(call); | 123 Node* control = NodeProperties::GetControlInput(call); |
124 Node* effect = NodeProperties::GetEffectInput(call); | 124 Node* effect = NodeProperties::GetEffectInput(call); |
125 | 125 |
126 // Context is last argument. | 126 // Context is last argument. |
127 int const inlinee_context_index = | 127 int const inlinee_context_index = |
128 static_cast<int>(start->op()->ValueOutputCount()) - 1; | 128 static_cast<int>(start->op()->ValueOutputCount()) - 1; |
129 | 129 |
130 // {inliner_inputs} counts JSFunction, Receiver, arguments, but not | 130 // {inliner_inputs} counts JSFunction, Receiver, arguments, but not |
131 // context, effect, control. | 131 // context, effect, control. |
132 int inliner_inputs = call->op()->ValueInputCount(); | 132 int inliner_inputs = call->op()->ValueInputCount(); |
133 // Iterate over all uses of the start node. | 133 // Iterate over all uses of the start node. |
134 for (Edge edge : start->use_edges()) { | 134 for (Edge edge : start->use_edges()) { |
135 Node* use = edge.from(); | 135 Node* use = edge.from(); |
136 switch (use->opcode()) { | 136 switch (use->opcode()) { |
137 case IrOpcode::kParameter: { | 137 case IrOpcode::kParameter: { |
138 int index = 1 + ParameterIndexOf(use->op()); | 138 int index = 1 + ParameterIndexOf(use->op()); |
139 if (index < inliner_inputs && index < inlinee_context_index) { | 139 if (index < inliner_inputs && index < inlinee_context_index) { |
140 // There is an input from the call, and the index is a value | 140 // There is an input from the call, and the index is a value |
141 // projection but not the context, so rewire the input. | 141 // projection but not the context, so rewire the input. |
142 ReplaceWithValue(use, call->InputAt(index)); | 142 Replace(use, call->InputAt(index)); |
143 } else if (index == inlinee_context_index) { | 143 } else if (index == inlinee_context_index) { |
144 // TODO(turbofan): We always context specialize inlinees currently, so | 144 Replace(use, context); |
145 // we should never get here. | |
146 UNREACHABLE(); | |
147 } else if (index < inlinee_context_index) { | 145 } else if (index < inlinee_context_index) { |
148 // Call has fewer arguments than required, fill with undefined. | 146 // Call has fewer arguments than required, fill with undefined. |
149 ReplaceWithValue(use, jsgraph_->UndefinedConstant()); | 147 Replace(use, jsgraph_->UndefinedConstant()); |
150 } else { | 148 } else { |
151 // We got too many arguments, discard for now. | 149 // We got too many arguments, discard for now. |
152 // TODO(sigurds): Fix to treat arguments array correctly. | 150 // TODO(sigurds): Fix to treat arguments array correctly. |
153 } | 151 } |
154 break; | 152 break; |
155 } | 153 } |
156 default: | 154 default: |
157 if (NodeProperties::IsEffectEdge(edge)) { | 155 if (NodeProperties::IsEffectEdge(edge)) { |
158 edge.UpdateTo(effect); | 156 edge.UpdateTo(effect); |
159 } else if (NodeProperties::IsControlEdge(edge)) { | 157 } else if (NodeProperties::IsControlEdge(edge)) { |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 return NoChange(); | 282 return NoChange(); |
285 } | 283 } |
286 | 284 |
287 TRACE("Inlining %s into %s\n", | 285 TRACE("Inlining %s into %s\n", |
288 function->shared()->DebugName()->ToCString().get(), | 286 function->shared()->DebugName()->ToCString().get(), |
289 info_->shared_info()->DebugName()->ToCString().get()); | 287 info_->shared_info()->DebugName()->ToCString().get()); |
290 | 288 |
291 Graph graph(info.zone()); | 289 Graph graph(info.zone()); |
292 JSGraph jsgraph(info.isolate(), &graph, jsgraph_->common(), | 290 JSGraph jsgraph(info.isolate(), &graph, jsgraph_->common(), |
293 jsgraph_->javascript(), jsgraph_->machine()); | 291 jsgraph_->javascript(), jsgraph_->machine()); |
| 292 AstGraphBuilder graph_builder(local_zone_, &info, &jsgraph); |
| 293 graph_builder.CreateGraph(false); |
294 | 294 |
295 // The inlinee specializes to the context from the JSFunction object. | 295 // The inlinee specializes to the context from the JSFunction object. |
296 // TODO(turbofan): We might want to load the context from the JSFunction at | 296 // TODO(turbofan): We might want to load the context from the JSFunction at |
297 // runtime in case we only know the SharedFunctionInfo once we have dynamic | 297 // runtime in case we only know the SharedFunctionInfo once we have dynamic |
298 // type feedback in the compiler. | 298 // type feedback in the compiler. |
299 AstGraphBuilder graph_builder(local_zone_, &info, &jsgraph); | 299 Node* context = jsgraph_->Constant(handle(function->context())); |
300 graph_builder.CreateGraph(true, false); | |
301 | 300 |
302 CopyVisitor visitor(&graph, jsgraph_->graph(), info.zone()); | 301 CopyVisitor visitor(&graph, jsgraph_->graph(), info.zone()); |
303 visitor.CopyGraph(); | 302 visitor.CopyGraph(); |
304 | 303 |
305 Node* start = visitor.GetCopy(graph.start()); | 304 Node* start = visitor.GetCopy(graph.start()); |
306 Node* end = visitor.GetCopy(graph.end()); | 305 Node* end = visitor.GetCopy(graph.end()); |
307 | 306 |
308 Node* frame_state = call.frame_state(); | 307 Node* frame_state = call.frame_state(); |
309 size_t const inlinee_formal_parameters = start->op()->ValueOutputCount() - 3; | 308 size_t const inlinee_formal_parameters = start->op()->ValueOutputCount() - 3; |
310 // Insert argument adaptor frame if required. | 309 // Insert argument adaptor frame if required. |
311 if (call.formal_arguments() != inlinee_formal_parameters) { | 310 if (call.formal_arguments() != inlinee_formal_parameters) { |
312 // In strong mode, in case of too few arguments we need to throw a | 311 // In strong mode, in case of too few arguments we need to throw a |
313 // TypeError so we must not inline this call. | 312 // TypeError so we must not inline this call. |
314 if (is_strong(info.language_mode()) && | 313 if (is_strong(info.language_mode()) && |
315 call.formal_arguments() < inlinee_formal_parameters) { | 314 call.formal_arguments() < inlinee_formal_parameters) { |
316 return NoChange(); | 315 return NoChange(); |
317 } | 316 } |
318 frame_state = CreateArgumentsAdaptorFrameState(&call, info.shared_info(), | 317 frame_state = CreateArgumentsAdaptorFrameState(&call, info.shared_info(), |
319 info.zone()); | 318 info.zone()); |
320 } | 319 } |
321 | 320 |
322 // Remember that we inlined this function. | 321 // Remember that we inlined this function. |
323 info_->AddInlinedFunction(info.shared_info()); | 322 info_->AddInlinedFunction(info.shared_info()); |
324 | 323 |
325 return InlineCall(node, frame_state, start, end); | 324 return InlineCall(node, context, frame_state, start, end); |
326 } | 325 } |
327 | 326 |
328 } // namespace compiler | 327 } // namespace compiler |
329 } // namespace internal | 328 } // namespace internal |
330 } // namespace v8 | 329 } // namespace v8 |
OLD | NEW |