| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |