| 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 1524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1535 // Generate inline cache check for 'num_args'. | 1535 // Generate inline cache check for 'num_args'. |
| 1536 // RA: return address | 1536 // RA: return address |
| 1537 // S5: Inline cache data object. | 1537 // S5: Inline cache data object. |
| 1538 // Control flow: | 1538 // Control flow: |
| 1539 // - If receiver is null -> jump to IC miss. | 1539 // - If receiver is null -> jump to IC miss. |
| 1540 // - If receiver is Smi -> load Smi class. | 1540 // - If receiver is Smi -> load Smi class. |
| 1541 // - If receiver is not-Smi -> load receiver's class. | 1541 // - If receiver is not-Smi -> load receiver's class. |
| 1542 // - Check if 'num_args' (including receiver) match any IC data group. | 1542 // - Check if 'num_args' (including receiver) match any IC data group. |
| 1543 // - Match found -> jump to target. | 1543 // - Match found -> jump to target. |
| 1544 // - Match not found -> jump to IC miss. | 1544 // - Match not found -> jump to IC miss. |
| 1545 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, | 1545 void StubCode::GenerateNArgsCheckInlineCacheStub( |
| 1546 intptr_t num_args) { | 1546 Assembler* assembler, |
| 1547 intptr_t num_args, |
| 1548 const RuntimeEntry& handle_ic_miss) { |
| 1547 __ TraceSimMsg("NArgsCheckInlineCacheStub"); | 1549 __ TraceSimMsg("NArgsCheckInlineCacheStub"); |
| 1548 ASSERT(num_args > 0); | 1550 ASSERT(num_args > 0); |
| 1549 #if defined(DEBUG) | 1551 #if defined(DEBUG) |
| 1550 { Label ok; | 1552 { Label ok; |
| 1551 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. | 1553 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. |
| 1552 // 'num_args_tested' is stored as an untagged int. | 1554 // 'num_args_tested' is stored as an untagged int. |
| 1553 __ lw(T0, FieldAddress(S5, ICData::num_args_tested_offset())); | 1555 __ lw(T0, FieldAddress(S5, ICData::num_args_tested_offset())); |
| 1554 __ BranchEqual(T0, num_args, &ok); | 1556 __ BranchEqual(T0, num_args, &ok); |
| 1555 __ Stop("Incorrect stub for IC data"); | 1557 __ Stop("Incorrect stub for IC data"); |
| 1556 __ Bind(&ok); | 1558 __ Bind(&ok); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1661 __ sw(S4, Address(SP, (num_slots - 2) * kWordSize)); | 1663 __ sw(S4, Address(SP, (num_slots - 2) * kWordSize)); |
| 1662 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null())); | 1664 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null())); |
| 1663 __ sw(TMP, Address(SP, (num_slots - 3) * kWordSize)); | 1665 __ sw(TMP, Address(SP, (num_slots - 3) * kWordSize)); |
| 1664 // Push call arguments. | 1666 // Push call arguments. |
| 1665 for (intptr_t i = 0; i < num_args; i++) { | 1667 for (intptr_t i = 0; i < num_args; i++) { |
| 1666 __ lw(TMP1, Address(T1, -i * kWordSize)); | 1668 __ lw(TMP1, Address(T1, -i * kWordSize)); |
| 1667 __ sw(TMP1, Address(SP, (num_slots - i - 4) * kWordSize)); | 1669 __ sw(TMP1, Address(SP, (num_slots - i - 4) * kWordSize)); |
| 1668 } | 1670 } |
| 1669 // Pass IC data object. | 1671 // Pass IC data object. |
| 1670 __ sw(S5, Address(SP, (num_slots - num_args - 4) * kWordSize)); | 1672 __ sw(S5, Address(SP, (num_slots - num_args - 4) * kWordSize)); |
| 1671 | 1673 __ CallRuntime(handle_ic_miss); |
| 1672 if (num_args == 1) { | |
| 1673 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry); | |
| 1674 } else if (num_args == 2) { | |
| 1675 __ CallRuntime(kInlineCacheMissHandlerTwoArgsRuntimeEntry); | |
| 1676 } else if (num_args == 3) { | |
| 1677 __ CallRuntime(kInlineCacheMissHandlerThreeArgsRuntimeEntry); | |
| 1678 } else { | |
| 1679 UNIMPLEMENTED(); | |
| 1680 } | |
| 1681 __ TraceSimMsg("NArgsCheckInlineCacheStub return"); | 1674 __ TraceSimMsg("NArgsCheckInlineCacheStub return"); |
| 1682 // Pop returned code object into T3 (null if not found). | 1675 // Pop returned code object into T3 (null if not found). |
| 1683 // Restore arguments descriptor array and IC data array. | 1676 // Restore arguments descriptor array and IC data array. |
| 1684 __ lw(T3, Address(SP, (num_slots - 3) * kWordSize)); | 1677 __ lw(T3, Address(SP, (num_slots - 3) * kWordSize)); |
| 1685 __ lw(S4, Address(SP, (num_slots - 2) * kWordSize)); | 1678 __ lw(S4, Address(SP, (num_slots - 2) * kWordSize)); |
| 1686 __ lw(S5, Address(SP, (num_slots - 1) * kWordSize)); | 1679 __ lw(S5, Address(SP, (num_slots - 1) * kWordSize)); |
| 1687 // Remove the call arguments pushed earlier, including the IC data object | 1680 // Remove the call arguments pushed earlier, including the IC data object |
| 1688 // and the arguments descriptor array. | 1681 // and the arguments descriptor array. |
| 1689 __ addiu(SP, SP, Immediate(num_slots * kWordSize)); | 1682 __ addiu(SP, SP, Immediate(num_slots * kWordSize)); |
| 1690 __ LeaveStubFrame(); | 1683 __ LeaveStubFrame(); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1742 // RA: Return address. | 1735 // RA: Return address. |
| 1743 // S5: Inline cache data object. | 1736 // S5: Inline cache data object. |
| 1744 // Inline cache data object structure: | 1737 // Inline cache data object structure: |
| 1745 // 0: function-name | 1738 // 0: function-name |
| 1746 // 1: N, number of arguments checked. | 1739 // 1: N, number of arguments checked. |
| 1747 // 2 .. (length - 1): group of checks, each check containing: | 1740 // 2 .. (length - 1): group of checks, each check containing: |
| 1748 // - N classes. | 1741 // - N classes. |
| 1749 // - 1 target function. | 1742 // - 1 target function. |
| 1750 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { | 1743 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { |
| 1751 GenerateUsageCounterIncrement(assembler, T0); | 1744 GenerateUsageCounterIncrement(assembler, T0); |
| 1752 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1745 GenerateNArgsCheckInlineCacheStub( |
| 1746 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry); |
| 1753 } | 1747 } |
| 1754 | 1748 |
| 1755 | 1749 |
| 1756 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { | 1750 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { |
| 1757 GenerateUsageCounterIncrement(assembler, T0); | 1751 GenerateUsageCounterIncrement(assembler, T0); |
| 1758 GenerateNArgsCheckInlineCacheStub(assembler, 2); | 1752 GenerateNArgsCheckInlineCacheStub( |
| 1753 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry); |
| 1759 } | 1754 } |
| 1760 | 1755 |
| 1761 | 1756 |
| 1762 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { | 1757 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { |
| 1763 GenerateUsageCounterIncrement(assembler, T0); | 1758 GenerateUsageCounterIncrement(assembler, T0); |
| 1764 GenerateNArgsCheckInlineCacheStub(assembler, 3); | 1759 GenerateNArgsCheckInlineCacheStub( |
| 1760 assembler, 3, kInlineCacheMissHandlerThreeArgsRuntimeEntry); |
| 1765 } | 1761 } |
| 1766 | 1762 |
| 1767 | 1763 |
| 1768 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( | 1764 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( |
| 1769 Assembler* assembler) { | 1765 Assembler* assembler) { |
| 1770 GenerateOptimizedUsageCounterIncrement(assembler); | 1766 GenerateOptimizedUsageCounterIncrement(assembler); |
| 1771 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1767 GenerateNArgsCheckInlineCacheStub( |
| 1768 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry); |
| 1772 } | 1769 } |
| 1773 | 1770 |
| 1774 | 1771 |
| 1775 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( | 1772 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( |
| 1776 Assembler* assembler) { | 1773 Assembler* assembler) { |
| 1777 GenerateOptimizedUsageCounterIncrement(assembler); | 1774 GenerateOptimizedUsageCounterIncrement(assembler); |
| 1778 GenerateNArgsCheckInlineCacheStub(assembler, 2); | 1775 GenerateNArgsCheckInlineCacheStub( |
| 1776 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry); |
| 1779 } | 1777 } |
| 1780 | 1778 |
| 1781 | 1779 |
| 1782 void StubCode::GenerateThreeArgsOptimizedCheckInlineCacheStub( | 1780 void StubCode::GenerateThreeArgsOptimizedCheckInlineCacheStub( |
| 1783 Assembler* assembler) { | 1781 Assembler* assembler) { |
| 1784 GenerateOptimizedUsageCounterIncrement(assembler); | 1782 GenerateOptimizedUsageCounterIncrement(assembler); |
| 1785 GenerateNArgsCheckInlineCacheStub(assembler, 3); | 1783 GenerateNArgsCheckInlineCacheStub( |
| 1784 assembler, 3, kInlineCacheMissHandlerThreeArgsRuntimeEntry); |
| 1786 } | 1785 } |
| 1787 | 1786 |
| 1788 | 1787 |
| 1789 void StubCode::GenerateClosureCallInlineCacheStub(Assembler* assembler) { | 1788 void StubCode::GenerateClosureCallInlineCacheStub(Assembler* assembler) { |
| 1790 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1789 GenerateNArgsCheckInlineCacheStub( |
| 1790 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry); |
| 1791 } | 1791 } |
| 1792 | 1792 |
| 1793 | 1793 |
| 1794 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { | 1794 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { |
| 1795 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1795 GenerateNArgsCheckInlineCacheStub( |
| 1796 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry); |
| 1796 } | 1797 } |
| 1797 | 1798 |
| 1798 | 1799 |
| 1799 // Intermediary stub between a static call and its target. ICData contains | 1800 // Intermediary stub between a static call and its target. ICData contains |
| 1800 // the target function and the call count. | 1801 // the target function and the call count. |
| 1801 // S5: ICData | 1802 // S5: ICData |
| 1802 void StubCode::GenerateUnoptimizedStaticCallStub(Assembler* assembler) { | 1803 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1803 GenerateUsageCounterIncrement(assembler, T0); | 1804 GenerateUsageCounterIncrement(assembler, T0); |
| 1804 __ TraceSimMsg("UnoptimizedStaticCallStub"); | 1805 __ TraceSimMsg("UnoptimizedStaticCallStub"); |
| 1805 #if defined(DEBUG) | 1806 #if defined(DEBUG) |
| 1806 { Label ok; | 1807 { Label ok; |
| 1807 // Check that the IC data array has NumberOfArgumentsChecked() == 0. | 1808 // Check that the IC data array has NumberOfArgumentsChecked() == 0. |
| 1808 // 'num_args_tested' is stored as an untagged int. | 1809 // 'num_args_tested' is stored as an untagged int. |
| 1809 __ lw(T0, FieldAddress(S5, ICData::num_args_tested_offset())); | 1810 __ lw(T0, FieldAddress(S5, ICData::num_args_tested_offset())); |
| 1810 __ beq(T0, ZR, &ok); | 1811 __ beq(T0, ZR, &ok); |
| 1811 __ Stop("Incorrect IC data for unoptimized static call"); | 1812 __ Stop("Incorrect IC data for unoptimized static call"); |
| 1812 __ Bind(&ok); | 1813 __ Bind(&ok); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1875 // T4: target code. | 1876 // T4: target code. |
| 1876 __ lw(T3, FieldAddress(T4, Code::instructions_offset())); | 1877 __ lw(T3, FieldAddress(T4, Code::instructions_offset())); |
| 1877 __ AddImmediate(T3, Instructions::HeaderSize() - kHeapObjectTag); | 1878 __ AddImmediate(T3, Instructions::HeaderSize() - kHeapObjectTag); |
| 1878 __ jr(T3); | 1879 __ jr(T3); |
| 1879 // Load arguments descriptor into S4. | 1880 // Load arguments descriptor into S4. |
| 1880 __ delay_slot()-> | 1881 __ delay_slot()-> |
| 1881 lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); | 1882 lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); |
| 1882 } | 1883 } |
| 1883 | 1884 |
| 1884 | 1885 |
| 1886 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1887 GenerateUsageCounterIncrement(assembler, T0); |
| 1888 GenerateNArgsCheckInlineCacheStub( |
| 1889 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); |
| 1890 } |
| 1891 |
| 1892 |
| 1885 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { | 1893 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { |
| 1886 __ Unimplemented("BreakpointRuntime stub"); | 1894 __ Unimplemented("BreakpointRuntime stub"); |
| 1887 } | 1895 } |
| 1888 | 1896 |
| 1889 | 1897 |
| 1890 // RA: return address (Dart code). | 1898 // RA: return address (Dart code). |
| 1891 // S5: IC data (unoptimized static call). | 1899 // S5: IC data (unoptimized static call). |
| 1892 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { | 1900 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { |
| 1893 __ TraceSimMsg("BreakpointStaticStub"); | 1901 __ TraceSimMsg("BreakpointStaticStub"); |
| 1894 // Create a stub frame as we are pushing some objects on the stack before | 1902 // Create a stub frame as we are pushing some objects on the stack before |
| (...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2372 __ lw(left, Address(SP, 1 * kWordSize)); | 2380 __ lw(left, Address(SP, 1 * kWordSize)); |
| 2373 __ lw(temp2, Address(SP, 2 * kWordSize)); | 2381 __ lw(temp2, Address(SP, 2 * kWordSize)); |
| 2374 __ lw(temp1, Address(SP, 3 * kWordSize)); | 2382 __ lw(temp1, Address(SP, 3 * kWordSize)); |
| 2375 __ Ret(); | 2383 __ Ret(); |
| 2376 __ delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); | 2384 __ delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); |
| 2377 } | 2385 } |
| 2378 | 2386 |
| 2379 } // namespace dart | 2387 } // namespace dart |
| 2380 | 2388 |
| 2381 #endif // defined TARGET_ARCH_MIPS | 2389 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |