2015-05-05 09:42:59 +00:00
|
|
|
// Copyright 2015 the V8 project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
#include "src/compiler/linkage.h"
|
|
|
|
#include "src/compiler/tail-call-optimization.h"
|
|
|
|
#include "test/unittests/compiler/graph-unittest.h"
|
|
|
|
#include "test/unittests/compiler/node-test-utils.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
namespace compiler {
|
|
|
|
|
|
|
|
class TailCallOptimizationTest : public GraphTest {
|
|
|
|
public:
|
|
|
|
explicit TailCallOptimizationTest(int num_parameters = 1)
|
|
|
|
: GraphTest(num_parameters) {}
|
|
|
|
~TailCallOptimizationTest() override {}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
Reduction Reduce(Node* node) {
|
|
|
|
TailCallOptimization tco(common(), graph());
|
|
|
|
return tco.Reduce(node);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
TEST_F(TailCallOptimizationTest, CallCodeObject0) {
|
2016-07-11 10:37:24 +00:00
|
|
|
LinkageLocation kLocationSignature[] = {
|
|
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
|
|
|
LinkageLocation::ForRegister(1, MachineType::Pointer())};
|
2015-05-05 09:42:59 +00:00
|
|
|
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
|
2015-12-10 09:03:30 +00:00
|
|
|
CallDescriptor::kCallCodeObject, MachineType::AnyTagged(),
|
2016-07-11 10:37:24 +00:00
|
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
2015-05-05 09:42:59 +00:00
|
|
|
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
|
2015-06-30 13:22:36 +00:00
|
|
|
Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
|
2015-05-05 09:42:59 +00:00
|
|
|
Node* p0 = Parameter(0);
|
|
|
|
Node* p1 = Parameter(1);
|
|
|
|
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
|
|
|
|
graph()->start(), graph()->start());
|
|
|
|
Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
|
2016-11-02 13:15:39 +00:00
|
|
|
Node* zero = graph()->NewNode(common()->Int32Constant(0));
|
|
|
|
Node* ret =
|
|
|
|
graph()->NewNode(common()->Return(), zero, call, call, if_success);
|
2015-05-05 09:42:59 +00:00
|
|
|
Reduction r = Reduce(ret);
|
|
|
|
ASSERT_FALSE(r.Changed());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_F(TailCallOptimizationTest, CallCodeObject1) {
|
2016-07-11 10:37:24 +00:00
|
|
|
LinkageLocation kLocationSignature[] = {
|
|
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
|
|
|
LinkageLocation::ForRegister(1, MachineType::Pointer())};
|
2015-05-05 09:42:59 +00:00
|
|
|
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
|
2015-12-10 09:03:30 +00:00
|
|
|
CallDescriptor::kCallCodeObject, MachineType::AnyTagged(),
|
2016-07-11 10:37:24 +00:00
|
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
2015-05-05 09:42:59 +00:00
|
|
|
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
|
2015-06-30 13:22:36 +00:00
|
|
|
Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
|
2015-05-05 09:42:59 +00:00
|
|
|
Node* p0 = Parameter(0);
|
|
|
|
Node* p1 = Parameter(1);
|
|
|
|
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
|
|
|
|
graph()->start(), graph()->start());
|
|
|
|
Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
|
2016-08-02 14:48:21 +00:00
|
|
|
Node* if_exception = graph()->NewNode(common()->IfException(), call, call);
|
2016-11-02 13:15:39 +00:00
|
|
|
Node* zero = graph()->NewNode(common()->Int32Constant(0));
|
|
|
|
Node* ret =
|
|
|
|
graph()->NewNode(common()->Return(), zero, call, call, if_success);
|
2015-05-26 10:31:55 +00:00
|
|
|
Node* end = graph()->NewNode(common()->End(1), if_exception);
|
2015-05-05 09:42:59 +00:00
|
|
|
graph()->SetEnd(end);
|
|
|
|
Reduction r = Reduce(ret);
|
|
|
|
ASSERT_FALSE(r.Changed());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_F(TailCallOptimizationTest, CallCodeObject2) {
|
2016-07-11 10:37:24 +00:00
|
|
|
LinkageLocation kLocationSignature[] = {
|
|
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
|
|
|
LinkageLocation::ForRegister(1, MachineType::Pointer())};
|
2015-05-05 09:42:59 +00:00
|
|
|
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
|
2015-12-10 09:03:30 +00:00
|
|
|
CallDescriptor::kCallCodeObject, MachineType::AnyTagged(),
|
2016-07-11 10:37:24 +00:00
|
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
2015-05-05 09:42:59 +00:00
|
|
|
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
|
2015-06-30 13:22:36 +00:00
|
|
|
Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
|
2015-05-05 09:42:59 +00:00
|
|
|
Node* p0 = Parameter(0);
|
|
|
|
Node* p1 = Parameter(1);
|
|
|
|
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
|
|
|
|
graph()->start(), graph()->start());
|
|
|
|
Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
|
2016-11-02 13:15:39 +00:00
|
|
|
Node* zero = graph()->NewNode(common()->Int32Constant(0));
|
|
|
|
Node* ret =
|
|
|
|
graph()->NewNode(common()->Return(), zero, call, call, if_success);
|
2015-05-05 09:42:59 +00:00
|
|
|
Reduction r = Reduce(ret);
|
|
|
|
ASSERT_TRUE(r.Changed());
|
|
|
|
EXPECT_THAT(r.replacement(), IsTailCall(kCallDescriptor, p0, p1,
|
|
|
|
graph()->start(), graph()->start()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_F(TailCallOptimizationTest, CallJSFunction0) {
|
2016-07-11 10:37:24 +00:00
|
|
|
LinkageLocation kLocationSignature[] = {
|
|
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
|
|
|
LinkageLocation::ForRegister(1, MachineType::Pointer())};
|
2015-05-05 09:42:59 +00:00
|
|
|
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
|
2015-12-10 09:03:30 +00:00
|
|
|
CallDescriptor::kCallJSFunction, MachineType::AnyTagged(),
|
2016-07-11 10:37:24 +00:00
|
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
2015-05-05 09:42:59 +00:00
|
|
|
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
|
2015-06-30 13:22:36 +00:00
|
|
|
Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
|
2015-05-05 09:42:59 +00:00
|
|
|
Node* p0 = Parameter(0);
|
|
|
|
Node* p1 = Parameter(1);
|
|
|
|
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
|
|
|
|
graph()->start(), graph()->start());
|
|
|
|
Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
|
2016-11-02 13:15:39 +00:00
|
|
|
Node* zero = graph()->NewNode(common()->Int32Constant(0));
|
|
|
|
Node* ret =
|
|
|
|
graph()->NewNode(common()->Return(), zero, call, call, if_success);
|
2015-05-05 09:42:59 +00:00
|
|
|
Reduction r = Reduce(ret);
|
|
|
|
ASSERT_FALSE(r.Changed());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_F(TailCallOptimizationTest, CallJSFunction1) {
|
2016-07-11 10:37:24 +00:00
|
|
|
LinkageLocation kLocationSignature[] = {
|
|
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
|
|
|
LinkageLocation::ForRegister(1, MachineType::Pointer())};
|
2015-05-05 09:42:59 +00:00
|
|
|
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
|
2015-12-10 09:03:30 +00:00
|
|
|
CallDescriptor::kCallJSFunction, MachineType::AnyTagged(),
|
2015-07-30 14:52:13 +00:00
|
|
|
LinkageLocation::ForRegister(0),
|
2015-05-05 09:42:59 +00:00
|
|
|
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
|
2015-06-30 13:22:36 +00:00
|
|
|
Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
|
2015-05-05 09:42:59 +00:00
|
|
|
Node* p0 = Parameter(0);
|
|
|
|
Node* p1 = Parameter(1);
|
|
|
|
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
|
|
|
|
graph()->start(), graph()->start());
|
|
|
|
Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
|
2016-08-02 14:48:21 +00:00
|
|
|
Node* if_exception = graph()->NewNode(common()->IfException(), call, call);
|
2016-11-02 13:15:39 +00:00
|
|
|
Node* zero = graph()->NewNode(common()->Int32Constant(0));
|
|
|
|
Node* ret =
|
|
|
|
graph()->NewNode(common()->Return(), zero, call, call, if_success);
|
2015-05-26 10:31:55 +00:00
|
|
|
Node* end = graph()->NewNode(common()->End(1), if_exception);
|
2015-05-05 09:42:59 +00:00
|
|
|
graph()->SetEnd(end);
|
|
|
|
Reduction r = Reduce(ret);
|
|
|
|
ASSERT_FALSE(r.Changed());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_F(TailCallOptimizationTest, CallJSFunction2) {
|
2015-07-30 14:52:13 +00:00
|
|
|
LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
|
|
|
|
LinkageLocation::ForRegister(1)};
|
2015-05-05 09:42:59 +00:00
|
|
|
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
|
2015-12-10 09:03:30 +00:00
|
|
|
CallDescriptor::kCallJSFunction, MachineType::AnyTagged(),
|
2015-07-30 14:52:13 +00:00
|
|
|
LinkageLocation::ForRegister(0),
|
2015-05-05 09:42:59 +00:00
|
|
|
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
|
2015-06-30 13:22:36 +00:00
|
|
|
Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
|
2015-05-05 09:42:59 +00:00
|
|
|
Node* p0 = Parameter(0);
|
|
|
|
Node* p1 = Parameter(1);
|
|
|
|
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
|
|
|
|
graph()->start(), graph()->start());
|
|
|
|
Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
|
2016-11-02 13:15:39 +00:00
|
|
|
Node* zero = graph()->NewNode(common()->Int32Constant(0));
|
|
|
|
Node* ret =
|
|
|
|
graph()->NewNode(common()->Return(), zero, call, call, if_success);
|
2015-05-05 09:42:59 +00:00
|
|
|
Reduction r = Reduce(ret);
|
|
|
|
ASSERT_TRUE(r.Changed());
|
|
|
|
EXPECT_THAT(r.replacement(), IsTailCall(kCallDescriptor, p0, p1,
|
|
|
|
graph()->start(), graph()->start()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace compiler
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|