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: 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 44 LinkageLocation StackLocation(int loc) { 45 return LinkageLocation::ForCallerFrameSlot(-loc); 46 } 47 48 LinkageLocation RegisterLocation(int loc) { 49 return LinkageLocation::ForRegister(loc); 50 } 51 }; 52 53 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 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 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 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 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 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 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 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 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 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 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 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 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