| Index: src/arm64/macro-assembler-arm64.cc
|
| diff --git a/src/arm64/macro-assembler-arm64.cc b/src/arm64/macro-assembler-arm64.cc
|
| index 5edcd7b0449bff8457356c544eef0456b587b7b5..8cdfa5d9efe6e03a1f9c9a504d50bbf12ce646cd 100644
|
| --- a/src/arm64/macro-assembler-arm64.cc
|
| +++ b/src/arm64/macro-assembler-arm64.cc
|
| @@ -1791,14 +1791,12 @@ void MacroAssembler::CallCFunction(ExternalReference function,
|
| CallCFunction(temp, num_of_reg_args, num_of_double_args);
|
| }
|
|
|
| +static const int kRegisterPassedArguments = 8;
|
|
|
| void MacroAssembler::CallCFunction(Register function,
|
| int num_of_reg_args,
|
| int num_of_double_args) {
|
| DCHECK(has_frame());
|
| - // We can pass 8 integer arguments in registers. If we need to pass more than
|
| - // that, we'll need to implement support for passing them on the stack.
|
| - DCHECK(num_of_reg_args <= 8);
|
|
|
| // If we're passing doubles, we're limited to the following prototypes
|
| // (defined by ExternalReference::Type):
|
| @@ -1811,6 +1809,10 @@ void MacroAssembler::CallCFunction(Register function,
|
| DCHECK((num_of_double_args + num_of_reg_args) <= 2);
|
| }
|
|
|
| + // We rely on the frame alignment being 16 bytes, which means we never need
|
| + // to align the CSP by an unknown number of bytes and we always know the delta
|
| + // between the stack pointer and the frame pointer.
|
| + DCHECK(ActivationFrameAlignment() == 16);
|
|
|
| // If the stack pointer is not csp, we need to derive an aligned csp from the
|
| // current stack pointer.
|
| @@ -1819,16 +1821,18 @@ void MacroAssembler::CallCFunction(Register function,
|
| AssertStackConsistency();
|
|
|
| int sp_alignment = ActivationFrameAlignment();
|
| - // The ABI mandates at least 16-byte alignment.
|
| - DCHECK(sp_alignment >= 16);
|
| - DCHECK(base::bits::IsPowerOfTwo32(sp_alignment));
|
| -
|
| // The current stack pointer is a callee saved register, and is preserved
|
| // across the call.
|
| DCHECK(kCalleeSaved.IncludesAliasOf(old_stack_pointer));
|
|
|
| - // Align and synchronize the system stack pointer with jssp.
|
| - Bic(csp, old_stack_pointer, sp_alignment - 1);
|
| + // If more than eight arguments are passed to the function, we expect the
|
| + // ninth argument onwards to have been placed on the csp-based stack
|
| + // already. We assume csp already points to the last stack-passed argument
|
| + // in that case.
|
| + // Otherwise, align and synchronize the system stack pointer with jssp.
|
| + if (num_of_reg_args <= kRegisterPassedArguments) {
|
| + Bic(csp, old_stack_pointer, sp_alignment - 1);
|
| + }
|
| SetStackPointer(csp);
|
| }
|
|
|
| @@ -1836,19 +1840,39 @@ void MacroAssembler::CallCFunction(Register function,
|
| // so the return address in the link register stays correct.
|
| Call(function);
|
|
|
| - if (!csp.Is(old_stack_pointer)) {
|
| + if (csp.Is(old_stack_pointer)) {
|
| + if (num_of_reg_args > kRegisterPassedArguments) {
|
| + // Drop the register passed arguments.
|
| + int claim_slots = RoundUp(num_of_reg_args - kRegisterPassedArguments, 2);
|
| + Drop(claim_slots);
|
| + }
|
| + } else {
|
| + DCHECK(jssp.Is(old_stack_pointer));
|
| if (emit_debug_code()) {
|
| - // Because the stack pointer must be aligned on a 16-byte boundary, the
|
| - // aligned csp can be up to 12 bytes below the jssp. This is the case
|
| - // where we only pushed one W register on top of an aligned jssp.
|
| UseScratchRegisterScope temps(this);
|
| Register temp = temps.AcquireX();
|
| - DCHECK(ActivationFrameAlignment() == 16);
|
| - Sub(temp, csp, old_stack_pointer);
|
| - // We want temp <= 0 && temp >= -12.
|
| - Cmp(temp, 0);
|
| - Ccmp(temp, -12, NFlag, le);
|
| - Check(ge, kTheStackWasCorruptedByMacroAssemblerCall);
|
| +
|
| + if (num_of_reg_args > kRegisterPassedArguments) {
|
| + // We don't need to drop stack arguments, as the stack pointer will be
|
| + // jssp when returning from this function. However, in debug builds, we
|
| + // can check that jssp is as expected.
|
| + int claim_slots =
|
| + RoundUp(num_of_reg_args - kRegisterPassedArguments, 2);
|
| +
|
| + // Check jssp matches the previous value on the stack.
|
| + Ldr(temp, MemOperand(csp, claim_slots * kPointerSize));
|
| + Cmp(jssp, temp);
|
| + Check(eq, kTheStackWasCorruptedByMacroAssemblerCall);
|
| + } else {
|
| + // Because the stack pointer must be aligned on a 16-byte boundary, the
|
| + // aligned csp can be up to 12 bytes below the jssp. This is the case
|
| + // where we only pushed one W register on top of an aligned jssp.
|
| + Sub(temp, csp, old_stack_pointer);
|
| + // We want temp <= 0 && temp >= -12.
|
| + Cmp(temp, 0);
|
| + Ccmp(temp, -12, NFlag, le);
|
| + Check(ge, kTheStackWasCorruptedByMacroAssemblerCall);
|
| + }
|
| }
|
| SetStackPointer(old_stack_pointer);
|
| }
|
|
|