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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « no previous file | src/compiler/arm64/code-generator-arm64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if V8_TARGET_ARCH_ARM64 5 #if V8_TARGET_ARCH_ARM64
6 6
7 #include "src/arm64/frames-arm64.h" 7 #include "src/arm64/frames-arm64.h"
8 #include "src/assembler.h" 8 #include "src/assembler.h"
9 #include "src/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/base/division-by-constant.h" 10 #include "src/base/division-by-constant.h"
(...skipping 1773 matching lines...) Expand 10 before | Expand all | Expand 10 after
1784 1784
1785 void MacroAssembler::CallCFunction(ExternalReference function, 1785 void MacroAssembler::CallCFunction(ExternalReference function,
1786 int num_of_reg_args, 1786 int num_of_reg_args,
1787 int num_of_double_args) { 1787 int num_of_double_args) {
1788 UseScratchRegisterScope temps(this); 1788 UseScratchRegisterScope temps(this);
1789 Register temp = temps.AcquireX(); 1789 Register temp = temps.AcquireX();
1790 Mov(temp, function); 1790 Mov(temp, function);
1791 CallCFunction(temp, num_of_reg_args, num_of_double_args); 1791 CallCFunction(temp, num_of_reg_args, num_of_double_args);
1792 } 1792 }
1793 1793
1794 static const int kRegisterPassedArguments = 8;
1794 1795
1795 void MacroAssembler::CallCFunction(Register function, 1796 void MacroAssembler::CallCFunction(Register function,
1796 int num_of_reg_args, 1797 int num_of_reg_args,
1797 int num_of_double_args) { 1798 int num_of_double_args) {
1798 DCHECK(has_frame()); 1799 DCHECK(has_frame());
1799 // We can pass 8 integer arguments in registers. If we need to pass more than
1800 // that, we'll need to implement support for passing them on the stack.
1801 DCHECK(num_of_reg_args <= 8);
1802 1800
1803 // If we're passing doubles, we're limited to the following prototypes 1801 // If we're passing doubles, we're limited to the following prototypes
1804 // (defined by ExternalReference::Type): 1802 // (defined by ExternalReference::Type):
1805 // BUILTIN_COMPARE_CALL: int f(double, double) 1803 // BUILTIN_COMPARE_CALL: int f(double, double)
1806 // BUILTIN_FP_FP_CALL: double f(double, double) 1804 // BUILTIN_FP_FP_CALL: double f(double, double)
1807 // BUILTIN_FP_CALL: double f(double) 1805 // BUILTIN_FP_CALL: double f(double)
1808 // BUILTIN_FP_INT_CALL: double f(double, int) 1806 // BUILTIN_FP_INT_CALL: double f(double, int)
1809 if (num_of_double_args > 0) { 1807 if (num_of_double_args > 0) {
1810 DCHECK(num_of_reg_args <= 1); 1808 DCHECK(num_of_reg_args <= 1);
1811 DCHECK((num_of_double_args + num_of_reg_args) <= 2); 1809 DCHECK((num_of_double_args + num_of_reg_args) <= 2);
1812 } 1810 }
1813 1811
1812 // We rely on the frame alignment being 16 bytes, which means we never need
1813 // to align the CSP by an unknown number of bytes and we always know the delta
1814 // between the stack pointer and the frame pointer.
1815 DCHECK(ActivationFrameAlignment() == 16);
1814 1816
1815 // If the stack pointer is not csp, we need to derive an aligned csp from the 1817 // If the stack pointer is not csp, we need to derive an aligned csp from the
1816 // current stack pointer. 1818 // current stack pointer.
1817 const Register old_stack_pointer = StackPointer(); 1819 const Register old_stack_pointer = StackPointer();
1818 if (!csp.Is(old_stack_pointer)) { 1820 if (!csp.Is(old_stack_pointer)) {
1819 AssertStackConsistency(); 1821 AssertStackConsistency();
1820 1822
1821 int sp_alignment = ActivationFrameAlignment(); 1823 int sp_alignment = ActivationFrameAlignment();
1822 // The ABI mandates at least 16-byte alignment.
1823 DCHECK(sp_alignment >= 16);
1824 DCHECK(base::bits::IsPowerOfTwo32(sp_alignment));
1825
1826 // The current stack pointer is a callee saved register, and is preserved 1824 // The current stack pointer is a callee saved register, and is preserved
1827 // across the call. 1825 // across the call.
1828 DCHECK(kCalleeSaved.IncludesAliasOf(old_stack_pointer)); 1826 DCHECK(kCalleeSaved.IncludesAliasOf(old_stack_pointer));
1829 1827
1830 // Align and synchronize the system stack pointer with jssp. 1828 // If more than eight arguments are passed to the function, we expect the
1831 Bic(csp, old_stack_pointer, sp_alignment - 1); 1829 // ninth argument onwards to have been placed on the csp-based stack
1830 // already. We assume csp already points to the last stack-passed argument
1831 // in that case.
1832 // Otherwise, align and synchronize the system stack pointer with jssp.
1833 if (num_of_reg_args <= kRegisterPassedArguments) {
1834 Bic(csp, old_stack_pointer, sp_alignment - 1);
1835 }
1832 SetStackPointer(csp); 1836 SetStackPointer(csp);
1833 } 1837 }
1834 1838
1835 // Call directly. The function called cannot cause a GC, or allow preemption, 1839 // Call directly. The function called cannot cause a GC, or allow preemption,
1836 // so the return address in the link register stays correct. 1840 // so the return address in the link register stays correct.
1837 Call(function); 1841 Call(function);
1838 1842
1839 if (!csp.Is(old_stack_pointer)) { 1843 if (csp.Is(old_stack_pointer)) {
1844 if (num_of_reg_args > kRegisterPassedArguments) {
1845 // Drop the register passed arguments.
1846 int claim_slots = RoundUp(num_of_reg_args - kRegisterPassedArguments, 2);
1847 Drop(claim_slots);
1848 }
1849 } else {
1850 DCHECK(jssp.Is(old_stack_pointer));
1840 if (emit_debug_code()) { 1851 if (emit_debug_code()) {
1841 // Because the stack pointer must be aligned on a 16-byte boundary, the
1842 // aligned csp can be up to 12 bytes below the jssp. This is the case
1843 // where we only pushed one W register on top of an aligned jssp.
1844 UseScratchRegisterScope temps(this); 1852 UseScratchRegisterScope temps(this);
1845 Register temp = temps.AcquireX(); 1853 Register temp = temps.AcquireX();
1846 DCHECK(ActivationFrameAlignment() == 16); 1854
1847 Sub(temp, csp, old_stack_pointer); 1855 if (num_of_reg_args > kRegisterPassedArguments) {
1848 // We want temp <= 0 && temp >= -12. 1856 // We don't need to drop stack arguments, as the stack pointer will be
1849 Cmp(temp, 0); 1857 // jssp when returning from this function. However, in debug builds, we
1850 Ccmp(temp, -12, NFlag, le); 1858 // can check that jssp is as expected.
1851 Check(ge, kTheStackWasCorruptedByMacroAssemblerCall); 1859 int claim_slots =
1860 RoundUp(num_of_reg_args - kRegisterPassedArguments, 2);
1861
1862 // Check jssp matches the previous value on the stack.
1863 Ldr(temp, MemOperand(csp, claim_slots * kPointerSize));
1864 Cmp(jssp, temp);
1865 Check(eq, kTheStackWasCorruptedByMacroAssemblerCall);
1866 } else {
1867 // Because the stack pointer must be aligned on a 16-byte boundary, the
1868 // aligned csp can be up to 12 bytes below the jssp. This is the case
1869 // where we only pushed one W register on top of an aligned jssp.
1870 Sub(temp, csp, old_stack_pointer);
1871 // We want temp <= 0 && temp >= -12.
1872 Cmp(temp, 0);
1873 Ccmp(temp, -12, NFlag, le);
1874 Check(ge, kTheStackWasCorruptedByMacroAssemblerCall);
1875 }
1852 } 1876 }
1853 SetStackPointer(old_stack_pointer); 1877 SetStackPointer(old_stack_pointer);
1854 } 1878 }
1855 } 1879 }
1856 1880
1857 1881
1858 void MacroAssembler::Jump(Register target) { 1882 void MacroAssembler::Jump(Register target) {
1859 Br(target); 1883 Br(target);
1860 } 1884 }
1861 1885
(...skipping 2723 matching lines...) Expand 10 before | Expand all | Expand 10 after
4585 } 4609 }
4586 4610
4587 4611
4588 #undef __ 4612 #undef __
4589 4613
4590 4614
4591 } // namespace internal 4615 } // namespace internal
4592 } // namespace v8 4616 } // namespace v8
4593 4617
4594 #endif // V8_TARGET_ARCH_ARM64 4618 #endif // V8_TARGET_ARCH_ARM64
OLDNEW
« 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