Reland "[compiler] Rework calculation to start of return slots"

This is a reland of 2f3cda580b

GetFirstUnusedStackSlot is restored, and used for finding the padding
slot location, if any.

Original change's description:
> [compiler] Rework calculation to start of return slots
>
> - Changes GetOffsetToReturns to take into account return slot padding
>   and argument padding.
> - Changes GetStackParameterDelta to use GetOffsetToReturns for the SP
>   delta calculation.
> - Removes GetFirstUnusedStackSlot.
>
> Change-Id: I13df72e86750c62798bae262f0560cf1d7f981db
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2593306
> Commit-Queue: Bill Budge <bbudge@chromium.org>
> Reviewed-by: Andreas Haas <ahaas@chromium.org>
> Reviewed-by: Georg Neis <neis@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#72078}

Change-Id: I954d7e7487728dbd6a545a6c84efb8f8f65d894d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2626979
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Commit-Queue: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72115}
This commit is contained in:
Bill Budge 2021-01-14 09:27:25 -08:00 committed by Commit Bot
parent 9b606e3ee4
commit ce793786ef
3 changed files with 61 additions and 29 deletions

View File

@ -77,21 +77,6 @@ MachineSignature* CallDescriptor::GetMachineSignature(Zone* zone) const {
return zone->New<MachineSignature>(return_count, param_count, types);
}
int CallDescriptor::GetFirstUnusedStackSlot() const {
int 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 > slots_above_sp) {
slots_above_sp = new_candidate;
}
}
}
return slots_above_sp;
}
int CallDescriptor::GetStackParameterDelta(
CallDescriptor const* tail_caller) const {
// In the IsTailCallForTierUp case, the callee has
@ -100,8 +85,8 @@ int CallDescriptor::GetStackParameterDelta(
// inputs to the TailCall node, since they already exist on the stack.
if (IsTailCallForTierUp()) return 0;
int callee_slots_above_sp = GetFirstUnusedStackSlot();
int tail_caller_slots_above_sp = tail_caller->GetFirstUnusedStackSlot();
int callee_slots_above_sp = GetOffsetToReturns();
int tail_caller_slots_above_sp = tail_caller->GetOffsetToReturns();
int stack_param_delta = callee_slots_above_sp - tail_caller_slots_above_sp;
if (ShouldPadArguments(stack_param_delta)) {
if (callee_slots_above_sp % 2 != 0) {
@ -119,10 +104,43 @@ int CallDescriptor::GetStackParameterDelta(
return stack_param_delta;
}
int CallDescriptor::GetFirstUnusedStackSlot() const {
int start_of_args = 0;
for (size_t i = 0; i < InputCount(); ++i) {
LinkageLocation operand = GetInputLocation(i);
if (!operand.IsRegister()) {
// Reverse, since arguments have negative offsets in the frame.
int reverse_location =
-operand.GetLocation() + operand.GetSizeInPointers() - 1;
DCHECK_GE(reverse_location, 0);
start_of_args = std::max(start_of_args, reverse_location);
}
}
return start_of_args;
}
int CallDescriptor::GetOffsetToReturns() const {
int offset = static_cast<int>(StackParameterCount());
if (ShouldPadArguments(offset)) offset++;
return offset;
// If there are return stack slots, return the first slot of the last one.
constexpr int kNoReturnSlot = std::numeric_limits<int>::max();
int end_of_returns = kNoReturnSlot;
for (size_t i = 0; i < ReturnCount(); ++i) {
LinkageLocation operand = GetReturnLocation(i);
if (!operand.IsRegister()) {
// Reverse, since returns have negative offsets in the frame.
int reverse_location = -operand.GetLocation() - 1;
DCHECK_GE(reverse_location, 0);
end_of_returns = std::min(end_of_returns, reverse_location);
}
}
if (end_of_returns != kNoReturnSlot) return end_of_returns;
// Otherwise, return the first unused slot before the parameters, with any
// additional padding slot if it exists.
end_of_returns = GetFirstUnusedStackSlot();
if (ShouldPadArguments(end_of_returns)) end_of_returns++;
DCHECK_EQ(end_of_returns == 0, StackParameterCount() == 0);
return end_of_returns;
}
int CallDescriptor::GetTaggedParameterSlots() const {
@ -138,11 +156,12 @@ int CallDescriptor::GetTaggedParameterSlots() const {
bool CallDescriptor::CanTailCall(const CallDescriptor* callee) const {
if (ReturnCount() != callee->ReturnCount()) return false;
const int stack_param_delta = callee->GetStackParameterDelta(this);
const int stack_returns_delta =
GetOffsetToReturns() - callee->GetOffsetToReturns();
for (size_t i = 0; i < ReturnCount(); ++i) {
if (GetReturnLocation(i).IsCallerFrameSlot() &&
callee->GetReturnLocation(i).IsCallerFrameSlot()) {
if (GetReturnLocation(i).AsCallerFrameSlot() - stack_param_delta !=
if (GetReturnLocation(i).AsCallerFrameSlot() + stack_returns_delta !=
callee->GetReturnLocation(i).AsCallerFrameSlot()) {
return false;
}

View File

@ -389,12 +389,15 @@ class V8_EXPORT_PRIVATE CallDescriptor final
bool UsesOnlyRegisters() const;
// Returns the first stack slot that is not used by the stack parameters.
int GetFirstUnusedStackSlot() const;
int GetStackParameterDelta(const CallDescriptor* tail_caller) const;
// Returns the number of slots to the first return value slot.
// Returns the first stack slot that is not used by the stack parameters,
// which is the return slot area, or a padding slot for frame alignment.
int GetFirstUnusedStackSlot() const;
// If there are return stack slots, returns the first slot of the last one.
// Otherwise, return the first unused slot before the parameters. This is the
// slot where returns would go if there were any.
int GetOffsetToReturns() const;
int GetTaggedParameterSlots() const;

View File

@ -29,16 +29,26 @@ class LinkageTailCall : public TestWithZone {
DCHECK(arraysize(kMachineTypes) >=
locations->return_count() + locations->parameter_count());
USE(kMachineTypes);
size_t stack_arguments = 0;
for (size_t i = 0; i < locations->parameter_count(); ++i) {
if (locations->GetParam(i).IsCallerFrameSlot()) stack_arguments++;
}
size_t stack_returns = 0;
for (size_t i = 0; i < locations->return_count(); ++i) {
if (locations->GetReturn(i).IsCallerFrameSlot()) stack_returns++;
}
return zone()->New<CallDescriptor>(
CallDescriptor::kCallCodeObject, MachineType::AnyTagged(),
LinkageLocation::ForAnyRegister(MachineType::Pointer()),
locations, // location_sig
0, // js_parameter_count
locations, // location_sig
stack_arguments,
Operator::kNoProperties, // properties
0, // callee-saved
0, // callee-saved fp
CallDescriptor::kNoFlags, // flags,
"");
"", StackArgumentOrder::kDefault,
0, // allocatable_registers
stack_returns);
}
LinkageLocation StackLocation(int loc) {