| 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 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
| 8 | 8 |
| 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 1730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1741 | 1741 |
| 1742 // Place the necessary arguments. | 1742 // Place the necessary arguments. |
| 1743 Mov(x0, num_arguments); | 1743 Mov(x0, num_arguments); |
| 1744 Mov(x1, ExternalReference(f, isolate())); | 1744 Mov(x1, ExternalReference(f, isolate())); |
| 1745 | 1745 |
| 1746 CEntryStub stub(isolate(), 1, save_doubles); | 1746 CEntryStub stub(isolate(), 1, save_doubles); |
| 1747 CallStub(&stub); | 1747 CallStub(&stub); |
| 1748 } | 1748 } |
| 1749 | 1749 |
| 1750 | 1750 |
| 1751 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { | |
| 1752 return ref0.address() - ref1.address(); | |
| 1753 } | |
| 1754 | |
| 1755 | |
| 1756 void MacroAssembler::CallApiFunctionAndReturn( | |
| 1757 Register function_address, ExternalReference thunk_ref, int stack_space, | |
| 1758 MemOperand* stack_space_operand, int spill_offset, | |
| 1759 MemOperand return_value_operand, MemOperand* context_restore_operand) { | |
| 1760 ASM_LOCATION("CallApiFunctionAndReturn"); | |
| 1761 ExternalReference next_address = | |
| 1762 ExternalReference::handle_scope_next_address(isolate()); | |
| 1763 const int kNextOffset = 0; | |
| 1764 const int kLimitOffset = AddressOffset( | |
| 1765 ExternalReference::handle_scope_limit_address(isolate()), | |
| 1766 next_address); | |
| 1767 const int kLevelOffset = AddressOffset( | |
| 1768 ExternalReference::handle_scope_level_address(isolate()), | |
| 1769 next_address); | |
| 1770 | |
| 1771 DCHECK(function_address.is(x1) || function_address.is(x2)); | |
| 1772 | |
| 1773 Label profiler_disabled; | |
| 1774 Label end_profiler_check; | |
| 1775 Mov(x10, ExternalReference::is_profiling_address(isolate())); | |
| 1776 Ldrb(w10, MemOperand(x10)); | |
| 1777 Cbz(w10, &profiler_disabled); | |
| 1778 Mov(x3, thunk_ref); | |
| 1779 B(&end_profiler_check); | |
| 1780 | |
| 1781 Bind(&profiler_disabled); | |
| 1782 Mov(x3, function_address); | |
| 1783 Bind(&end_profiler_check); | |
| 1784 | |
| 1785 // Save the callee-save registers we are going to use. | |
| 1786 // TODO(all): Is this necessary? ARM doesn't do it. | |
| 1787 STATIC_ASSERT(kCallApiFunctionSpillSpace == 4); | |
| 1788 Poke(x19, (spill_offset + 0) * kXRegSize); | |
| 1789 Poke(x20, (spill_offset + 1) * kXRegSize); | |
| 1790 Poke(x21, (spill_offset + 2) * kXRegSize); | |
| 1791 Poke(x22, (spill_offset + 3) * kXRegSize); | |
| 1792 | |
| 1793 // Allocate HandleScope in callee-save registers. | |
| 1794 // We will need to restore the HandleScope after the call to the API function, | |
| 1795 // by allocating it in callee-save registers they will be preserved by C code. | |
| 1796 Register handle_scope_base = x22; | |
| 1797 Register next_address_reg = x19; | |
| 1798 Register limit_reg = x20; | |
| 1799 Register level_reg = w21; | |
| 1800 | |
| 1801 Mov(handle_scope_base, next_address); | |
| 1802 Ldr(next_address_reg, MemOperand(handle_scope_base, kNextOffset)); | |
| 1803 Ldr(limit_reg, MemOperand(handle_scope_base, kLimitOffset)); | |
| 1804 Ldr(level_reg, MemOperand(handle_scope_base, kLevelOffset)); | |
| 1805 Add(level_reg, level_reg, 1); | |
| 1806 Str(level_reg, MemOperand(handle_scope_base, kLevelOffset)); | |
| 1807 | |
| 1808 if (FLAG_log_timer_events) { | |
| 1809 FrameScope frame(this, StackFrame::MANUAL); | |
| 1810 PushSafepointRegisters(); | |
| 1811 Mov(x0, ExternalReference::isolate_address(isolate())); | |
| 1812 CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1); | |
| 1813 PopSafepointRegisters(); | |
| 1814 } | |
| 1815 | |
| 1816 // Native call returns to the DirectCEntry stub which redirects to the | |
| 1817 // return address pushed on stack (could have moved after GC). | |
| 1818 // DirectCEntry stub itself is generated early and never moves. | |
| 1819 DirectCEntryStub stub(isolate()); | |
| 1820 stub.GenerateCall(this, x3); | |
| 1821 | |
| 1822 if (FLAG_log_timer_events) { | |
| 1823 FrameScope frame(this, StackFrame::MANUAL); | |
| 1824 PushSafepointRegisters(); | |
| 1825 Mov(x0, ExternalReference::isolate_address(isolate())); | |
| 1826 CallCFunction(ExternalReference::log_leave_external_function(isolate()), 1); | |
| 1827 PopSafepointRegisters(); | |
| 1828 } | |
| 1829 | |
| 1830 Label promote_scheduled_exception; | |
| 1831 Label exception_handled; | |
| 1832 Label delete_allocated_handles; | |
| 1833 Label leave_exit_frame; | |
| 1834 Label return_value_loaded; | |
| 1835 | |
| 1836 // Load value from ReturnValue. | |
| 1837 Ldr(x0, return_value_operand); | |
| 1838 Bind(&return_value_loaded); | |
| 1839 // No more valid handles (the result handle was the last one). Restore | |
| 1840 // previous handle scope. | |
| 1841 Str(next_address_reg, MemOperand(handle_scope_base, kNextOffset)); | |
| 1842 if (emit_debug_code()) { | |
| 1843 Ldr(w1, MemOperand(handle_scope_base, kLevelOffset)); | |
| 1844 Cmp(w1, level_reg); | |
| 1845 Check(eq, kUnexpectedLevelAfterReturnFromApiCall); | |
| 1846 } | |
| 1847 Sub(level_reg, level_reg, 1); | |
| 1848 Str(level_reg, MemOperand(handle_scope_base, kLevelOffset)); | |
| 1849 Ldr(x1, MemOperand(handle_scope_base, kLimitOffset)); | |
| 1850 Cmp(limit_reg, x1); | |
| 1851 B(ne, &delete_allocated_handles); | |
| 1852 | |
| 1853 Bind(&leave_exit_frame); | |
| 1854 // Restore callee-saved registers. | |
| 1855 Peek(x19, (spill_offset + 0) * kXRegSize); | |
| 1856 Peek(x20, (spill_offset + 1) * kXRegSize); | |
| 1857 Peek(x21, (spill_offset + 2) * kXRegSize); | |
| 1858 Peek(x22, (spill_offset + 3) * kXRegSize); | |
| 1859 | |
| 1860 // Check if the function scheduled an exception. | |
| 1861 Mov(x5, ExternalReference::scheduled_exception_address(isolate())); | |
| 1862 Ldr(x5, MemOperand(x5)); | |
| 1863 JumpIfNotRoot(x5, Heap::kTheHoleValueRootIndex, &promote_scheduled_exception); | |
| 1864 Bind(&exception_handled); | |
| 1865 | |
| 1866 bool restore_context = context_restore_operand != NULL; | |
| 1867 if (restore_context) { | |
| 1868 Ldr(cp, *context_restore_operand); | |
| 1869 } | |
| 1870 | |
| 1871 if (stack_space_operand != NULL) { | |
| 1872 Ldr(w2, *stack_space_operand); | |
| 1873 } | |
| 1874 | |
| 1875 LeaveExitFrame(false, x1, !restore_context); | |
| 1876 if (stack_space_operand != NULL) { | |
| 1877 Drop(x2, 1); | |
| 1878 } else { | |
| 1879 Drop(stack_space); | |
| 1880 } | |
| 1881 Ret(); | |
| 1882 | |
| 1883 Bind(&promote_scheduled_exception); | |
| 1884 { | |
| 1885 FrameScope frame(this, StackFrame::INTERNAL); | |
| 1886 CallExternalReference( | |
| 1887 ExternalReference( | |
| 1888 Runtime::kPromoteScheduledException, isolate()), 0); | |
| 1889 } | |
| 1890 B(&exception_handled); | |
| 1891 | |
| 1892 // HandleScope limit has changed. Delete allocated extensions. | |
| 1893 Bind(&delete_allocated_handles); | |
| 1894 Str(limit_reg, MemOperand(handle_scope_base, kLimitOffset)); | |
| 1895 // Save the return value in a callee-save register. | |
| 1896 Register saved_result = x19; | |
| 1897 Mov(saved_result, x0); | |
| 1898 Mov(x0, ExternalReference::isolate_address(isolate())); | |
| 1899 CallCFunction( | |
| 1900 ExternalReference::delete_handle_scope_extensions(isolate()), 1); | |
| 1901 Mov(x0, saved_result); | |
| 1902 B(&leave_exit_frame); | |
| 1903 } | |
| 1904 | |
| 1905 | |
| 1906 void MacroAssembler::CallExternalReference(const ExternalReference& ext, | 1751 void MacroAssembler::CallExternalReference(const ExternalReference& ext, |
| 1907 int num_arguments) { | 1752 int num_arguments) { |
| 1908 Mov(x0, num_arguments); | 1753 Mov(x0, num_arguments); |
| 1909 Mov(x1, ext); | 1754 Mov(x1, ext); |
| 1910 | 1755 |
| 1911 CEntryStub stub(isolate(), 1); | 1756 CEntryStub stub(isolate(), 1); |
| 1912 CallStub(&stub); | 1757 CallStub(&stub); |
| 1913 } | 1758 } |
| 1914 | 1759 |
| 1915 | 1760 |
| (...skipping 3482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5398 } | 5243 } |
| 5399 } | 5244 } |
| 5400 | 5245 |
| 5401 | 5246 |
| 5402 #undef __ | 5247 #undef __ |
| 5403 | 5248 |
| 5404 | 5249 |
| 5405 } } // namespace v8::internal | 5250 } } // namespace v8::internal |
| 5406 | 5251 |
| 5407 #endif // V8_TARGET_ARCH_ARM64 | 5252 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |