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 1385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1396 // - If receiver is Smi -> load Smi class. | 1396 // - If receiver is Smi -> load Smi class. |
1397 // - If receiver is not-Smi -> load receiver's class. | 1397 // - If receiver is not-Smi -> load receiver's class. |
1398 // - Check if 'num_args' (including receiver) match any IC data group. | 1398 // - Check if 'num_args' (including receiver) match any IC data group. |
1399 // - Match found -> jump to target. | 1399 // - Match found -> jump to target. |
1400 // - Match not found -> jump to IC miss. | 1400 // - Match not found -> jump to IC miss. |
1401 void StubCode::GenerateNArgsCheckInlineCacheStub( | 1401 void StubCode::GenerateNArgsCheckInlineCacheStub( |
1402 Assembler* assembler, | 1402 Assembler* assembler, |
1403 intptr_t num_args, | 1403 intptr_t num_args, |
1404 const RuntimeEntry& handle_ic_miss, | 1404 const RuntimeEntry& handle_ic_miss, |
1405 Token::Kind kind, | 1405 Token::Kind kind, |
1406 RangeCollectionMode range_collection_mode, | |
1407 bool optimized) { | 1406 bool optimized) { |
1408 __ Comment("NArgsCheckInlineCacheStub"); | 1407 __ Comment("NArgsCheckInlineCacheStub"); |
1409 ASSERT(num_args > 0); | 1408 ASSERT(num_args > 0); |
1410 #if defined(DEBUG) | 1409 #if defined(DEBUG) |
1411 { Label ok; | 1410 { Label ok; |
1412 // Check that the IC data array has NumArgsTested() == num_args. | 1411 // Check that the IC data array has NumArgsTested() == num_args. |
1413 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. | 1412 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. |
1414 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); | 1413 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); |
1415 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1414 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
1416 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); | 1415 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); |
1417 __ BranchEqual(T0, Immediate(num_args), &ok); | 1416 __ BranchEqual(T0, Immediate(num_args), &ok); |
1418 __ Stop("Incorrect stub for IC data"); | 1417 __ Stop("Incorrect stub for IC data"); |
1419 __ Bind(&ok); | 1418 __ Bind(&ok); |
1420 } | 1419 } |
1421 #endif // DEBUG | 1420 #endif // DEBUG |
1422 | 1421 |
1423 | 1422 |
1424 Label stepping, done_stepping; | 1423 Label stepping, done_stepping; |
1425 if (FLAG_support_debugger && !optimized) { | 1424 if (FLAG_support_debugger && !optimized) { |
1426 __ Comment("Check single stepping"); | 1425 __ Comment("Check single stepping"); |
1427 __ LoadIsolate(T0); | 1426 __ LoadIsolate(T0); |
1428 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 1427 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
1429 __ BranchNotEqual(T0, Immediate(0), &stepping); | 1428 __ BranchNotEqual(T0, Immediate(0), &stepping); |
1430 __ Bind(&done_stepping); | 1429 __ Bind(&done_stepping); |
1431 } | 1430 } |
1432 | 1431 |
1433 __ Comment("Range feedback collection"); | |
1434 Label not_smi_or_overflow; | 1432 Label not_smi_or_overflow; |
1435 if (range_collection_mode == kCollectRanges) { | |
1436 ASSERT((num_args == 1) || (num_args == 2)); | |
1437 if (num_args == 2) { | |
1438 __ lw(T0, Address(SP, 1 * kWordSize)); | |
1439 __ UpdateRangeFeedback(T0, 0, S5, T1, ¬_smi_or_overflow); | |
1440 } | |
1441 | |
1442 __ lw(T0, Address(SP, 0 * kWordSize)); | |
1443 __ UpdateRangeFeedback(T0, num_args - 1, S5, T1, ¬_smi_or_overflow); | |
1444 } | |
1445 if (kind != Token::kILLEGAL) { | 1433 if (kind != Token::kILLEGAL) { |
1446 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); | 1434 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); |
1447 } | 1435 } |
1448 __ Bind(¬_smi_or_overflow); | 1436 __ Bind(¬_smi_or_overflow); |
1449 | 1437 |
1450 __ Comment("Extract ICData initial values and receiver cid"); | 1438 __ Comment("Extract ICData initial values and receiver cid"); |
1451 // Load argument descriptor into S4. | 1439 // Load argument descriptor into S4. |
1452 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); | 1440 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); |
1453 // Preserve return address, since RA is needed for subroutine call. | 1441 // Preserve return address, since RA is needed for subroutine call. |
1454 __ mov(T2, RA); | 1442 __ mov(T2, RA); |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1582 __ movz(T4, T7, CMPRES1); | 1570 __ movz(T4, T7, CMPRES1); |
1583 __ sw(T4, Address(T0, count_offset)); | 1571 __ sw(T4, Address(T0, count_offset)); |
1584 } | 1572 } |
1585 | 1573 |
1586 __ Comment("Call target"); | 1574 __ Comment("Call target"); |
1587 __ Bind(&call_target_function); | 1575 __ Bind(&call_target_function); |
1588 // T0 <- T3: Target function. | 1576 // T0 <- T3: Target function. |
1589 __ mov(T0, T3); | 1577 __ mov(T0, T3); |
1590 Label is_compiled; | 1578 Label is_compiled; |
1591 __ lw(T4, FieldAddress(T0, Function::entry_point_offset())); | 1579 __ lw(T4, FieldAddress(T0, Function::entry_point_offset())); |
1592 if (range_collection_mode == kCollectRanges) { | 1580 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset())); |
1593 const intptr_t frame_size = num_args + 2; | 1581 __ jr(T4); |
1594 __ lw(T3, Address(SP, 0 * kWordSize)); | |
1595 if (num_args == 2) { | |
1596 __ lw(T1, Address(SP, 1 * kWordSize)); | |
1597 } | |
1598 __ EnterStubFrame(); | |
1599 __ addiu(SP, SP, Immediate(- frame_size * kWordSize)); | |
1600 __ sw(RA, Address(SP, (frame_size - 1) * kWordSize)); // Return address. | |
1601 __ sw(S5, Address(SP, (frame_size - 2) * kWordSize)); // Preserve IC data. | |
1602 __ sw(T3, Address(SP, 0 * kWordSize)); | |
1603 if (num_args == 2) { | |
1604 __ sw(T1, Address(SP, 1 * kWordSize)); | |
1605 } | |
1606 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset())); | |
1607 __ jalr(T4); | |
1608 __ lw(S5, Address(SP, (frame_size - 2) * kWordSize)); | |
1609 __ lw(RA, Address(SP, (frame_size - 1) * kWordSize)); | |
1610 Label done; | |
1611 __ UpdateRangeFeedback(V0, 2, S5, T1, &done); | |
1612 __ Bind(&done); | |
1613 __ addiu(SP, SP, Immediate(frame_size * kWordSize)); | |
1614 __ RestoreCodePointer(); | |
1615 __ LeaveStubFrame(); | |
1616 __ Ret(); | |
1617 } else { | |
1618 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset())); | |
1619 __ jr(T4); | |
1620 } | |
1621 | 1582 |
1622 // Call single step callback in debugger. | 1583 // Call single step callback in debugger. |
1623 if (FLAG_support_debugger && !optimized) { | 1584 if (FLAG_support_debugger && !optimized) { |
1624 __ Bind(&stepping); | 1585 __ Bind(&stepping); |
1625 __ EnterStubFrame(); | 1586 __ EnterStubFrame(); |
1626 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1587 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
1627 __ sw(S5, Address(SP, 1 * kWordSize)); // Preserve IC data. | 1588 __ sw(S5, Address(SP, 1 * kWordSize)); // Preserve IC data. |
1628 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. | 1589 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. |
1629 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1590 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1630 __ lw(RA, Address(SP, 0 * kWordSize)); | 1591 __ lw(RA, Address(SP, 0 * kWordSize)); |
(...skipping 12 matching lines...) Expand all Loading... |
1643 // S5: Inline cache data object. | 1604 // S5: Inline cache data object. |
1644 // Inline cache data object structure: | 1605 // Inline cache data object structure: |
1645 // 0: function-name | 1606 // 0: function-name |
1646 // 1: N, number of arguments checked. | 1607 // 1: N, number of arguments checked. |
1647 // 2 .. (length - 1): group of checks, each check containing: | 1608 // 2 .. (length - 1): group of checks, each check containing: |
1648 // - N classes. | 1609 // - N classes. |
1649 // - 1 target function. | 1610 // - 1 target function. |
1650 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { | 1611 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { |
1651 GenerateUsageCounterIncrement(assembler, T0); | 1612 GenerateUsageCounterIncrement(assembler, T0); |
1652 GenerateNArgsCheckInlineCacheStub(assembler, 1, | 1613 GenerateNArgsCheckInlineCacheStub(assembler, 1, |
1653 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL, | 1614 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); |
1654 kIgnoreRanges); | |
1655 } | 1615 } |
1656 | 1616 |
1657 | 1617 |
1658 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { | 1618 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { |
1659 GenerateUsageCounterIncrement(assembler, T0); | 1619 GenerateUsageCounterIncrement(assembler, T0); |
1660 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1620 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1661 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL, | 1621 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL); |
1662 kIgnoreRanges); | |
1663 } | 1622 } |
1664 | 1623 |
1665 | 1624 |
1666 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) { | 1625 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) { |
1667 GenerateUsageCounterIncrement(assembler, T0); | 1626 GenerateUsageCounterIncrement(assembler, T0); |
1668 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1627 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1669 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD, | 1628 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD); |
1670 kCollectRanges); | |
1671 } | 1629 } |
1672 | 1630 |
1673 | 1631 |
1674 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) { | 1632 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) { |
1675 GenerateUsageCounterIncrement(assembler, T0); | 1633 GenerateUsageCounterIncrement(assembler, T0); |
1676 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1634 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1677 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB, | 1635 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB); |
1678 kCollectRanges); | |
1679 } | 1636 } |
1680 | 1637 |
1681 | 1638 |
1682 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) { | 1639 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) { |
1683 GenerateUsageCounterIncrement(assembler, T0); | 1640 GenerateUsageCounterIncrement(assembler, T0); |
1684 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1641 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1685 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ, | 1642 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ); |
1686 kIgnoreRanges); | |
1687 } | 1643 } |
1688 | 1644 |
1689 | 1645 |
1690 void StubCode::GenerateUnaryRangeCollectingInlineCacheStub( | 1646 void StubCode::GenerateUnaryRangeCollectingInlineCacheStub( |
1691 Assembler* assembler) { | 1647 Assembler* assembler) { |
1692 GenerateUsageCounterIncrement(assembler, T0); | 1648 GenerateUsageCounterIncrement(assembler, T0); |
1693 GenerateNArgsCheckInlineCacheStub(assembler, 1, | 1649 GenerateNArgsCheckInlineCacheStub(assembler, 1, |
1694 kInlineCacheMissHandlerOneArgRuntimeEntry, | 1650 kInlineCacheMissHandlerOneArgRuntimeEntry, |
1695 Token::kILLEGAL, | 1651 Token::kILLEGAL); |
1696 kCollectRanges); | |
1697 } | 1652 } |
1698 | 1653 |
1699 | 1654 |
1700 void StubCode::GenerateBinaryRangeCollectingInlineCacheStub( | 1655 void StubCode::GenerateBinaryRangeCollectingInlineCacheStub( |
1701 Assembler* assembler) { | 1656 Assembler* assembler) { |
1702 GenerateUsageCounterIncrement(assembler, T0); | 1657 GenerateUsageCounterIncrement(assembler, T0); |
1703 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1658 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1704 kInlineCacheMissHandlerTwoArgsRuntimeEntry, | 1659 kInlineCacheMissHandlerTwoArgsRuntimeEntry, |
1705 Token::kILLEGAL, | 1660 Token::kILLEGAL); |
1706 kCollectRanges); | |
1707 } | 1661 } |
1708 | 1662 |
1709 | 1663 |
1710 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( | 1664 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( |
1711 Assembler* assembler) { | 1665 Assembler* assembler) { |
1712 GenerateOptimizedUsageCounterIncrement(assembler); | 1666 GenerateOptimizedUsageCounterIncrement(assembler); |
1713 GenerateNArgsCheckInlineCacheStub(assembler, 1, | 1667 GenerateNArgsCheckInlineCacheStub(assembler, 1, |
1714 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL, | 1668 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL, |
1715 kIgnoreRanges, true /* optimized */); | 1669 true /* optimized */); |
1716 } | 1670 } |
1717 | 1671 |
1718 | 1672 |
1719 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( | 1673 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( |
1720 Assembler* assembler) { | 1674 Assembler* assembler) { |
1721 GenerateOptimizedUsageCounterIncrement(assembler); | 1675 GenerateOptimizedUsageCounterIncrement(assembler); |
1722 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1676 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1723 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL, | 1677 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL, |
1724 kIgnoreRanges, true /* optimized */); | 1678 true /* optimized */); |
1725 } | 1679 } |
1726 | 1680 |
1727 | 1681 |
1728 // Intermediary stub between a static call and its target. ICData contains | 1682 // Intermediary stub between a static call and its target. ICData contains |
1729 // the target function and the call count. | 1683 // the target function and the call count. |
1730 // S5: ICData | 1684 // S5: ICData |
1731 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1685 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
1732 GenerateUsageCounterIncrement(assembler, T0); | 1686 GenerateUsageCounterIncrement(assembler, T0); |
1733 __ Comment("UnoptimizedStaticCallStub"); | 1687 __ Comment("UnoptimizedStaticCallStub"); |
1734 #if defined(DEBUG) | 1688 #if defined(DEBUG) |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1794 __ RestoreCodePointer(); | 1748 __ RestoreCodePointer(); |
1795 __ LeaveStubFrame(); | 1749 __ LeaveStubFrame(); |
1796 __ b(&done_stepping); | 1750 __ b(&done_stepping); |
1797 } | 1751 } |
1798 } | 1752 } |
1799 | 1753 |
1800 | 1754 |
1801 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { | 1755 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { |
1802 GenerateUsageCounterIncrement(assembler, T0); | 1756 GenerateUsageCounterIncrement(assembler, T0); |
1803 GenerateNArgsCheckInlineCacheStub( | 1757 GenerateNArgsCheckInlineCacheStub( |
1804 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL, | 1758 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); |
1805 kIgnoreRanges); | |
1806 } | 1759 } |
1807 | 1760 |
1808 | 1761 |
1809 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1762 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
1810 GenerateUsageCounterIncrement(assembler, T0); | 1763 GenerateUsageCounterIncrement(assembler, T0); |
1811 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1764 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1812 kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL, | 1765 kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL); |
1813 kIgnoreRanges); | |
1814 } | 1766 } |
1815 | 1767 |
1816 | 1768 |
1817 // Stub for compiling a function and jumping to the compiled code. | 1769 // Stub for compiling a function and jumping to the compiled code. |
1818 // S5: IC-Data (for methods). | 1770 // S5: IC-Data (for methods). |
1819 // S4: Arguments descriptor. | 1771 // S4: Arguments descriptor. |
1820 // T0: Function. | 1772 // T0: Function. |
1821 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { | 1773 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { |
1822 __ EnterStubFrame(); | 1774 __ EnterStubFrame(); |
1823 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | 1775 __ addiu(SP, SP, Immediate(-3 * kWordSize)); |
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2339 } | 2291 } |
2340 | 2292 |
2341 | 2293 |
2342 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { | 2294 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { |
2343 __ break_(0); | 2295 __ break_(0); |
2344 } | 2296 } |
2345 | 2297 |
2346 } // namespace dart | 2298 } // namespace dart |
2347 | 2299 |
2348 #endif // defined TARGET_ARCH_MIPS | 2300 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |