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/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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 Node* receiver() { | 48 Node* receiver() { |
49 DCHECK_EQ(IrOpcode::kJSCallFunction, call_->opcode()); | 49 DCHECK_EQ(IrOpcode::kJSCallFunction, call_->opcode()); |
50 return call_->InputAt(1); | 50 return call_->InputAt(1); |
51 } | 51 } |
52 | 52 |
53 Node* new_target() { | 53 Node* new_target() { |
54 DCHECK_EQ(IrOpcode::kJSCallConstruct, call_->opcode()); | 54 DCHECK_EQ(IrOpcode::kJSCallConstruct, call_->opcode()); |
55 return call_->InputAt(formal_arguments() + 1); | 55 return call_->InputAt(formal_arguments() + 1); |
56 } | 56 } |
57 | 57 |
58 Node* frame_state_before() { | 58 Node* frame_state() { |
59 return NodeProperties::GetFrameStateInput(call_, 1); | 59 // Both, {JSCallFunction} and {JSCallConstruct}, have frame state. |
60 } | |
61 | |
62 Node* frame_state_after() { | |
63 // Both, {JSCallFunction} and {JSCallConstruct}, have frame state after. | |
64 return NodeProperties::GetFrameStateInput(call_, 0); | 60 return NodeProperties::GetFrameStateInput(call_, 0); |
65 } | 61 } |
66 | 62 |
67 int formal_arguments() { | 63 int formal_arguments() { |
68 // Both, {JSCallFunction} and {JSCallConstruct}, have two extra inputs: | 64 // Both, {JSCallFunction} and {JSCallConstruct}, have two extra inputs: |
69 // - JSCallConstruct: Includes target function and new target. | 65 // - JSCallConstruct: Includes target function and new target. |
70 // - JSCallFunction: Includes target function and receiver. | 66 // - JSCallFunction: Includes target function and receiver. |
71 return call_->op()->ValueInputCount() - 2; | 67 return call_->op()->ValueInputCount() - 2; |
72 } | 68 } |
73 | 69 |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 info_->context()->native_context()) { | 323 info_->context()->native_context()) { |
328 TRACE("Not inlining %s into %s because of different native contexts\n", | 324 TRACE("Not inlining %s into %s because of different native contexts\n", |
329 shared_info->DebugName()->ToCString().get(), | 325 shared_info->DebugName()->ToCString().get(), |
330 info_->shared_info()->DebugName()->ToCString().get()); | 326 info_->shared_info()->DebugName()->ToCString().get()); |
331 return NoChange(); | 327 return NoChange(); |
332 } | 328 } |
333 | 329 |
334 // TODO(turbofan): TranslatedState::GetAdaptedArguments() currently relies on | 330 // TODO(turbofan): TranslatedState::GetAdaptedArguments() currently relies on |
335 // not inlining recursive functions. We might want to relax that at some | 331 // not inlining recursive functions. We might want to relax that at some |
336 // point. | 332 // point. |
337 for (Node* frame_state = call.frame_state_after(); | 333 for (Node* frame_state = call.frame_state(); |
338 frame_state->opcode() == IrOpcode::kFrameState; | 334 frame_state->opcode() == IrOpcode::kFrameState; |
339 frame_state = frame_state->InputAt(kFrameStateOuterStateInput)) { | 335 frame_state = frame_state->InputAt(kFrameStateOuterStateInput)) { |
340 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state); | 336 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state); |
341 Handle<SharedFunctionInfo> frame_shared_info; | 337 Handle<SharedFunctionInfo> frame_shared_info; |
342 if (frame_info.shared_info().ToHandle(&frame_shared_info) && | 338 if (frame_info.shared_info().ToHandle(&frame_shared_info) && |
343 *frame_shared_info == *shared_info) { | 339 *frame_shared_info == *shared_info) { |
344 TRACE("Not inlining %s into %s because call is recursive\n", | 340 TRACE("Not inlining %s into %s because call is recursive\n", |
345 shared_info->DebugName()->ToCString().get(), | 341 shared_info->DebugName()->ToCString().get(), |
346 info_->shared_info()->DebugName()->ToCString().get()); | 342 info_->shared_info()->DebugName()->ToCString().get()); |
347 return NoChange(); | 343 return NoChange(); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
412 Graph::SubgraphScope scope(graph()); | 408 Graph::SubgraphScope scope(graph()); |
413 AstGraphBuilder graph_builder(&zone, &info, jsgraph(), loop_assignment, | 409 AstGraphBuilder graph_builder(&zone, &info, jsgraph(), loop_assignment, |
414 type_hint_analysis); | 410 type_hint_analysis); |
415 graph_builder.CreateGraph(false); | 411 graph_builder.CreateGraph(false); |
416 | 412 |
417 // Extract the inlinee start/end nodes. | 413 // Extract the inlinee start/end nodes. |
418 start = graph()->start(); | 414 start = graph()->start(); |
419 end = graph()->end(); | 415 end = graph()->end(); |
420 } | 416 } |
421 | 417 |
422 Node* frame_state = call.frame_state_after(); | 418 Node* frame_state = call.frame_state(); |
423 Node* new_target = jsgraph_->UndefinedConstant(); | 419 Node* new_target = jsgraph_->UndefinedConstant(); |
424 | 420 |
425 // Inline {JSCallConstruct} requires some additional magic. | 421 // Inline {JSCallConstruct} requires some additional magic. |
426 if (node->opcode() == IrOpcode::kJSCallConstruct) { | 422 if (node->opcode() == IrOpcode::kJSCallConstruct) { |
427 // 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 |
428 // constructor dispatch (allocate implicit receiver and check return value). | 424 // constructor dispatch (allocate implicit receiver and check return value). |
429 // This models the behavior usually accomplished by our {JSConstructStub}. | 425 // This models the behavior usually accomplished by our {JSConstructStub}. |
430 // 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). |
431 Node* receiver = jsgraph_->UndefinedConstant(); // Implicit receiver. | 427 Node* receiver = jsgraph_->UndefinedConstant(); // Implicit receiver. |
432 if (NeedsImplicitReceiver(shared_info)) { | 428 if (NeedsImplicitReceiver(shared_info)) { |
| 429 Node* frame_state_before = NodeProperties::FindFrameStateBefore(node); |
433 Node* effect = NodeProperties::GetEffectInput(node); | 430 Node* effect = NodeProperties::GetEffectInput(node); |
434 Node* context = NodeProperties::GetContextInput(node); | 431 Node* context = NodeProperties::GetContextInput(node); |
435 Node* create = jsgraph_->graph()->NewNode( | 432 Node* create = jsgraph_->graph()->NewNode( |
436 jsgraph_->javascript()->Create(), call.target(), call.new_target(), | 433 jsgraph_->javascript()->Create(), call.target(), call.new_target(), |
437 context, call.frame_state_before(), effect); | 434 context, frame_state_before, effect); |
438 NodeProperties::ReplaceEffectInput(node, create); | 435 NodeProperties::ReplaceEffectInput(node, create); |
439 // 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 |
440 // value | 437 // value |
441 // 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. |
442 Node* check = jsgraph_->graph()->NewNode( | 439 Node* check = jsgraph_->graph()->NewNode( |
443 jsgraph_->javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), | 440 jsgraph_->javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), |
444 node, context, node, start); | 441 node, context, node, start); |
445 Node* select = jsgraph_->graph()->NewNode( | 442 Node* select = jsgraph_->graph()->NewNode( |
446 jsgraph_->common()->Select(MachineRepresentation::kTagged), check, | 443 jsgraph_->common()->Select(MachineRepresentation::kTagged), check, |
447 node, create); | 444 node, create); |
(...skipping 26 matching lines...) Expand all Loading... |
474 | 471 |
475 // Insert a JSConvertReceiver node for sloppy callees. Note that the context | 472 // Insert a JSConvertReceiver node for sloppy callees. Note that the context |
476 // 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 |
477 // 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 |
478 // 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 |
479 // 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 |
480 // any number of times, it's not observable. | 477 // any number of times, it's not observable. |
481 if (node->opcode() == IrOpcode::kJSCallFunction && | 478 if (node->opcode() == IrOpcode::kJSCallFunction && |
482 is_sloppy(parse_info.language_mode()) && !shared_info->native()) { | 479 is_sloppy(parse_info.language_mode()) && !shared_info->native()) { |
483 const CallFunctionParameters& p = CallFunctionParametersOf(node->op()); | 480 const CallFunctionParameters& p = CallFunctionParametersOf(node->op()); |
| 481 Node* frame_state_before = NodeProperties::FindFrameStateBefore(node); |
484 Node* effect = NodeProperties::GetEffectInput(node); | 482 Node* effect = NodeProperties::GetEffectInput(node); |
485 Node* convert = jsgraph_->graph()->NewNode( | 483 Node* convert = jsgraph_->graph()->NewNode( |
486 jsgraph_->javascript()->ConvertReceiver(p.convert_mode()), | 484 jsgraph_->javascript()->ConvertReceiver(p.convert_mode()), |
487 call.receiver(), context, call.frame_state_before(), effect, start); | 485 call.receiver(), context, frame_state_before, effect, start); |
488 NodeProperties::ReplaceValueInput(node, convert, 1); | 486 NodeProperties::ReplaceValueInput(node, convert, 1); |
489 NodeProperties::ReplaceEffectInput(node, convert); | 487 NodeProperties::ReplaceEffectInput(node, convert); |
490 } | 488 } |
491 | 489 |
492 // 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 |
493 // 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 |
494 // make the call stack be consistent with non-inlining case. | 492 // make the call stack be consistent with non-inlining case. |
495 // 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 |
496 // 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 |
497 // potential arguments adaptor frame that belongs to outermost function when | 495 // potential arguments adaptor frame that belongs to outermost function when |
(...skipping 18 matching lines...) Expand all Loading... |
516 } | 514 } |
517 | 515 |
518 return InlineCall(node, new_target, context, frame_state, start, end); | 516 return InlineCall(node, new_target, context, frame_state, start, end); |
519 } | 517 } |
520 | 518 |
521 Graph* JSInliner::graph() const { return jsgraph()->graph(); } | 519 Graph* JSInliner::graph() const { return jsgraph()->graph(); } |
522 | 520 |
523 } // namespace compiler | 521 } // namespace compiler |
524 } // namespace internal | 522 } // namespace internal |
525 } // namespace v8 | 523 } // namespace v8 |
OLD | NEW |