Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(758)

Unified Diff: src/arm64/macro-assembler-arm64.cc

Issue 2833463002: [arm64] Support passing more than eight arguments to C functions (Closed)
Patch Set: [arm64] Support passing more than eight arguments to C functions Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/compiler/arm64/code-generator-arm64.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
}
« no previous file with comments | « no previous file | src/compiler/arm64/code-generator-arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698