blob: 3441c68b961090cae49bba8d8c497d9c8f4066c0 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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/linkage.h"
6#include "src/compiler/tail-call-optimization.h"
7#include "test/unittests/compiler/graph-unittest.h"
8#include "test/unittests/compiler/node-test-utils.h"
9
10namespace v8 {
11namespace internal {
12namespace compiler {
13
14class TailCallOptimizationTest : public GraphTest {
15 public:
16 explicit TailCallOptimizationTest(int num_parameters = 1)
17 : GraphTest(num_parameters) {}
18 ~TailCallOptimizationTest() override {}
19
20 protected:
21 Reduction Reduce(Node* node) {
22 TailCallOptimization tco(common(), graph());
23 return tco.Reduce(node);
24 }
25};
26
27
28TEST_F(TailCallOptimizationTest, CallCodeObject0) {
29 MachineType kMachineSignature[] = {MachineType::AnyTagged(),
30 MachineType::AnyTagged()};
31 LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
32 LinkageLocation::ForRegister(1)};
33 const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
34 CallDescriptor::kCallCodeObject, MachineType::AnyTagged(),
35 LinkageLocation::ForRegister(0),
36 new (zone()) MachineSignature(1, 1, kMachineSignature),
37 new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
38 Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
39 Node* p0 = Parameter(0);
40 Node* p1 = Parameter(1);
41 Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
42 graph()->start(), graph()->start());
43 Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
44 Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
45 Reduction r = Reduce(ret);
46 ASSERT_FALSE(r.Changed());
47}
48
49
50TEST_F(TailCallOptimizationTest, CallCodeObject1) {
51 MachineType kMachineSignature[] = {MachineType::AnyTagged(),
52 MachineType::AnyTagged()};
53 LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
54 LinkageLocation::ForRegister(1)};
55 const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
56 CallDescriptor::kCallCodeObject, MachineType::AnyTagged(),
57 LinkageLocation::ForRegister(0),
58 new (zone()) MachineSignature(1, 1, kMachineSignature),
59 new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
60 Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
61 Node* p0 = Parameter(0);
62 Node* p1 = Parameter(1);
63 Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
64 graph()->start(), graph()->start());
65 Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
66 Node* if_exception = graph()->NewNode(
67 common()->IfException(IfExceptionHint::kLocallyUncaught), call, call);
68 Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
69 Node* end = graph()->NewNode(common()->End(1), if_exception);
70 graph()->SetEnd(end);
71 Reduction r = Reduce(ret);
72 ASSERT_FALSE(r.Changed());
73}
74
75
76TEST_F(TailCallOptimizationTest, CallCodeObject2) {
77 MachineType kMachineSignature[] = {MachineType::AnyTagged(),
78 MachineType::AnyTagged()};
79 LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
80 LinkageLocation::ForRegister(1)};
81 const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
82 CallDescriptor::kCallCodeObject, MachineType::AnyTagged(),
83 LinkageLocation::ForRegister(0),
84 new (zone()) MachineSignature(1, 1, kMachineSignature),
85 new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
86 Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
87 Node* p0 = Parameter(0);
88 Node* p1 = Parameter(1);
89 Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
90 graph()->start(), graph()->start());
91 Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
92 Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
93 Reduction r = Reduce(ret);
94 ASSERT_TRUE(r.Changed());
95 EXPECT_THAT(r.replacement(), IsTailCall(kCallDescriptor, p0, p1,
96 graph()->start(), graph()->start()));
97}
98
99
100TEST_F(TailCallOptimizationTest, CallJSFunction0) {
101 MachineType kMachineSignature[] = {MachineType::AnyTagged(),
102 MachineType::AnyTagged()};
103 LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
104 LinkageLocation::ForRegister(1)};
105 const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
106 CallDescriptor::kCallJSFunction, MachineType::AnyTagged(),
107 LinkageLocation::ForRegister(0),
108 new (zone()) MachineSignature(1, 1, kMachineSignature),
109 new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
110 Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
111 Node* p0 = Parameter(0);
112 Node* p1 = Parameter(1);
113 Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
114 graph()->start(), graph()->start());
115 Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
116 Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
117 Reduction r = Reduce(ret);
118 ASSERT_FALSE(r.Changed());
119}
120
121
122TEST_F(TailCallOptimizationTest, CallJSFunction1) {
123 MachineType kMachineSignature[] = {MachineType::AnyTagged(),
124 MachineType::AnyTagged()};
125 LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
126 LinkageLocation::ForRegister(1)};
127 const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
128 CallDescriptor::kCallJSFunction, MachineType::AnyTagged(),
129 LinkageLocation::ForRegister(0),
130 new (zone()) MachineSignature(1, 1, kMachineSignature),
131 new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
132 Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
133 Node* p0 = Parameter(0);
134 Node* p1 = Parameter(1);
135 Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
136 graph()->start(), graph()->start());
137 Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
138 Node* if_exception = graph()->NewNode(
139 common()->IfException(IfExceptionHint::kLocallyUncaught), call, call);
140 Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
141 Node* end = graph()->NewNode(common()->End(1), if_exception);
142 graph()->SetEnd(end);
143 Reduction r = Reduce(ret);
144 ASSERT_FALSE(r.Changed());
145}
146
147
148TEST_F(TailCallOptimizationTest, CallJSFunction2) {
149 MachineType kMachineSignature[] = {MachineType::AnyTagged(),
150 MachineType::AnyTagged()};
151 LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
152 LinkageLocation::ForRegister(1)};
153 const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
154 CallDescriptor::kCallJSFunction, MachineType::AnyTagged(),
155 LinkageLocation::ForRegister(0),
156 new (zone()) MachineSignature(1, 1, kMachineSignature),
157 new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
158 Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
159 Node* p0 = Parameter(0);
160 Node* p1 = Parameter(1);
161 Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
162 graph()->start(), graph()->start());
163 Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
164 Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
165 Reduction r = Reduce(ret);
166 ASSERT_TRUE(r.Changed());
167 EXPECT_THAT(r.replacement(), IsTailCall(kCallDescriptor, p0, p1,
168 graph()->start(), graph()->start()));
169}
170
171
172} // namespace compiler
173} // namespace internal
174} // namespace v8