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 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 return NoChange(); | 298 return NoChange(); |
301 } | 299 } |
302 | 300 |
303 TRACE("Inlining %s into %s\n", | 301 TRACE("Inlining %s into %s\n", |
304 function->shared()->DebugName()->ToCString().get(), | 302 function->shared()->DebugName()->ToCString().get(), |
305 info_->shared_info()->DebugName()->ToCString().get()); | 303 info_->shared_info()->DebugName()->ToCString().get()); |
306 | 304 |
307 Graph graph(info.zone()); | 305 Graph graph(info.zone()); |
308 JSGraph jsgraph(info.isolate(), &graph, jsgraph_->common(), | 306 JSGraph jsgraph(info.isolate(), &graph, jsgraph_->common(), |
309 jsgraph_->javascript(), jsgraph_->machine()); | 307 jsgraph_->javascript(), jsgraph_->machine()); |
| 308 AstGraphBuilder graph_builder(local_zone_, &info, &jsgraph); |
| 309 graph_builder.CreateGraph(false); |
310 | 310 |
311 // The inlinee specializes to the context from the JSFunction object. | 311 // The inlinee specializes to the context from the JSFunction object. |
312 // TODO(turbofan): We might want to load the context from the JSFunction at | 312 // TODO(turbofan): We might want to load the context from the JSFunction at |
313 // runtime in case we only know the SharedFunctionInfo once we have dynamic | 313 // runtime in case we only know the SharedFunctionInfo once we have dynamic |
314 // type feedback in the compiler. | 314 // type feedback in the compiler. |
315 AstGraphBuilder graph_builder(local_zone_, &info, &jsgraph); | 315 Node* context = jsgraph_->Constant(handle(function->context())); |
316 graph_builder.CreateGraph(true, false); | |
317 | 316 |
318 CopyVisitor visitor(&graph, jsgraph_->graph(), info.zone()); | 317 CopyVisitor visitor(&graph, jsgraph_->graph(), info.zone()); |
319 visitor.CopyGraph(); | 318 visitor.CopyGraph(); |
320 | 319 |
321 Node* start = visitor.GetCopy(graph.start()); | 320 Node* start = visitor.GetCopy(graph.start()); |
322 Node* end = visitor.GetCopy(graph.end()); | 321 Node* end = visitor.GetCopy(graph.end()); |
323 | 322 |
324 Node* frame_state = call.frame_state(); | 323 Node* frame_state = call.frame_state(); |
325 size_t const inlinee_formal_parameters = start->op()->ValueOutputCount() - 3; | 324 size_t const inlinee_formal_parameters = start->op()->ValueOutputCount() - 3; |
326 // Insert argument adaptor frame if required. | 325 // Insert argument adaptor frame if required. |
327 if (call.formal_arguments() != inlinee_formal_parameters) { | 326 if (call.formal_arguments() != inlinee_formal_parameters) { |
328 // In strong mode, in case of too few arguments we need to throw a | 327 // In strong mode, in case of too few arguments we need to throw a |
329 // TypeError so we must not inline this call. | 328 // TypeError so we must not inline this call. |
330 if (is_strong(info.language_mode()) && | 329 if (is_strong(info.language_mode()) && |
331 call.formal_arguments() < inlinee_formal_parameters) { | 330 call.formal_arguments() < inlinee_formal_parameters) { |
332 return NoChange(); | 331 return NoChange(); |
333 } | 332 } |
334 frame_state = CreateArgumentsAdaptorFrameState(&call, info.shared_info(), | 333 frame_state = CreateArgumentsAdaptorFrameState(&call, info.shared_info(), |
335 info.zone()); | 334 info.zone()); |
336 } | 335 } |
337 | 336 |
338 // Remember that we inlined this function. | 337 // Remember that we inlined this function. |
339 info_->AddInlinedFunction(info.shared_info()); | 338 info_->AddInlinedFunction(info.shared_info()); |
340 | 339 |
341 return InlineCall(node, frame_state, start, end); | 340 return InlineCall(node, context, frame_state, start, end); |
342 } | 341 } |
343 | 342 |
344 } // namespace compiler | 343 } // namespace compiler |
345 } // namespace internal | 344 } // namespace internal |
346 } // namespace v8 | 345 } // namespace v8 |
OLD | NEW |