Line data Source code
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-matchers.h"
11 : #include "src/compiler/node-properties.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 : namespace compiler {
16 :
17 44498710 : Reduction TailCallOptimization::Reduce(Node* node) {
18 44495489 : if (node->opcode() != IrOpcode::kReturn) return NoChange();
19 : // The value which is returned must be the result of a potential tail call,
20 : // there must be no try/catch/finally around the Call, and there must be no
21 : // other effect or control between the Call and the Return nodes.
22 566517 : Node* const call = NodeProperties::GetValueInput(node, 1);
23 819789 : if (call->opcode() == IrOpcode::kCall &&
24 256852 : CallDescriptorOf(call->op())->SupportsTailCalls() &&
25 714 : NodeProperties::GetEffectInput(node) == call &&
26 712 : NodeProperties::GetControlInput(node) == call &&
27 564004 : !NodeProperties::IsExceptionalCall(call) && call->UseCount() == 3) {
28 : // Ensure that no additional arguments are being popped other than those in
29 : // the CallDescriptor, otherwise the tail call transformation is invalid.
30 : DCHECK_EQ(0, Int32Matcher(NodeProperties::GetValueInput(node, 0)).Value());
31 : // Furthermore, the Return node value, effect, and control depends
32 : // directly on the Call, no other uses of the Call node exist.
33 : //
34 : // The input graph looks as follows:
35 :
36 : // Value1 ... ValueN Effect Control
37 : // ^ ^ ^ ^
38 : // | | | |
39 : // | +--+ +-+ |
40 : // +----------+ | | +------+
41 : // \ | | /
42 : // Call[Descriptor]
43 : // ^ ^ ^
44 : // Int32(0) <-+ | | |
45 : // \ | | |
46 : // Return
47 : // ^
48 : // |
49 :
50 : // The resulting graph looks like this:
51 :
52 : // Value1 ... ValueN Effect Control
53 : // ^ ^ ^ ^
54 : // | | | |
55 : // | +--+ +-+ |
56 : // +----------+ | | +------+
57 : // \ | | /
58 : // TailCall[Descriptor]
59 : // ^
60 : // |
61 :
62 : DCHECK_EQ(4, node->InputCount());
63 355 : node->ReplaceInput(0, NodeProperties::GetEffectInput(call));
64 355 : node->ReplaceInput(1, NodeProperties::GetControlInput(call));
65 355 : node->RemoveInput(3);
66 355 : node->RemoveInput(2);
67 9663 : for (int index = 0; index < call->op()->ValueInputCount(); ++index) {
68 : node->InsertInput(graph()->zone(), index,
69 5732 : NodeProperties::GetValueInput(call, index));
70 : }
71 : NodeProperties::ChangeOp(node,
72 710 : common()->TailCall(CallDescriptorOf(call->op())));
73 : return Changed(node);
74 : }
75 : return NoChange();
76 : }
77 :
78 : } // namespace compiler
79 : } // namespace internal
80 : } // namespace v8
|