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
3 // found in the LICENSE file.
4
5 #include "src/compiler/common-operator.h"
6 #include "src/compiler/graph.h"
7 #include "src/compiler/linkage.h"
8 #include "src/compiler/node.h"
9 #include "test/unittests/test-utils.h"
10
11 namespace v8 {
12 namespace internal {
13 namespace compiler {
14
15 namespace {
16
17 MachineType kMachineTypes[] = {
18 MachineType::AnyTagged(), MachineType::AnyTagged(),
19 MachineType::AnyTagged(), MachineType::AnyTagged(),
20 MachineType::AnyTagged(), MachineType::AnyTagged(),
21 MachineType::AnyTagged(), MachineType::AnyTagged()};
22 }
23
24 class LinkageTailCall : public TestWithZone {
25 protected:
NewStandardCallDescriptor(LocationSignature * locations)26 CallDescriptor* NewStandardCallDescriptor(LocationSignature* locations) {
27 DCHECK(arraysize(kMachineTypes) >=
28 locations->return_count() + locations->parameter_count());
29 MachineSignature* types = new (zone()) MachineSignature(
30 locations->return_count(), locations->parameter_count(), kMachineTypes);
31 return new (zone()) CallDescriptor(CallDescriptor::kCallCodeObject,
32 MachineType::AnyTagged(),
33 LinkageLocation::ForAnyRegister(),
34 types, // machine_sig
35 locations, // location_sig
36 0, // js_parameter_count
37 Operator::kNoProperties, // properties
38 0, // callee-saved
39 0, // callee-saved fp
40 CallDescriptor::kNoFlags, // flags,
41 "");
42 }
43
StackLocation(int loc)44 LinkageLocation StackLocation(int loc) {
45 return LinkageLocation::ForCallerFrameSlot(-loc);
46 }
47
RegisterLocation(int loc)48 LinkageLocation RegisterLocation(int loc) {
49 return LinkageLocation::ForRegister(loc);
50 }
51 };
52
53
TEST_F(LinkageTailCall,EmptyToEmpty)54 TEST_F(LinkageTailCall, EmptyToEmpty) {
55 LocationSignature locations(0, 0, nullptr);
56 CallDescriptor* desc = NewStandardCallDescriptor(&locations);
57 CommonOperatorBuilder common(zone());
58 const Operator* op = common.Call(desc);
59 Node* const node = Node::New(zone(), 1, op, 0, nullptr, false);
60 int stack_param_delta = 0;
61 EXPECT_TRUE(desc->CanTailCall(node, &stack_param_delta));
62 EXPECT_EQ(0, stack_param_delta);
63 }
64
65
TEST_F(LinkageTailCall,SameReturn)66 TEST_F(LinkageTailCall, SameReturn) {
67 // Caller
68 LinkageLocation location_array[] = {RegisterLocation(0)};
69 LocationSignature locations1(1, 0, location_array);
70 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1);
71
72 // Callee
73 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations1);
74
75 CommonOperatorBuilder common(zone());
76 const Operator* op = common.Call(desc2);
77 Node* const node = Node::New(zone(), 1, op, 0, nullptr, false);
78 int stack_param_delta = 0;
79 EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
80 EXPECT_EQ(0, stack_param_delta);
81 }
82
83
TEST_F(LinkageTailCall,DifferingReturn)84 TEST_F(LinkageTailCall, DifferingReturn) {
85 // Caller
86 LinkageLocation location_array1[] = {RegisterLocation(0)};
87 LocationSignature locations1(1, 0, location_array1);
88 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1);
89
90 // Callee
91 LinkageLocation location_array2[] = {RegisterLocation(1)};
92 LocationSignature locations2(1, 0, location_array2);
93 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations2);
94
95 CommonOperatorBuilder common(zone());
96 const Operator* op = common.Call(desc2);
97 Node* const node = Node::New(zone(), 1, op, 0, nullptr, false);
98 int stack_param_delta = 0;
99 EXPECT_FALSE(desc1->CanTailCall(node, &stack_param_delta));
100 EXPECT_EQ(0, stack_param_delta);
101 }
102
103
TEST_F(LinkageTailCall,MoreRegisterParametersCallee)104 TEST_F(LinkageTailCall, MoreRegisterParametersCallee) {
105 // Caller
106 LinkageLocation location_array1[] = {RegisterLocation(0)};
107 LocationSignature locations1(1, 0, location_array1);
108 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1);
109
110 // Callee
111 LinkageLocation location_array2[] = {RegisterLocation(0),
112 RegisterLocation(0)};
113 LocationSignature locations2(1, 1, location_array2);
114 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations2);
115
116 CommonOperatorBuilder common(zone());
117 const Operator* op = common.Call(desc2);
118 Node* const node = Node::New(zone(), 1, op, 0, nullptr, false);
119 int stack_param_delta = 0;
120 EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
121 EXPECT_EQ(0, stack_param_delta);
122 }
123
124
TEST_F(LinkageTailCall,MoreRegisterParametersCaller)125 TEST_F(LinkageTailCall, MoreRegisterParametersCaller) {
126 // Caller
127 LinkageLocation location_array1[] = {RegisterLocation(0),
128 RegisterLocation(0)};
129 LocationSignature locations1(1, 1, location_array1);
130 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1);
131
132 // Callee
133 LinkageLocation location_array2[] = {RegisterLocation(0)};
134 LocationSignature locations2(1, 0, location_array2);
135 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations2);
136
137 CommonOperatorBuilder common(zone());
138 const Operator* op = common.Call(desc2);
139 Node* const node = Node::New(zone(), 1, op, 0, nullptr, false);
140 int stack_param_delta = 0;
141 EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
142 EXPECT_EQ(0, stack_param_delta);
143 }
144
145
TEST_F(LinkageTailCall,MoreRegisterAndStackParametersCallee)146 TEST_F(LinkageTailCall, MoreRegisterAndStackParametersCallee) {
147 // Caller
148 LinkageLocation location_array1[] = {RegisterLocation(0)};
149 LocationSignature locations1(1, 0, location_array1);
150 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1);
151
152 // Callee
153 LinkageLocation location_array2[] = {RegisterLocation(0), RegisterLocation(0),
154 RegisterLocation(1), StackLocation(1)};
155 LocationSignature locations2(1, 3, location_array2);
156 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations2);
157
158 CommonOperatorBuilder common(zone());
159 const Operator* op = common.Call(desc2);
160 Node* const node = Node::New(zone(), 1, op, 0, nullptr, false);
161 int stack_param_delta = 0;
162 EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
163 EXPECT_EQ(-1, stack_param_delta);
164 }
165
166
TEST_F(LinkageTailCall,MoreRegisterAndStackParametersCaller)167 TEST_F(LinkageTailCall, MoreRegisterAndStackParametersCaller) {
168 // Caller
169 LinkageLocation location_array[] = {RegisterLocation(0), RegisterLocation(0),
170 RegisterLocation(1), StackLocation(1)};
171 LocationSignature locations1(1, 3, location_array);
172 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1);
173
174 // Callee
175 LinkageLocation location_array2[] = {RegisterLocation(0)};
176 LocationSignature locations2(1, 0, location_array2);
177 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations2);
178
179 CommonOperatorBuilder common(zone());
180 const Operator* op = common.Call(desc2);
181 Node* const node = Node::New(zone(), 1, op, 0, nullptr, false);
182 int stack_param_delta = 0;
183 EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
184 EXPECT_EQ(1, stack_param_delta);
185 }
186
187
TEST_F(LinkageTailCall,MatchingStackParameters)188 TEST_F(LinkageTailCall, MatchingStackParameters) {
189 // Caller
190 LinkageLocation location_array[] = {RegisterLocation(0), StackLocation(3),
191 StackLocation(2), StackLocation(1)};
192 LocationSignature locations1(1, 3, location_array);
193 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1);
194
195 // Caller
196 LocationSignature locations2(1, 3, location_array);
197 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations1);
198
199 CommonOperatorBuilder common(zone());
200 Node* p0 = Node::New(zone(), 0, nullptr, 0, nullptr, false);
201 Node* p1 = Node::New(zone(), 0, common.Parameter(0), 0, nullptr, false);
202 Node* p2 = Node::New(zone(), 0, common.Parameter(1), 0, nullptr, false);
203 Node* p3 = Node::New(zone(), 0, common.Parameter(2), 0, nullptr, false);
204 Node* parameters[] = {p0, p1, p2, p3};
205 const Operator* op = common.Call(desc2);
206 Node* const node =
207 Node::New(zone(), 1, op, arraysize(parameters), parameters, false);
208 int stack_param_delta = 0;
209 EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
210 EXPECT_EQ(0, stack_param_delta);
211 }
212
213
TEST_F(LinkageTailCall,NonMatchingStackParameters)214 TEST_F(LinkageTailCall, NonMatchingStackParameters) {
215 // Caller
216 LinkageLocation location_array[] = {RegisterLocation(0), StackLocation(3),
217 StackLocation(2), StackLocation(1)};
218 LocationSignature locations1(1, 3, location_array);
219 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1);
220
221 // Caller
222 LocationSignature locations2(1, 3, location_array);
223 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations1);
224
225 CommonOperatorBuilder common(zone());
226 Node* p0 = Node::New(zone(), 0, nullptr, 0, nullptr, false);
227 Node* p1 = Node::New(zone(), 0, common.Parameter(0), 0, nullptr, false);
228 Node* p2 = Node::New(zone(), 0, common.Parameter(2), 0, nullptr, false);
229 Node* p3 = Node::New(zone(), 0, common.Parameter(1), 0, nullptr, false);
230 Node* parameters[] = {p0, p1, p2, p3};
231 const Operator* op = common.Call(desc2);
232 Node* const node =
233 Node::New(zone(), 1, op, arraysize(parameters), parameters, false);
234 int stack_param_delta = 0;
235 EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
236 EXPECT_EQ(0, stack_param_delta);
237 }
238
239
TEST_F(LinkageTailCall,MatchingStackParametersExtraCallerRegisters)240 TEST_F(LinkageTailCall, MatchingStackParametersExtraCallerRegisters) {
241 // Caller
242 LinkageLocation location_array[] = {RegisterLocation(0), StackLocation(3),
243 StackLocation(2), StackLocation(1),
244 RegisterLocation(0), RegisterLocation(1)};
245 LocationSignature locations1(1, 5, location_array);
246 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1);
247
248 // Caller
249 LocationSignature locations2(1, 3, location_array);
250 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations1);
251
252 CommonOperatorBuilder common(zone());
253 Node* p0 = Node::New(zone(), 0, nullptr, 0, nullptr, false);
254 Node* p1 = Node::New(zone(), 0, common.Parameter(0), 0, nullptr, false);
255 Node* p2 = Node::New(zone(), 0, common.Parameter(1), 0, nullptr, false);
256 Node* p3 = Node::New(zone(), 0, common.Parameter(2), 0, nullptr, false);
257 Node* parameters[] = {p0, p1, p2, p3};
258 const Operator* op = common.Call(desc2);
259 Node* const node =
260 Node::New(zone(), 1, op, arraysize(parameters), parameters, false);
261 int stack_param_delta = 0;
262 EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
263 EXPECT_EQ(0, stack_param_delta);
264 }
265
266
TEST_F(LinkageTailCall,MatchingStackParametersExtraCalleeRegisters)267 TEST_F(LinkageTailCall, MatchingStackParametersExtraCalleeRegisters) {
268 // Caller
269 LinkageLocation location_array[] = {RegisterLocation(0), StackLocation(3),
270 StackLocation(2), StackLocation(1),
271 RegisterLocation(0), RegisterLocation(1)};
272 LocationSignature locations1(1, 3, location_array);
273 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1);
274
275 // Caller
276 LocationSignature locations2(1, 5, location_array);
277 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations1);
278
279 CommonOperatorBuilder common(zone());
280 Node* p0 = Node::New(zone(), 0, nullptr, 0, nullptr, false);
281 Node* p1 = Node::New(zone(), 0, common.Parameter(0), 0, nullptr, false);
282 Node* p2 = Node::New(zone(), 0, common.Parameter(1), 0, nullptr, false);
283 Node* p3 = Node::New(zone(), 0, common.Parameter(2), 0, nullptr, false);
284 Node* p4 = Node::New(zone(), 0, common.Parameter(3), 0, nullptr, false);
285 Node* parameters[] = {p0, p1, p2, p3, p4};
286 const Operator* op = common.Call(desc2);
287 Node* const node =
288 Node::New(zone(), 1, op, arraysize(parameters), parameters, false);
289 int stack_param_delta = 0;
290 EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
291 EXPECT_EQ(0, stack_param_delta);
292 }
293
294
TEST_F(LinkageTailCall,MatchingStackParametersExtraCallerRegistersAndStack)295 TEST_F(LinkageTailCall, MatchingStackParametersExtraCallerRegistersAndStack) {
296 // Caller
297 LinkageLocation location_array[] = {RegisterLocation(0), StackLocation(3),
298 StackLocation(2), StackLocation(1),
299 RegisterLocation(0), StackLocation(4)};
300 LocationSignature locations1(1, 5, location_array);
301 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1);
302
303 // Caller
304 LocationSignature locations2(1, 3, location_array);
305 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations2);
306
307 CommonOperatorBuilder common(zone());
308 Node* p0 = Node::New(zone(), 0, nullptr, 0, nullptr, false);
309 Node* p1 = Node::New(zone(), 0, common.Parameter(0), 0, nullptr, false);
310 Node* p2 = Node::New(zone(), 0, common.Parameter(1), 0, nullptr, false);
311 Node* p3 = Node::New(zone(), 0, common.Parameter(2), 0, nullptr, false);
312 Node* p4 = Node::New(zone(), 0, common.Parameter(3), 0, nullptr, false);
313 Node* parameters[] = {p0, p1, p2, p3, p4};
314 const Operator* op = common.Call(desc2);
315 Node* const node =
316 Node::New(zone(), 1, op, arraysize(parameters), parameters, false);
317 int stack_param_delta = 0;
318 EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
319 EXPECT_EQ(1, stack_param_delta);
320 }
321
322
TEST_F(LinkageTailCall,MatchingStackParametersExtraCalleeRegistersAndStack)323 TEST_F(LinkageTailCall, MatchingStackParametersExtraCalleeRegistersAndStack) {
324 // Caller
325 LinkageLocation location_array[] = {RegisterLocation(0), StackLocation(3),
326 StackLocation(2), RegisterLocation(0),
327 RegisterLocation(1), StackLocation(4)};
328 LocationSignature locations1(1, 3, location_array);
329 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1);
330
331 // Caller
332 LocationSignature locations2(1, 5, location_array);
333 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations2);
334
335 CommonOperatorBuilder common(zone());
336 Node* p0 = Node::New(zone(), 0, nullptr, 0, nullptr, false);
337 Node* p1 = Node::New(zone(), 0, common.Parameter(0), 0, nullptr, false);
338 Node* p2 = Node::New(zone(), 0, common.Parameter(1), 0, nullptr, false);
339 Node* p3 = Node::New(zone(), 0, common.Parameter(2), 0, nullptr, false);
340 Node* p4 = Node::New(zone(), 0, common.Parameter(3), 0, nullptr, false);
341 Node* parameters[] = {p0, p1, p2, p3, p4};
342 const Operator* op = common.Call(desc2);
343 Node* const node =
344 Node::New(zone(), 1, op, arraysize(parameters), parameters, false);
345 int stack_param_delta = 0;
346 EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
347 EXPECT_EQ(-1, stack_param_delta);
348 }
349
350 } // namespace compiler
351 } // namespace internal
352 } // namespace v8
353