• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/compiler/tail-call-optimization.h"
6 
7 #include "src/compiler/common-operator.h"
8 #include "src/compiler/graph.h"
9 #include "src/compiler/linkage.h"
10 #include "src/compiler/node-properties.h"
11 
12 namespace v8 {
13 namespace internal {
14 namespace compiler {
15 
Reduce(Node * node)16 Reduction TailCallOptimization::Reduce(Node* node) {
17   if (node->opcode() != IrOpcode::kReturn) return NoChange();
18   // The value which is returned must be the result of a potential tail call,
19   // there must be no try/catch/finally around the Call, and there must be no
20   // other effect between the Call and the Return nodes.
21   Node* const call = NodeProperties::GetValueInput(node, 0);
22   if (call->opcode() == IrOpcode::kCall &&
23       OpParameter<CallDescriptor const*>(call)->SupportsTailCalls() &&
24       NodeProperties::GetEffectInput(node) == call &&
25       !NodeProperties::IsExceptionalCall(call)) {
26     Node* const control = NodeProperties::GetControlInput(node);
27     if (control->opcode() == IrOpcode::kIfSuccess &&
28         call->OwnedBy(node, control) && control->OwnedBy(node)) {
29       // Furthermore, control has to flow via an IfSuccess from the Call, so
30       // the Return node value and effect depends directly on the Call node,
31       // and indirectly control depends on the Call via an IfSuccess.
32 
33       // Value1 ... ValueN Effect Control
34       //   ^          ^      ^       ^
35       //   |          |      |       |
36       //   |          +--+ +-+       |
37       //   +----------+  | |  +------+
38       //               \ | | /
39       //             Call[Descriptor]
40       //                ^ ^ ^
41       //                | | |
42       //              +-+ | |
43       //              |   | |
44       //              | +-+ |
45       //              | | IfSuccess
46       //              | |  ^
47       //              | |  |
48       //              Return
49       //                ^
50       //                |
51 
52       // The resulting graph looks like this:
53 
54       // Value1 ... ValueN Effect Control
55       //   ^          ^      ^       ^
56       //   |          |      |       |
57       //   |          +--+ +-+       |
58       //   +----------+  | |  +------+
59       //               \ | | /
60       //           TailCall[Descriptor]
61       //                 ^
62       //                 |
63 
64       DCHECK_EQ(call, NodeProperties::GetControlInput(control, 0));
65       DCHECK_EQ(3, node->InputCount());
66       node->ReplaceInput(0, NodeProperties::GetEffectInput(call));
67       node->ReplaceInput(1, NodeProperties::GetControlInput(call));
68       node->RemoveInput(2);
69       for (int index = 0; index < call->op()->ValueInputCount(); ++index) {
70         node->InsertInput(graph()->zone(), index,
71                           NodeProperties::GetValueInput(call, index));
72       }
73       NodeProperties::ChangeOp(
74           node, common()->TailCall(OpParameter<CallDescriptor const*>(call)));
75       return Changed(node);
76     }
77   }
78   return NoChange();
79 }
80 
81 }  // namespace compiler
82 }  // namespace internal
83 }  // namespace v8
84