From 5ff309ded46390b187951576ad3daaf3a2a46d82 Mon Sep 17 00:00:00 2001 From: Lu Yahan Date: Thu, 14 Oct 2021 16:34:22 +0800 Subject: [PATCH] [riscv64] Argument Count Consistency Port 255aaed95bd588e36791521b96b8d8028bb3f4de Port 6bd44dfe57d8d9673c34eda1ae27d66a7f5ec637 Change-Id: I9d57cf7782c267bda4532d0408e69b671e6001f1 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3220271 Reviewed-by: ji qiu Reviewed-by: Jakob Gruber Commit-Queue: ji qiu Commit-Queue: Yahan Lu Auto-Submit: Yahan Lu Cr-Commit-Position: refs/heads/main@{#77407} --- BUILD.gn | 2 +- .../riscv64/baseline-assembler-riscv64-inl.h | 7 +- src/builtins/riscv64/builtins-riscv64.cc | 332 +++++++++++------- .../riscv64/macro-assembler-riscv64.cc | 46 ++- src/codegen/riscv64/macro-assembler-riscv64.h | 9 + .../backend/riscv64/code-generator-riscv64.cc | 4 +- 6 files changed, 269 insertions(+), 131 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index adb84fed25..ddbd158ed3 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -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. diff --git a/src/baseline/riscv64/baseline-assembler-riscv64-inl.h b/src/baseline/riscv64/baseline-assembler-riscv64-inl.h index 7bf6bd2f4e..85ada600f1 100644 --- a/src/baseline/riscv64/baseline-assembler-riscv64-inl.h +++ b/src/baseline/riscv64/baseline-assembler-riscv64-inl.h @@ -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(); } diff --git a/src/builtins/riscv64/builtins-riscv64.cc b/src/builtins/riscv64/builtins-riscv64.cc index 307aaaf60b..1f42a10c56 100644 --- a/src/builtins/riscv64/builtins-riscv64.cc +++ b/src/builtins/riscv64/builtins-riscv64.cc @@ -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) { @@ -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(©); - __ 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(©, 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) { // ----------- 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(©); - __ 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(©, 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 // -- diff --git a/src/codegen/riscv64/macro-assembler-riscv64.cc b/src/codegen/riscv64/macro-assembler-riscv64.cc index 94ad73747d..b999c4770a 100644 --- a/src/codegen/riscv64/macro-assembler-riscv64.cc +++ b/src/codegen/riscv64/macro-assembler-riscv64.cc @@ -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(©, ge, t0, Operand(zero_reg)); + if (kJSArgcIncludesReceiver) { + Branch(©, gt, t0, Operand(zero_reg)); + } else { + Branch(©, 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 diff --git a/src/codegen/riscv64/macro-assembler-riscv64.h b/src/codegen/riscv64/macro-assembler-riscv64.h index 1dc4d2075c..4ea0ad6fca 100644 --- a/src/codegen/riscv64/macro-assembler-riscv64.h +++ b/src/codegen/riscv64/macro-assembler-riscv64.h @@ -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); diff --git a/src/compiler/backend/riscv64/code-generator-riscv64.cc b/src/compiler/backend/riscv64/code-generator-riscv64.cc index 147541bee7..7d56576702 100644 --- a/src/compiler/backend/riscv64/code-generator-riscv64.cc +++ b/src/compiler/backend/riscv64/code-generator-riscv64.cc @@ -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);