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