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