Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: src/compiler/js-inlining.cc

Issue 2211963002: [turbofan] Refactor js-inlining.cc to use more graph(), jsgraph(), javascript(), common(). (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@p8-base
Patch Set: Doh. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/js-inlining.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/ast-numbering.h" 7 #include "src/ast/ast-numbering.h"
8 #include "src/ast/ast.h" 8 #include "src/ast/ast.h"
9 #include "src/ast/scopes.h" 9 #include "src/ast/scopes.h"
10 #include "src/compiler.h" 10 #include "src/compiler.h"
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 DCHECK_LE(index, inlinee_context_index); 99 DCHECK_LE(index, inlinee_context_index);
100 if (index < inliner_inputs && index < inlinee_new_target_index) { 100 if (index < inliner_inputs && index < inlinee_new_target_index) {
101 // There is an input from the call, and the index is a value 101 // There is an input from the call, and the index is a value
102 // projection but not the context, so rewire the input. 102 // projection but not the context, so rewire the input.
103 Replace(use, call->InputAt(index)); 103 Replace(use, call->InputAt(index));
104 } else if (index == inlinee_new_target_index) { 104 } else if (index == inlinee_new_target_index) {
105 // The projection is requesting the new target value. 105 // The projection is requesting the new target value.
106 Replace(use, new_target); 106 Replace(use, new_target);
107 } else if (index == inlinee_arity_index) { 107 } else if (index == inlinee_arity_index) {
108 // The projection is requesting the number of arguments. 108 // The projection is requesting the number of arguments.
109 Replace(use, jsgraph_->Int32Constant(inliner_inputs - 2)); 109 Replace(use, jsgraph()->Int32Constant(inliner_inputs - 2));
110 } else if (index == inlinee_context_index) { 110 } else if (index == inlinee_context_index) {
111 // The projection is requesting the inlinee function context. 111 // The projection is requesting the inlinee function context.
112 Replace(use, context); 112 Replace(use, context);
113 } else { 113 } else {
114 // Call has fewer arguments than required, fill with undefined. 114 // Call has fewer arguments than required, fill with undefined.
115 Replace(use, jsgraph_->UndefinedConstant()); 115 Replace(use, jsgraph()->UndefinedConstant());
116 } 116 }
117 break; 117 break;
118 } 118 }
119 default: 119 default:
120 if (NodeProperties::IsEffectEdge(edge)) { 120 if (NodeProperties::IsEffectEdge(edge)) {
121 edge.UpdateTo(effect); 121 edge.UpdateTo(effect);
122 } else if (NodeProperties::IsControlEdge(edge)) { 122 } else if (NodeProperties::IsControlEdge(edge)) {
123 edge.UpdateTo(control); 123 edge.UpdateTo(control);
124 } else if (NodeProperties::IsFrameStateEdge(edge)) { 124 } else if (NodeProperties::IsFrameStateEdge(edge)) {
125 edge.UpdateTo(frame_state); 125 edge.UpdateTo(frame_state);
(...skipping 10 matching lines...) Expand all
136 for (Node* const input : end->inputs()) { 136 for (Node* const input : end->inputs()) {
137 switch (input->opcode()) { 137 switch (input->opcode()) {
138 case IrOpcode::kReturn: 138 case IrOpcode::kReturn:
139 values.push_back(NodeProperties::GetValueInput(input, 0)); 139 values.push_back(NodeProperties::GetValueInput(input, 0));
140 effects.push_back(NodeProperties::GetEffectInput(input)); 140 effects.push_back(NodeProperties::GetEffectInput(input));
141 controls.push_back(NodeProperties::GetControlInput(input)); 141 controls.push_back(NodeProperties::GetControlInput(input));
142 break; 142 break;
143 case IrOpcode::kDeoptimize: 143 case IrOpcode::kDeoptimize:
144 case IrOpcode::kTerminate: 144 case IrOpcode::kTerminate:
145 case IrOpcode::kThrow: 145 case IrOpcode::kThrow:
146 NodeProperties::MergeControlToEnd(jsgraph_->graph(), jsgraph_->common(), 146 NodeProperties::MergeControlToEnd(graph(), common(), input);
147 input); 147 Revisit(graph()->end());
148 Revisit(jsgraph_->graph()->end());
149 break; 148 break;
150 default: 149 default:
151 UNREACHABLE(); 150 UNREACHABLE();
152 break; 151 break;
153 } 152 }
154 } 153 }
155 DCHECK_EQ(values.size(), effects.size()); 154 DCHECK_EQ(values.size(), effects.size());
156 DCHECK_EQ(values.size(), controls.size()); 155 DCHECK_EQ(values.size(), controls.size());
157 156
158 // Depending on whether the inlinee produces a value, we either replace value 157 // Depending on whether the inlinee produces a value, we either replace value
159 // uses with said value or kill value uses if no value can be returned. 158 // uses with said value or kill value uses if no value can be returned.
160 if (values.size() > 0) { 159 if (values.size() > 0) {
161 int const input_count = static_cast<int>(controls.size()); 160 int const input_count = static_cast<int>(controls.size());
162 Node* control_output = jsgraph_->graph()->NewNode( 161 Node* control_output = graph()->NewNode(common()->Merge(input_count),
163 jsgraph_->common()->Merge(input_count), input_count, &controls.front()); 162 input_count, &controls.front());
164 values.push_back(control_output); 163 values.push_back(control_output);
165 effects.push_back(control_output); 164 effects.push_back(control_output);
166 Node* value_output = jsgraph_->graph()->NewNode( 165 Node* value_output = graph()->NewNode(
167 jsgraph_->common()->Phi(MachineRepresentation::kTagged, input_count), 166 common()->Phi(MachineRepresentation::kTagged, input_count),
168 static_cast<int>(values.size()), &values.front()); 167 static_cast<int>(values.size()), &values.front());
169 Node* effect_output = jsgraph_->graph()->NewNode( 168 Node* effect_output =
170 jsgraph_->common()->EffectPhi(input_count), 169 graph()->NewNode(common()->EffectPhi(input_count),
171 static_cast<int>(effects.size()), &effects.front()); 170 static_cast<int>(effects.size()), &effects.front());
172 ReplaceWithValue(call, value_output, effect_output, control_output); 171 ReplaceWithValue(call, value_output, effect_output, control_output);
173 return Changed(value_output); 172 return Changed(value_output);
174 } else { 173 } else {
175 ReplaceWithValue(call, call, call, jsgraph_->Dead()); 174 ReplaceWithValue(call, call, call, jsgraph()->Dead());
176 return Changed(call); 175 return Changed(call);
177 } 176 }
178 } 177 }
179 178
180 179
181 Node* JSInliner::CreateArtificialFrameState(Node* node, Node* outer_frame_state, 180 Node* JSInliner::CreateArtificialFrameState(Node* node, Node* outer_frame_state,
182 int parameter_count, 181 int parameter_count,
183 FrameStateType frame_state_type, 182 FrameStateType frame_state_type,
184 Handle<SharedFunctionInfo> shared) { 183 Handle<SharedFunctionInfo> shared) {
185 const FrameStateFunctionInfo* state_info = 184 const FrameStateFunctionInfo* state_info =
186 jsgraph_->common()->CreateFrameStateFunctionInfo( 185 common()->CreateFrameStateFunctionInfo(frame_state_type,
187 frame_state_type, parameter_count + 1, 0, shared); 186 parameter_count + 1, 0, shared);
188 187
189 const Operator* op = jsgraph_->common()->FrameState( 188 const Operator* op = common()->FrameState(
190 BailoutId(-1), OutputFrameStateCombine::Ignore(), state_info); 189 BailoutId(-1), OutputFrameStateCombine::Ignore(), state_info);
191 const Operator* op0 = jsgraph_->common()->StateValues(0); 190 const Operator* op0 = common()->StateValues(0);
192 Node* node0 = jsgraph_->graph()->NewNode(op0); 191 Node* node0 = graph()->NewNode(op0);
193 NodeVector params(local_zone_); 192 NodeVector params(local_zone_);
194 for (int parameter = 0; parameter < parameter_count + 1; ++parameter) { 193 for (int parameter = 0; parameter < parameter_count + 1; ++parameter) {
195 params.push_back(node->InputAt(1 + parameter)); 194 params.push_back(node->InputAt(1 + parameter));
196 } 195 }
197 const Operator* op_param = 196 const Operator* op_param =
198 jsgraph_->common()->StateValues(static_cast<int>(params.size())); 197 common()->StateValues(static_cast<int>(params.size()));
199 Node* params_node = jsgraph_->graph()->NewNode( 198 Node* params_node = graph()->NewNode(
200 op_param, static_cast<int>(params.size()), &params.front()); 199 op_param, static_cast<int>(params.size()), &params.front());
201 return jsgraph_->graph()->NewNode(op, params_node, node0, node0, 200 return graph()->NewNode(op, params_node, node0, node0,
202 jsgraph_->UndefinedConstant(), 201 jsgraph()->UndefinedConstant(), node->InputAt(0),
203 node->InputAt(0), outer_frame_state); 202 outer_frame_state);
204 } 203 }
205 204
206 Node* JSInliner::CreateTailCallerFrameState(Node* node, Node* frame_state) { 205 Node* JSInliner::CreateTailCallerFrameState(Node* node, Node* frame_state) {
207 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state); 206 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state);
208 Handle<SharedFunctionInfo> shared; 207 Handle<SharedFunctionInfo> shared;
209 frame_info.shared_info().ToHandle(&shared); 208 frame_info.shared_info().ToHandle(&shared);
210 209
211 Node* function = frame_state->InputAt(kFrameStateFunctionInput); 210 Node* function = frame_state->InputAt(kFrameStateFunctionInput);
212 211
213 // If we are inlining a tail call drop caller's frame state and an 212 // If we are inlining a tail call drop caller's frame state and an
214 // arguments adaptor if it exists. 213 // arguments adaptor if it exists.
215 frame_state = NodeProperties::GetFrameStateInput(frame_state); 214 frame_state = NodeProperties::GetFrameStateInput(frame_state);
216 if (frame_state->opcode() == IrOpcode::kFrameState) { 215 if (frame_state->opcode() == IrOpcode::kFrameState) {
217 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state); 216 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state);
218 if (frame_info.type() == FrameStateType::kArgumentsAdaptor) { 217 if (frame_info.type() == FrameStateType::kArgumentsAdaptor) {
219 frame_state = NodeProperties::GetFrameStateInput(frame_state); 218 frame_state = NodeProperties::GetFrameStateInput(frame_state);
220 } 219 }
221 } 220 }
222 221
223 const FrameStateFunctionInfo* state_info = 222 const FrameStateFunctionInfo* state_info =
224 jsgraph_->common()->CreateFrameStateFunctionInfo( 223 common()->CreateFrameStateFunctionInfo(
225 FrameStateType::kTailCallerFunction, 0, 0, shared); 224 FrameStateType::kTailCallerFunction, 0, 0, shared);
226 225
227 const Operator* op = jsgraph_->common()->FrameState( 226 const Operator* op = common()->FrameState(
228 BailoutId(-1), OutputFrameStateCombine::Ignore(), state_info); 227 BailoutId(-1), OutputFrameStateCombine::Ignore(), state_info);
229 const Operator* op0 = jsgraph_->common()->StateValues(0); 228 const Operator* op0 = common()->StateValues(0);
230 Node* node0 = jsgraph_->graph()->NewNode(op0); 229 Node* node0 = graph()->NewNode(op0);
231 return jsgraph_->graph()->NewNode(op, node0, node0, node0, 230 return graph()->NewNode(op, node0, node0, node0,
232 jsgraph_->UndefinedConstant(), function, 231 jsgraph()->UndefinedConstant(), function,
233 frame_state); 232 frame_state);
234 } 233 }
235 234
236 namespace { 235 namespace {
237 236
238 // TODO(mstarzinger,verwaest): Move this predicate onto SharedFunctionInfo? 237 // TODO(mstarzinger,verwaest): Move this predicate onto SharedFunctionInfo?
239 bool NeedsImplicitReceiver(Handle<SharedFunctionInfo> shared_info) { 238 bool NeedsImplicitReceiver(Handle<SharedFunctionInfo> shared_info) {
240 DisallowHeapAllocation no_gc; 239 DisallowHeapAllocation no_gc;
241 Isolate* const isolate = shared_info->GetIsolate(); 240 Isolate* const isolate = shared_info->GetIsolate();
242 Code* const construct_stub = shared_info->construct_stub(); 241 Code* const construct_stub = shared_info->construct_stub();
243 return construct_stub != *isolate->builtins()->JSBuiltinsConstructStub() && 242 return construct_stub != *isolate->builtins()->JSBuiltinsConstructStub() &&
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 AstGraphBuilder graph_builder(&zone, &info, jsgraph(), loop_assignment, 409 AstGraphBuilder graph_builder(&zone, &info, jsgraph(), loop_assignment,
411 type_hint_analysis); 410 type_hint_analysis);
412 graph_builder.CreateGraph(false); 411 graph_builder.CreateGraph(false);
413 412
414 // Extract the inlinee start/end nodes. 413 // Extract the inlinee start/end nodes.
415 start = graph()->start(); 414 start = graph()->start();
416 end = graph()->end(); 415 end = graph()->end();
417 } 416 }
418 417
419 Node* frame_state = call.frame_state(); 418 Node* frame_state = call.frame_state();
420 Node* new_target = jsgraph_->UndefinedConstant(); 419 Node* new_target = jsgraph()->UndefinedConstant();
421 420
422 // Inline {JSCallConstruct} requires some additional magic. 421 // Inline {JSCallConstruct} requires some additional magic.
423 if (node->opcode() == IrOpcode::kJSCallConstruct) { 422 if (node->opcode() == IrOpcode::kJSCallConstruct) {
424 // Insert nodes around the call that model the behavior required for a 423 // Insert nodes around the call that model the behavior required for a
425 // constructor dispatch (allocate implicit receiver and check return value). 424 // constructor dispatch (allocate implicit receiver and check return value).
426 // This models the behavior usually accomplished by our {JSConstructStub}. 425 // This models the behavior usually accomplished by our {JSConstructStub}.
427 // Note that the context has to be the callers context (input to call node). 426 // Note that the context has to be the callers context (input to call node).
428 Node* receiver = jsgraph_->UndefinedConstant(); // Implicit receiver. 427 Node* receiver = jsgraph()->UndefinedConstant(); // Implicit receiver.
429 if (NeedsImplicitReceiver(shared_info)) { 428 if (NeedsImplicitReceiver(shared_info)) {
430 Node* frame_state_before = NodeProperties::FindFrameStateBefore(node); 429 Node* frame_state_before = NodeProperties::FindFrameStateBefore(node);
431 Node* effect = NodeProperties::GetEffectInput(node); 430 Node* effect = NodeProperties::GetEffectInput(node);
432 Node* context = NodeProperties::GetContextInput(node); 431 Node* context = NodeProperties::GetContextInput(node);
433 Node* create = jsgraph_->graph()->NewNode( 432 Node* create = graph()->NewNode(javascript()->Create(), call.target(),
434 jsgraph_->javascript()->Create(), call.target(), call.new_target(), 433 call.new_target(), context,
435 context, frame_state_before, effect); 434 frame_state_before, effect);
436 NodeProperties::ReplaceEffectInput(node, create); 435 NodeProperties::ReplaceEffectInput(node, create);
437 // Insert a check of the return value to determine whether the return 436 // Insert a check of the return value to determine whether the return
438 // value 437 // value
439 // or the implicit receiver should be selected as a result of the call. 438 // or the implicit receiver should be selected as a result of the call.
440 Node* check = jsgraph_->graph()->NewNode( 439 Node* check = graph()->NewNode(
441 jsgraph_->javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), 440 javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), node,
442 node, context, node, start); 441 context, node, start);
443 Node* select = jsgraph_->graph()->NewNode( 442 Node* select =
444 jsgraph_->common()->Select(MachineRepresentation::kTagged), check, 443 graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
445 node, create); 444 check, node, create);
446 NodeProperties::ReplaceUses(node, select, check, node, node); 445 NodeProperties::ReplaceUses(node, select, check, node, node);
447 NodeProperties::ReplaceValueInput(select, node, 1); 446 NodeProperties::ReplaceValueInput(select, node, 1);
448 NodeProperties::ReplaceValueInput(check, node, 0); 447 NodeProperties::ReplaceValueInput(check, node, 0);
449 NodeProperties::ReplaceEffectInput(check, node); 448 NodeProperties::ReplaceEffectInput(check, node);
450 receiver = create; // The implicit receiver. 449 receiver = create; // The implicit receiver.
451 } 450 }
452 451
453 // Swizzle the inputs of the {JSCallConstruct} node to look like inputs to a 452 // Swizzle the inputs of the {JSCallConstruct} node to look like inputs to a
454 // normal {JSCallFunction} node so that the rest of the inlining machinery 453 // normal {JSCallFunction} node so that the rest of the inlining machinery
455 // behaves as if we were dealing with a regular function invocation. 454 // behaves as if we were dealing with a regular function invocation.
456 new_target = call.new_target(); // Retrieve new target value input. 455 new_target = call.new_target(); // Retrieve new target value input.
457 node->RemoveInput(call.formal_arguments() + 1); // Drop new target. 456 node->RemoveInput(call.formal_arguments() + 1); // Drop new target.
458 node->InsertInput(jsgraph_->graph()->zone(), 1, receiver); 457 node->InsertInput(graph()->zone(), 1, receiver);
459 458
460 // Insert a construct stub frame into the chain of frame states. This will 459 // Insert a construct stub frame into the chain of frame states. This will
461 // reconstruct the proper frame when deoptimizing within the constructor. 460 // reconstruct the proper frame when deoptimizing within the constructor.
462 frame_state = CreateArtificialFrameState( 461 frame_state = CreateArtificialFrameState(
463 node, frame_state, call.formal_arguments(), 462 node, frame_state, call.formal_arguments(),
464 FrameStateType::kConstructStub, info.shared_info()); 463 FrameStateType::kConstructStub, info.shared_info());
465 } 464 }
466 465
467 // The inlinee specializes to the context from the JSFunction object. 466 // The inlinee specializes to the context from the JSFunction object.
468 // TODO(turbofan): We might want to load the context from the JSFunction at 467 // TODO(turbofan): We might want to load the context from the JSFunction at
469 // runtime in case we only know the SharedFunctionInfo once we have dynamic 468 // runtime in case we only know the SharedFunctionInfo once we have dynamic
470 // type feedback in the compiler. 469 // type feedback in the compiler.
471 Node* context = jsgraph_->Constant(handle(function->context())); 470 Node* context = jsgraph()->Constant(handle(function->context()));
472 471
473 // Insert a JSConvertReceiver node for sloppy callees. Note that the context 472 // Insert a JSConvertReceiver node for sloppy callees. Note that the context
474 // passed into this node has to be the callees context (loaded above). Note 473 // passed into this node has to be the callees context (loaded above). Note
475 // that the frame state passed to the JSConvertReceiver must be the frame 474 // that the frame state passed to the JSConvertReceiver must be the frame
476 // state _before_ the call; it is not necessary to fiddle with the receiver 475 // state _before_ the call; it is not necessary to fiddle with the receiver
477 // in that frame state tho, as the conversion of the receiver can be repeated 476 // in that frame state tho, as the conversion of the receiver can be repeated
478 // any number of times, it's not observable. 477 // any number of times, it's not observable.
479 if (node->opcode() == IrOpcode::kJSCallFunction && 478 if (node->opcode() == IrOpcode::kJSCallFunction &&
480 is_sloppy(parse_info.language_mode()) && !shared_info->native()) { 479 is_sloppy(parse_info.language_mode()) && !shared_info->native()) {
481 const CallFunctionParameters& p = CallFunctionParametersOf(node->op()); 480 const CallFunctionParameters& p = CallFunctionParametersOf(node->op());
482 Node* frame_state_before = NodeProperties::FindFrameStateBefore(node); 481 Node* frame_state_before = NodeProperties::FindFrameStateBefore(node);
483 Node* effect = NodeProperties::GetEffectInput(node); 482 Node* effect = NodeProperties::GetEffectInput(node);
484 Node* convert = jsgraph_->graph()->NewNode( 483 Node* convert = graph()->NewNode(
485 jsgraph_->javascript()->ConvertReceiver(p.convert_mode()), 484 javascript()->ConvertReceiver(p.convert_mode()), call.receiver(),
486 call.receiver(), context, frame_state_before, effect, start); 485 context, frame_state_before, effect, start);
487 NodeProperties::ReplaceValueInput(node, convert, 1); 486 NodeProperties::ReplaceValueInput(node, convert, 1);
488 NodeProperties::ReplaceEffectInput(node, convert); 487 NodeProperties::ReplaceEffectInput(node, convert);
489 } 488 }
490 489
491 // If we are inlining a JS call at tail position then we have to pop current 490 // If we are inlining a JS call at tail position then we have to pop current
492 // frame state and its potential arguments adaptor frame state in order to 491 // frame state and its potential arguments adaptor frame state in order to
493 // make the call stack be consistent with non-inlining case. 492 // make the call stack be consistent with non-inlining case.
494 // After that we add a tail caller frame state which lets deoptimizer handle 493 // After that we add a tail caller frame state which lets deoptimizer handle
495 // the case when the outermost function inlines a tail call (it should remove 494 // the case when the outermost function inlines a tail call (it should remove
496 // potential arguments adaptor frame that belongs to outermost function when 495 // potential arguments adaptor frame that belongs to outermost function when
(...skipping 15 matching lines...) Expand all
512 frame_state = CreateArtificialFrameState( 511 frame_state = CreateArtificialFrameState(
513 node, frame_state, call.formal_arguments(), 512 node, frame_state, call.formal_arguments(),
514 FrameStateType::kArgumentsAdaptor, shared_info); 513 FrameStateType::kArgumentsAdaptor, shared_info);
515 } 514 }
516 515
517 return InlineCall(node, new_target, context, frame_state, start, end); 516 return InlineCall(node, new_target, context, frame_state, start, end);
518 } 517 }
519 518
520 Graph* JSInliner::graph() const { return jsgraph()->graph(); } 519 Graph* JSInliner::graph() const { return jsgraph()->graph(); }
521 520
521 JSOperatorBuilder* JSInliner::javascript() const {
522 return jsgraph()->javascript();
523 }
524
525 CommonOperatorBuilder* JSInliner::common() const { return jsgraph()->common(); }
526
522 } // namespace compiler 527 } // namespace compiler
523 } // namespace internal 528 } // namespace internal
524 } // namespace v8 529 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-inlining.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698