| 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[] = {kMachAnyTagged, kMachAnyTagged}; | 29   MachineType kMachineSignature[] = {kMachAnyTagged, kMachAnyTagged}; | 
| 30   LinkageLocation kLocationSignature[] = {LinkageLocation(0), | 30   LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0), | 
| 31                                           LinkageLocation(1)}; | 31                                           LinkageLocation::ForRegister(1)}; | 
| 32   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor( | 32   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor( | 
| 33       CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0), | 33       CallDescriptor::kCallCodeObject, kMachAnyTagged, | 
|  | 34       LinkageLocation::ForRegister(0), | 
| 34       new (zone()) MachineSignature(1, 1, kMachineSignature), | 35       new (zone()) MachineSignature(1, 1, kMachineSignature), | 
| 35       new (zone()) LocationSignature(1, 1, kLocationSignature), 0, | 36       new (zone()) LocationSignature(1, 1, kLocationSignature), 0, | 
| 36       Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags); | 37       Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags); | 
| 37   Node* p0 = Parameter(0); | 38   Node* p0 = Parameter(0); | 
| 38   Node* p1 = Parameter(1); | 39   Node* p1 = Parameter(1); | 
| 39   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, | 40   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, | 
| 40                                 graph()->start(), graph()->start()); | 41                                 graph()->start(), graph()->start()); | 
| 41   Node* if_success = graph()->NewNode(common()->IfSuccess(), call); | 42   Node* if_success = graph()->NewNode(common()->IfSuccess(), call); | 
| 42   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success); | 43   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success); | 
| 43   Reduction r = Reduce(ret); | 44   Reduction r = Reduce(ret); | 
| 44   ASSERT_FALSE(r.Changed()); | 45   ASSERT_FALSE(r.Changed()); | 
| 45 } | 46 } | 
| 46 | 47 | 
| 47 | 48 | 
| 48 TEST_F(TailCallOptimizationTest, CallCodeObject1) { | 49 TEST_F(TailCallOptimizationTest, CallCodeObject1) { | 
| 49   MachineType kMachineSignature[] = {kMachAnyTagged, kMachAnyTagged}; | 50   MachineType kMachineSignature[] = {kMachAnyTagged, kMachAnyTagged}; | 
| 50   LinkageLocation kLocationSignature[] = {LinkageLocation(0), | 51   LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0), | 
| 51                                           LinkageLocation(1)}; | 52                                           LinkageLocation::ForRegister(1)}; | 
| 52   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor( | 53   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor( | 
| 53       CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0), | 54       CallDescriptor::kCallCodeObject, kMachAnyTagged, | 
|  | 55       LinkageLocation::ForRegister(0), | 
| 54       new (zone()) MachineSignature(1, 1, kMachineSignature), | 56       new (zone()) MachineSignature(1, 1, kMachineSignature), | 
| 55       new (zone()) LocationSignature(1, 1, kLocationSignature), 0, | 57       new (zone()) LocationSignature(1, 1, kLocationSignature), 0, | 
| 56       Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls); | 58       Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls); | 
| 57   Node* p0 = Parameter(0); | 59   Node* p0 = Parameter(0); | 
| 58   Node* p1 = Parameter(1); | 60   Node* p1 = Parameter(1); | 
| 59   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, | 61   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, | 
| 60                                 graph()->start(), graph()->start()); | 62                                 graph()->start(), graph()->start()); | 
| 61   Node* if_success = graph()->NewNode(common()->IfSuccess(), call); | 63   Node* if_success = graph()->NewNode(common()->IfSuccess(), call); | 
| 62   Node* if_exception = graph()->NewNode( | 64   Node* if_exception = graph()->NewNode( | 
| 63       common()->IfException(IfExceptionHint::kLocallyUncaught), call, call); | 65       common()->IfException(IfExceptionHint::kLocallyUncaught), call, call); | 
| 64   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success); | 66   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success); | 
| 65   Node* end = graph()->NewNode(common()->End(1), if_exception); | 67   Node* end = graph()->NewNode(common()->End(1), if_exception); | 
| 66   graph()->SetEnd(end); | 68   graph()->SetEnd(end); | 
| 67   Reduction r = Reduce(ret); | 69   Reduction r = Reduce(ret); | 
| 68   ASSERT_FALSE(r.Changed()); | 70   ASSERT_FALSE(r.Changed()); | 
| 69 } | 71 } | 
| 70 | 72 | 
| 71 | 73 | 
| 72 TEST_F(TailCallOptimizationTest, CallCodeObject2) { | 74 TEST_F(TailCallOptimizationTest, CallCodeObject2) { | 
| 73   MachineType kMachineSignature[] = {kMachAnyTagged, kMachAnyTagged}; | 75   MachineType kMachineSignature[] = {kMachAnyTagged, kMachAnyTagged}; | 
| 74   LinkageLocation kLocationSignature[] = {LinkageLocation(0), | 76   LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0), | 
| 75                                           LinkageLocation(1)}; | 77                                           LinkageLocation::ForRegister(1)}; | 
| 76   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor( | 78   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor( | 
| 77       CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0), | 79       CallDescriptor::kCallCodeObject, kMachAnyTagged, | 
|  | 80       LinkageLocation::ForRegister(0), | 
| 78       new (zone()) MachineSignature(1, 1, kMachineSignature), | 81       new (zone()) MachineSignature(1, 1, kMachineSignature), | 
| 79       new (zone()) LocationSignature(1, 1, kLocationSignature), 0, | 82       new (zone()) LocationSignature(1, 1, kLocationSignature), 0, | 
| 80       Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls); | 83       Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls); | 
| 81   Node* p0 = Parameter(0); | 84   Node* p0 = Parameter(0); | 
| 82   Node* p1 = Parameter(1); | 85   Node* p1 = Parameter(1); | 
| 83   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, | 86   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, | 
| 84                                 graph()->start(), graph()->start()); | 87                                 graph()->start(), graph()->start()); | 
| 85   Node* if_success = graph()->NewNode(common()->IfSuccess(), call); | 88   Node* if_success = graph()->NewNode(common()->IfSuccess(), call); | 
| 86   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success); | 89   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success); | 
| 87   Reduction r = Reduce(ret); | 90   Reduction r = Reduce(ret); | 
| 88   ASSERT_TRUE(r.Changed()); | 91   ASSERT_TRUE(r.Changed()); | 
| 89   EXPECT_THAT(r.replacement(), IsTailCall(kCallDescriptor, p0, p1, | 92   EXPECT_THAT(r.replacement(), IsTailCall(kCallDescriptor, p0, p1, | 
| 90                                           graph()->start(), graph()->start())); | 93                                           graph()->start(), graph()->start())); | 
| 91 } | 94 } | 
| 92 | 95 | 
| 93 | 96 | 
| 94 TEST_F(TailCallOptimizationTest, CallJSFunction0) { | 97 TEST_F(TailCallOptimizationTest, CallJSFunction0) { | 
| 95   MachineType kMachineSignature[] = {kMachAnyTagged, kMachAnyTagged}; | 98   MachineType kMachineSignature[] = {kMachAnyTagged, kMachAnyTagged}; | 
| 96   LinkageLocation kLocationSignature[] = {LinkageLocation(0), | 99   LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0), | 
| 97                                           LinkageLocation(1)}; | 100                                           LinkageLocation::ForRegister(1)}; | 
| 98   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor( | 101   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor( | 
| 99       CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0), | 102       CallDescriptor::kCallJSFunction, kMachAnyTagged, | 
|  | 103       LinkageLocation::ForRegister(0), | 
| 100       new (zone()) MachineSignature(1, 1, kMachineSignature), | 104       new (zone()) MachineSignature(1, 1, kMachineSignature), | 
| 101       new (zone()) LocationSignature(1, 1, kLocationSignature), 0, | 105       new (zone()) LocationSignature(1, 1, kLocationSignature), 0, | 
| 102       Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags); | 106       Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags); | 
| 103   Node* p0 = Parameter(0); | 107   Node* p0 = Parameter(0); | 
| 104   Node* p1 = Parameter(1); | 108   Node* p1 = Parameter(1); | 
| 105   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, | 109   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, | 
| 106                                 graph()->start(), graph()->start()); | 110                                 graph()->start(), graph()->start()); | 
| 107   Node* if_success = graph()->NewNode(common()->IfSuccess(), call); | 111   Node* if_success = graph()->NewNode(common()->IfSuccess(), call); | 
| 108   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success); | 112   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success); | 
| 109   Reduction r = Reduce(ret); | 113   Reduction r = Reduce(ret); | 
| 110   ASSERT_FALSE(r.Changed()); | 114   ASSERT_FALSE(r.Changed()); | 
| 111 } | 115 } | 
| 112 | 116 | 
| 113 | 117 | 
| 114 TEST_F(TailCallOptimizationTest, CallJSFunction1) { | 118 TEST_F(TailCallOptimizationTest, CallJSFunction1) { | 
| 115   MachineType kMachineSignature[] = {kMachAnyTagged, kMachAnyTagged}; | 119   MachineType kMachineSignature[] = {kMachAnyTagged, kMachAnyTagged}; | 
| 116   LinkageLocation kLocationSignature[] = {LinkageLocation(0), | 120   LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0), | 
| 117                                           LinkageLocation(1)}; | 121                                           LinkageLocation::ForRegister(1)}; | 
| 118   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor( | 122   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor( | 
| 119       CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0), | 123       CallDescriptor::kCallJSFunction, kMachAnyTagged, | 
|  | 124       LinkageLocation::ForRegister(0), | 
| 120       new (zone()) MachineSignature(1, 1, kMachineSignature), | 125       new (zone()) MachineSignature(1, 1, kMachineSignature), | 
| 121       new (zone()) LocationSignature(1, 1, kLocationSignature), 0, | 126       new (zone()) LocationSignature(1, 1, kLocationSignature), 0, | 
| 122       Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls); | 127       Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls); | 
| 123   Node* p0 = Parameter(0); | 128   Node* p0 = Parameter(0); | 
| 124   Node* p1 = Parameter(1); | 129   Node* p1 = Parameter(1); | 
| 125   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, | 130   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, | 
| 126                                 graph()->start(), graph()->start()); | 131                                 graph()->start(), graph()->start()); | 
| 127   Node* if_success = graph()->NewNode(common()->IfSuccess(), call); | 132   Node* if_success = graph()->NewNode(common()->IfSuccess(), call); | 
| 128   Node* if_exception = graph()->NewNode( | 133   Node* if_exception = graph()->NewNode( | 
| 129       common()->IfException(IfExceptionHint::kLocallyUncaught), call, call); | 134       common()->IfException(IfExceptionHint::kLocallyUncaught), call, call); | 
| 130   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success); | 135   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success); | 
| 131   Node* end = graph()->NewNode(common()->End(1), if_exception); | 136   Node* end = graph()->NewNode(common()->End(1), if_exception); | 
| 132   graph()->SetEnd(end); | 137   graph()->SetEnd(end); | 
| 133   Reduction r = Reduce(ret); | 138   Reduction r = Reduce(ret); | 
| 134   ASSERT_FALSE(r.Changed()); | 139   ASSERT_FALSE(r.Changed()); | 
| 135 } | 140 } | 
| 136 | 141 | 
| 137 | 142 | 
| 138 TEST_F(TailCallOptimizationTest, CallJSFunction2) { | 143 TEST_F(TailCallOptimizationTest, CallJSFunction2) { | 
| 139   MachineType kMachineSignature[] = {kMachAnyTagged, kMachAnyTagged}; | 144   MachineType kMachineSignature[] = {kMachAnyTagged, kMachAnyTagged}; | 
| 140   LinkageLocation kLocationSignature[] = {LinkageLocation(0), | 145   LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0), | 
| 141                                           LinkageLocation(1)}; | 146                                           LinkageLocation::ForRegister(1)}; | 
| 142   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor( | 147   const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor( | 
| 143       CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0), | 148       CallDescriptor::kCallJSFunction, kMachAnyTagged, | 
|  | 149       LinkageLocation::ForRegister(0), | 
| 144       new (zone()) MachineSignature(1, 1, kMachineSignature), | 150       new (zone()) MachineSignature(1, 1, kMachineSignature), | 
| 145       new (zone()) LocationSignature(1, 1, kLocationSignature), 0, | 151       new (zone()) LocationSignature(1, 1, kLocationSignature), 0, | 
| 146       Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls); | 152       Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls); | 
| 147   Node* p0 = Parameter(0); | 153   Node* p0 = Parameter(0); | 
| 148   Node* p1 = Parameter(1); | 154   Node* p1 = Parameter(1); | 
| 149   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, | 155   Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, | 
| 150                                 graph()->start(), graph()->start()); | 156                                 graph()->start(), graph()->start()); | 
| 151   Node* if_success = graph()->NewNode(common()->IfSuccess(), call); | 157   Node* if_success = graph()->NewNode(common()->IfSuccess(), call); | 
| 152   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success); | 158   Node* ret = graph()->NewNode(common()->Return(), call, call, if_success); | 
| 153   Reduction r = Reduce(ret); | 159   Reduction r = Reduce(ret); | 
| 154   ASSERT_TRUE(r.Changed()); | 160   ASSERT_TRUE(r.Changed()); | 
| 155   EXPECT_THAT(r.replacement(), IsTailCall(kCallDescriptor, p0, p1, | 161   EXPECT_THAT(r.replacement(), IsTailCall(kCallDescriptor, p0, p1, | 
| 156                                           graph()->start(), graph()->start())); | 162                                           graph()->start(), graph()->start())); | 
| 157 } | 163 } | 
| 158 | 164 | 
| 159 | 165 | 
| 160 }  // namespace compiler | 166 }  // namespace compiler | 
| 161 }  // namespace internal | 167 }  // namespace internal | 
| 162 }  // namespace v8 | 168 }  // namespace v8 | 
| OLD | NEW | 
|---|