Commit 15237298 authored by Victor Gomes's avatar Victor Gomes Committed by Commit Bot

[x64] Simplify AssembleReturn

- Shortcut return when argc < param_count
- Simplify return code due to PopAndReturn invariant

Change-Id: Ie41d559cdbe0ba2cc4fdbfbbb622b0aec8429f03
Bug: v8:10201
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2474777
Commit-Queue: Victor Gomes <victorgomes@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Auto-Submit: Victor Gomes <victorgomes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70541}
parent 382ae3f7
...@@ -57,6 +57,7 @@ namespace internal { ...@@ -57,6 +57,7 @@ namespace internal {
V(kStackAccessBelowStackPointer, "Stack access below stack pointer") \ V(kStackAccessBelowStackPointer, "Stack access below stack pointer") \
V(kStackFrameTypesMustMatch, "Stack frame types must match") \ V(kStackFrameTypesMustMatch, "Stack frame types must match") \
V(kUnalignedCellInWriteBarrier, "Unaligned cell in write barrier") \ V(kUnalignedCellInWriteBarrier, "Unaligned cell in write barrier") \
V(kUnexpectedAdditionalPopValue, "Unexpected additional pop value") \
V(kUnexpectedElementsKindInArrayConstructor, \ V(kUnexpectedElementsKindInArrayConstructor, \
"Unexpected ElementsKind in array constructor") \ "Unexpected ElementsKind in array constructor") \
V(kUnexpectedFPCRMode, "Unexpected FPCR mode.") \ V(kUnexpectedFPCRMode, "Unexpected FPCR mode.") \
......
...@@ -4447,15 +4447,22 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) { ...@@ -4447,15 +4447,22 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
// We might need rcx and r10 for scratch. // We might need rcx and r10 for scratch.
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & rcx.bit()); DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & rcx.bit());
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & r10.bit()); DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & r10.bit());
X64OperandConverter g(this, nullptr);
int parameter_count = int parameter_count =
static_cast<int>(call_descriptor->StackParameterCount()); static_cast<int>(call_descriptor->StackParameterCount());
X64OperandConverter g(this, nullptr);
Register pop_reg = additional_pop_count->IsImmediate() // {aditional_pop_count} is only greater than zero if {parameter_count = 0}.
? rcx // Check RawMachineAssembler::PopAndReturn.
: g.ToRegister(additional_pop_count); if (parameter_count != 0) {
Register scratch_reg = pop_reg == rcx ? r10 : rcx; if (additional_pop_count->IsImmediate()) {
Register argc_reg = DCHECK_EQ(g.ToConstant(additional_pop_count).ToInt32(), 0);
additional_pop_count->IsImmediate() ? pop_reg : scratch_reg; } else if (__ emit_debug_code()) {
__ cmpq(g.ToRegister(additional_pop_count), Immediate(0));
__ Assert(equal, AbortReason::kUnexpectedAdditionalPopValue);
}
}
Register argc_reg = rcx;
#ifdef V8_NO_ARGUMENTS_ADAPTOR #ifdef V8_NO_ARGUMENTS_ADAPTOR
// Functions with JS linkage have at least one parameter (the receiver). // Functions with JS linkage have at least one parameter (the receiver).
// If {parameter_count} == 0, it means it is a builtin with // If {parameter_count} == 0, it means it is a builtin with
...@@ -4488,41 +4495,33 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) { ...@@ -4488,41 +4495,33 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
} }
if (drop_jsargs) { if (drop_jsargs) {
// In addition to the slots given by {additional_pop_count}, we must pop all // We must pop all arguments from the stack (including the receiver). This
// arguments from the stack (including the receiver). This number of // number of arguments is given by max(1 + argc_reg, parameter_count).
// arguments is given by max(1 + argc_reg, parameter_count). int parameter_count_without_receiver =
Label argc_reg_has_final_count; parameter_count - 1; // Exclude the receiver to simplify the
// Exclude the receiver to simplify the computation. We'll account for it at // computation. We'll account for it at the end.
// the end. Label mismatch_return;
int parameter_count_withouth_receiver = parameter_count - 1; Register scratch_reg = r10;
if (parameter_count_withouth_receiver != 0) { DCHECK_NE(argc_reg, scratch_reg);
__ cmpq(argc_reg, Immediate(parameter_count_withouth_receiver)); __ cmpq(argc_reg, Immediate(parameter_count_without_receiver));
__ j(greater_equal, &argc_reg_has_final_count, Label::kNear); __ j(greater, &mismatch_return, Label::kNear);
__ movq(argc_reg, Immediate(parameter_count_withouth_receiver)); __ Ret(parameter_count * kSystemPointerSize, scratch_reg);
__ bind(&argc_reg_has_final_count); __ bind(&mismatch_return);
}
// Add additional pop count.
if (additional_pop_count->IsImmediate()) {
DCHECK_EQ(pop_reg, argc_reg);
int additional_count = g.ToConstant(additional_pop_count).ToInt32();
if (additional_count != 0) {
__ addq(pop_reg, Immediate(additional_count));
}
} else {
__ addq(pop_reg, argc_reg);
}
__ PopReturnAddressTo(scratch_reg); __ PopReturnAddressTo(scratch_reg);
__ leaq(rsp, Operand(rsp, pop_reg, times_system_pointer_size, __ leaq(rsp, Operand(rsp, argc_reg, times_system_pointer_size,
kSystemPointerSize)); // Also pop the receiver. kSystemPointerSize)); // Also pop the receiver.
// We use a return instead of a jump for better return address prediction. // We use a return instead of a jump for better return address prediction.
__ PushReturnAddressFrom(scratch_reg); __ PushReturnAddressFrom(scratch_reg);
__ Ret(); __ Ret();
} else if (additional_pop_count->IsImmediate()) { } else if (additional_pop_count->IsImmediate()) {
Register scratch_reg = r10;
int additional_count = g.ToConstant(additional_pop_count).ToInt32(); int additional_count = g.ToConstant(additional_pop_count).ToInt32();
size_t pop_size = (parameter_count + additional_count) * kSystemPointerSize; size_t pop_size = (parameter_count + additional_count) * kSystemPointerSize;
CHECK_LE(pop_size, static_cast<size_t>(std::numeric_limits<int>::max())); CHECK_LE(pop_size, static_cast<size_t>(std::numeric_limits<int>::max()));
__ Ret(static_cast<int>(pop_size), scratch_reg); __ Ret(static_cast<int>(pop_size), scratch_reg);
} else { } else {
Register pop_reg = g.ToRegister(additional_pop_count);
Register scratch_reg = pop_reg == r10 ? rcx : r10;
int pop_size = static_cast<int>(parameter_count * kSystemPointerSize); int pop_size = static_cast<int>(parameter_count * kSystemPointerSize);
__ PopReturnAddressTo(scratch_reg); __ PopReturnAddressTo(scratch_reg);
__ leaq(rsp, Operand(rsp, pop_reg, times_system_pointer_size, __ leaq(rsp, Operand(rsp, pop_reg, times_system_pointer_size,
......
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