Home | History | Annotate | Download | only in compiler
      1 // Copyright 2015 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/linkage.h"
      6 #include "src/compiler/tail-call-optimization.h"
      7 #include "test/unittests/compiler/graph-unittest.h"
      8 #include "test/unittests/compiler/node-test-utils.h"
      9 
     10 namespace v8 {
     11 namespace internal {
     12 namespace compiler {
     13 
     14 class TailCallOptimizationTest : public GraphTest {
     15  public:
     16   explicit TailCallOptimizationTest(int num_parameters = 1)
     17       : GraphTest(num_parameters) {}
     18   ~TailCallOptimizationTest() override {}
     19 
     20  protected:
     21   Reduction Reduce(Node* node) {
     22     TailCallOptimization tco(common(), graph());
     23     return tco.Reduce(node);
     24   }
     25 };
     26 
     27 
     28 TEST_F(TailCallOptimizationTest, CallCodeObject0) {
     29   MachineType kMachineSignature[] = {MachineType::AnyTagged(),
     30                                      MachineType::AnyTagged()};
     31   LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
     32                                           LinkageLocation::ForRegister(1)};
     33   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
     34       CallDescriptor::kCallCodeObject, MachineType::AnyTagged(),
     35       LinkageLocation::ForRegister(0),
     36       new (zone()) MachineSignature(1, 1, kMachineSignature),
     37       new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
     38       Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
     39   Node* p0 = Parameter(0);
     40   Node* p1 = Parameter(1);
     41   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
     42                                 graph()->start(), graph()->start());
     43   Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
     44   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
     45   Reduction r = Reduce(ret);
     46   ASSERT_FALSE(r.Changed());
     47 }
     48 
     49 
     50 TEST_F(TailCallOptimizationTest, CallCodeObject1) {
     51   MachineType kMachineSignature[] = {MachineType::AnyTagged(),
     52                                      MachineType::AnyTagged()};
     53   LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
     54                                           LinkageLocation::ForRegister(1)};
     55   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
     56       CallDescriptor::kCallCodeObject, MachineType::AnyTagged(),
     57       LinkageLocation::ForRegister(0),
     58       new (zone()) MachineSignature(1, 1, kMachineSignature),
     59       new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
     60       Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
     61   Node* p0 = Parameter(0);
     62   Node* p1 = Parameter(1);
     63   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
     64                                 graph()->start(), graph()->start());
     65   Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
     66   Node* if_exception = graph()->NewNode(
     67       common()->IfException(IfExceptionHint::kLocallyUncaught), call, call);
     68   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
     69   Node* end = graph()->NewNode(common()->End(1), if_exception);
     70   graph()->SetEnd(end);
     71   Reduction r = Reduce(ret);
     72   ASSERT_FALSE(r.Changed());
     73 }
     74 
     75 
     76 TEST_F(TailCallOptimizationTest, CallCodeObject2) {
     77   MachineType kMachineSignature[] = {MachineType::AnyTagged(),
     78                                      MachineType::AnyTagged()};
     79   LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
     80                                           LinkageLocation::ForRegister(1)};
     81   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
     82       CallDescriptor::kCallCodeObject, MachineType::AnyTagged(),
     83       LinkageLocation::ForRegister(0),
     84       new (zone()) MachineSignature(1, 1, kMachineSignature),
     85       new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
     86       Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
     87   Node* p0 = Parameter(0);
     88   Node* p1 = Parameter(1);
     89   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
     90                                 graph()->start(), graph()->start());
     91   Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
     92   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
     93   Reduction r = Reduce(ret);
     94   ASSERT_TRUE(r.Changed());
     95   EXPECT_THAT(r.replacement(), IsTailCall(kCallDescriptor, p0, p1,
     96                                           graph()->start(), graph()->start()));
     97 }
     98 
     99 
    100 TEST_F(TailCallOptimizationTest, CallJSFunction0) {
    101   MachineType kMachineSignature[] = {MachineType::AnyTagged(),
    102                                      MachineType::AnyTagged()};
    103   LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
    104                                           LinkageLocation::ForRegister(1)};
    105   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
    106       CallDescriptor::kCallJSFunction, MachineType::AnyTagged(),
    107       LinkageLocation::ForRegister(0),
    108       new (zone()) MachineSignature(1, 1, kMachineSignature),
    109       new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
    110       Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
    111   Node* p0 = Parameter(0);
    112   Node* p1 = Parameter(1);
    113   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
    114                                 graph()->start(), graph()->start());
    115   Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
    116   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
    117   Reduction r = Reduce(ret);
    118   ASSERT_FALSE(r.Changed());
    119 }
    120 
    121 
    122 TEST_F(TailCallOptimizationTest, CallJSFunction1) {
    123   MachineType kMachineSignature[] = {MachineType::AnyTagged(),
    124                                      MachineType::AnyTagged()};
    125   LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
    126                                           LinkageLocation::ForRegister(1)};
    127   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
    128       CallDescriptor::kCallJSFunction, MachineType::AnyTagged(),
    129       LinkageLocation::ForRegister(0),
    130       new (zone()) MachineSignature(1, 1, kMachineSignature),
    131       new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
    132       Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
    133   Node* p0 = Parameter(0);
    134   Node* p1 = Parameter(1);
    135   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
    136                                 graph()->start(), graph()->start());
    137   Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
    138   Node* if_exception = graph()->NewNode(
    139       common()->IfException(IfExceptionHint::kLocallyUncaught), call, call);
    140   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
    141   Node* end = graph()->NewNode(common()->End(1), if_exception);
    142   graph()->SetEnd(end);
    143   Reduction r = Reduce(ret);
    144   ASSERT_FALSE(r.Changed());
    145 }
    146 
    147 
    148 TEST_F(TailCallOptimizationTest, CallJSFunction2) {
    149   MachineType kMachineSignature[] = {MachineType::AnyTagged(),
    150                                      MachineType::AnyTagged()};
    151   LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
    152                                           LinkageLocation::ForRegister(1)};
    153   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
    154       CallDescriptor::kCallJSFunction, MachineType::AnyTagged(),
    155       LinkageLocation::ForRegister(0),
    156       new (zone()) MachineSignature(1, 1, kMachineSignature),
    157       new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
    158       Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
    159   Node* p0 = Parameter(0);
    160   Node* p1 = Parameter(1);
    161   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
    162                                 graph()->start(), graph()->start());
    163   Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
    164   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
    165   Reduction r = Reduce(ret);
    166   ASSERT_TRUE(r.Changed());
    167   EXPECT_THAT(r.replacement(), IsTailCall(kCallDescriptor, p0, p1,
    168                                           graph()->start(), graph()->start()));
    169 }
    170 
    171 
    172 }  // namespace compiler
    173 }  // namespace internal
    174 }  // namespace v8
    175