| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 1781 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1792 __ EnterStubFrame(); | 1792 __ EnterStubFrame(); |
| 1793 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1793 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1794 __ LeaveStubFrame(); | 1794 __ LeaveStubFrame(); |
| 1795 __ b(&done_stepping); | 1795 __ b(&done_stepping); |
| 1796 } | 1796 } |
| 1797 | 1797 |
| 1798 | 1798 |
| 1799 // Used to check class and type arguments. Arguments passed in registers: | 1799 // Used to check class and type arguments. Arguments passed in registers: |
| 1800 // LR: return address. | 1800 // LR: return address. |
| 1801 // R0: instance (must be preserved). | 1801 // R0: instance (must be preserved). |
| 1802 // R1: instantiator type arguments or NULL. | 1802 // R1: instantiator type arguments (only if n == 4, can be raw_null). |
| 1803 // R2: cache array. | 1803 // R2: function type arguments (only if n == 4, can be raw_null). |
| 1804 // R3: SubtypeTestCache. |
| 1804 // Result in R1: null -> not found, otherwise result (true or false). | 1805 // Result in R1: null -> not found, otherwise result (true or false). |
| 1805 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 1806 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
| 1806 ASSERT((1 <= n) && (n <= 3)); | 1807 ASSERT((n == 1) || (n == 2) || (n == 4)); |
| 1807 if (n > 1) { | 1808 if (n > 1) { |
| 1808 // Get instance type arguments. | 1809 __ LoadClass(R6, R0); |
| 1809 __ LoadClass(R3, R0); | |
| 1810 // Compute instance type arguments into R4. | 1810 // Compute instance type arguments into R4. |
| 1811 Label has_no_type_arguments; | 1811 Label has_no_type_arguments; |
| 1812 __ LoadObject(R4, Object::null_object()); | 1812 __ LoadObject(R4, Object::null_object()); |
| 1813 __ LoadFieldFromOffset( | 1813 __ LoadFieldFromOffset( |
| 1814 R5, R3, Class::type_arguments_field_offset_in_words_offset(), kWord); | 1814 R5, R6, Class::type_arguments_field_offset_in_words_offset(), kWord); |
| 1815 __ CompareImmediate(R5, Class::kNoTypeArguments); | 1815 __ CompareImmediate(R5, Class::kNoTypeArguments); |
| 1816 __ b(&has_no_type_arguments, EQ); | 1816 __ b(&has_no_type_arguments, EQ); |
| 1817 __ add(R5, R0, Operand(R5, LSL, 3)); | 1817 __ add(R5, R0, Operand(R5, LSL, 3)); |
| 1818 __ LoadFieldFromOffset(R4, R5, 0); | 1818 __ LoadFieldFromOffset(R4, R5, 0); |
| 1819 __ Bind(&has_no_type_arguments); | 1819 __ Bind(&has_no_type_arguments); |
| 1820 } | 1820 } |
| 1821 __ LoadClassId(R3, R0); | 1821 __ LoadClassId(R6, R0); |
| 1822 // R0: instance. | 1822 // R0: instance. |
| 1823 // R1: instantiator type arguments or NULL. | 1823 // R1: instantiator type arguments (only if n == 4, can be raw_null). |
| 1824 // R2: SubtypeTestCache. | 1824 // R2: function type arguments (only if n == 4, can be raw_null). |
| 1825 // R3: instance class id. | 1825 // R3: SubtypeTestCache. |
| 1826 // R6: instance class id. |
| 1826 // R4: instance type arguments (null if none), used only if n > 1. | 1827 // R4: instance type arguments (null if none), used only if n > 1. |
| 1827 __ LoadFieldFromOffset(R2, R2, SubtypeTestCache::cache_offset()); | 1828 __ LoadFieldFromOffset(R3, R3, SubtypeTestCache::cache_offset()); |
| 1828 __ AddImmediate(R2, R2, Array::data_offset() - kHeapObjectTag); | 1829 __ AddImmediate(R3, R3, Array::data_offset() - kHeapObjectTag); |
| 1829 | 1830 |
| 1830 Label loop, found, not_found, next_iteration; | 1831 Label loop, found, not_found, next_iteration; |
| 1831 // R2: entry start. | 1832 // R3: entry start. |
| 1832 // R3: instance class id. | 1833 // R6: instance class id. |
| 1833 // R4: instance type arguments (still null if closure). | 1834 // R4: instance type arguments (still null if closure). |
| 1834 __ SmiTag(R3); | 1835 __ SmiTag(R6); |
| 1835 __ CompareImmediate(R3, Smi::RawValue(kClosureCid)); | 1836 __ CompareImmediate(R6, Smi::RawValue(kClosureCid)); |
| 1836 __ b(&loop, NE); | 1837 __ b(&loop, NE); |
| 1837 __ LoadFieldFromOffset(R4, R0, Closure::instantiator_offset()); | 1838 __ LoadFieldFromOffset(R4, R0, Closure::instantiator_offset()); |
| 1838 __ LoadFieldFromOffset(R3, R0, Closure::function_offset()); | 1839 __ LoadFieldFromOffset(R6, R0, Closure::function_offset()); |
| 1839 // R3: instance class id as Smi or function. | 1840 // R6: instance class id as Smi or function. |
| 1840 __ Bind(&loop); | 1841 __ Bind(&loop); |
| 1841 __ LoadFromOffset(R5, R2, | 1842 __ LoadFromOffset(R5, R3, |
| 1842 kWordSize * SubtypeTestCache::kInstanceClassIdOrFunction); | 1843 kWordSize * SubtypeTestCache::kInstanceClassIdOrFunction); |
| 1843 __ CompareObject(R5, Object::null_object()); | 1844 __ CompareObject(R5, Object::null_object()); |
| 1844 __ b(¬_found, EQ); | 1845 __ b(¬_found, EQ); |
| 1845 __ CompareRegisters(R5, R3); | 1846 __ CompareRegisters(R5, R6); |
| 1846 if (n == 1) { | 1847 if (n == 1) { |
| 1847 __ b(&found, EQ); | 1848 __ b(&found, EQ); |
| 1848 } else { | 1849 } else { |
| 1849 __ b(&next_iteration, NE); | 1850 __ b(&next_iteration, NE); |
| 1850 __ LoadFromOffset(R5, R2, | 1851 __ LoadFromOffset(R5, R3, |
| 1851 kWordSize * SubtypeTestCache::kInstanceTypeArguments); | 1852 kWordSize * SubtypeTestCache::kInstanceTypeArguments); |
| 1852 __ CompareRegisters(R5, R4); | 1853 __ CompareRegisters(R5, R4); |
| 1853 if (n == 2) { | 1854 if (n == 2) { |
| 1854 __ b(&found, EQ); | 1855 __ b(&found, EQ); |
| 1855 } else { | 1856 } else { |
| 1856 __ b(&next_iteration, NE); | 1857 __ b(&next_iteration, NE); |
| 1857 __ LoadFromOffset( | 1858 __ LoadFromOffset( |
| 1858 R5, R2, kWordSize * SubtypeTestCache::kInstantiatorTypeArguments); | 1859 R5, R3, kWordSize * SubtypeTestCache::kInstantiatorTypeArguments); |
| 1859 __ CompareRegisters(R5, R1); | 1860 __ CompareRegisters(R5, R1); |
| 1861 __ b(&next_iteration, NE); |
| 1862 __ LoadFromOffset(R5, R3, |
| 1863 kWordSize * SubtypeTestCache::kFunctionTypeArguments); |
| 1864 __ CompareRegisters(R5, R2); |
| 1860 __ b(&found, EQ); | 1865 __ b(&found, EQ); |
| 1861 } | 1866 } |
| 1862 } | 1867 } |
| 1863 __ Bind(&next_iteration); | 1868 __ Bind(&next_iteration); |
| 1864 __ AddImmediate(R2, R2, kWordSize * SubtypeTestCache::kTestEntryLength); | 1869 __ AddImmediate(R3, R3, kWordSize * SubtypeTestCache::kTestEntryLength); |
| 1865 __ b(&loop); | 1870 __ b(&loop); |
| 1866 // Fall through to not found. | 1871 // Fall through to not found. |
| 1867 __ Bind(¬_found); | 1872 __ Bind(¬_found); |
| 1868 __ LoadObject(R1, Object::null_object()); | 1873 __ LoadObject(R1, Object::null_object()); |
| 1869 __ ret(); | 1874 __ ret(); |
| 1870 | 1875 |
| 1871 __ Bind(&found); | 1876 __ Bind(&found); |
| 1872 __ LoadFromOffset(R1, R2, kWordSize * SubtypeTestCache::kTestResult); | 1877 __ LoadFromOffset(R1, R3, kWordSize * SubtypeTestCache::kTestResult); |
| 1873 __ ret(); | 1878 __ ret(); |
| 1874 } | 1879 } |
| 1875 | 1880 |
| 1876 | 1881 |
| 1877 // Used to check class and type arguments. Arguments passed on stack: | 1882 // Used to check class and type arguments. Arguments passed on stack: |
| 1878 // TOS + 0: return address. | 1883 // LR: return address. |
| 1879 // TOS + 1: instantiator type arguments or NULL. | 1884 // R0: instance (must be preserved). |
| 1880 // TOS + 2: instance. | 1885 // R1: unused. |
| 1881 // TOS + 3: cache array. | 1886 // R2: unused. |
| 1882 // Result in RCX: null -> not found, otherwise result (true or false). | 1887 // R3: SubtypeTestCache. |
| 1888 // Result in R1: null -> not found, otherwise result (true or false). |
| 1883 void StubCode::GenerateSubtype1TestCacheStub(Assembler* assembler) { | 1889 void StubCode::GenerateSubtype1TestCacheStub(Assembler* assembler) { |
| 1884 GenerateSubtypeNTestCacheStub(assembler, 1); | 1890 GenerateSubtypeNTestCacheStub(assembler, 1); |
| 1885 } | 1891 } |
| 1886 | 1892 |
| 1887 | 1893 |
| 1888 // Used to check class and type arguments. Arguments passed in registers: | 1894 // Used to check class and type arguments. Arguments passed in registers: |
| 1889 // LR: return address. | 1895 // LR: return address. |
| 1890 // R0: instance (must be preserved). | 1896 // R0: instance (must be preserved). |
| 1891 // R1: instantiator type arguments or NULL. | 1897 // R1: unused. |
| 1892 // R2: cache array. | 1898 // R2: unused. |
| 1899 // R3: SubtypeTestCache. |
| 1893 // Result in R1: null -> not found, otherwise result (true or false). | 1900 // Result in R1: null -> not found, otherwise result (true or false). |
| 1894 void StubCode::GenerateSubtype2TestCacheStub(Assembler* assembler) { | 1901 void StubCode::GenerateSubtype2TestCacheStub(Assembler* assembler) { |
| 1895 GenerateSubtypeNTestCacheStub(assembler, 2); | 1902 GenerateSubtypeNTestCacheStub(assembler, 2); |
| 1896 } | 1903 } |
| 1897 | 1904 |
| 1898 | 1905 |
| 1899 // Used to check class and type arguments. Arguments passed on stack: | 1906 // Used to check class and type arguments. Arguments passed on stack: |
| 1900 // TOS + 0: return address. | 1907 // LR: return address. |
| 1901 // TOS + 1: instantiator type arguments. | 1908 // R0: instance (must be preserved). |
| 1902 // TOS + 2: instance. | 1909 // R1: instantiator type arguments (can be raw_null). |
| 1903 // TOS + 3: cache array. | 1910 // R2: function type arguments (can be raw_null). |
| 1904 // Result in RCX: null -> not found, otherwise result (true or false). | 1911 // R3: SubtypeTestCache. |
| 1905 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { | 1912 // Result in R1: null -> not found, otherwise result (true or false). |
| 1906 GenerateSubtypeNTestCacheStub(assembler, 3); | 1913 void StubCode::GenerateSubtype4TestCacheStub(Assembler* assembler) { |
| 1914 GenerateSubtypeNTestCacheStub(assembler, 4); |
| 1907 } | 1915 } |
| 1908 | 1916 |
| 1909 | 1917 |
| 1910 void StubCode::GenerateGetStackPointerStub(Assembler* assembler) { | 1918 void StubCode::GenerateGetStackPointerStub(Assembler* assembler) { |
| 1911 __ mov(R0, SP); | 1919 __ mov(R0, SP); |
| 1912 __ ret(); | 1920 __ ret(); |
| 1913 } | 1921 } |
| 1914 | 1922 |
| 1915 | 1923 |
| 1916 // Jump to a frame on the call stack. | 1924 // Jump to a frame on the call stack. |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2350 } | 2358 } |
| 2351 | 2359 |
| 2352 | 2360 |
| 2353 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { | 2361 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { |
| 2354 __ brk(0); | 2362 __ brk(0); |
| 2355 } | 2363 } |
| 2356 | 2364 |
| 2357 } // namespace dart | 2365 } // namespace dart |
| 2358 | 2366 |
| 2359 #endif // defined TARGET_ARCH_ARM64 | 2367 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |