Commit 9acf61bc authored by Milad Fa's avatar Milad Fa Committed by V8 LUCI CQ

PPC/S390: [masm] Create helpers to manipulate arguments on the stack.

Port: 89933af6

Bug: v8:11112
Change-Id: I59d5cf363e427e7e5157be8c9eb033a11614fad1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3251587Reviewed-by: 's avatarJunliang Yan <junyan@redhat.com>
Commit-Queue: Milad Fa <mfarazma@redhat.com>
Cr-Commit-Position: refs/heads/main@{#77630}
parent 6640495b
......@@ -69,6 +69,32 @@ 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,
ArgumentsElementType element_type) {
DCHECK(!AreAliased(array, argc, scratch));
Label loop, done;
__ cmpi(argc, Operand::Zero());
__ beq(&done);
__ ShiftLeftU64(scratch, argc, Operand(kSystemPointerSizeLog2));
__ add(scratch, array, scratch);
__ mtctr(argc);
__ bind(&loop);
__ LoadU64WithUpdate(ip, MemOperand(scratch, -kSystemPointerSize));
if (element_type == ArgumentsElementType::kHandle) {
__ LoadU64(ip, MemOperand(ip));
}
__ push(ip);
__ bdnz(&loop);
__ bind(&done);
}
void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r3 : number of arguments
......@@ -99,12 +125,15 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// correct position (including any undefined), instead of delaying this to
// InvokeFunction.
// Set up pointer to last argument (skip receiver).
// Set up pointer to first argument (skip receiver).
__ addi(
r7, fp,
Operand(StandardFrameConstants::kCallerSPOffset + kSystemPointerSize));
// Copy arguments and receiver to the expression stack.
__ PushArray(r7, r3, r8, r0);
// r7: Pointer to start of arguments.
// r3: Number of arguments.
Generate_PushArguments(masm, r7, r3, r8, ArgumentsElementType::kRaw);
// The receiver for the builtin/api call.
__ PushRoot(RootIndex::kTheHoleValue);
......@@ -234,8 +263,10 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
Label stack_overflow;
__ StackOverflowCheck(r3, r8, &stack_overflow);
// Copy arguments and receiver to the expression stack.
__ PushArray(r7, r3, r8, r0);
// Copy arguments to the expression stack.
// r7: Pointer to start of argument.
// r3: Number of arguments.
Generate_PushArguments(masm, r7, r3, r8, ArgumentsElementType::kRaw);
// Push implicit receiver.
__ Push(r9);
......@@ -711,25 +742,11 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
__ bind(&enough_stack_space);
// Copy arguments to the stack in a loop.
// Copy arguments to the stack.
// r4: function
// r7: argc
// r8: argv, i.e. points to first arg
Label loop, done;
__ cmpi(r7, Operand::Zero());
__ beq(&done);
__ ShiftLeftU64(r9, r7, Operand(kSystemPointerSizeLog2));
__ add(r8, r8, r9); // point to last arg
__ mtctr(r7);
__ bind(&loop);
__ LoadU64WithUpdate(
r9, MemOperand(r8, -kSystemPointerSize)); // read next parameter
__ LoadU64(r0, MemOperand(r9)); // dereference handle
__ push(r0); // push parameter
__ bdnz(&loop);
__ bind(&done);
Generate_PushArguments(masm, r8, r7, r9, ArgumentsElementType::kHandle);
// Push the receiver.
__ Push(r6);
......@@ -1851,6 +1868,40 @@ 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, Register scratch1, Register scratch2) {
DCHECK(!AreAliased(count, argc_in_out, pointer_to_new_space_out, scratch1,
scratch2));
Register old_sp = scratch1;
Register new_space = scratch2;
__ addi(old_sp, sp, Operand(-kSystemPointerSize));
__ ShiftLeftU64(new_space, count, Operand(kSystemPointerSizeLog2));
__ AllocateStackSpace(new_space);
Register dest = pointer_to_new_space_out;
__ addi(dest, sp, Operand(-kSystemPointerSize));
__ addi(r0, argc_in_out, Operand(1));
__ mtctr(r0);
Label loop;
__ bind(&loop);
__ LoadU64WithUpdate(r0, MemOperand(old_sp, kSystemPointerSize));
__ StoreU64WithUpdate(r0, MemOperand(dest, kSystemPointerSize));
__ bdnz(&loop);
// Update total number of arguments, restore dest.
__ add(argc_in_out, argc_in_out, count);
__ addi(dest, dest, Operand(kSystemPointerSize));
}
} // namespace
// static
// TODO(v8:11615): Observe Code::kMaxArguments in CallOrConstructVarargs
void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm,
......@@ -1891,22 +1942,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 = r9, dest = r8;
__ addi(src, sp, Operand(-kSystemPointerSize));
__ ShiftLeftU64(r0, r7, Operand(kSystemPointerSizeLog2));
__ sub(sp, sp, r0);
// Update stack pointer.
__ addi(dest, sp, Operand(-kSystemPointerSize));
__ addi(r0, r3, Operand(1));
__ mtctr(r0);
__ bind(&copy);
__ LoadU64WithUpdate(r0, MemOperand(src, kSystemPointerSize));
__ StoreU64WithUpdate(r0, MemOperand(dest, kSystemPointerSize));
__ bdnz(&copy);
}
// r7: Number of arguments to make room for.
// r3: Number of arguments already on the stack.
// r8: Points to first free slot on the stack after arguments were shifted.
Generate_AllocateSpaceAndShiftExistingArguments(masm, r7, r3, r8, ip, r9);
// Push arguments onto the stack (thisArgument is already on the stack).
{
......@@ -1923,10 +1962,10 @@ void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm,
__ bne(&skip);
__ LoadRoot(scratch, RootIndex::kUndefinedValue);
__ bind(&skip);
__ StoreU64WithUpdate(scratch, MemOperand(r8, kSystemPointerSize));
__ StoreU64(scratch, MemOperand(r8));
__ addi(r8, r8, Operand(kSystemPointerSize));
__ bdnz(&loop);
__ bind(&no_args);
__ add(r3, r3, r7);
}
// Tail-call to the actual Call or Construct builtin.
......@@ -1995,29 +2034,17 @@ void Builtins::Generate_CallOrConstructForwardVarargs(MacroAssembler* masm,
// Move the arguments already in the stack,
// including the receiver and the return address.
{
Label copy;
Register src = ip, dest = r5; // r7 and r10 are context and root.
__ addi(src, sp, Operand(-kSystemPointerSize));
// Update stack pointer.
__ ShiftLeftU64(scratch, r8, Operand(kSystemPointerSizeLog2));
__ sub(sp, sp, scratch);
__ addi(dest, sp, Operand(-kSystemPointerSize));
__ addi(r0, r3, Operand(1));
__ mtctr(r0);
__ bind(&copy);
__ LoadU64WithUpdate(r0, MemOperand(src, kSystemPointerSize));
__ StoreU64WithUpdate(r0, MemOperand(dest, kSystemPointerSize));
__ bdnz(&copy);
}
// r8: Number of arguments to make room for.
// r3: Number of arguments already on the stack.
// r5: Points to first free slot on the stack after arguments were shifted.
Generate_AllocateSpaceAndShiftExistingArguments(masm, r8, r3, r5, scratch,
ip);
// Copy arguments from the caller frame.
// TODO(victorgomes): Consider using forward order as potentially more cache
// friendly.
{
Label loop;
__ add(r3, r3, r8);
__ addi(r5, r5, Operand(kSystemPointerSize));
__ bind(&loop);
{
__ subi(r8, r8, Operand(1));
......
......@@ -69,6 +69,32 @@ 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,
ArgumentsElementType element_type) {
DCHECK(!AreAliased(array, argc, scratch));
Register counter = scratch;
Register value = ip;
Label loop, entry;
__ mov(counter, argc);
__ b(&entry);
__ bind(&loop);
__ ShiftLeftU64(value, counter, Operand(kSystemPointerSizeLog2));
__ LoadU64(value, MemOperand(array, value));
if (element_type == ArgumentsElementType::kHandle) {
__ LoadU64(value, MemOperand(value));
}
__ push(value);
__ bind(&entry);
__ SubS64(counter, counter, Operand(1));
__ bge(&loop);
}
void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r2 : number of arguments
......@@ -98,11 +124,14 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// correct position (including any undefined), instead of delaying this to
// InvokeFunction.
// Set up pointer to last argument (skip receiver).
// Set up pointer to first argument (skip receiver).
__ la(r6, MemOperand(fp, StandardFrameConstants::kCallerSPOffset +
kSystemPointerSize));
// Copy arguments and receiver to the expression stack.
__ PushArray(r6, r2, r1, r0);
// r6: Pointer to start of arguments.
// r2: Number of arguments.
Generate_PushArguments(masm, r6, r2, r1, ArgumentsElementType::kRaw);
// The receiver for the builtin/api call.
__ PushRoot(RootIndex::kTheHoleValue);
......@@ -230,7 +259,9 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ StackOverflowCheck(r2, r7, &stack_overflow);
// Copy arguments and receiver to the expression stack.
__ PushArray(r6, r2, r1, r0);
// r6: Pointer to start of argument.
// r2: Number of arguments.
Generate_PushArguments(masm, r6, r2, r1, ArgumentsElementType::kRaw);
// Push implicit receiver.
__ Push(r8);
......@@ -759,7 +790,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
__ bind(&enough_stack_space);
// Copy arguments to the stack in a loop from argv to sp.
// Copy arguments to the stack from argv to sp.
// The arguments are actually placed in reverse order on sp
// compared to argv (i.e. arg1 is highest memory in sp).
// r2: argc
......@@ -769,24 +800,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
// r7: scratch reg to hold scaled argc
// r8: scratch reg to hold arg handle
// r9: scratch reg to hold index into argv
Label argLoop, argExit;
__ ShiftLeftU64(r9, r2, Operand(kSystemPointerSizeLog2));
__ lay(r9, MemOperand(r6, r9, -kSystemPointerSize)); // point to last arg
__ ltgr(r7, r2);
__ beq(&argExit, Label::kNear);
__ bind(&argLoop);
__ LoadU64(r8, MemOperand(r9)); // read next parameter
__ LoadU64(r0, MemOperand(r8)); // dereference handle
__ Push(r0);
__ lay(r9, MemOperand(r9, -kSystemPointerSize)); // r9++;
__ SubS64(r7, r7, Operand(1));
__ bgt(&argLoop);
__ bind(&argExit);
Generate_PushArguments(masm, r6, r2, r1, ArgumentsElementType::kHandle);
// Push the receiver.
__ Push(r5);
......@@ -1886,6 +1900,46 @@ 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, Register scratch1, Register scratch2) {
DCHECK(!AreAliased(count, argc_in_out, pointer_to_new_space_out, scratch1,
scratch2));
Register old_sp = scratch1;
Register new_space = scratch2;
__ mov(old_sp, sp);
__ ShiftLeftU64(new_space, count, Operand(kSystemPointerSizeLog2));
__ AllocateStackSpace(new_space);
Register end = scratch2;
Register value = r1;
Register dest = pointer_to_new_space_out;
__ mov(dest, sp);
__ ShiftLeftU64(r0, argc_in_out, Operand(kSystemPointerSizeLog2));
__ AddS64(end, old_sp, r0);
Label loop, done;
__ bind(&loop);
__ CmpS64(old_sp, end);
__ bgt(&done);
__ LoadU64(value, MemOperand(old_sp));
__ lay(old_sp, MemOperand(old_sp, kSystemPointerSize));
__ StoreU64(value, MemOperand(dest));
__ lay(dest, MemOperand(dest, kSystemPointerSize));
__ b(&loop);
__ bind(&done);
// Update total number of arguments.
__ AddS64(argc_in_out, argc_in_out, count);
}
} // namespace
// static
// TODO(v8:11615): Observe Code::kMaxArguments in CallOrConstructVarargs
void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm,
......@@ -1927,25 +1981,10 @@ void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm,
// Move the arguments already in the stack,
// including the receiver and the return address.
{
Label copy, check;
Register num = ip, src = r8, dest = r7;
__ mov(src, sp);
__ ShiftLeftU64(r1, r6, Operand(kSystemPointerSizeLog2));
__ SubS64(sp, sp, r1);
// Update stack pointer.
__ mov(dest, sp);
__ ltgr(num, r2);
__ b(&check);
__ bind(&copy);
__ LoadU64(r0, MemOperand(src));
__ lay(src, MemOperand(src, kSystemPointerSize));
__ StoreU64(r0, MemOperand(dest));
__ lay(dest, MemOperand(dest, kSystemPointerSize));
__ SubS64(num, num, Operand(1));
__ bind(&check);
__ b(ge, &copy);
}
// r6: Number of arguments to make room for.
// r2: Number of arguments already on the stack.
// r7: Points to first free slot on the stack after arguments were shifted.
Generate_AllocateSpaceAndShiftExistingArguments(masm, r6, r2, r7, ip, r8);
// Push arguments onto the stack (thisArgument is already on the stack).
{
......@@ -1966,7 +2005,6 @@ void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm,
__ lay(r7, MemOperand(r7, kSystemPointerSize));
__ BranchOnCount(r1, &loop);
__ bind(&no_args);
__ AddS64(r2, r2, r6);
}
// Tail-call to the actual Call or Construct builtin.
......@@ -2036,33 +2074,17 @@ void Builtins::Generate_CallOrConstructForwardVarargs(MacroAssembler* masm,
// Move the arguments already in the stack,
// including the receiver and the return address.
{
Label copy, check;
Register num = r1, src = ip,
dest = r4; // r7 and r10 are context and root.
__ mov(src, sp);
// Update stack pointer.
__ ShiftLeftU64(scratch, r7, Operand(kSystemPointerSizeLog2));
__ SubS64(sp, sp, scratch);
__ mov(dest, sp);
__ ltgr(num, r2);
__ b(&check);
__ bind(&copy);
__ LoadU64(r0, MemOperand(src));
__ lay(src, MemOperand(src, kSystemPointerSize));
__ StoreU64(r0, MemOperand(dest));
__ lay(dest, MemOperand(dest, kSystemPointerSize));
__ SubS64(num, num, Operand(1));
__ bind(&check);
__ b(ge, &copy);
}
// r7: Number of arguments to make room for.0
// r2: Number of arguments already on the stack.
// r4: Points to first free slot on the stack after arguments were shifted.
Generate_AllocateSpaceAndShiftExistingArguments(masm, r7, r2, r4, scratch,
ip);
// Copy arguments from the caller frame.
// TODO(victorgomes): Consider using forward order as potentially more cache
// friendly.
{
Label loop;
__ AddS64(r2, r2, r7);
__ bind(&loop);
{
__ SubS64(r7, r7, Operand(1));
......
......@@ -106,6 +106,8 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
AddS64(sp, sp, Operand(-bytes), r0);
}
void AllocateStackSpace(Register bytes) { sub(sp, sp, bytes); }
// Push a fixed frame, consisting of lr, fp, constant pool.
void PushCommonFrame(Register marker_reg = no_reg);
......
......@@ -1045,6 +1045,8 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
lay(sp, MemOperand(sp, -bytes));
}
void AllocateStackSpace(Register bytes) { SubS64(sp, sp, bytes); }
void CheckPageFlag(Register object, Register scratch, int mask, Condition cc,
Label* condition_met);
......
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