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 |