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 | 28 |
29 DECLARE_FLAG(bool, enable_debugger); | |
30 | |
31 // Input parameters: | 29 // Input parameters: |
32 // RA : return address. | 30 // RA : return address. |
33 // SP : address of last argument in argument array. | 31 // SP : address of last argument in argument array. |
34 // SP + 4*S4 - 4 : address of first argument in argument array. | 32 // SP + 4*S4 - 4 : address of first argument in argument array. |
35 // SP + 4*S4 : address of return value. | 33 // SP + 4*S4 : address of return value. |
36 // S5 : address of the runtime function to call. | 34 // S5 : address of the runtime function to call. |
37 // S4 : number of arguments to the call. | 35 // S4 : number of arguments to the call. |
38 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { | 36 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
39 const intptr_t isolate_offset = NativeArguments::isolate_offset(); | 37 const intptr_t isolate_offset = NativeArguments::isolate_offset(); |
40 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); | 38 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); |
(...skipping 1357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1398 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1396 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
1399 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); | 1397 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); |
1400 __ BranchEqual(T0, num_args, &ok); | 1398 __ BranchEqual(T0, num_args, &ok); |
1401 __ Stop("Incorrect stub for IC data"); | 1399 __ Stop("Incorrect stub for IC data"); |
1402 __ Bind(&ok); | 1400 __ Bind(&ok); |
1403 } | 1401 } |
1404 #endif // DEBUG | 1402 #endif // DEBUG |
1405 | 1403 |
1406 | 1404 |
1407 Label stepping, done_stepping; | 1405 Label stepping, done_stepping; |
1408 if (FLAG_enable_debugger) { | 1406 // Check single stepping. |
1409 // Check single stepping. | 1407 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); |
1410 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); | 1408 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
1411 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 1409 __ BranchNotEqual(T0, 0, &stepping); |
1412 __ BranchNotEqual(T0, 0, &stepping); | 1410 __ Bind(&done_stepping); |
1413 __ Bind(&done_stepping); | |
1414 } | |
1415 | 1411 |
1416 // Load argument descriptor into S4. | 1412 // Load argument descriptor into S4. |
1417 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); | 1413 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); |
1418 // Preserve return address, since RA is needed for subroutine call. | 1414 // Preserve return address, since RA is needed for subroutine call. |
1419 __ mov(T2, RA); | 1415 __ mov(T2, RA); |
1420 // Loop that checks if there is an IC data match. | 1416 // Loop that checks if there is an IC data match. |
1421 Label loop, update, test, found; | 1417 Label loop, update, test, found; |
1422 // S5: IC data object (preserved). | 1418 // S5: IC data object (preserved). |
1423 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); | 1419 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); |
1424 // T0: ic_data_array with check entries: classes and target functions. | 1420 // T0: ic_data_array with check entries: classes and target functions. |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1539 __ sw(T4, Address(T0, count_offset)); | 1535 __ sw(T4, Address(T0, count_offset)); |
1540 | 1536 |
1541 __ Bind(&call_target_function); | 1537 __ Bind(&call_target_function); |
1542 // T0 <- T3: Target function. | 1538 // T0 <- T3: Target function. |
1543 __ mov(T0, T3); | 1539 __ mov(T0, T3); |
1544 Label is_compiled; | 1540 Label is_compiled; |
1545 __ lw(T4, FieldAddress(T0, Function::instructions_offset())); | 1541 __ lw(T4, FieldAddress(T0, Function::instructions_offset())); |
1546 __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag); | 1542 __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag); |
1547 __ jr(T4); | 1543 __ jr(T4); |
1548 | 1544 |
1549 if (FLAG_enable_debugger) { | 1545 // Call single step callback in debugger. |
1550 // Call single step callback in debugger. | 1546 __ Bind(&stepping); |
1551 __ Bind(&stepping); | 1547 __ EnterStubFrame(); |
1552 __ EnterStubFrame(); | 1548 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
1553 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1549 __ sw(S5, Address(SP, 1 * kWordSize)); // Preserve IC data. |
1554 __ sw(S5, Address(SP, 1 * kWordSize)); // Preserve IC data. | 1550 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. |
1555 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. | 1551 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1556 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1552 __ lw(RA, Address(SP, 0 * kWordSize)); |
1557 __ lw(RA, Address(SP, 0 * kWordSize)); | 1553 __ lw(S5, Address(SP, 1 * kWordSize)); |
1558 __ lw(S5, Address(SP, 1 * kWordSize)); | 1554 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
1559 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 1555 __ LeaveStubFrame(); |
1560 __ LeaveStubFrame(); | 1556 __ b(&done_stepping); |
1561 __ b(&done_stepping); | |
1562 } | |
1563 } | 1557 } |
1564 | 1558 |
1565 | 1559 |
1566 // Use inline cache data array to invoke the target or continue in inline | 1560 // Use inline cache data array to invoke the target or continue in inline |
1567 // cache miss handler. Stub for 1-argument check (receiver class). | 1561 // cache miss handler. Stub for 1-argument check (receiver class). |
1568 // RA: Return address. | 1562 // RA: Return address. |
1569 // S5: Inline cache data object. | 1563 // S5: Inline cache data object. |
1570 // Inline cache data object structure: | 1564 // Inline cache data object structure: |
1571 // 0: function-name | 1565 // 0: function-name |
1572 // 1: N, number of arguments checked. | 1566 // 1: N, number of arguments checked. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1636 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. | 1630 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. |
1637 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); | 1631 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); |
1638 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1632 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
1639 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); | 1633 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); |
1640 __ beq(T0, ZR, &ok); | 1634 __ beq(T0, ZR, &ok); |
1641 __ Stop("Incorrect IC data for unoptimized static call"); | 1635 __ Stop("Incorrect IC data for unoptimized static call"); |
1642 __ Bind(&ok); | 1636 __ Bind(&ok); |
1643 } | 1637 } |
1644 #endif // DEBUG | 1638 #endif // DEBUG |
1645 | 1639 |
1646 if (FLAG_enable_debugger) { | 1640 // Check single stepping. |
1647 // Check single stepping. | 1641 Label not_stepping; |
1648 Label not_stepping; | 1642 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); |
1649 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); | 1643 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
1650 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 1644 __ BranchEqual(T0, 0, ¬_stepping); |
1651 __ BranchEqual(T0, 0, ¬_stepping); | 1645 // Call single step callback in debugger. |
1652 // Call single step callback in debugger. | 1646 __ EnterStubFrame(); |
1653 __ EnterStubFrame(); | 1647 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
1654 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1648 __ sw(S5, Address(SP, 1 * kWordSize)); // Preserve IC data. |
1655 __ sw(S5, Address(SP, 1 * kWordSize)); // Preserve IC data. | 1649 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. |
1656 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. | 1650 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1657 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1651 __ lw(RA, Address(SP, 0 * kWordSize)); |
1658 __ lw(RA, Address(SP, 0 * kWordSize)); | 1652 __ lw(S5, Address(SP, 1 * kWordSize)); |
1659 __ lw(S5, Address(SP, 1 * kWordSize)); | 1653 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
1660 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 1654 __ LeaveStubFrame(); |
1661 __ LeaveStubFrame(); | 1655 __ Bind(¬_stepping); |
1662 __ Bind(¬_stepping); | |
1663 } | |
1664 | 1656 |
1665 // S5: IC data object (preserved). | 1657 // S5: IC data object (preserved). |
1666 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); | 1658 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); |
1667 // T0: ic_data_array with entries: target functions and count. | 1659 // T0: ic_data_array with entries: target functions and count. |
1668 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); | 1660 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); |
1669 // T0: points directly to the first ic data array element. | 1661 // T0: points directly to the first ic data array element. |
1670 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1662 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
1671 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1663 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
1672 | 1664 |
1673 // Increment count for this call. | 1665 // Increment count for this call. |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1779 __ lw(T0, Address(SP, 0 * kWordSize)); | 1771 __ lw(T0, Address(SP, 0 * kWordSize)); |
1780 __ addiu(SP, SP, Immediate(3 * kWordSize)); | 1772 __ addiu(SP, SP, Immediate(3 * kWordSize)); |
1781 __ LeaveStubFrame(); | 1773 __ LeaveStubFrame(); |
1782 __ jr(T0); | 1774 __ jr(T0); |
1783 } | 1775 } |
1784 | 1776 |
1785 | 1777 |
1786 // Called only from unoptimized code. All relevant registers have been saved. | 1778 // Called only from unoptimized code. All relevant registers have been saved. |
1787 // RA: return address. | 1779 // RA: return address. |
1788 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { | 1780 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { |
1789 if (FLAG_enable_debugger) { | 1781 // Check single stepping. |
1790 // Check single stepping. | 1782 Label not_stepping; |
1791 Label not_stepping; | 1783 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); |
1792 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); | 1784 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
1793 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 1785 __ BranchEqual(T0, 0, ¬_stepping); |
1794 __ BranchEqual(T0, 0, ¬_stepping); | 1786 // Call single step callback in debugger. |
1795 // Call single step callback in debugger. | 1787 __ EnterStubFrame(); |
1796 __ EnterStubFrame(); | 1788 __ addiu(SP, SP, Immediate(-1 * kWordSize)); |
1797 __ addiu(SP, SP, Immediate(-1 * kWordSize)); | 1789 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. |
1798 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. | 1790 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1799 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1791 __ lw(RA, Address(SP, 0 * kWordSize)); |
1800 __ lw(RA, Address(SP, 0 * kWordSize)); | 1792 __ addiu(SP, SP, Immediate(1 * kWordSize)); |
1801 __ addiu(SP, SP, Immediate(1 * kWordSize)); | 1793 __ LeaveStubFrame(); |
1802 __ LeaveStubFrame(); | 1794 __ Bind(¬_stepping); |
1803 __ Bind(¬_stepping); | 1795 |
1804 } | |
1805 __ Ret(); | 1796 __ Ret(); |
1806 } | 1797 } |
1807 | 1798 |
1808 | 1799 |
1809 // Used to check class and type arguments. Arguments passed in registers: | 1800 // Used to check class and type arguments. Arguments passed in registers: |
1810 // RA: return address. | 1801 // RA: return address. |
1811 // A0: instance (must be preserved). | 1802 // A0: instance (must be preserved). |
1812 // A1: instantiator type arguments or NULL. | 1803 // A1: instantiator type arguments or NULL. |
1813 // A2: cache array. | 1804 // A2: cache array. |
1814 // Result in V0: null -> not found, otherwise result (true or false). | 1805 // Result in V0: null -> not found, otherwise result (true or false). |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2065 } | 2056 } |
2066 | 2057 |
2067 | 2058 |
2068 // Called only from unoptimized code. All relevant registers have been saved. | 2059 // Called only from unoptimized code. All relevant registers have been saved. |
2069 // RA: return address. | 2060 // RA: return address. |
2070 // SP + 4: left operand. | 2061 // SP + 4: left operand. |
2071 // SP + 0: right operand. | 2062 // SP + 0: right operand. |
2072 // Returns: CMPRES1 is zero if equal, non-zero otherwise. | 2063 // Returns: CMPRES1 is zero if equal, non-zero otherwise. |
2073 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 2064 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
2074 Assembler* assembler) { | 2065 Assembler* assembler) { |
2075 if (FLAG_enable_debugger) { | 2066 // Check single stepping. |
2076 // Check single stepping. | 2067 Label not_stepping; |
2077 Label not_stepping; | 2068 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); |
2078 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); | 2069 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
2079 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 2070 __ BranchEqual(T0, 0, ¬_stepping); |
2080 __ BranchEqual(T0, 0, ¬_stepping); | 2071 // Call single step callback in debugger. |
2081 // Call single step callback in debugger. | 2072 __ EnterStubFrame(); |
2082 __ EnterStubFrame(); | 2073 __ addiu(SP, SP, Immediate(-1 * kWordSize)); |
2083 __ addiu(SP, SP, Immediate(-1 * kWordSize)); | 2074 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. |
2084 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. | 2075 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
2085 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 2076 __ lw(RA, Address(SP, 0 * kWordSize)); |
2086 __ lw(RA, Address(SP, 0 * kWordSize)); | 2077 __ addiu(SP, SP, Immediate(1 * kWordSize)); |
2087 __ addiu(SP, SP, Immediate(1 * kWordSize)); | 2078 __ LeaveStubFrame(); |
2088 __ LeaveStubFrame(); | 2079 __ Bind(¬_stepping); |
2089 __ Bind(¬_stepping); | |
2090 } | |
2091 | 2080 |
2092 const Register temp1 = T2; | 2081 const Register temp1 = T2; |
2093 const Register temp2 = T3; | 2082 const Register temp2 = T3; |
2094 const Register left = T1; | 2083 const Register left = T1; |
2095 const Register right = T0; | 2084 const Register right = T0; |
2096 __ lw(left, Address(SP, 1 * kWordSize)); | 2085 __ lw(left, Address(SP, 1 * kWordSize)); |
2097 __ lw(right, Address(SP, 0 * kWordSize)); | 2086 __ lw(right, Address(SP, 0 * kWordSize)); |
2098 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); | 2087 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); |
2099 __ Ret(); | 2088 __ Ret(); |
2100 } | 2089 } |
(...skipping 11 matching lines...) Expand all Loading... |
2112 const Register right = T0; | 2101 const Register right = T0; |
2113 __ lw(left, Address(SP, 1 * kWordSize)); | 2102 __ lw(left, Address(SP, 1 * kWordSize)); |
2114 __ lw(right, Address(SP, 0 * kWordSize)); | 2103 __ lw(right, Address(SP, 0 * kWordSize)); |
2115 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); | 2104 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); |
2116 __ Ret(); | 2105 __ Ret(); |
2117 } | 2106 } |
2118 | 2107 |
2119 } // namespace dart | 2108 } // namespace dart |
2120 | 2109 |
2121 #endif // defined TARGET_ARCH_MIPS | 2110 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |