[riscv64] Argument Count Consistency

Port 255aaed95b
Port 6bd44dfe57

Change-Id: I9d57cf7782c267bda4532d0408e69b671e6001f1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3220271
Reviewed-by: ji qiu <qiuji@iscas.ac.cn>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: ji qiu <qiuji@iscas.ac.cn>
Commit-Queue: Yahan Lu <yahan@iscas.ac.cn>
Auto-Submit: Yahan Lu <yahan@iscas.ac.cn>
Cr-Commit-Position: refs/heads/main@{#77407}
This commit is contained in:
Lu Yahan 2021-10-14 16:34:22 +08:00 committed by V8 LUCI CQ
parent 40d6e7de85
commit 5ff309ded4
6 changed files with 269 additions and 131 deletions

View File

@ -357,7 +357,7 @@ declare_args() {
v8_current_cpu == "x86" || v8_current_cpu == "x64" ||
v8_current_cpu == "arm" || v8_current_cpu == "arm64" ||
v8_current_cpu == "mips64el" || v8_current_cpu == "mipsel" ||
v8_current_cpu == "loong64"
v8_current_cpu == "loong64" || v8_current_cpu == "riscv64"
}
# Derived defaults.

View File

@ -503,9 +503,10 @@ void BaselineAssembler::EmitReturn(MacroAssembler* masm) {
__ masm()->LeaveFrame(StackFrame::BASELINE);
// Drop receiver + arguments.
__ masm()->Add64(params_size, params_size, 1); // Include the receiver.
__ masm()->slli(params_size, params_size, kSystemPointerSizeLog2);
__ masm()->Add64(sp, sp, params_size);
__ masm()->DropArguments(params_size, MacroAssembler::kCountIsInteger,
kJSArgcIncludesReceiver
? MacroAssembler::kCountIncludesReceiver
: MacroAssembler::kCountExcludesReceiver);
__ masm()->Ret();
}

View File

@ -70,6 +70,34 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm,
namespace {
enum class ArgumentsElementType {
kRaw, // Push arguments as they are.
kHandle // Dereference arguments before pushing.
};
void Generate_PushArguments(MacroAssembler* masm, Register array, Register argc,
Register scratch, Register scratch2,
ArgumentsElementType element_type) {
DCHECK(!AreAliased(array, argc, scratch));
Label loop, entry;
if (kJSArgcIncludesReceiver) {
__ Sub64(scratch, argc, Operand(kJSArgcReceiverSlots));
} else {
__ mv(scratch, argc);
}
__ Branch(&entry);
__ bind(&loop);
__ CalcScaledAddress(scratch2, array, scratch, kSystemPointerSizeLog2);
__ Ld(scratch2, MemOperand(scratch2));
if (element_type == ArgumentsElementType::kHandle) {
__ Ld(scratch2, MemOperand(scratch2));
}
__ push(scratch2);
__ bind(&entry);
__ Add64(scratch, scratch, Operand(-1));
__ Branch(&loop, greater_equal, scratch, Operand(zero_reg));
}
void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
@ -89,15 +117,18 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
__ Push(cp, a0);
__ SmiUntag(a0);
// Set up pointer to last argument (skip receiver).
UseScratchRegisterScope temps(masm);
temps.Include(t0);
Register scratch = temps.Acquire();
// Set up pointer to first argument (skip receiver).
__ Add64(
scratch, fp,
t2, fp,
Operand(StandardFrameConstants::kCallerSPOffset + kSystemPointerSize));
// Copy arguments and receiver to the expression stack.
__ PushArray(scratch, a0);
// t2: Pointer to start of arguments.
// a0: Number of arguments.
{
UseScratchRegisterScope temps(masm);
temps.Include(t0);
Generate_PushArguments(masm, t2, a0, temps.Acquire(), temps.Acquire(),
ArgumentsElementType::kRaw);
}
// The receiver for the builtin/api call.
__ PushRoot(RootIndex::kTheHoleValue);
@ -115,9 +146,11 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
}
// Remove caller arguments from the stack and return.
__ SmiScale(kScratchReg, kScratchReg, kSystemPointerSizeLog2);
__ Add64(sp, sp, kScratchReg);
__ Add64(sp, sp, kSystemPointerSize);
__ DropArguments(kScratchReg, MacroAssembler::kCountIsSmi,
kJSArgcIncludesReceiver
? MacroAssembler::kCountIncludesReceiver
: MacroAssembler::kCountExcludesReceiver,
kScratchReg);
__ Ret();
}
@ -201,10 +234,9 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// since a0 will store the return value of callRuntime.
__ Move(a6, a0);
// Set up pointer to last argument.
Register scratch = temps.Acquire();
// Set up pointer to first argument (skip receiver)..
__ Add64(
scratch, fp,
t2, fp,
Operand(StandardFrameConstants::kCallerSPOffset + kSystemPointerSize));
// ----------- S t a t e -------------
@ -234,7 +266,13 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// InvokeFunction.
// Copy arguments and receiver to the expression stack.
__ PushArray(scratch, a0);
// t2: Pointer to start of argument.
// a0: Number of arguments.
{
UseScratchRegisterScope temps(masm);
Generate_PushArguments(masm, t2, a0, temps.Acquire(), temps.Acquire(),
ArgumentsElementType::kRaw);
}
// We need two copies because we may have to return the original one
// and the calling conventions dictate that the called function pops the
// receiver. The second copy is pushed after the arguments,
@ -283,9 +321,11 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ LeaveFrame(StackFrame::CONSTRUCT);
// Remove caller arguments from the stack and return.
__ SmiScale(a4, a1, kSystemPointerSizeLog2);
__ Add64(sp, sp, a4);
__ Add64(sp, sp, kSystemPointerSize);
__ DropArguments(a1, MacroAssembler::kCountIsSmi,
kJSArgcIncludesReceiver
? MacroAssembler::kCountIncludesReceiver
: MacroAssembler::kCountExcludesReceiver,
a4);
__ Ret();
__ bind(&check_receiver);
@ -411,6 +451,9 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
a3, FieldMemOperand(a4, JSFunction::kSharedFunctionInfoOffset));
__ Lhu(a3,
FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
if (kJSArgcIncludesReceiver) {
__ Sub64(a3, a3, Operand(kJSArgcReceiverSlots));
}
__ LoadTaggedPointerField(
t1,
FieldMemOperand(a1, JSGeneratorObject::kParametersAndRegistersOffset));
@ -754,24 +797,21 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
__ Push(a2);
// Check if we have enough stack space to push all arguments.
__ Add64(a6, a4, 1);
if (kJSArgcIncludesReceiver) {
__ mv(a6, a4);
} else {
__ Add64(a6, a4, 1);
}
Generate_CheckStackOverflow(masm, a6, a0, s2);
// Copy arguments to the stack in a loop.
// Copy arguments to the stack.
// a4: argc
// a5: argv, i.e. points to first arg
Label loop, entry;
__ CalcScaledAddress(s1, a5, a4, kSystemPointerSizeLog2);
__ BranchShort(&entry);
// s1 points past last arg.
__ bind(&loop);
__ Add64(s1, s1, -kSystemPointerSize);
__ Ld(s2, MemOperand(s1)); // Read next parameter.
__ Ld(s2, MemOperand(s2)); // Dereference handle.
__ push(s2); // Push parameter.
__ bind(&entry);
__ Branch(&loop, ne, a5, Operand(s1));
{
UseScratchRegisterScope temps(masm);
Generate_PushArguments(masm, a5, a4, temps.Acquire(), temps.Acquire(),
ArgumentsElementType::kHandle);
}
// Push the receive.
__ Push(a3);
@ -855,8 +895,10 @@ static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch1,
__ Ld(actual_params_size,
MemOperand(fp, StandardFrameConstants::kArgCOffset));
__ Sll64(actual_params_size, actual_params_size, kSystemPointerSizeLog2);
__ Add64(actual_params_size, actual_params_size, Operand(kSystemPointerSize));
if (!kJSArgcIncludesReceiver) {
__ Add64(actual_params_size, actual_params_size,
Operand(kSystemPointerSize));
}
// If actual is bigger than formal, then we should use it to free up the stack
// arguments.
__ Branch(&L1, le, actual_params_size, Operand(params_size),
@ -868,7 +910,8 @@ static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch1,
__ LeaveFrame(StackFrame::INTERPRETED);
// Drop receiver + arguments.
__ Add64(sp, sp, params_size);
__ DropArguments(params_size, MacroAssembler::kCountIsBytes,
MacroAssembler::kCountIncludesReceiver);
}
// Tail-call |function_id| if |actual_marker| == |expected_marker|
@ -1241,7 +1284,7 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
// stack left to right.
//
// The live registers are:
// o a0 : actual argument count (not including the receiver)
// o a0 : actual argument count
// o a1: the JS function object being called.
// o a3: the incoming new target or generator object
// o cp: our context
@ -1538,7 +1581,7 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
InterpreterPushArgsMode mode) {
DCHECK(mode != InterpreterPushArgsMode::kArrayFunction);
// ----------- S t a t e -------------
// -- a0 : the number of arguments (not including the receiver)
// -- a0 : the number of arguments
// -- a2 : the address of the first argument to be pushed. Subsequent
// arguments should be consecutive above this, in the same order as
// they are to be pushed onto the stack.
@ -1550,18 +1593,19 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
__ Sub64(a0, a0, Operand(1));
}
__ Add64(a3, a0, Operand(1)); // Add one for receiver.
__ StackOverflowCheck(a3, a4, t0, &stack_overflow);
if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
// Don't copy receiver.
const bool skip_receiver =
receiver_mode == ConvertReceiverMode::kNullOrUndefined;
if (kJSArgcIncludesReceiver && skip_receiver) {
__ Sub64(a3, a0, Operand(kJSArgcReceiverSlots));
} else if (!kJSArgcIncludesReceiver && !skip_receiver) {
__ Add64(a3, a0, Operand(1));
} else {
__ Move(a3, a0);
}
__ StackOverflowCheck(a3, a4, t0, &stack_overflow);
// This function modifies a2 and a4.
GenerateInterpreterPushArgs(masm, a3, a2, a4);
if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
__ PushRoot(RootIndex::kUndefinedValue);
}
@ -1594,23 +1638,26 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
MacroAssembler* masm, InterpreterPushArgsMode mode) {
// ----------- S t a t e -------------
// -- a0 : argument count (not including receiver)
// -- a0 : argument count
// -- a3 : new target
// -- a1 : constructor to call
// -- a2 : allocation site feedback if available, undefined otherwise.
// -- a4 : address of the first argument
// -----------------------------------
Label stack_overflow;
__ Add64(a6, a0, 1);
__ StackOverflowCheck(a6, a5, t0, &stack_overflow);
__ StackOverflowCheck(a0, a5, t0, &stack_overflow);
if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
// The spread argument should not be pushed.
__ Sub64(a0, a0, Operand(1));
}
Register argc_without_receiver = a0;
if (kJSArgcIncludesReceiver) {
argc_without_receiver = a6;
__ Sub64(argc_without_receiver, a0, Operand(kJSArgcReceiverSlots));
}
// Push the arguments, This function modifies a4 and a5.
GenerateInterpreterPushArgs(masm, a0, a4, a5);
GenerateInterpreterPushArgs(masm, argc_without_receiver, a4, a5);
// Push a slot for the receiver.
__ push(zero_reg);
@ -1813,13 +1860,14 @@ void Generate_ContinueToBuiltinHelper(MacroAssembler* masm,
// Overwrite the hole inserted by the deoptimizer with the return value from
// the LAZY deopt point. t0 contains the arguments count, the return value
// from LAZY is always the last argument.
__ Add64(a0, a0,
Operand(BuiltinContinuationFrameConstants::kFixedSlotCount));
constexpr int return_value_offset =
BuiltinContinuationFrameConstants::kFixedSlotCount -
kJSArgcReceiverSlots;
__ Add64(a0, a0, Operand(return_value_offset));
__ CalcScaledAddress(t0, sp, a0, kSystemPointerSizeLog2);
__ Sd(scratch, MemOperand(t0));
// Recover arguments count.
__ Sub64(a0, a0,
Operand(BuiltinContinuationFrameConstants::kFixedSlotCount));
__ Sub64(a0, a0, Operand(return_value_offset));
}
__ Ld(fp, MemOperand(
@ -1945,18 +1993,23 @@ void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
__ Ld(arg_array, MemOperand(sp, 2 * kSystemPointerSize));
Label done0, done1;
__ Branch(&done0, ne, argc, Operand(zero_reg), Label::Distance::kNear);
UseScratchRegisterScope temps(masm);
Register scratch = temps.Acquire();
__ Sub64(scratch, argc, JSParameterCount(0));
__ Branch(&done0, ne, scratch, Operand(zero_reg), Label::Distance::kNear);
__ Move(arg_array, undefined_value); // if argc == 0
__ Move(this_arg, undefined_value); // if argc == 0
__ bind(&done0); // else (i.e., argc > 0)
__ Branch(&done1, ne, argc, Operand(1), Label::Distance::kNear);
__ Branch(&done1, ne, scratch, Operand(1), Label::Distance::kNear);
__ Move(arg_array, undefined_value); // if argc == 1
__ bind(&done1); // else (i.e., argc > 1)
__ Ld(receiver, MemOperand(sp));
__ CalcScaledAddress(sp, sp, argc, kSystemPointerSizeLog2);
__ Sd(this_arg, MemOperand(sp));
__ DropArgumentsAndPushNewReceiver(
argc, this_arg, MacroAssembler::kCountIsInteger,
kJSArgcIncludesReceiver ? MacroAssembler::kCountIncludesReceiver
: MacroAssembler::kCountExcludesReceiver);
}
// ----------- S t a t e -------------
@ -1984,7 +2037,7 @@ void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// arguments to the receiver.
__ bind(&no_arguments);
{
__ Move(a0, zero_reg);
__ li(a0, JSParameterCount(0));
DCHECK(receiver == a1);
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
}
@ -1999,7 +2052,8 @@ void Builtins::Generate_FunctionPrototypeCall(MacroAssembler* masm) {
// a0: actual number of arguments
{
Label done;
__ Branch(&done, ne, a0, Operand(zero_reg), Label::Distance::kNear);
__ Branch(&done, ne, a0, Operand(JSParameterCount(0)),
Label::Distance::kNear);
__ PushRoot(RootIndex::kUndefinedValue);
__ Add64(a0, a0, Operand(1));
__ bind(&done);
@ -2041,23 +2095,28 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
__ Ld(arguments_list, MemOperand(sp, 3 * kSystemPointerSize));
Label done0, done1, done2;
__ Branch(&done0, ne, argc, Operand(zero_reg), Label::Distance::kNear);
UseScratchRegisterScope temps(masm);
Register scratch = temps.Acquire();
__ Sub64(scratch, argc, Operand(JSParameterCount(0)));
__ Branch(&done0, ne, scratch, Operand(zero_reg), Label::Distance::kNear);
__ Move(arguments_list, undefined_value); // if argc == 0
__ Move(this_argument, undefined_value); // if argc == 0
__ Move(target, undefined_value); // if argc == 0
__ bind(&done0); // argc != 0
__ Branch(&done1, ne, argc, Operand(1), Label::Distance::kNear);
__ Branch(&done1, ne, scratch, Operand(1), Label::Distance::kNear);
__ Move(arguments_list, undefined_value); // if argc == 1
__ Move(this_argument, undefined_value); // if argc == 1
__ bind(&done1); // argc > 1
__ Branch(&done2, ne, argc, Operand(2), Label::Distance::kNear);
__ Branch(&done2, ne, scratch, Operand(2), Label::Distance::kNear);
__ Move(arguments_list, undefined_value); // if argc == 2
__ bind(&done2); // argc > 2
__ CalcScaledAddress(sp, sp, argc, kSystemPointerSizeLog2);
__ Sd(this_argument, MemOperand(sp, 0)); // Overwrite receiver
__ DropArgumentsAndPushNewReceiver(
argc, this_argument, MacroAssembler::kCountIsInteger,
kJSArgcIncludesReceiver ? MacroAssembler::kCountIncludesReceiver
: MacroAssembler::kCountExcludesReceiver);
}
// ----------- S t a t e -------------
@ -2104,23 +2163,28 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ Ld(new_target, MemOperand(sp, 3 * kSystemPointerSize));
Label done0, done1, done2;
__ Branch(&done0, ne, argc, Operand(zero_reg), Label::Distance::kNear);
UseScratchRegisterScope temps(masm);
Register scratch = temps.Acquire();
__ Sub64(scratch, argc, Operand(JSParameterCount(0)));
__ Branch(&done0, ne, scratch, Operand(zero_reg), Label::Distance::kNear);
__ Move(arguments_list, undefined_value); // if argc == 0
__ Move(new_target, undefined_value); // if argc == 0
__ Move(target, undefined_value); // if argc == 0
__ bind(&done0);
__ Branch(&done1, ne, argc, Operand(1), Label::Distance::kNear);
__ Branch(&done1, ne, scratch, Operand(1), Label::Distance::kNear);
__ Move(arguments_list, undefined_value); // if argc == 1
__ Move(new_target, target); // if argc == 1
__ bind(&done1);
__ Branch(&done2, ne, argc, Operand(2), Label::Distance::kNear);
__ Branch(&done2, ne, scratch, Operand(2), Label::Distance::kNear);
__ Move(new_target, target); // if argc == 2
__ bind(&done2);
__ CalcScaledAddress(sp, sp, argc, kSystemPointerSizeLog2);
__ Sd(undefined_value, MemOperand(sp, 0)); // Overwrite receiver
__ DropArgumentsAndPushNewReceiver(
argc, undefined_value, MacroAssembler::kCountIsInteger,
kJSArgcIncludesReceiver ? MacroAssembler::kCountIncludesReceiver
: MacroAssembler::kCountExcludesReceiver);
}
// ----------- S t a t e -------------
@ -2143,6 +2207,56 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
RelocInfo::CODE_TARGET);
}
namespace {
// Allocate new stack space for |count| arguments and shift all existing
// arguments already on the stack. |pointer_to_new_space_out| points to the
// first free slot on the stack to copy additional arguments to and
// |argc_in_out| is updated to include |count|.
void Generate_AllocateSpaceAndShiftExistingArguments(
MacroAssembler* masm, Register count, Register argc_in_out,
Register pointer_to_new_space_out) {
UseScratchRegisterScope temps(masm);
Register scratch1 = temps.Acquire();
Register scratch2 = temps.Acquire();
Register scratch3 = temps.Acquire();
DCHECK(!AreAliased(count, argc_in_out, pointer_to_new_space_out, scratch1,
scratch2));
Register old_sp = scratch1;
Register new_space = scratch2;
__ mv(old_sp, sp);
__ slli(new_space, count, kPointerSizeLog2);
__ Sub64(sp, sp, Operand(new_space));
Register end = scratch2;
Register value = scratch3;
Register dest = pointer_to_new_space_out;
__ mv(dest, sp);
__ CalcScaledAddress(end, old_sp, argc_in_out, kSystemPointerSizeLog2);
Label loop, done;
if (kJSArgcIncludesReceiver) {
__ Branch(&done, ge, old_sp, Operand(end));
} else {
__ Branch(&done, gt, old_sp, Operand(end));
}
__ bind(&loop);
__ Ld(value, MemOperand(old_sp, 0));
__ Sd(value, MemOperand(dest, 0));
__ Add64(old_sp, old_sp, Operand(kSystemPointerSize));
__ Add64(dest, dest, Operand(kSystemPointerSize));
if (kJSArgcIncludesReceiver) {
__ Branch(&loop, lt, old_sp, Operand(end));
} else {
__ Branch(&loop, le, old_sp, Operand(end));
}
__ bind(&done);
// Update total number of arguments.
__ Add64(argc_in_out, argc_in_out, count);
}
} // namespace
// static
void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm,
Handle<Code> code) {
@ -2150,7 +2264,7 @@ void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm,
temps.Include(t1, t0);
// ----------- S t a t e -------------
// -- a1 : target
// -- a0 : number of parameters on the stack (not including the receiver)
// -- a0 : number of parameters on the stack
// -- a2 : arguments list (a FixedArray)
// -- a4 : len (number of elements to push from args)
// -- a3 : new.target (for [[Construct]])
@ -2181,27 +2295,10 @@ void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm,
// Move the arguments already in the stack,
// including the receiver and the return address.
{
Label copy;
Register src = a6, dest = a7;
UseScratchRegisterScope temps(masm);
Register size = temps.Acquire();
Register vlaue = temps.Acquire();
__ Move(src, sp);
__ Sll64(size, len, kSystemPointerSizeLog2);
__ Sub64(sp, sp, Operand(size));
// Update stack pointer.
__ Move(dest, sp);
__ Add64(size, a0, Operand(zero_reg));
__ bind(&copy);
__ Ld(vlaue, MemOperand(src, 0));
__ Sd(vlaue, MemOperand(dest, 0));
__ Sub64(size, size, Operand(1));
__ Add64(src, src, Operand(kSystemPointerSize));
__ Add64(dest, dest, Operand(kSystemPointerSize));
__ Branch(&copy, ge, size, Operand(zero_reg));
}
// a4: Number of arguments to make room for.
// a0: Number of arguments already on the stack.
// a7: Points to first free slot on the stack after arguments were shifted.
Generate_AllocateSpaceAndShiftExistingArguments(masm, a4, a0, a7);
// Push arguments onto the stack (thisArgument is already on the stack).
{
@ -2211,7 +2308,6 @@ void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm,
UseScratchRegisterScope temps(masm);
Register hole_value = temps.Acquire();
__ Add64(src, args, FixedArray::kHeaderSize - kHeapObjectTag);
__ Add64(a0, a0, len); // The 'len' argument for Call() or Construct().
__ Branch(&done, eq, len, Operand(zero_reg), Label::Distance::kNear);
__ Sll64(scratch, len, kTaggedSizeLog2);
__ Sub64(scratch, sp, Operand(scratch));
@ -2241,7 +2337,7 @@ void Builtins::Generate_CallOrConstructForwardVarargs(MacroAssembler* masm,
CallOrConstructMode mode,
Handle<Code> code) {
// ----------- S t a t e -------------
// -- a0 : the number of arguments (not including the receiver)
// -- a0 : the number of arguments
// -- a3 : the new.target (for [[Construct]] calls)
// -- a1 : the target to call (can be any Object)
// -- a2 : start index (to support rest parameters)
@ -2277,7 +2373,10 @@ void Builtins::Generate_CallOrConstructForwardVarargs(MacroAssembler* masm,
__ Ld(a7, MemOperand(fp, StandardFrameConstants::kArgCOffset));
Label stack_done, stack_overflow;
__ Sub32(a7, a7, a2);
if (kJSArgcIncludesReceiver) {
__ Sub64(a7, a7, Operand(kJSArgcReceiverSlots));
}
__ Sub64(a7, a7, a2);
__ Branch(&stack_done, le, a7, Operand(zero_reg));
{
// Check for stack overflow.
@ -2293,33 +2392,16 @@ void Builtins::Generate_CallOrConstructForwardVarargs(MacroAssembler* masm,
// Move the arguments already in the stack,
// including the receiver and the return address.
{
Label copy;
UseScratchRegisterScope temps(masm);
Register src = temps.Acquire(), dest = a2, scratch = temps.Acquire();
Register count = temps.Acquire();
__ Move(src, sp);
// Update stack pointer.
__ Sll64(scratch, a7, kSystemPointerSizeLog2);
__ Sub64(sp, sp, Operand(scratch));
__ Move(dest, sp);
__ Move(count, a0);
__ bind(&copy);
__ Ld(scratch, MemOperand(src, 0));
__ Sd(scratch, MemOperand(dest, 0));
__ Sub64(count, count, Operand(1));
__ Add64(src, src, Operand(kSystemPointerSize));
__ Add64(dest, dest, Operand(kSystemPointerSize));
__ Branch(&copy, ge, count, Operand(zero_reg));
}
// a7: Number of arguments to make room for.
// a0: Number of arguments already on the stack.
// a2: Points to first free slot on the stack after arguments were shifted.
Generate_AllocateSpaceAndShiftExistingArguments(masm, a7, a0, a2);
// Copy arguments from the caller frame.
// TODO(victorgomes): Consider using forward order as potentially more cache
// friendly.
{
Label loop;
__ Add64(a0, a0, a7);
__ bind(&loop);
{
UseScratchRegisterScope temps(masm);
@ -2346,7 +2428,7 @@ void Builtins::Generate_CallOrConstructForwardVarargs(MacroAssembler* masm,
void Builtins::Generate_CallFunction(MacroAssembler* masm,
ConvertReceiverMode mode) {
// ----------- S t a t e -------------
// -- a0 : the number of arguments (not including the receiver)
// -- a0 : the number of arguments
// -- a1 : the function to call (checked to be a JSFunction)
// -----------------------------------
__ AssertFunction(a1);
@ -2367,7 +2449,7 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ Branch(&done_convert, ne, kScratchReg, Operand(zero_reg));
{
// ----------- S t a t e -------------
// -- a0 : the number of arguments (not including the receiver)
// -- a0 : the number of arguments
// -- a1 : the function to call (checked to be a JSFunction)
// -- a2 : the shared function info.
// -- cp : the function context.
@ -2421,7 +2503,7 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ bind(&done_convert);
// ----------- S t a t e -------------
// -- a0 : the number of arguments (not including the receiver)
// -- a0 : the number of arguments
// -- a1 : the function to call (checked to be a JSFunction)
// -- a2 : the shared function info.
// -- cp : the function context.
@ -2436,7 +2518,7 @@ namespace {
void Generate_PushBoundArguments(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : the number of arguments (not including the receiver)
// -- a0 : the number of arguments
// -- a1 : target (checked to be a JSBoundFunction)
// -- a3 : new.target (only in case of [[Construct]])
// -----------------------------------
@ -2453,7 +2535,7 @@ void Generate_PushBoundArguments(MacroAssembler* masm) {
__ Branch(&no_bound_arguments, eq, bound_argc, Operand(zero_reg));
{
// ----------- S t a t e -------------
// -- a0 : the number of arguments (not including the receiver)
// -- a0 : the number of arguments
// -- a1 : target (checked to be a JSBoundFunction)
// -- a2 : the [[BoundArguments]] (implemented as FixedArray)
// -- a3 : new.target (only in case of [[Construct]])
@ -2507,7 +2589,7 @@ void Generate_PushBoundArguments(MacroAssembler* masm) {
// static
void Builtins::Generate_CallBoundFunctionImpl(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : the number of arguments (not including the receiver)
// -- a0 : the number of arguments
// -- a1 : the function to call (checked to be a JSBoundFunction)
// -----------------------------------
__ AssertBoundFunction(a1);
@ -2534,7 +2616,7 @@ void Builtins::Generate_CallBoundFunctionImpl(MacroAssembler* masm) {
// static
void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
// ----------- S t a t e -------------
// -- a0 : the number of arguments (not including the receiver)
// -- a0 : the number of arguments
// -- a1 : the target to call (can be any Object).
// -----------------------------------
@ -2596,7 +2678,7 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
void Builtins::Generate_ConstructFunction(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : the number of arguments (not including the receiver)
// -- a0 : the number of arguments
// -- a1 : the constructor to call (checked to be a JSFunction)
// -- a3 : the new target (checked to be a constructor)
// -----------------------------------
@ -2628,7 +2710,7 @@ void Builtins::Generate_ConstructFunction(MacroAssembler* masm) {
// static
void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : the number of arguments (not including the receiver)
// -- a0 : the number of arguments
// -- a1 : the function to call (checked to be a JSBoundFunction)
// -- a3 : the new target (checked to be a constructor)
// -----------------------------------
@ -2658,7 +2740,7 @@ void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) {
// static
void Builtins::Generate_Construct(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : the number of arguments (not including the receiver)
// -- a0 : the number of arguments
// -- a1 : the constructor to call (can be any Object)
// -- a3 : the new target (either the same as the constructor or
// the JSFunction on which new was invoked initially)
@ -3184,7 +3266,7 @@ void Builtins::Generate_CallApiCallback(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- cp : context
// -- a1 : api function address
// -- a2 : arguments count (not including the receiver)
// -- a2 : arguments count
// -- a3 : call data
// -- a0 : holder
// --

View File

@ -3751,7 +3751,11 @@ void MacroAssembler::InvokePrologue(Register expected_parameter_count,
Sub64(t0, t0, Operand(1));
Add64(src, src, Operand(kSystemPointerSize));
Add64(dest, dest, Operand(kSystemPointerSize));
Branch(&copy, ge, t0, Operand(zero_reg));
if (kJSArgcIncludesReceiver) {
Branch(&copy, gt, t0, Operand(zero_reg));
} else {
Branch(&copy, ge, t0, Operand(zero_reg));
}
}
// Fill remaining expected arguments with undefined values.
@ -5031,6 +5035,46 @@ void TurboAssembler::DecompressAnyTagged(const Register& destination,
RecordComment("]");
}
void MacroAssembler::DropArguments(Register count, ArgumentsCountType type,
ArgumentsCountMode mode, Register scratch) {
switch (type) {
case kCountIsInteger: {
CalcScaledAddress(sp, sp, count, kPointerSizeLog2);
break;
}
case kCountIsSmi: {
STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
DCHECK_NE(scratch, no_reg);
SmiScale(scratch, count, kPointerSizeLog2);
Add64(sp, sp, scratch);
break;
}
case kCountIsBytes: {
Add64(sp, sp, count);
break;
}
}
if (mode == kCountExcludesReceiver) {
Add64(sp, sp, kSystemPointerSize);
}
}
void MacroAssembler::DropArgumentsAndPushNewReceiver(Register argc,
Register receiver,
ArgumentsCountType type,
ArgumentsCountMode mode,
Register scratch) {
DCHECK(!AreAliased(argc, receiver));
if (mode == kCountExcludesReceiver) {
// Drop arguments without receiver and override old receiver.
DropArguments(argc, type, kCountIncludesReceiver, scratch);
Sd(receiver, MemOperand(sp));
} else {
DropArguments(argc, type, mode, scratch);
push(receiver);
}
}
} // namespace internal
} // namespace v8

View File

@ -1252,6 +1252,15 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
And(scratch, value, Operand(kSmiTagMask));
}
enum ArgumentsCountMode { kCountIncludesReceiver, kCountExcludesReceiver };
enum ArgumentsCountType { kCountIsInteger, kCountIsSmi, kCountIsBytes };
void DropArguments(Register count, ArgumentsCountType type,
ArgumentsCountMode mode, Register scratch = no_reg);
void DropArgumentsAndPushNewReceiver(Register argc, Register receiver,
ArgumentsCountType type,
ArgumentsCountMode mode,
Register scratch = no_reg);
// Jump if the register contains a non-smi.
void JumpIfNotSmi(Register value, Label* not_smi_label);

View File

@ -3212,7 +3212,9 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
if (drop_jsargs) {
// We must pop all arguments from the stack (including the receiver). This
// number of arguments is given by max(1 + argc_reg, parameter_slots).
__ Add64(t0, t0, Operand(1)); // Also pop the receiver.
if (!kJSArgcIncludesReceiver) {
__ Add64(t0, t0, Operand(1)); // Also pop the receiver.
}
if (parameter_slots > 1) {
Label done;
__ li(kScratchReg, parameter_slots);