Home | History | Annotate | Download | only in compiler
      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