Commit e92e9118 authored by danno's avatar danno Committed by Commit bot

[turbofan] Robustify tail parameter stack size computations

This CL separates the check whether something is tail-callable from
the computation of the size of the stack parameters that a function
takes.

In order to track this precisely, the stack parameter size calculation
uses the recently landed MachineType information that's embedded
in return and parameter value LinkageLocations.

Review-Url: https://codereview.chromium.org/2121753002
Cr-Commit-Position: refs/heads/master@{#37668}
parent bbb61d8a
......@@ -1754,11 +1754,10 @@ void InstructionSelector::VisitTailCall(Node* node) {
CallDescriptor const* descriptor = CallDescriptorOf(node->op());
DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls);
// TODO(turbofan): Relax restriction for stack parameters.
int stack_param_delta = 0;
if (linkage()->GetIncomingDescriptor()->CanTailCall(node,
&stack_param_delta)) {
CallDescriptor* caller = linkage()->GetIncomingDescriptor();
if (caller->CanTailCall(node)) {
const CallDescriptor* callee = CallDescriptorOf(node->op());
int stack_param_delta = callee->GetStackParameterDelta(caller);
CallBuffer buffer(zone(), descriptor, nullptr);
// Compute InstructionOperands for inputs and outputs.
......
......@@ -100,33 +100,36 @@ bool CallDescriptor::HasSameReturnLocationsAs(
return true;
}
bool CallDescriptor::CanTailCall(const Node* node,
int* stack_param_delta) const {
CallDescriptor const* other = CallDescriptorOf(node->op());
size_t current_input = 0;
size_t other_input = 0;
*stack_param_delta = 0;
bool more_other = true;
bool more_this = true;
while (more_other || more_this) {
if (other_input < other->InputCount()) {
if (!other->GetInputLocation(other_input).IsRegister()) {
(*stack_param_delta)++;
int CallDescriptor::GetStackParameterDelta(
CallDescriptor const* tail_caller) const {
int callee_slots_above_sp = 0;
for (size_t i = 0; i < InputCount(); ++i) {
LinkageLocation operand = GetInputLocation(i);
if (!operand.IsRegister()) {
int new_candidate =
-operand.GetLocation() + operand.GetSizeInPointers() - 1;
if (new_candidate > callee_slots_above_sp) {
callee_slots_above_sp = new_candidate;
}
} else {
more_other = false;
}
if (current_input < InputCount()) {
if (!GetInputLocation(current_input).IsRegister()) {
(*stack_param_delta)--;
}
int tail_caller_slots_above_sp = 0;
if (tail_caller != nullptr) {
for (size_t i = 0; i < tail_caller->InputCount(); ++i) {
LinkageLocation operand = tail_caller->GetInputLocation(i);
if (!operand.IsRegister()) {
int new_candidate =
-operand.GetLocation() + operand.GetSizeInPointers() - 1;
if (new_candidate > tail_caller_slots_above_sp) {
tail_caller_slots_above_sp = new_candidate;
}
}
} else {
more_this = false;
}
++current_input;
++other_input;
}
return callee_slots_above_sp - tail_caller_slots_above_sp;
}
bool CallDescriptor::CanTailCall(const Node* node) const {
return HasSameReturnLocationsAs(CallDescriptorOf(node->op()));
}
......
......@@ -290,7 +290,9 @@ class CallDescriptor final : public ZoneObject {
bool HasSameReturnLocationsAs(const CallDescriptor* other) const;
bool CanTailCall(const Node* call, int* stack_param_delta) const;
int GetStackParameterDelta(const CallDescriptor* tail_caller = nullptr) const;
bool CanTailCall(const Node* call) const;
private:
friend class Linkage;
......
......@@ -54,8 +54,9 @@ TEST_F(LinkageTailCall, EmptyToEmpty) {
CommonOperatorBuilder common(zone());
const Operator* op = common.Call(desc);
Node* const node = Node::New(zone(), 1, op, 0, nullptr, false);
int stack_param_delta = 0;
EXPECT_TRUE(desc->CanTailCall(node, &stack_param_delta));
EXPECT_TRUE(desc->CanTailCall(node));
const CallDescriptor* callee = CallDescriptorOf(node->op());
int stack_param_delta = callee->GetStackParameterDelta(desc);
EXPECT_EQ(0, stack_param_delta);
}
......@@ -72,8 +73,8 @@ TEST_F(LinkageTailCall, SameReturn) {
CommonOperatorBuilder common(zone());
const Operator* op = common.Call(desc2);
Node* const node = Node::New(zone(), 1, op, 0, nullptr, false);
int stack_param_delta = 0;
EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
EXPECT_TRUE(desc1->CanTailCall(node));
int stack_param_delta = desc2->GetStackParameterDelta(desc1);
EXPECT_EQ(0, stack_param_delta);
}
......@@ -92,9 +93,7 @@ TEST_F(LinkageTailCall, DifferingReturn) {
CommonOperatorBuilder common(zone());
const Operator* op = common.Call(desc2);
Node* const node = Node::New(zone(), 1, op, 0, nullptr, false);
int stack_param_delta = 0;
EXPECT_FALSE(desc1->CanTailCall(node, &stack_param_delta));
EXPECT_EQ(0, stack_param_delta);
EXPECT_TRUE(!desc1->CanTailCall(node));
}
......@@ -113,8 +112,8 @@ TEST_F(LinkageTailCall, MoreRegisterParametersCallee) {
CommonOperatorBuilder common(zone());
const Operator* op = common.Call(desc2);
Node* const node = Node::New(zone(), 1, op, 0, nullptr, false);
int stack_param_delta = 0;
EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
EXPECT_TRUE(desc1->CanTailCall(node));
int stack_param_delta = desc2->GetStackParameterDelta(desc1);
EXPECT_EQ(0, stack_param_delta);
}
......@@ -134,8 +133,8 @@ TEST_F(LinkageTailCall, MoreRegisterParametersCaller) {
CommonOperatorBuilder common(zone());
const Operator* op = common.Call(desc2);
Node* const node = Node::New(zone(), 1, op, 0, nullptr, false);
int stack_param_delta = 0;
EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
EXPECT_TRUE(desc1->CanTailCall(node));
int stack_param_delta = desc2->GetStackParameterDelta(desc1);
EXPECT_EQ(0, stack_param_delta);
}
......@@ -155,8 +154,8 @@ TEST_F(LinkageTailCall, MoreRegisterAndStackParametersCallee) {
CommonOperatorBuilder common(zone());
const Operator* op = common.Call(desc2);
Node* const node = Node::New(zone(), 1, op, 0, nullptr, false);
int stack_param_delta = 0;
EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
EXPECT_TRUE(desc1->CanTailCall(node));
int stack_param_delta = desc2->GetStackParameterDelta(desc1);
EXPECT_EQ(1, stack_param_delta);
}
......@@ -176,8 +175,8 @@ TEST_F(LinkageTailCall, MoreRegisterAndStackParametersCaller) {
CommonOperatorBuilder common(zone());
const Operator* op = common.Call(desc2);
Node* const node = Node::New(zone(), 1, op, 0, nullptr, false);
int stack_param_delta = 0;
EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
EXPECT_TRUE(desc1->CanTailCall(node));
int stack_param_delta = desc2->GetStackParameterDelta(desc1);
EXPECT_EQ(-1, stack_param_delta);
}
......@@ -202,8 +201,8 @@ TEST_F(LinkageTailCall, MatchingStackParameters) {
const Operator* op = common.Call(desc2);
Node* const node =
Node::New(zone(), 1, op, arraysize(parameters), parameters, false);
int stack_param_delta = 0;
EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
EXPECT_TRUE(desc1->CanTailCall(node));
int stack_param_delta = desc2->GetStackParameterDelta(desc1);
EXPECT_EQ(0, stack_param_delta);
}
......@@ -228,8 +227,8 @@ TEST_F(LinkageTailCall, NonMatchingStackParameters) {
const Operator* op = common.Call(desc2);
Node* const node =
Node::New(zone(), 1, op, arraysize(parameters), parameters, false);
int stack_param_delta = 0;
EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
EXPECT_TRUE(desc1->CanTailCall(node));
int stack_param_delta = desc2->GetStackParameterDelta(desc1);
EXPECT_EQ(0, stack_param_delta);
}
......@@ -255,8 +254,8 @@ TEST_F(LinkageTailCall, MatchingStackParametersExtraCallerRegisters) {
const Operator* op = common.Call(desc2);
Node* const node =
Node::New(zone(), 1, op, arraysize(parameters), parameters, false);
int stack_param_delta = 0;
EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
EXPECT_TRUE(desc1->CanTailCall(node));
int stack_param_delta = desc2->GetStackParameterDelta(desc1);
EXPECT_EQ(0, stack_param_delta);
}
......@@ -283,8 +282,8 @@ TEST_F(LinkageTailCall, MatchingStackParametersExtraCalleeRegisters) {
const Operator* op = common.Call(desc2);
Node* const node =
Node::New(zone(), 1, op, arraysize(parameters), parameters, false);
int stack_param_delta = 0;
EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
EXPECT_TRUE(desc1->CanTailCall(node));
int stack_param_delta = desc2->GetStackParameterDelta(desc1);
EXPECT_EQ(0, stack_param_delta);
}
......@@ -311,8 +310,8 @@ TEST_F(LinkageTailCall, MatchingStackParametersExtraCallerRegistersAndStack) {
const Operator* op = common.Call(desc2);
Node* const node =
Node::New(zone(), 1, op, arraysize(parameters), parameters, false);
int stack_param_delta = 0;
EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
EXPECT_TRUE(desc1->CanTailCall(node));
int stack_param_delta = desc2->GetStackParameterDelta(desc1);
EXPECT_EQ(-1, stack_param_delta);
}
......@@ -339,8 +338,8 @@ TEST_F(LinkageTailCall, MatchingStackParametersExtraCalleeRegistersAndStack) {
const Operator* op = common.Call(desc2);
Node* const node =
Node::New(zone(), 1, op, arraysize(parameters), parameters, false);
int stack_param_delta = 0;
EXPECT_TRUE(desc1->CanTailCall(node, &stack_param_delta));
EXPECT_TRUE(desc1->CanTailCall(node));
int stack_param_delta = desc2->GetStackParameterDelta(desc1);
EXPECT_EQ(1, stack_param_delta);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment