| 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 // Load closure function code in T2. |
| 916 Label function_compiled; | 917 Label function_compiled; |
| 917 // Load closure function code in T0. | 918 __ lw(T2, FieldAddress(T0, Function::code_offset())); |
| 918 __ lw(T0, FieldAddress(T2, Function::code_offset())); | 919 __ beq(T2, T7, &function_compiled); |
| 919 __ bne(T0, T7, &function_compiled); | 920 __ Branch(&StubCode::LazyCompileClosureLabel()); |
| 920 | |
| 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 | 921 |
| 941 __ Bind(&function_compiled); | 922 __ Bind(&function_compiled); |
| 942 // T0: Code. | 923 __ lw(T2, FieldAddress(T2, Code::instructions_offset())); |
| 943 // S4: Arguments descriptor array. | 924 __ AddImmediate(T2, Instructions::HeaderSize() - kHeapObjectTag); |
| 944 __ lw(T0, FieldAddress(T0, Code::instructions_offset())); | 925 __ jr(T2); |
| 945 __ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag); | |
| 946 __ jr(T0); | |
| 947 | 926 |
| 948 __ Bind(¬_closure); | 927 __ Bind(¬_closure); |
| 949 // Call runtime to attempt to resolve and invoke a call method on a | 928 // 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, | 929 // non-closure object, passing the non-closure object and its arguments array, |
| 951 // returning here. | 930 // returning here. |
| 952 // If no call method exists, throw a NoSuchMethodError. | 931 // If no call method exists, throw a NoSuchMethodError. |
| 953 // T1: non-closure object. | 932 // T1: non-closure object. |
| 954 // S4: arguments descriptor array. | 933 // S4: arguments descriptor array. |
| 955 | 934 |
| 956 // Create a stub frame as we are pushing some objects on the stack before | 935 // 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 | 1710 |
| 1732 __ AddImmediateDetectOverflow(T4, T4, Smi::RawValue(1), T5, T6); | 1711 __ AddImmediateDetectOverflow(T4, T4, Smi::RawValue(1), T5, T6); |
| 1733 | 1712 |
| 1734 __ bgez(T5, &call_target_function); // No overflow. | 1713 __ bgez(T5, &call_target_function); // No overflow. |
| 1735 __ delay_slot()->sw(T4, Address(T0, count_offset)); | 1714 __ delay_slot()->sw(T4, Address(T0, count_offset)); |
| 1736 | 1715 |
| 1737 __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue)); | 1716 __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue)); |
| 1738 __ sw(T1, Address(T0, count_offset)); | 1717 __ sw(T1, Address(T0, count_offset)); |
| 1739 | 1718 |
| 1740 __ Bind(&call_target_function); | 1719 __ Bind(&call_target_function); |
| 1741 // T3: Target function. | 1720 // T0 <- T3: Target function. |
| 1721 __ mov(T0, T3); |
| 1742 Label is_compiled; | 1722 Label is_compiled; |
| 1743 __ lw(T4, FieldAddress(T3, Function::code_offset())); | 1723 __ lw(T4, FieldAddress(T3, Function::code_offset())); |
| 1744 if (FLAG_collect_code) { | 1724 if (FLAG_collect_code) { |
| 1745 __ BranchNotEqual(T4, reinterpret_cast<int32_t>(Object::null()), | 1725 __ BranchNotEqual(T4, reinterpret_cast<int32_t>(Object::null()), |
| 1746 &is_compiled); | 1726 &is_compiled); |
| 1747 __ EnterStubFrame(); | 1727 __ Branch(&StubCode::LazyCompileLabel()); |
| 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); | 1728 __ Bind(&is_compiled); |
| 1760 } | 1729 } |
| 1761 __ lw(T3, FieldAddress(T4, Code::instructions_offset())); | 1730 __ lw(T3, FieldAddress(T4, Code::instructions_offset())); |
| 1762 __ AddImmediate(T3, Instructions::HeaderSize() - kHeapObjectTag); | 1731 __ AddImmediate(T3, Instructions::HeaderSize() - kHeapObjectTag); |
| 1763 __ jr(T3); | 1732 __ jr(T3); |
| 1764 | 1733 |
| 1765 // Instance in T3, return its class-id in T3 as Smi. | 1734 // Instance in T3, return its class-id in T3 as Smi. |
| 1766 __ Bind(&get_class_id_as_smi); | 1735 __ Bind(&get_class_id_as_smi); |
| 1767 Label not_smi; | 1736 Label not_smi; |
| 1768 // Test if Smi -> load Smi class for comparison. | 1737 // Test if Smi -> load Smi class for comparison. |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1893 __ lw(T4, Address(T0, count_offset)); | 1862 __ lw(T4, Address(T0, count_offset)); |
| 1894 __ AddImmediateDetectOverflow(T4, T4, Smi::RawValue(1), T5, T6); | 1863 __ AddImmediateDetectOverflow(T4, T4, Smi::RawValue(1), T5, T6); |
| 1895 __ bgez(T5, &increment_done); // No overflow. | 1864 __ bgez(T5, &increment_done); // No overflow. |
| 1896 __ delay_slot()->sw(T4, Address(T0, count_offset)); | 1865 __ delay_slot()->sw(T4, Address(T0, count_offset)); |
| 1897 | 1866 |
| 1898 __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue)); | 1867 __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue)); |
| 1899 __ sw(T1, Address(T0, count_offset)); | 1868 __ sw(T1, Address(T0, count_offset)); |
| 1900 | 1869 |
| 1901 __ Bind(&increment_done); | 1870 __ Bind(&increment_done); |
| 1902 | 1871 |
| 1872 // Load arguments descriptor into S4. |
| 1873 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); |
| 1874 |
| 1903 Label target_is_compiled; | 1875 Label target_is_compiled; |
| 1904 // Get function and call it, if possible. | 1876 // Get function and call it, if possible. |
| 1905 __ lw(T3, Address(T0, target_offset)); | 1877 __ lw(T0, Address(T0, target_offset)); |
| 1906 __ lw(T4, FieldAddress(T3, Function::code_offset())); | 1878 __ lw(T4, FieldAddress(T0, Function::code_offset())); |
| 1907 __ LoadImmediate(CMPRES1, reinterpret_cast<intptr_t>(Object::null())); | 1879 __ LoadImmediate(CMPRES1, reinterpret_cast<intptr_t>(Object::null())); |
| 1908 __ bne(T4, CMPRES1, &target_is_compiled); | 1880 __ bne(T4, CMPRES1, &target_is_compiled); |
| 1909 | 1881 __ Branch(&StubCode::LazyCompileLabel()); |
| 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 | 1882 |
| 1925 __ Bind(&target_is_compiled); | 1883 __ Bind(&target_is_compiled); |
| 1926 // T4: target code. | 1884 // T4: target code. |
| 1927 __ lw(T3, FieldAddress(T4, Code::instructions_offset())); | 1885 __ lw(T3, FieldAddress(T4, Code::instructions_offset())); |
| 1928 __ AddImmediate(T3, Instructions::HeaderSize() - kHeapObjectTag); | 1886 __ AddImmediate(T3, Instructions::HeaderSize() - kHeapObjectTag); |
| 1929 __ jr(T3); | 1887 __ jr(T3); |
| 1930 // Load arguments descriptor into S4. | |
| 1931 __ delay_slot()-> | |
| 1932 lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); | |
| 1933 } | 1888 } |
| 1934 | 1889 |
| 1935 | 1890 |
| 1936 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1891 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1937 GenerateUsageCounterIncrement(assembler, T0); | 1892 GenerateUsageCounterIncrement(assembler, T0); |
| 1938 GenerateNArgsCheckInlineCacheStub( | 1893 GenerateNArgsCheckInlineCacheStub( |
| 1939 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); | 1894 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); |
| 1940 } | 1895 } |
| 1941 | 1896 |
| 1942 | 1897 |
| 1943 // Stub for calling the CompileFunction runtime call. | 1898 // Stub for compiling a function and jumping to the compiled code. |
| 1944 // S5: IC-Data. | 1899 // S5: IC-Data. |
| 1945 // S4: Arguments descriptor. | 1900 // S4: Arguments descriptor. |
| 1946 // T0: Function. | 1901 // T0: Function. |
| 1947 void StubCode::GenerateCompileFunctionRuntimeCallStub(Assembler* assembler) { | 1902 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { |
| 1948 __ EnterStubFrame(); | 1903 __ EnterStubFrame(); |
| 1949 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | 1904 __ addiu(SP, SP, Immediate(-3 * kWordSize)); |
| 1950 __ sw(S5, Address(SP, 2 * kWordSize)); // Preserve IC data object. | 1905 __ sw(S5, Address(SP, 2 * kWordSize)); // Preserve IC data object. |
| 1951 __ sw(S4, Address(SP, 1 * kWordSize)); // Preserve args descriptor array. | 1906 __ sw(S4, Address(SP, 1 * kWordSize)); // Preserve args descriptor array. |
| 1952 __ sw(T0, Address(SP, 0 * kWordSize)); // Pass function. | 1907 __ sw(T0, Address(SP, 0 * kWordSize)); // Pass function. |
| 1953 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | 1908 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); |
| 1954 __ lw(T0, Address(SP, 0 * kWordSize)); // Restore function. | 1909 __ lw(T0, Address(SP, 0 * kWordSize)); // Restore function. |
| 1955 __ lw(S4, Address(SP, 1 * kWordSize)); // Restore args descriptor array. | 1910 __ lw(S4, Address(SP, 1 * kWordSize)); // Restore args descriptor array. |
| 1956 __ lw(S5, Address(SP, 2 * kWordSize)); // Restore IC data array. | 1911 __ lw(S5, Address(SP, 2 * kWordSize)); // Restore IC data array. |
| 1912 __ LeaveStubFrame(); |
| 1913 |
| 1914 __ lw(T2, FieldAddress(T0, Function::code_offset())); |
| 1915 __ lw(T2, FieldAddress(T2, Code::instructions_offset())); |
| 1916 __ AddImmediate(T2, Instructions::HeaderSize() - kHeapObjectTag); |
| 1917 __ jr(T2); |
| 1918 } |
| 1919 |
| 1920 |
| 1921 // Stub for compiling a closure and jumping to the compiled code. |
| 1922 // S5: IC-Data. |
| 1923 // S4: Arguments descriptor. |
| 1924 // T0: Function. |
| 1925 void StubCode::GenerateLazyCompileClosureStub(Assembler* assembler) { |
| 1926 __ EnterStubFrame(); |
| 1927 __ addiu(SP, SP, Immediate(-3 * kWordSize)); |
| 1928 __ sw(S4, Address(SP, 1 * kWordSize)); // Preserve args descriptor array. |
| 1929 __ sw(T0, Address(SP, 0 * kWordSize)); // Pass function. |
| 1930 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); |
| 1931 __ lw(T0, Address(SP, 0 * kWordSize)); // Restore function. |
| 1932 __ lw(S4, Address(SP, 1 * kWordSize)); // Restore args descriptor array. |
| 1933 __ LeaveStubFrame(); |
| 1934 |
| 1935 __ lw(T2, FieldAddress(T0, Function::code_offset())); |
| 1936 __ lw(T2, FieldAddress(T2, Code::instructions_offset())); |
| 1937 __ AddImmediate(T2, Instructions::HeaderSize() - kHeapObjectTag); |
| 1938 __ jr(T2); |
| 1939 } |
| 1940 |
| 1941 |
| 1942 // Stub for calling the CompileFunction runtime call. |
| 1943 // T0: Function. |
| 1944 void StubCode::GenerateCompileFunctionRuntimeCallStub(Assembler* assembler) { |
| 1945 __ EnterStubFrame(); |
| 1946 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
| 1947 __ sw(T0, Address(SP, 0 * kWordSize)); // Pass function. |
| 1948 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); |
| 1949 __ lw(T0, Address(SP, 0 * kWordSize)); // Restore function. |
| 1957 __ LeaveStubFrameAndReturn(); | 1950 __ LeaveStubFrameAndReturn(); |
| 1958 } | 1951 } |
| 1959 | 1952 |
| 1960 | 1953 |
| 1961 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { | 1954 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { |
| 1962 __ Comment("BreakpointRuntime stub"); | 1955 __ Comment("BreakpointRuntime stub"); |
| 1963 __ EnterStubFrame(); | 1956 __ EnterStubFrame(); |
| 1964 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | 1957 __ addiu(SP, SP, Immediate(-3 * kWordSize)); |
| 1965 __ sw(S5, Address(SP, 2 * kWordSize)); | 1958 __ sw(S5, Address(SP, 2 * kWordSize)); |
| 1966 __ sw(S4, Address(SP, 1 * kWordSize)); | 1959 __ sw(S4, Address(SP, 1 * kWordSize)); |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2295 const Register right = T0; | 2288 const Register right = T0; |
| 2296 __ lw(left, Address(SP, 1 * kWordSize)); | 2289 __ lw(left, Address(SP, 1 * kWordSize)); |
| 2297 __ lw(right, Address(SP, 0 * kWordSize)); | 2290 __ lw(right, Address(SP, 0 * kWordSize)); |
| 2298 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); | 2291 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); |
| 2299 __ Ret(); | 2292 __ Ret(); |
| 2300 } | 2293 } |
| 2301 | 2294 |
| 2302 } // namespace dart | 2295 } // namespace dart |
| 2303 | 2296 |
| 2304 #endif // defined TARGET_ARCH_MIPS | 2297 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |