Commit 6bd44dfe authored by Patrick Thier's avatar Patrick Thier Committed by V8 LUCI CQ

[masm][x64] Introduce Helper to drop arguments.

- Add DropArguments() to x64 TurboAssembler to get rid of arguments on
the stack while preserving the return address.
- Add DropArgumentsAndPushNewReceiver() to x64 TurboAssembler to get rid
of arguments on the stack and push a new receiver, while preserving
the return address.

Bug: v8:11112
Change-Id: I39ea012219ae3748a73933188eb860ce794de2f1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3045349
Commit-Queue: Patrick Thier <pthier@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75859}
parent d70ee61c
......@@ -129,10 +129,7 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
}
// Remove caller arguments from the stack and return.
__ PopReturnAddressTo(rcx);
SmiIndex index = masm->SmiToIndex(rbx, rbx, kSystemPointerSizeLog2);
__ leaq(rsp, Operand(rsp, index.reg, index.scale, 1 * kSystemPointerSize));
__ PushReturnAddressFrom(rcx);
__ DropArguments(rbx, rcx, MacroAssembler::kCountIsSmi);
__ ret(0);
......@@ -281,10 +278,7 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ movq(rbx, Operand(rbp, ConstructFrameConstants::kLengthOffset));
__ LeaveFrame(StackFrame::CONSTRUCT);
// Remove caller arguments from the stack and return.
__ PopReturnAddressTo(rcx);
SmiIndex index = masm->SmiToIndex(rbx, rbx, kSystemPointerSizeLog2);
__ leaq(rsp, Operand(rsp, index.reg, index.scale, 1 * kSystemPointerSize));
__ PushReturnAddressFrom(rcx);
__ DropArguments(rbx, rcx, MacroAssembler::kCountIsSmi);
__ ret(0);
// If the result is a smi, it is *not* an object in the ECMA sense.
......@@ -880,10 +874,8 @@ static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch1,
__ leave();
// Drop receiver + arguments.
Register return_pc = scratch2;
__ PopReturnAddressTo(return_pc);
__ addq(rsp, params_size);
__ PushReturnAddressFrom(return_pc);
__ DropArguments(params_size, scratch2, MacroAssembler::kCountIsBytes,
MacroAssembler::kCountIncludesReceiver);
}
// Tail-call |function_id| if |actual_marker| == |expected_marker|
......@@ -1899,11 +1891,7 @@ void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
__ bind(&no_arg_array);
}
__ bind(&no_this_arg);
__ PopReturnAddressTo(rcx);
__ leaq(rsp,
Operand(rsp, rax, times_system_pointer_size, kSystemPointerSize));
__ Push(rdx);
__ PushReturnAddressFrom(rcx);
__ DropArgumentsAndPushNewReceiver(rax, rdx, rcx);
}
// ----------- S t a t e -------------
......@@ -2006,11 +1994,7 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
__ j(below, &done, Label::kNear);
__ movq(rbx, args[3]); // argumentsList
__ bind(&done);
__ PopReturnAddressTo(rcx);
__ leaq(rsp,
Operand(rsp, rax, times_system_pointer_size, kSystemPointerSize));
__ Push(rdx);
__ PushReturnAddressFrom(rcx);
__ DropArgumentsAndPushNewReceiver(rax, rdx, rcx);
}
// ----------- S t a t e -------------
......@@ -2059,11 +2043,8 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ j(below, &done, Label::kNear);
__ movq(rdx, args[3]); // new.target
__ bind(&done);
__ PopReturnAddressTo(rcx);
__ leaq(rsp,
Operand(rsp, rax, times_system_pointer_size, kSystemPointerSize));
__ PushRoot(RootIndex::kUndefinedValue);
__ PushReturnAddressFrom(rcx);
__ DropArgumentsAndPushNewReceiver(
rax, masm->RootAsOperand(RootIndex::kUndefinedValue), rcx);
}
// ----------- S t a t e -------------
......@@ -3345,16 +3326,7 @@ void Builtins::Generate_GenericJSToWasmWrapper(MacroAssembler* masm) {
// expected to be on the top of the stack).
// We cannot use just the ret instruction for this, because we cannot pass the
// number of slots to remove in a Register as an argument.
Register return_addr = rbx;
__ popq(return_addr);
Register caller_frame_slots_count = param_count;
// Add one to also pop the receiver. The receiver is passed to a JSFunction
// over the stack but is neither included in the number of parameters passed
// to this function nor in the number of parameters expected in this function.
__ addq(caller_frame_slots_count, Immediate(1));
__ shlq(caller_frame_slots_count, Immediate(kSystemPointerSizeLog2));
__ addq(rsp, caller_frame_slots_count);
__ pushq(return_addr);
__ DropArguments(param_count, rbx);
__ ret(0);
// --------------------------------------------------------------------------
......
......@@ -1669,6 +1669,64 @@ void MacroAssembler::DropUnderReturnAddress(int stack_elements,
PushReturnAddressFrom(scratch);
}
void TurboAssembler::DropArguments(Register count, ArgumentsCountType type,
ArgumentsCountMode mode) {
int receiver_bytes =
(mode == kCountExcludesReceiver) ? kSystemPointerSize : 0;
switch (type) {
case kCountIsInteger: {
leaq(rsp, Operand(rsp, count, times_system_pointer_size, receiver_bytes));
break;
}
case kCountIsSmi: {
SmiIndex index = SmiToIndex(count, count, kSystemPointerSizeLog2);
leaq(rsp, Operand(rsp, index.reg, index.scale, receiver_bytes));
break;
}
case kCountIsBytes: {
if (receiver_bytes == 0) {
addq(rsp, count);
} else {
leaq(rsp, Operand(rsp, count, times_1, receiver_bytes));
}
}
}
}
void TurboAssembler::DropArguments(Register count, Register scratch,
ArgumentsCountType type,
ArgumentsCountMode mode) {
DCHECK(!AreAliased(count, scratch));
PopReturnAddressTo(scratch);
DropArguments(count, type, mode);
PushReturnAddressFrom(scratch);
}
void TurboAssembler::DropArgumentsAndPushNewReceiver(Register argc,
Register receiver,
Register scratch,
ArgumentsCountType type,
ArgumentsCountMode mode) {
DCHECK(!AreAliased(argc, receiver, scratch));
PopReturnAddressTo(scratch);
DropArguments(argc, type, mode);
Push(receiver);
PushReturnAddressFrom(scratch);
}
void TurboAssembler::DropArgumentsAndPushNewReceiver(Register argc,
Operand receiver,
Register scratch,
ArgumentsCountType type,
ArgumentsCountMode mode) {
DCHECK(!AreAliased(argc, scratch));
DCHECK(!receiver.AddressUsesRegister(scratch));
PopReturnAddressTo(scratch);
DropArguments(argc, type, mode);
Push(receiver);
PushReturnAddressFrom(scratch);
}
void TurboAssembler::Push(Register src) { pushq(src); }
void TurboAssembler::Push(Operand src) { pushq(src); }
......
......@@ -510,6 +510,21 @@ class V8_EXPORT_PRIVATE TurboAssembler : public SharedTurboAssembler {
void StubPrologue(StackFrame::Type type);
void Prologue();
// Helpers for argument handling
enum ArgumentsCountMode { kCountIncludesReceiver, kCountExcludesReceiver };
enum ArgumentsCountType { kCountIsInteger, kCountIsSmi, kCountIsBytes };
void DropArguments(Register count, Register scratch,
ArgumentsCountType type = kCountIsInteger,
ArgumentsCountMode mode = kCountExcludesReceiver);
void DropArgumentsAndPushNewReceiver(
Register argc, Register receiver, Register scratch,
ArgumentsCountType type = kCountIsInteger,
ArgumentsCountMode mode = kCountExcludesReceiver);
void DropArgumentsAndPushNewReceiver(
Register argc, Operand receiver, Register scratch,
ArgumentsCountType type = kCountIsInteger,
ArgumentsCountMode mode = kCountExcludesReceiver);
// Calls Abort(msg) if the condition cc is not satisfied.
// Use --debug_code to enable.
void Assert(Condition cc, AbortReason reason);
......@@ -694,6 +709,10 @@ class V8_EXPORT_PRIVATE TurboAssembler : public SharedTurboAssembler {
// Returns a register holding the smi value. The register MUST NOT be
// modified. It may be the "smi 1 constant" register.
Register GetSmiConstant(Smi value);
// Drops arguments assuming that the return address was already popped.
void DropArguments(Register count, ArgumentsCountType type = kCountIsInteger,
ArgumentsCountMode mode = kCountExcludesReceiver);
};
// MacroAssembler implements a collection of frequently used macros.
......
......@@ -4891,11 +4891,8 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
__ j(greater, &mismatch_return, Label::kNear);
__ Ret(parameter_slots * kSystemPointerSize, scratch_reg);
__ bind(&mismatch_return);
__ PopReturnAddressTo(scratch_reg);
__ leaq(rsp, Operand(rsp, argc_reg, times_system_pointer_size,
kSystemPointerSize)); // Also pop the receiver.
__ DropArguments(argc_reg, scratch_reg);
// We use a return instead of a jump for better return address prediction.
__ PushReturnAddressFrom(scratch_reg);
__ Ret();
} else if (additional_pop_count->IsImmediate()) {
Register scratch_reg = r10;
......
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