| 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 |