3e2085eba4
By adding MachineType to LinkageLocation, it is possible not only to reason about the location of a LinkageLocation on the stack, but also about it's size. This will be useful in follow-on CLs that attempt to merge some of the parameter passing logic of tail calls and normal (non-tail) calls. As a nice side-effect, it is no longer necessary to separately keep a MachineSignature in a CallDescriptor, because the MachineTypes contianed in LinkageLocation for all of the Descriptor's parameters and return types are sufficient. This CL therefore removes the MachineSignature from the CallDescriptor and adjusts all the calling code accordingly, simplifying and de-duplicating code in a bunch of places. R=titzer@chromium.org, bmeurer@chromium.org LOG=N Review-Url: https://codereview.chromium.org/2124023003 Cr-Commit-Position: refs/heads/master@{#37633}
162 lines
7.0 KiB
C++
162 lines
7.0 KiB
C++
// 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) {
|
|
LinkageLocation kLocationSignature[] = {
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
|
LinkageLocation::ForRegister(1, MachineType::Pointer())};
|
|
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
|
|
CallDescriptor::kCallCodeObject, MachineType::AnyTagged(),
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
|
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
|
|
Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
|
|
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);
|
|
Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
|
|
Reduction r = Reduce(ret);
|
|
ASSERT_FALSE(r.Changed());
|
|
}
|
|
|
|
|
|
TEST_F(TailCallOptimizationTest, CallCodeObject1) {
|
|
LinkageLocation kLocationSignature[] = {
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
|
LinkageLocation::ForRegister(1, MachineType::Pointer())};
|
|
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
|
|
CallDescriptor::kCallCodeObject, MachineType::AnyTagged(),
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
|
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
|
|
Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
|
|
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);
|
|
Node* if_exception = graph()->NewNode(
|
|
common()->IfException(IfExceptionHint::kLocallyUncaught), call, call);
|
|
Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
|
|
Node* end = graph()->NewNode(common()->End(1), if_exception);
|
|
graph()->SetEnd(end);
|
|
Reduction r = Reduce(ret);
|
|
ASSERT_FALSE(r.Changed());
|
|
}
|
|
|
|
|
|
TEST_F(TailCallOptimizationTest, CallCodeObject2) {
|
|
LinkageLocation kLocationSignature[] = {
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
|
LinkageLocation::ForRegister(1, MachineType::Pointer())};
|
|
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
|
|
CallDescriptor::kCallCodeObject, MachineType::AnyTagged(),
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
|
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
|
|
Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
|
|
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);
|
|
Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
|
|
Reduction r = Reduce(ret);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsTailCall(kCallDescriptor, p0, p1,
|
|
graph()->start(), graph()->start()));
|
|
}
|
|
|
|
|
|
TEST_F(TailCallOptimizationTest, CallJSFunction0) {
|
|
LinkageLocation kLocationSignature[] = {
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
|
LinkageLocation::ForRegister(1, MachineType::Pointer())};
|
|
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
|
|
CallDescriptor::kCallJSFunction, MachineType::AnyTagged(),
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
|
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
|
|
Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
|
|
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);
|
|
Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
|
|
Reduction r = Reduce(ret);
|
|
ASSERT_FALSE(r.Changed());
|
|
}
|
|
|
|
|
|
TEST_F(TailCallOptimizationTest, CallJSFunction1) {
|
|
LinkageLocation kLocationSignature[] = {
|
|
LinkageLocation::ForRegister(0, MachineType::Pointer()),
|
|
LinkageLocation::ForRegister(1, MachineType::Pointer())};
|
|
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
|
|
CallDescriptor::kCallJSFunction, MachineType::AnyTagged(),
|
|
LinkageLocation::ForRegister(0),
|
|
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
|
|
Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
|
|
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);
|
|
Node* if_exception = graph()->NewNode(
|
|
common()->IfException(IfExceptionHint::kLocallyUncaught), call, call);
|
|
Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
|
|
Node* end = graph()->NewNode(common()->End(1), if_exception);
|
|
graph()->SetEnd(end);
|
|
Reduction r = Reduce(ret);
|
|
ASSERT_FALSE(r.Changed());
|
|
}
|
|
|
|
|
|
TEST_F(TailCallOptimizationTest, CallJSFunction2) {
|
|
LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
|
|
LinkageLocation::ForRegister(1)};
|
|
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
|
|
CallDescriptor::kCallJSFunction, MachineType::AnyTagged(),
|
|
LinkageLocation::ForRegister(0),
|
|
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
|
|
Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
|
|
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);
|
|
Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
|
|
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
|