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