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:
parent
9b606e3ee4
commit
ce793786ef
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user