| 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 1620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1631 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); | 1631 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); |
| 1632 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1632 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1633 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); | 1633 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); |
| 1634 __ beq(T0, ZR, &ok); | 1634 __ beq(T0, ZR, &ok); |
| 1635 __ Stop("Incorrect IC data for unoptimized static call"); | 1635 __ Stop("Incorrect IC data for unoptimized static call"); |
| 1636 __ Bind(&ok); | 1636 __ Bind(&ok); |
| 1637 } | 1637 } |
| 1638 #endif // DEBUG | 1638 #endif // DEBUG |
| 1639 | 1639 |
| 1640 // Check single stepping. | 1640 // Check single stepping. |
| 1641 Label not_stepping; | 1641 Label stepping, done_stepping; |
| 1642 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); | 1642 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); |
| 1643 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 1643 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
| 1644 __ BranchEqual(T0, 0, ¬_stepping); | 1644 __ BranchNotEqual(T0, 0, &stepping); |
| 1645 // Call single step callback in debugger. | 1645 __ Bind(&done_stepping); |
| 1646 __ EnterStubFrame(); | |
| 1647 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | |
| 1648 __ sw(S5, Address(SP, 1 * kWordSize)); // Preserve IC data. | |
| 1649 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. | |
| 1650 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | |
| 1651 __ lw(RA, Address(SP, 0 * kWordSize)); | |
| 1652 __ lw(S5, Address(SP, 1 * kWordSize)); | |
| 1653 __ addiu(SP, SP, Immediate(2 * kWordSize)); | |
| 1654 __ LeaveStubFrame(); | |
| 1655 __ Bind(¬_stepping); | |
| 1656 | 1646 |
| 1657 // S5: IC data object (preserved). | 1647 // S5: IC data object (preserved). |
| 1658 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); | 1648 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); |
| 1659 // T0: ic_data_array with entries: target functions and count. | 1649 // T0: ic_data_array with entries: target functions and count. |
| 1660 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); | 1650 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); |
| 1661 // T0: points directly to the first ic data array element. | 1651 // T0: points directly to the first ic data array element. |
| 1662 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1652 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
| 1663 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1653 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
| 1664 | 1654 |
| 1665 // Increment count for this call. | 1655 // Increment count for this call. |
| 1666 Label increment_done; | |
| 1667 __ lw(T4, Address(T0, count_offset)); | 1656 __ lw(T4, Address(T0, count_offset)); |
| 1668 __ AddImmediateDetectOverflow(T4, T4, Smi::RawValue(1), T5, T6); | 1657 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6); |
| 1669 __ bgez(T5, &increment_done); // No overflow. | 1658 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow. |
| 1670 __ delay_slot()->sw(T4, Address(T0, count_offset)); | 1659 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue)); |
| 1671 | 1660 __ movz(T4, T7, CMPRES1); |
| 1672 __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue)); | 1661 __ sw(T4, Address(T0, count_offset)); |
| 1673 __ sw(T1, Address(T0, count_offset)); | |
| 1674 | |
| 1675 __ Bind(&increment_done); | |
| 1676 | 1662 |
| 1677 // Load arguments descriptor into S4. | 1663 // Load arguments descriptor into S4. |
| 1678 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); | 1664 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); |
| 1679 | 1665 |
| 1680 // Get function and call it, if possible. | 1666 // Get function and call it, if possible. |
| 1681 __ lw(T0, Address(T0, target_offset)); | 1667 __ lw(T0, Address(T0, target_offset)); |
| 1682 __ lw(T4, FieldAddress(T0, Function::instructions_offset())); | 1668 __ lw(T4, FieldAddress(T0, Function::instructions_offset())); |
| 1683 | 1669 |
| 1684 // T4: target instructions. | 1670 // T4: target instructions. |
| 1685 __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag); | 1671 __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag); |
| 1686 __ jr(T4); | 1672 __ jr(T4); |
| 1673 |
| 1674 // Call single step callback in debugger. |
| 1675 __ Bind(&stepping); |
| 1676 __ EnterStubFrame(); |
| 1677 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
| 1678 __ sw(S5, Address(SP, 1 * kWordSize)); // Preserve IC data. |
| 1679 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. |
| 1680 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1681 __ lw(RA, Address(SP, 0 * kWordSize)); |
| 1682 __ lw(S5, Address(SP, 1 * kWordSize)); |
| 1683 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
| 1684 __ LeaveStubFrame(); |
| 1685 __ b(&done_stepping); |
| 1687 } | 1686 } |
| 1688 | 1687 |
| 1689 | 1688 |
| 1690 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1689 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1691 GenerateUsageCounterIncrement(assembler, T0); | 1690 GenerateUsageCounterIncrement(assembler, T0); |
| 1692 GenerateNArgsCheckInlineCacheStub( | 1691 GenerateNArgsCheckInlineCacheStub( |
| 1693 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); | 1692 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); |
| 1694 } | 1693 } |
| 1695 | 1694 |
| 1696 | 1695 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1772 __ addiu(SP, SP, Immediate(3 * kWordSize)); | 1771 __ addiu(SP, SP, Immediate(3 * kWordSize)); |
| 1773 __ LeaveStubFrame(); | 1772 __ LeaveStubFrame(); |
| 1774 __ jr(T0); | 1773 __ jr(T0); |
| 1775 } | 1774 } |
| 1776 | 1775 |
| 1777 | 1776 |
| 1778 // Called only from unoptimized code. All relevant registers have been saved. | 1777 // Called only from unoptimized code. All relevant registers have been saved. |
| 1779 // RA: return address. | 1778 // RA: return address. |
| 1780 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { | 1779 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { |
| 1781 // Check single stepping. | 1780 // Check single stepping. |
| 1782 Label not_stepping; | 1781 Label stepping, done_stepping; |
| 1783 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); | 1782 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); |
| 1784 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 1783 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
| 1785 __ BranchEqual(T0, 0, ¬_stepping); | 1784 __ BranchNotEqual(T0, 0, &stepping); |
| 1785 __ Bind(&done_stepping); |
| 1786 |
| 1787 __ Ret(); |
| 1788 |
| 1786 // Call single step callback in debugger. | 1789 // Call single step callback in debugger. |
| 1790 __ Bind(&stepping); |
| 1787 __ EnterStubFrame(); | 1791 __ EnterStubFrame(); |
| 1788 __ addiu(SP, SP, Immediate(-1 * kWordSize)); | 1792 __ addiu(SP, SP, Immediate(-1 * kWordSize)); |
| 1789 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. | 1793 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. |
| 1790 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1794 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1791 __ lw(RA, Address(SP, 0 * kWordSize)); | 1795 __ lw(RA, Address(SP, 0 * kWordSize)); |
| 1792 __ addiu(SP, SP, Immediate(1 * kWordSize)); | 1796 __ addiu(SP, SP, Immediate(1 * kWordSize)); |
| 1793 __ LeaveStubFrame(); | 1797 __ LeaveStubFrame(); |
| 1794 __ Bind(¬_stepping); | 1798 __ b(&done_stepping); |
| 1795 | |
| 1796 __ Ret(); | |
| 1797 } | 1799 } |
| 1798 | 1800 |
| 1799 | 1801 |
| 1800 // Used to check class and type arguments. Arguments passed in registers: | 1802 // Used to check class and type arguments. Arguments passed in registers: |
| 1801 // RA: return address. | 1803 // RA: return address. |
| 1802 // A0: instance (must be preserved). | 1804 // A0: instance (must be preserved). |
| 1803 // A1: instantiator type arguments or NULL. | 1805 // A1: instantiator type arguments or NULL. |
| 1804 // A2: cache array. | 1806 // A2: cache array. |
| 1805 // Result in V0: null -> not found, otherwise result (true or false). | 1807 // Result in V0: null -> not found, otherwise result (true or false). |
| 1806 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 1808 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2057 | 2059 |
| 2058 | 2060 |
| 2059 // Called only from unoptimized code. All relevant registers have been saved. | 2061 // Called only from unoptimized code. All relevant registers have been saved. |
| 2060 // RA: return address. | 2062 // RA: return address. |
| 2061 // SP + 4: left operand. | 2063 // SP + 4: left operand. |
| 2062 // SP + 0: right operand. | 2064 // SP + 0: right operand. |
| 2063 // Returns: CMPRES1 is zero if equal, non-zero otherwise. | 2065 // Returns: CMPRES1 is zero if equal, non-zero otherwise. |
| 2064 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 2066 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
| 2065 Assembler* assembler) { | 2067 Assembler* assembler) { |
| 2066 // Check single stepping. | 2068 // Check single stepping. |
| 2067 Label not_stepping; | 2069 Label stepping, done_stepping; |
| 2068 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); | 2070 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); |
| 2069 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 2071 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
| 2070 __ BranchEqual(T0, 0, ¬_stepping); | 2072 __ BranchNotEqual(T0, 0, &stepping); |
| 2071 // Call single step callback in debugger. | 2073 __ Bind(&done_stepping); |
| 2072 __ EnterStubFrame(); | |
| 2073 __ addiu(SP, SP, Immediate(-1 * kWordSize)); | |
| 2074 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. | |
| 2075 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | |
| 2076 __ lw(RA, Address(SP, 0 * kWordSize)); | |
| 2077 __ addiu(SP, SP, Immediate(1 * kWordSize)); | |
| 2078 __ LeaveStubFrame(); | |
| 2079 __ Bind(¬_stepping); | |
| 2080 | 2074 |
| 2081 const Register temp1 = T2; | 2075 const Register temp1 = T2; |
| 2082 const Register temp2 = T3; | 2076 const Register temp2 = T3; |
| 2083 const Register left = T1; | 2077 const Register left = T1; |
| 2084 const Register right = T0; | 2078 const Register right = T0; |
| 2085 __ lw(left, Address(SP, 1 * kWordSize)); | 2079 __ lw(left, Address(SP, 1 * kWordSize)); |
| 2086 __ lw(right, Address(SP, 0 * kWordSize)); | 2080 __ lw(right, Address(SP, 0 * kWordSize)); |
| 2087 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); | 2081 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); |
| 2088 __ Ret(); | 2082 __ Ret(); |
| 2083 |
| 2084 // Call single step callback in debugger. |
| 2085 __ Bind(&stepping); |
| 2086 __ EnterStubFrame(); |
| 2087 __ addiu(SP, SP, Immediate(-1 * kWordSize)); |
| 2088 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. |
| 2089 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 2090 __ lw(RA, Address(SP, 0 * kWordSize)); |
| 2091 __ addiu(SP, SP, Immediate(1 * kWordSize)); |
| 2092 __ LeaveStubFrame(); |
| 2093 __ b(&done_stepping); |
| 2089 } | 2094 } |
| 2090 | 2095 |
| 2091 | 2096 |
| 2092 // Called from optimized code only. | 2097 // Called from optimized code only. |
| 2093 // SP + 4: left operand. | 2098 // SP + 4: left operand. |
| 2094 // SP + 0: right operand. | 2099 // SP + 0: right operand. |
| 2095 // Returns: CMPRES1 is zero if equal, non-zero otherwise. | 2100 // Returns: CMPRES1 is zero if equal, non-zero otherwise. |
| 2096 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( | 2101 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( |
| 2097 Assembler* assembler) { | 2102 Assembler* assembler) { |
| 2098 const Register temp1 = T2; | 2103 const Register temp1 = T2; |
| 2099 const Register temp2 = T3; | 2104 const Register temp2 = T3; |
| 2100 const Register left = T1; | 2105 const Register left = T1; |
| 2101 const Register right = T0; | 2106 const Register right = T0; |
| 2102 __ lw(left, Address(SP, 1 * kWordSize)); | 2107 __ lw(left, Address(SP, 1 * kWordSize)); |
| 2103 __ lw(right, Address(SP, 0 * kWordSize)); | 2108 __ lw(right, Address(SP, 0 * kWordSize)); |
| 2104 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); | 2109 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); |
| 2105 __ Ret(); | 2110 __ Ret(); |
| 2106 } | 2111 } |
| 2107 | 2112 |
| 2108 } // namespace dart | 2113 } // namespace dart |
| 2109 | 2114 |
| 2110 #endif // defined TARGET_ARCH_MIPS | 2115 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |