OLD | NEW |
(Empty) | |
| 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[] = {kMachAnyTagged, kMachAnyTagged, kMachAnyTagged, |
| 18 kMachAnyTagged, kMachAnyTagged, kMachAnyTagged, |
| 19 kMachAnyTagged, kMachAnyTagged}; |
| 20 } |
| 21 |
| 22 class LinkageTailCall : public TestWithZone { |
| 23 protected: |
| 24 CallDescriptor* NewStandardCallDescriptor(LocationSignature* locations) { |
| 25 DCHECK(arraysize(kMachineTypes) >= |
| 26 locations->return_count() + locations->parameter_count()); |
| 27 MachineSignature* types = new (zone()) MachineSignature( |
| 28 locations->return_count(), locations->parameter_count(), kMachineTypes); |
| 29 return new (zone()) |
| 30 CallDescriptor(CallDescriptor::kCallCodeObject, kMachAnyTagged, |
| 31 LinkageLocation::AnyRegister(), |
| 32 types, // machine_sig |
| 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 ""); |
| 40 } |
| 41 |
| 42 LinkageLocation StackLocation(int loc) { return LinkageLocation(-loc); } |
| 43 |
| 44 LinkageLocation RegisterLocation(int loc) { return LinkageLocation(loc); } |
| 45 }; |
| 46 |
| 47 |
| 48 TEST_F(LinkageTailCall, EmptyToEmpty) { |
| 49 LocationSignature locations(0, 0, nullptr); |
| 50 CallDescriptor* desc = NewStandardCallDescriptor(&locations); |
| 51 CommonOperatorBuilder common(zone()); |
| 52 const Operator* op = common.Call(desc); |
| 53 Node* const node = Node::New(zone(), 1, op, 0, nullptr, false); |
| 54 EXPECT_TRUE(desc->CanTailCall(node)); |
| 55 } |
| 56 |
| 57 |
| 58 TEST_F(LinkageTailCall, SameReturn) { |
| 59 // Caller |
| 60 LinkageLocation location_array[] = {RegisterLocation(0)}; |
| 61 LocationSignature locations1(1, 0, location_array); |
| 62 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1); |
| 63 |
| 64 // Callee |
| 65 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations1); |
| 66 |
| 67 CommonOperatorBuilder common(zone()); |
| 68 const Operator* op = common.Call(desc2); |
| 69 Node* const node = Node::New(zone(), 1, op, 0, nullptr, false); |
| 70 EXPECT_TRUE(desc1->CanTailCall(node)); |
| 71 } |
| 72 |
| 73 |
| 74 TEST_F(LinkageTailCall, DifferingReturn) { |
| 75 // Caller |
| 76 LinkageLocation location_array1[] = {RegisterLocation(0)}; |
| 77 LocationSignature locations1(1, 0, location_array1); |
| 78 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1); |
| 79 |
| 80 // Callee |
| 81 LinkageLocation location_array2[] = {RegisterLocation(1)}; |
| 82 LocationSignature locations2(1, 0, location_array2); |
| 83 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations2); |
| 84 |
| 85 CommonOperatorBuilder common(zone()); |
| 86 const Operator* op = common.Call(desc2); |
| 87 Node* const node = Node::New(zone(), 1, op, 0, nullptr, false); |
| 88 EXPECT_FALSE(desc1->CanTailCall(node)); |
| 89 } |
| 90 |
| 91 |
| 92 TEST_F(LinkageTailCall, MoreRegisterParametersCallee) { |
| 93 // Caller |
| 94 LinkageLocation location_array1[] = {RegisterLocation(0)}; |
| 95 LocationSignature locations1(1, 0, location_array1); |
| 96 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1); |
| 97 |
| 98 // Callee |
| 99 LinkageLocation location_array2[] = {RegisterLocation(0), |
| 100 RegisterLocation(0)}; |
| 101 LocationSignature locations2(1, 1, location_array2); |
| 102 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations2); |
| 103 |
| 104 CommonOperatorBuilder common(zone()); |
| 105 const Operator* op = common.Call(desc2); |
| 106 Node* const node = Node::New(zone(), 1, op, 0, nullptr, false); |
| 107 EXPECT_TRUE(desc1->CanTailCall(node)); |
| 108 } |
| 109 |
| 110 |
| 111 TEST_F(LinkageTailCall, MoreRegisterParametersCaller) { |
| 112 // Caller |
| 113 LinkageLocation location_array1[] = {RegisterLocation(0), |
| 114 RegisterLocation(0)}; |
| 115 LocationSignature locations1(1, 1, location_array1); |
| 116 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1); |
| 117 |
| 118 // Callee |
| 119 LinkageLocation location_array2[] = {RegisterLocation(0)}; |
| 120 LocationSignature locations2(1, 0, location_array2); |
| 121 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations2); |
| 122 |
| 123 CommonOperatorBuilder common(zone()); |
| 124 const Operator* op = common.Call(desc2); |
| 125 Node* const node = Node::New(zone(), 1, op, 0, nullptr, false); |
| 126 EXPECT_TRUE(desc1->CanTailCall(node)); |
| 127 } |
| 128 |
| 129 |
| 130 TEST_F(LinkageTailCall, MoreRegisterAndStackParametersCallee) { |
| 131 // Caller |
| 132 LinkageLocation location_array1[] = {RegisterLocation(0)}; |
| 133 LocationSignature locations1(1, 0, location_array1); |
| 134 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1); |
| 135 |
| 136 // Callee |
| 137 LinkageLocation location_array2[] = {RegisterLocation(0), RegisterLocation(0), |
| 138 RegisterLocation(1), StackLocation(1)}; |
| 139 LocationSignature locations2(1, 3, location_array2); |
| 140 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations2); |
| 141 |
| 142 CommonOperatorBuilder common(zone()); |
| 143 const Operator* op = common.Call(desc2); |
| 144 Node* const node = Node::New(zone(), 1, op, 0, nullptr, false); |
| 145 EXPECT_FALSE(desc1->CanTailCall(node)); |
| 146 } |
| 147 |
| 148 |
| 149 TEST_F(LinkageTailCall, MoreRegisterAndStackParametersCaller) { |
| 150 // Caller |
| 151 LinkageLocation location_array[] = {RegisterLocation(0), RegisterLocation(0), |
| 152 RegisterLocation(1), StackLocation(1)}; |
| 153 LocationSignature locations1(1, 3, location_array); |
| 154 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1); |
| 155 |
| 156 // Callee |
| 157 LinkageLocation location_array2[] = {RegisterLocation(0)}; |
| 158 LocationSignature locations2(1, 0, location_array2); |
| 159 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations2); |
| 160 |
| 161 CommonOperatorBuilder common(zone()); |
| 162 const Operator* op = common.Call(desc2); |
| 163 Node* const node = Node::New(zone(), 1, op, 0, nullptr, false); |
| 164 EXPECT_FALSE(desc1->CanTailCall(node)); |
| 165 } |
| 166 |
| 167 |
| 168 TEST_F(LinkageTailCall, MatchingStackParameters) { |
| 169 // Caller |
| 170 LinkageLocation location_array[] = {RegisterLocation(0), StackLocation(3), |
| 171 StackLocation(2), StackLocation(1)}; |
| 172 LocationSignature locations1(1, 3, location_array); |
| 173 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1); |
| 174 |
| 175 // Caller |
| 176 LocationSignature locations2(1, 3, location_array); |
| 177 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations1); |
| 178 |
| 179 CommonOperatorBuilder common(zone()); |
| 180 Node* p0 = Node::New(zone(), 0, nullptr, 0, nullptr, false); |
| 181 Node* p1 = Node::New(zone(), 0, common.Parameter(0), 0, nullptr, false); |
| 182 Node* p2 = Node::New(zone(), 0, common.Parameter(1), 0, nullptr, false); |
| 183 Node* p3 = Node::New(zone(), 0, common.Parameter(2), 0, nullptr, false); |
| 184 Node* parameters[] = {p0, p1, p2, p3}; |
| 185 const Operator* op = common.Call(desc2); |
| 186 Node* const node = |
| 187 Node::New(zone(), 1, op, arraysize(parameters), parameters, false); |
| 188 EXPECT_TRUE(desc1->CanTailCall(node)); |
| 189 } |
| 190 |
| 191 |
| 192 TEST_F(LinkageTailCall, NonMatchingStackParameters) { |
| 193 // Caller |
| 194 LinkageLocation location_array[] = {RegisterLocation(0), StackLocation(3), |
| 195 StackLocation(2), StackLocation(1)}; |
| 196 LocationSignature locations1(1, 3, location_array); |
| 197 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1); |
| 198 |
| 199 // Caller |
| 200 LocationSignature locations2(1, 3, location_array); |
| 201 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations1); |
| 202 |
| 203 CommonOperatorBuilder common(zone()); |
| 204 Node* p0 = Node::New(zone(), 0, nullptr, 0, nullptr, false); |
| 205 Node* p1 = Node::New(zone(), 0, common.Parameter(0), 0, nullptr, false); |
| 206 Node* p2 = Node::New(zone(), 0, common.Parameter(2), 0, nullptr, false); |
| 207 Node* p3 = Node::New(zone(), 0, common.Parameter(1), 0, nullptr, false); |
| 208 Node* parameters[] = {p0, p1, p2, p3}; |
| 209 const Operator* op = common.Call(desc2); |
| 210 Node* const node = |
| 211 Node::New(zone(), 1, op, arraysize(parameters), parameters, false); |
| 212 EXPECT_FALSE(desc1->CanTailCall(node)); |
| 213 } |
| 214 |
| 215 |
| 216 TEST_F(LinkageTailCall, MatchingStackParametersExtraCallerRegisters) { |
| 217 // Caller |
| 218 LinkageLocation location_array[] = {RegisterLocation(0), StackLocation(3), |
| 219 StackLocation(2), StackLocation(1), |
| 220 RegisterLocation(0), RegisterLocation(1)}; |
| 221 LocationSignature locations1(1, 5, location_array); |
| 222 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1); |
| 223 |
| 224 // Caller |
| 225 LocationSignature locations2(1, 3, location_array); |
| 226 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations1); |
| 227 |
| 228 CommonOperatorBuilder common(zone()); |
| 229 Node* p0 = Node::New(zone(), 0, nullptr, 0, nullptr, false); |
| 230 Node* p1 = Node::New(zone(), 0, common.Parameter(0), 0, nullptr, false); |
| 231 Node* p2 = Node::New(zone(), 0, common.Parameter(1), 0, nullptr, false); |
| 232 Node* p3 = Node::New(zone(), 0, common.Parameter(2), 0, nullptr, false); |
| 233 Node* parameters[] = {p0, p1, p2, p3}; |
| 234 const Operator* op = common.Call(desc2); |
| 235 Node* const node = |
| 236 Node::New(zone(), 1, op, arraysize(parameters), parameters, false); |
| 237 EXPECT_TRUE(desc1->CanTailCall(node)); |
| 238 } |
| 239 |
| 240 |
| 241 TEST_F(LinkageTailCall, MatchingStackParametersExtraCalleeRegisters) { |
| 242 // Caller |
| 243 LinkageLocation location_array[] = {RegisterLocation(0), StackLocation(3), |
| 244 StackLocation(2), StackLocation(1), |
| 245 RegisterLocation(0), RegisterLocation(1)}; |
| 246 LocationSignature locations1(1, 3, location_array); |
| 247 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1); |
| 248 |
| 249 // Caller |
| 250 LocationSignature locations2(1, 5, location_array); |
| 251 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations1); |
| 252 |
| 253 CommonOperatorBuilder common(zone()); |
| 254 Node* p0 = Node::New(zone(), 0, nullptr, 0, nullptr, false); |
| 255 Node* p1 = Node::New(zone(), 0, common.Parameter(0), 0, nullptr, false); |
| 256 Node* p2 = Node::New(zone(), 0, common.Parameter(1), 0, nullptr, false); |
| 257 Node* p3 = Node::New(zone(), 0, common.Parameter(2), 0, nullptr, false); |
| 258 Node* p4 = Node::New(zone(), 0, common.Parameter(3), 0, nullptr, false); |
| 259 Node* parameters[] = {p0, p1, p2, p3, p4}; |
| 260 const Operator* op = common.Call(desc2); |
| 261 Node* const node = |
| 262 Node::New(zone(), 1, op, arraysize(parameters), parameters, false); |
| 263 EXPECT_TRUE(desc1->CanTailCall(node)); |
| 264 } |
| 265 |
| 266 |
| 267 TEST_F(LinkageTailCall, MatchingStackParametersExtraCallerRegistersAndStack) { |
| 268 // Caller |
| 269 LinkageLocation location_array[] = {RegisterLocation(0), StackLocation(3), |
| 270 StackLocation(2), StackLocation(1), |
| 271 RegisterLocation(0), StackLocation(4)}; |
| 272 LocationSignature locations1(1, 5, location_array); |
| 273 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1); |
| 274 |
| 275 // Caller |
| 276 LocationSignature locations2(1, 3, location_array); |
| 277 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations2); |
| 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 EXPECT_FALSE(desc1->CanTailCall(node)); |
| 290 } |
| 291 |
| 292 |
| 293 TEST_F(LinkageTailCall, MatchingStackParametersExtraCalleeRegistersAndStack) { |
| 294 // Caller |
| 295 LinkageLocation location_array[] = {RegisterLocation(0), StackLocation(3), |
| 296 StackLocation(2), RegisterLocation(0), |
| 297 RegisterLocation(1), StackLocation(4)}; |
| 298 LocationSignature locations1(1, 3, location_array); |
| 299 CallDescriptor* desc1 = NewStandardCallDescriptor(&locations1); |
| 300 |
| 301 // Caller |
| 302 LocationSignature locations2(1, 5, location_array); |
| 303 CallDescriptor* desc2 = NewStandardCallDescriptor(&locations2); |
| 304 |
| 305 CommonOperatorBuilder common(zone()); |
| 306 Node* p0 = Node::New(zone(), 0, nullptr, 0, nullptr, false); |
| 307 Node* p1 = Node::New(zone(), 0, common.Parameter(0), 0, nullptr, false); |
| 308 Node* p2 = Node::New(zone(), 0, common.Parameter(1), 0, nullptr, false); |
| 309 Node* p3 = Node::New(zone(), 0, common.Parameter(2), 0, nullptr, false); |
| 310 Node* p4 = Node::New(zone(), 0, common.Parameter(3), 0, nullptr, false); |
| 311 Node* parameters[] = {p0, p1, p2, p3, p4}; |
| 312 const Operator* op = common.Call(desc2); |
| 313 Node* const node = |
| 314 Node::New(zone(), 1, op, arraysize(parameters), parameters, false); |
| 315 EXPECT_FALSE(desc1->CanTailCall(node)); |
| 316 } |
| 317 |
| 318 } // namespace compiler |
| 319 } // namespace internal |
| 320 } // namespace v8 |
OLD | NEW |