| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 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 890 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 901 | 901 |
| 902 // Verify that the class of the object is a closure class by checking that | 902 // Verify that the class of the object is a closure class by checking that |
| 903 // class.signature_function() is not null. | 903 // class.signature_function() is not null. |
| 904 __ LoadClass(T0, T1); | 904 __ LoadClass(T0, T1); |
| 905 __ lw(T0, FieldAddress(T0, Class::signature_function_offset())); | 905 __ lw(T0, FieldAddress(T0, Class::signature_function_offset())); |
| 906 | 906 |
| 907 // See if actual class is not a closure class. | 907 // See if actual class is not a closure class. |
| 908 __ beq(T0, T7, ¬_closure); | 908 __ beq(T0, T7, ¬_closure); |
| 909 | 909 |
| 910 // T0 is just the signature function. Load the actual closure function. | 910 // T0 is just the signature function. Load the actual closure function. |
| 911 __ lw(T2, FieldAddress(T1, Closure::function_offset())); | 911 __ lw(T0, FieldAddress(T1, Closure::function_offset())); |
| 912 | 912 |
| 913 // Load closure context in CTX; note that CTX has already been preserved. | 913 // Load closure context in CTX; note that CTX has already been preserved. |
| 914 __ lw(CTX, FieldAddress(T1, Closure::context_offset())); | 914 __ lw(CTX, FieldAddress(T1, Closure::context_offset())); |
| 915 | 915 |
| 916 Label function_compiled; | 916 // Load closure function code in T2. |
| 917 // Load closure function code in T0. | 917 __ lw(T2, FieldAddress(T0, Function::code_offset())); |
| 918 __ lw(T0, FieldAddress(T2, Function::code_offset())); | 918 __ lw(T2, FieldAddress(T2, Code::instructions_offset())); |
| 919 __ bne(T0, T7, &function_compiled); | 919 __ AddImmediate(T2, Instructions::HeaderSize() - kHeapObjectTag); |
| 920 | 920 __ jr(T2); |
| 921 // Create a stub frame as we are pushing some objects on the stack before | |
| 922 // calling into the runtime. | |
| 923 __ EnterStubFrame(); | |
| 924 | |
| 925 // Preserve arguments descriptor array and read-only function object argument. | |
| 926 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | |
| 927 __ sw(S4, Address(SP, 1 * kWordSize)); | |
| 928 __ sw(T2, Address(SP, 0 * kWordSize)); | |
| 929 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | |
| 930 __ TraceSimMsg("GenerateCallClosureFunctionStub return"); | |
| 931 // Restore arguments descriptor array and read-only function object argument. | |
| 932 __ lw(T2, Address(SP, 0 * kWordSize)); | |
| 933 __ lw(S4, Address(SP, 1 * kWordSize)); | |
| 934 __ addiu(SP, SP, Immediate(2 * kWordSize)); | |
| 935 // Restore T0. | |
| 936 __ lw(T0, FieldAddress(T2, Function::code_offset())); | |
| 937 | |
| 938 // Remove the stub frame as we are about to jump to the closure function. | |
| 939 __ LeaveStubFrame(); | |
| 940 | |
| 941 __ Bind(&function_compiled); | |
| 942 // T0: Code. | |
| 943 // S4: Arguments descriptor array. | |
| 944 __ lw(T0, FieldAddress(T0, Code::instructions_offset())); | |
| 945 __ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag); | |
| 946 __ jr(T0); | |
| 947 | 921 |
| 948 __ Bind(¬_closure); | 922 __ Bind(¬_closure); |
| 949 // Call runtime to attempt to resolve and invoke a call method on a | 923 // Call runtime to attempt to resolve and invoke a call method on a |
| 950 // non-closure object, passing the non-closure object and its arguments array, | 924 // non-closure object, passing the non-closure object and its arguments array, |
| 951 // returning here. | 925 // returning here. |
| 952 // If no call method exists, throw a NoSuchMethodError. | 926 // If no call method exists, throw a NoSuchMethodError. |
| 953 // T1: non-closure object. | 927 // T1: non-closure object. |
| 954 // S4: arguments descriptor array. | 928 // S4: arguments descriptor array. |
| 955 | 929 |
| 956 // Create a stub frame as we are pushing some objects on the stack before | 930 // Create a stub frame as we are pushing some objects on the stack before |
| (...skipping 774 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1731 | 1705 |
| 1732 __ AddImmediateDetectOverflow(T4, T4, Smi::RawValue(1), T5, T6); | 1706 __ AddImmediateDetectOverflow(T4, T4, Smi::RawValue(1), T5, T6); |
| 1733 | 1707 |
| 1734 __ bgez(T5, &call_target_function); // No overflow. | 1708 __ bgez(T5, &call_target_function); // No overflow. |
| 1735 __ delay_slot()->sw(T4, Address(T0, count_offset)); | 1709 __ delay_slot()->sw(T4, Address(T0, count_offset)); |
| 1736 | 1710 |
| 1737 __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue)); | 1711 __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue)); |
| 1738 __ sw(T1, Address(T0, count_offset)); | 1712 __ sw(T1, Address(T0, count_offset)); |
| 1739 | 1713 |
| 1740 __ Bind(&call_target_function); | 1714 __ Bind(&call_target_function); |
| 1741 // T3: Target function. | 1715 // T0 <- T3: Target function. |
| 1716 __ mov(T0, T3); |
| 1742 Label is_compiled; | 1717 Label is_compiled; |
| 1743 __ lw(T4, FieldAddress(T3, Function::code_offset())); | 1718 __ lw(T4, FieldAddress(T0, Function::code_offset())); |
| 1744 if (FLAG_collect_code) { | 1719 __ lw(T4, FieldAddress(T4, Code::instructions_offset())); |
| 1745 __ BranchNotEqual(T4, reinterpret_cast<int32_t>(Object::null()), | 1720 __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag); |
| 1746 &is_compiled); | 1721 __ jr(T4); |
| 1747 __ EnterStubFrame(); | |
| 1748 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | |
| 1749 __ sw(S5, Address(SP, 2 * kWordSize)); // Preserve IC data. | |
| 1750 __ sw(S4, Address(SP, 1 * kWordSize)); // Preserve arg desc. | |
| 1751 __ sw(T3, Address(SP, 0 * kWordSize)); // Function argument. | |
| 1752 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | |
| 1753 __ lw(T3, Address(SP, 0 * kWordSize)); // Restore Function. | |
| 1754 __ lw(S4, Address(SP, 1 * kWordSize)); // Restore arg desc. | |
| 1755 __ lw(S5, Address(SP, 2 * kWordSize)); // Restore IC data. | |
| 1756 __ addiu(SP, SP, Immediate(3 * kWordSize)); | |
| 1757 __ LeaveStubFrame(); | |
| 1758 __ lw(T4, FieldAddress(T3, Function::code_offset())); | |
| 1759 __ Bind(&is_compiled); | |
| 1760 } | |
| 1761 __ lw(T3, FieldAddress(T4, Code::instructions_offset())); | |
| 1762 __ AddImmediate(T3, Instructions::HeaderSize() - kHeapObjectTag); | |
| 1763 __ jr(T3); | |
| 1764 | 1722 |
| 1765 // Instance in T3, return its class-id in T3 as Smi. | 1723 // Instance in T3, return its class-id in T3 as Smi. |
| 1766 __ Bind(&get_class_id_as_smi); | 1724 __ Bind(&get_class_id_as_smi); |
| 1767 Label not_smi; | 1725 Label not_smi; |
| 1768 // Test if Smi -> load Smi class for comparison. | 1726 // Test if Smi -> load Smi class for comparison. |
| 1769 __ andi(CMPRES1, T3, Immediate(kSmiTagMask)); | 1727 __ andi(CMPRES1, T3, Immediate(kSmiTagMask)); |
| 1770 __ bne(CMPRES1, ZR, ¬_smi); | 1728 __ bne(CMPRES1, ZR, ¬_smi); |
| 1771 __ jr(RA); | 1729 __ jr(RA); |
| 1772 __ delay_slot()->addiu(T3, ZR, Immediate(Smi::RawValue(kSmiCid))); | 1730 __ delay_slot()->addiu(T3, ZR, Immediate(Smi::RawValue(kSmiCid))); |
| 1773 | 1731 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1893 __ lw(T4, Address(T0, count_offset)); | 1851 __ lw(T4, Address(T0, count_offset)); |
| 1894 __ AddImmediateDetectOverflow(T4, T4, Smi::RawValue(1), T5, T6); | 1852 __ AddImmediateDetectOverflow(T4, T4, Smi::RawValue(1), T5, T6); |
| 1895 __ bgez(T5, &increment_done); // No overflow. | 1853 __ bgez(T5, &increment_done); // No overflow. |
| 1896 __ delay_slot()->sw(T4, Address(T0, count_offset)); | 1854 __ delay_slot()->sw(T4, Address(T0, count_offset)); |
| 1897 | 1855 |
| 1898 __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue)); | 1856 __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue)); |
| 1899 __ sw(T1, Address(T0, count_offset)); | 1857 __ sw(T1, Address(T0, count_offset)); |
| 1900 | 1858 |
| 1901 __ Bind(&increment_done); | 1859 __ Bind(&increment_done); |
| 1902 | 1860 |
| 1903 Label target_is_compiled; | 1861 // Load arguments descriptor into S4. |
| 1862 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); |
| 1863 |
| 1904 // Get function and call it, if possible. | 1864 // Get function and call it, if possible. |
| 1905 __ lw(T3, Address(T0, target_offset)); | 1865 __ lw(T0, Address(T0, target_offset)); |
| 1906 __ lw(T4, FieldAddress(T3, Function::code_offset())); | 1866 __ lw(T4, FieldAddress(T0, Function::code_offset())); |
| 1907 __ LoadImmediate(CMPRES1, reinterpret_cast<intptr_t>(Object::null())); | |
| 1908 __ bne(T4, CMPRES1, &target_is_compiled); | |
| 1909 | 1867 |
| 1910 __ EnterStubFrame(); | |
| 1911 // Preserve target function and IC data object. | |
| 1912 // Two preserved registers, one argument (function) => 3 slots. | |
| 1913 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | |
| 1914 __ sw(S5, Address(SP, 2 * kWordSize)); // Preserve IC data. | |
| 1915 __ sw(T3, Address(SP, 1 * kWordSize)); // Preserve function. | |
| 1916 __ sw(T3, Address(SP, 0 * kWordSize)); // Function argument. | |
| 1917 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | |
| 1918 __ lw(T3, Address(SP, 1 * kWordSize)); // Restore function. | |
| 1919 __ lw(S5, Address(SP, 2 * kWordSize)); // Restore IC data. | |
| 1920 __ addiu(SP, SP, Immediate(3 * kWordSize)); | |
| 1921 // T3: target function. | |
| 1922 __ lw(T4, FieldAddress(T3, Function::code_offset())); | |
| 1923 __ LeaveStubFrame(); | |
| 1924 | |
| 1925 __ Bind(&target_is_compiled); | |
| 1926 // T4: target code. | 1868 // T4: target code. |
| 1927 __ lw(T3, FieldAddress(T4, Code::instructions_offset())); | 1869 __ lw(T4, FieldAddress(T4, Code::instructions_offset())); |
| 1928 __ AddImmediate(T3, Instructions::HeaderSize() - kHeapObjectTag); | 1870 __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag); |
| 1929 __ jr(T3); | 1871 __ jr(T4); |
| 1930 // Load arguments descriptor into S4. | |
| 1931 __ delay_slot()-> | |
| 1932 lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); | |
| 1933 } | 1872 } |
| 1934 | 1873 |
| 1935 | 1874 |
| 1936 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1875 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1937 GenerateUsageCounterIncrement(assembler, T0); | 1876 GenerateUsageCounterIncrement(assembler, T0); |
| 1938 GenerateNArgsCheckInlineCacheStub( | 1877 GenerateNArgsCheckInlineCacheStub( |
| 1939 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); | 1878 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); |
| 1940 } | 1879 } |
| 1941 | 1880 |
| 1942 | 1881 |
| 1943 // Stub for calling the CompileFunction runtime call. | 1882 // Stub for compiling a function and jumping to the compiled code. |
| 1944 // S5: IC-Data. | 1883 // S5: IC-Data (for methods). |
| 1945 // S4: Arguments descriptor. | 1884 // S4: Arguments descriptor. |
| 1946 // T0: Function. | 1885 // T0: Function. |
| 1947 void StubCode::GenerateCompileFunctionRuntimeCallStub(Assembler* assembler) { | 1886 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { |
| 1948 __ EnterStubFrame(); | 1887 __ EnterStubFrame(); |
| 1949 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | 1888 __ addiu(SP, SP, Immediate(-3 * kWordSize)); |
| 1950 __ sw(S5, Address(SP, 2 * kWordSize)); // Preserve IC data object. | 1889 __ sw(S5, Address(SP, 2 * kWordSize)); // Preserve IC data object. |
| 1951 __ sw(S4, Address(SP, 1 * kWordSize)); // Preserve args descriptor array. | 1890 __ sw(S4, Address(SP, 1 * kWordSize)); // Preserve args descriptor array. |
| 1952 __ sw(T0, Address(SP, 0 * kWordSize)); // Pass function. | 1891 __ sw(T0, Address(SP, 0 * kWordSize)); // Pass function. |
| 1953 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | 1892 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); |
| 1954 __ lw(T0, Address(SP, 0 * kWordSize)); // Restore function. | 1893 __ lw(T0, Address(SP, 0 * kWordSize)); // Restore function. |
| 1955 __ lw(S4, Address(SP, 1 * kWordSize)); // Restore args descriptor array. | 1894 __ lw(S4, Address(SP, 1 * kWordSize)); // Restore args descriptor array. |
| 1956 __ lw(S5, Address(SP, 2 * kWordSize)); // Restore IC data array. | 1895 __ lw(S5, Address(SP, 2 * kWordSize)); // Restore IC data array. |
| 1957 __ LeaveStubFrameAndReturn(); | 1896 __ addiu(SP, SP, Immediate(3 * kWordSize)); |
| 1897 __ LeaveStubFrame(); |
| 1898 |
| 1899 __ lw(T2, FieldAddress(T0, Function::code_offset())); |
| 1900 __ lw(T2, FieldAddress(T2, Code::instructions_offset())); |
| 1901 __ AddImmediate(T2, Instructions::HeaderSize() - kHeapObjectTag); |
| 1902 __ jr(T2); |
| 1958 } | 1903 } |
| 1959 | 1904 |
| 1960 | 1905 |
| 1961 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { | 1906 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { |
| 1962 __ Comment("BreakpointRuntime stub"); | 1907 __ Comment("BreakpointRuntime stub"); |
| 1963 __ EnterStubFrame(); | 1908 __ EnterStubFrame(); |
| 1964 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | 1909 __ addiu(SP, SP, Immediate(-3 * kWordSize)); |
| 1965 __ sw(S5, Address(SP, 2 * kWordSize)); | 1910 __ sw(S5, Address(SP, 2 * kWordSize)); |
| 1966 __ sw(S4, Address(SP, 1 * kWordSize)); | 1911 __ sw(S4, Address(SP, 1 * kWordSize)); |
| 1967 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null())); | 1912 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null())); |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2295 const Register right = T0; | 2240 const Register right = T0; |
| 2296 __ lw(left, Address(SP, 1 * kWordSize)); | 2241 __ lw(left, Address(SP, 1 * kWordSize)); |
| 2297 __ lw(right, Address(SP, 0 * kWordSize)); | 2242 __ lw(right, Address(SP, 0 * kWordSize)); |
| 2298 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); | 2243 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); |
| 2299 __ Ret(); | 2244 __ Ret(); |
| 2300 } | 2245 } |
| 2301 | 2246 |
| 2302 } // namespace dart | 2247 } // namespace dart |
| 2303 | 2248 |
| 2304 #endif // defined TARGET_ARCH_MIPS | 2249 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |