• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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