| 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" |
| 11 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
| 12 #include "vm/flow_graph_compiler.h" | 12 #include "vm/flow_graph_compiler.h" |
| 13 #include "vm/heap.h" | 13 #include "vm/heap.h" |
| 14 #include "vm/instructions.h" | 14 #include "vm/instructions.h" |
| 15 #include "vm/object_store.h" | 15 #include "vm/object_store.h" |
| 16 #include "vm/stack_frame.h" | 16 #include "vm/stack_frame.h" |
| 17 #include "vm/stub_code.h" | 17 #include "vm/stub_code.h" |
| 18 #include "vm/tags.h" | 18 #include "vm/tags.h" |
| 19 | 19 |
| 20 #define __ assembler-> | 20 #define __ assembler-> |
| 21 | 21 |
| 22 namespace dart { | 22 namespace dart { |
| 23 | 23 |
| 24 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); | 24 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); |
| 25 DEFINE_FLAG(bool, use_slow_path, false, | 25 DEFINE_FLAG(bool, use_slow_path, false, |
| 26 "Set to true for debugging & verifying the slow paths."); | 26 "Set to true for debugging & verifying the slow paths."); |
| 27 DECLARE_FLAG(bool, trace_optimized_ic_calls); | 27 DECLARE_FLAG(bool, trace_optimized_ic_calls); |
| 28 DECLARE_FLAG(int, optimization_counter_threshold); | 28 DECLARE_FLAG(int, optimization_counter_threshold); |
| 29 DECLARE_FLAG(bool, support_debugger); |
| 29 | 30 |
| 30 // Input parameters: | 31 // Input parameters: |
| 31 // RA : return address. | 32 // RA : return address. |
| 32 // SP : address of last argument in argument array. | 33 // SP : address of last argument in argument array. |
| 33 // SP + 4*S4 - 4 : address of first argument in argument array. | 34 // SP + 4*S4 - 4 : address of first argument in argument array. |
| 34 // SP + 4*S4 : address of return value. | 35 // SP + 4*S4 : address of return value. |
| 35 // S5 : address of the runtime function to call. | 36 // S5 : address of the runtime function to call. |
| 36 // S4 : number of arguments to the call. | 37 // S4 : number of arguments to the call. |
| 37 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { | 38 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
| 38 const intptr_t isolate_offset = NativeArguments::isolate_offset(); | 39 const intptr_t isolate_offset = NativeArguments::isolate_offset(); |
| (...skipping 1408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1447 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); | 1448 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); |
| 1448 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1449 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1449 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); | 1450 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); |
| 1450 __ BranchEqual(T0, Immediate(num_args), &ok); | 1451 __ BranchEqual(T0, Immediate(num_args), &ok); |
| 1451 __ Stop("Incorrect stub for IC data"); | 1452 __ Stop("Incorrect stub for IC data"); |
| 1452 __ Bind(&ok); | 1453 __ Bind(&ok); |
| 1453 } | 1454 } |
| 1454 #endif // DEBUG | 1455 #endif // DEBUG |
| 1455 | 1456 |
| 1456 | 1457 |
| 1457 __ Comment("Check single stepping"); | |
| 1458 Label stepping, done_stepping; | 1458 Label stepping, done_stepping; |
| 1459 __ LoadIsolate(T0); | 1459 if (FLAG_support_debugger) { |
| 1460 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 1460 __ Comment("Check single stepping"); |
| 1461 __ BranchNotEqual(T0, Immediate(0), &stepping); | 1461 __ LoadIsolate(T0); |
| 1462 __ Bind(&done_stepping); | 1462 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
| 1463 __ BranchNotEqual(T0, Immediate(0), &stepping); |
| 1464 __ Bind(&done_stepping); |
| 1465 } |
| 1463 | 1466 |
| 1464 __ Comment("Range feedback collection"); | 1467 __ Comment("Range feedback collection"); |
| 1465 Label not_smi_or_overflow; | 1468 Label not_smi_or_overflow; |
| 1466 if (range_collection_mode == kCollectRanges) { | 1469 if (range_collection_mode == kCollectRanges) { |
| 1467 ASSERT((num_args == 1) || (num_args == 2)); | 1470 ASSERT((num_args == 1) || (num_args == 2)); |
| 1468 if (num_args == 2) { | 1471 if (num_args == 2) { |
| 1469 __ lw(T0, Address(SP, 1 * kWordSize)); | 1472 __ lw(T0, Address(SP, 1 * kWordSize)); |
| 1470 __ UpdateRangeFeedback(T0, 0, S5, T1, ¬_smi_or_overflow); | 1473 __ UpdateRangeFeedback(T0, 0, S5, T1, ¬_smi_or_overflow); |
| 1471 } | 1474 } |
| 1472 | 1475 |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1636 __ UpdateRangeFeedback(V0, 2, S5, T1, &done); | 1639 __ UpdateRangeFeedback(V0, 2, S5, T1, &done); |
| 1637 __ Bind(&done); | 1640 __ Bind(&done); |
| 1638 __ addiu(SP, SP, Immediate(frame_size * kWordSize)); | 1641 __ addiu(SP, SP, Immediate(frame_size * kWordSize)); |
| 1639 __ LeaveStubFrame(); | 1642 __ LeaveStubFrame(); |
| 1640 __ Ret(); | 1643 __ Ret(); |
| 1641 } else { | 1644 } else { |
| 1642 __ jr(T4); | 1645 __ jr(T4); |
| 1643 } | 1646 } |
| 1644 | 1647 |
| 1645 // Call single step callback in debugger. | 1648 // Call single step callback in debugger. |
| 1646 __ Bind(&stepping); | 1649 if (FLAG_support_debugger) { |
| 1647 __ EnterStubFrame(); | 1650 __ Bind(&stepping); |
| 1648 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1651 __ EnterStubFrame(); |
| 1649 __ sw(S5, Address(SP, 1 * kWordSize)); // Preserve IC data. | 1652 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
| 1650 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. | 1653 __ sw(S5, Address(SP, 1 * kWordSize)); // Preserve IC data. |
| 1651 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1654 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. |
| 1652 __ lw(RA, Address(SP, 0 * kWordSize)); | 1655 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1653 __ lw(S5, Address(SP, 1 * kWordSize)); | 1656 __ lw(RA, Address(SP, 0 * kWordSize)); |
| 1654 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 1657 __ lw(S5, Address(SP, 1 * kWordSize)); |
| 1655 __ LeaveStubFrame(); | 1658 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
| 1656 __ b(&done_stepping); | 1659 __ LeaveStubFrame(); |
| 1660 __ b(&done_stepping); |
| 1661 } |
| 1657 } | 1662 } |
| 1658 | 1663 |
| 1659 | 1664 |
| 1660 // Use inline cache data array to invoke the target or continue in inline | 1665 // Use inline cache data array to invoke the target or continue in inline |
| 1661 // cache miss handler. Stub for 1-argument check (receiver class). | 1666 // cache miss handler. Stub for 1-argument check (receiver class). |
| 1662 // RA: Return address. | 1667 // RA: Return address. |
| 1663 // S5: Inline cache data object. | 1668 // S5: Inline cache data object. |
| 1664 // Inline cache data object structure: | 1669 // Inline cache data object structure: |
| 1665 // 0: function-name | 1670 // 0: function-name |
| 1666 // 1: N, number of arguments checked. | 1671 // 1: N, number of arguments checked. |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1776 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1781 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1777 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); | 1782 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); |
| 1778 __ beq(T0, ZR, &ok); | 1783 __ beq(T0, ZR, &ok); |
| 1779 __ Stop("Incorrect IC data for unoptimized static call"); | 1784 __ Stop("Incorrect IC data for unoptimized static call"); |
| 1780 __ Bind(&ok); | 1785 __ Bind(&ok); |
| 1781 } | 1786 } |
| 1782 #endif // DEBUG | 1787 #endif // DEBUG |
| 1783 | 1788 |
| 1784 // Check single stepping. | 1789 // Check single stepping. |
| 1785 Label stepping, done_stepping; | 1790 Label stepping, done_stepping; |
| 1786 __ LoadIsolate(T0); | 1791 if (FLAG_support_debugger) { |
| 1787 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 1792 __ LoadIsolate(T0); |
| 1788 __ BranchNotEqual(T0, Immediate(0), &stepping); | 1793 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
| 1789 __ Bind(&done_stepping); | 1794 __ BranchNotEqual(T0, Immediate(0), &stepping); |
| 1795 __ Bind(&done_stepping); |
| 1796 } |
| 1790 | 1797 |
| 1791 // S5: IC data object (preserved). | 1798 // S5: IC data object (preserved). |
| 1792 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); | 1799 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); |
| 1793 // T0: ic_data_array with entries: target functions and count. | 1800 // T0: ic_data_array with entries: target functions and count. |
| 1794 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); | 1801 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); |
| 1795 // T0: points directly to the first ic data array element. | 1802 // T0: points directly to the first ic data array element. |
| 1796 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1803 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
| 1797 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1804 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
| 1798 | 1805 |
| 1799 if (FLAG_optimization_counter_threshold >= 0) { | 1806 if (FLAG_optimization_counter_threshold >= 0) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1811 | 1818 |
| 1812 // Get function and call it, if possible. | 1819 // Get function and call it, if possible. |
| 1813 __ lw(T0, Address(T0, target_offset)); | 1820 __ lw(T0, Address(T0, target_offset)); |
| 1814 __ lw(T4, FieldAddress(T0, Function::instructions_offset())); | 1821 __ lw(T4, FieldAddress(T0, Function::instructions_offset())); |
| 1815 | 1822 |
| 1816 // T4: target instructions. | 1823 // T4: target instructions. |
| 1817 __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag); | 1824 __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag); |
| 1818 __ jr(T4); | 1825 __ jr(T4); |
| 1819 | 1826 |
| 1820 // Call single step callback in debugger. | 1827 // Call single step callback in debugger. |
| 1821 __ Bind(&stepping); | 1828 if (FLAG_support_debugger) { |
| 1822 __ EnterStubFrame(); | 1829 __ Bind(&stepping); |
| 1823 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1830 __ EnterStubFrame(); |
| 1824 __ sw(S5, Address(SP, 1 * kWordSize)); // Preserve IC data. | 1831 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
| 1825 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. | 1832 __ sw(S5, Address(SP, 1 * kWordSize)); // Preserve IC data. |
| 1826 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1833 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. |
| 1827 __ lw(RA, Address(SP, 0 * kWordSize)); | 1834 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1828 __ lw(S5, Address(SP, 1 * kWordSize)); | 1835 __ lw(RA, Address(SP, 0 * kWordSize)); |
| 1829 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 1836 __ lw(S5, Address(SP, 1 * kWordSize)); |
| 1830 __ LeaveStubFrame(); | 1837 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
| 1831 __ b(&done_stepping); | 1838 __ LeaveStubFrame(); |
| 1839 __ b(&done_stepping); |
| 1840 } |
| 1832 } | 1841 } |
| 1833 | 1842 |
| 1834 | 1843 |
| 1835 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { | 1844 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1836 GenerateUsageCounterIncrement(assembler, T0); | 1845 GenerateUsageCounterIncrement(assembler, T0); |
| 1837 GenerateNArgsCheckInlineCacheStub( | 1846 GenerateNArgsCheckInlineCacheStub( |
| 1838 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL, | 1847 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL, |
| 1839 kIgnoreRanges); | 1848 kIgnoreRanges); |
| 1840 } | 1849 } |
| 1841 | 1850 |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2214 | 2223 |
| 2215 // Called only from unoptimized code. All relevant registers have been saved. | 2224 // Called only from unoptimized code. All relevant registers have been saved. |
| 2216 // RA: return address. | 2225 // RA: return address. |
| 2217 // SP + 4: left operand. | 2226 // SP + 4: left operand. |
| 2218 // SP + 0: right operand. | 2227 // SP + 0: right operand. |
| 2219 // Returns: CMPRES1 is zero if equal, non-zero otherwise. | 2228 // Returns: CMPRES1 is zero if equal, non-zero otherwise. |
| 2220 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 2229 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
| 2221 Assembler* assembler) { | 2230 Assembler* assembler) { |
| 2222 // Check single stepping. | 2231 // Check single stepping. |
| 2223 Label stepping, done_stepping; | 2232 Label stepping, done_stepping; |
| 2224 __ LoadIsolate(T0); | 2233 if (FLAG_support_debugger) { |
| 2225 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 2234 __ LoadIsolate(T0); |
| 2226 __ BranchNotEqual(T0, Immediate(0), &stepping); | 2235 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
| 2227 __ Bind(&done_stepping); | 2236 __ BranchNotEqual(T0, Immediate(0), &stepping); |
| 2237 __ Bind(&done_stepping); |
| 2238 } |
| 2228 | 2239 |
| 2229 const Register temp1 = T2; | 2240 const Register temp1 = T2; |
| 2230 const Register temp2 = T3; | 2241 const Register temp2 = T3; |
| 2231 const Register left = T1; | 2242 const Register left = T1; |
| 2232 const Register right = T0; | 2243 const Register right = T0; |
| 2233 __ lw(left, Address(SP, 1 * kWordSize)); | 2244 __ lw(left, Address(SP, 1 * kWordSize)); |
| 2234 __ lw(right, Address(SP, 0 * kWordSize)); | 2245 __ lw(right, Address(SP, 0 * kWordSize)); |
| 2235 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); | 2246 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); |
| 2236 __ Ret(); | 2247 __ Ret(); |
| 2237 | 2248 |
| 2238 // Call single step callback in debugger. | 2249 // Call single step callback in debugger. |
| 2239 __ Bind(&stepping); | 2250 if (FLAG_support_debugger) { |
| 2240 __ EnterStubFrame(); | 2251 __ Bind(&stepping); |
| 2241 __ addiu(SP, SP, Immediate(-1 * kWordSize)); | 2252 __ EnterStubFrame(); |
| 2242 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. | 2253 __ addiu(SP, SP, Immediate(-1 * kWordSize)); |
| 2243 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 2254 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. |
| 2244 __ lw(RA, Address(SP, 0 * kWordSize)); | 2255 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 2245 __ addiu(SP, SP, Immediate(1 * kWordSize)); | 2256 __ lw(RA, Address(SP, 0 * kWordSize)); |
| 2246 __ LeaveStubFrame(); | 2257 __ addiu(SP, SP, Immediate(1 * kWordSize)); |
| 2247 __ b(&done_stepping); | 2258 __ LeaveStubFrame(); |
| 2259 __ b(&done_stepping); |
| 2260 } |
| 2248 } | 2261 } |
| 2249 | 2262 |
| 2250 | 2263 |
| 2251 // Called from optimized code only. | 2264 // Called from optimized code only. |
| 2252 // SP + 4: left operand. | 2265 // SP + 4: left operand. |
| 2253 // SP + 0: right operand. | 2266 // SP + 0: right operand. |
| 2254 // Returns: CMPRES1 is zero if equal, non-zero otherwise. | 2267 // Returns: CMPRES1 is zero if equal, non-zero otherwise. |
| 2255 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( | 2268 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( |
| 2256 Assembler* assembler) { | 2269 Assembler* assembler) { |
| 2257 const Register temp1 = T2; | 2270 const Register temp1 = T2; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2315 // Result: | 2328 // Result: |
| 2316 // T1: entry point. | 2329 // T1: entry point. |
| 2317 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 2330 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
| 2318 EmitMegamorphicLookup(assembler, T0, T1, T1); | 2331 EmitMegamorphicLookup(assembler, T0, T1, T1); |
| 2319 __ Ret(); | 2332 __ Ret(); |
| 2320 } | 2333 } |
| 2321 | 2334 |
| 2322 } // namespace dart | 2335 } // namespace dart |
| 2323 | 2336 |
| 2324 #endif // defined TARGET_ARCH_MIPS | 2337 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |