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" // Needed here to get TARGET_ARCH_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
7 | 7 |
8 #include "vm/intrinsifier.h" | 8 #include "vm/intrinsifier.h" |
9 | 9 |
10 #include "vm/assembler.h" | 10 #include "vm/assembler.h" |
(...skipping 1671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1682 __ lw(T1, Address(SP, 1 * kWordSize)); | 1682 __ lw(T1, Address(SP, 1 * kWordSize)); |
1683 __ beq(T0, T1, &is_true); | 1683 __ beq(T0, T1, &is_true); |
1684 __ LoadObject(V0, Bool::False()); | 1684 __ LoadObject(V0, Bool::False()); |
1685 __ Ret(); | 1685 __ Ret(); |
1686 __ Bind(&is_true); | 1686 __ Bind(&is_true); |
1687 __ LoadObject(V0, Bool::True()); | 1687 __ LoadObject(V0, Bool::True()); |
1688 __ Ret(); | 1688 __ Ret(); |
1689 } | 1689 } |
1690 | 1690 |
1691 | 1691 |
| 1692 enum RangeCheckCondition { |
| 1693 kIfNotInRange, kIfInRange |
| 1694 }; |
| 1695 |
| 1696 |
| 1697 static void RangeCheck(Assembler* assembler, |
| 1698 Register val, |
| 1699 Register tmp, |
| 1700 intptr_t low, |
| 1701 intptr_t high, |
| 1702 RangeCheckCondition cc, |
| 1703 Label* target) { |
| 1704 __ AddImmediate(tmp, val, -low); |
| 1705 if (cc == kIfInRange) { |
| 1706 __ BranchUnsignedLessEqual(tmp, Immediate(high - low), target); |
| 1707 } else { |
| 1708 ASSERT(cc == kIfNotInRange); |
| 1709 __ BranchUnsignedGreater(tmp, Immediate(high - low), target); |
| 1710 } |
| 1711 } |
| 1712 |
| 1713 |
| 1714 static void JumpIfInteger(Assembler* assembler, |
| 1715 Register cid, |
| 1716 Register tmp, |
| 1717 Label* target) { |
| 1718 RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfInRange, target); |
| 1719 } |
| 1720 |
| 1721 |
| 1722 static void JumpIfNotInteger(Assembler* assembler, |
| 1723 Register cid, |
| 1724 Register tmp, |
| 1725 Label* target) { |
| 1726 RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfNotInRange, target); |
| 1727 } |
| 1728 |
| 1729 |
| 1730 static void JumpIfString(Assembler* assembler, |
| 1731 Register cid, |
| 1732 Register tmp, |
| 1733 Label* target) { |
| 1734 RangeCheck(assembler, |
| 1735 cid, |
| 1736 tmp, |
| 1737 kOneByteStringCid, |
| 1738 kExternalTwoByteStringCid, |
| 1739 kIfInRange, |
| 1740 target); |
| 1741 } |
| 1742 |
| 1743 |
| 1744 static void JumpIfNotString(Assembler* assembler, |
| 1745 Register cid, |
| 1746 Register tmp, |
| 1747 Label* target) { |
| 1748 RangeCheck(assembler, |
| 1749 cid, |
| 1750 tmp, |
| 1751 kOneByteStringCid, |
| 1752 kExternalTwoByteStringCid, |
| 1753 kIfNotInRange, |
| 1754 target); |
| 1755 } |
| 1756 |
| 1757 |
1692 // Return type quickly for simple types (not parameterized and not signature). | 1758 // Return type quickly for simple types (not parameterized and not signature). |
1693 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { | 1759 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { |
1694 Label fall_through; | 1760 Label fall_through, use_canonical_type, not_integer, not_double; |
1695 __ lw(T0, Address(SP, 0 * kWordSize)); | 1761 __ lw(T0, Address(SP, 0 * kWordSize)); |
1696 __ LoadClassIdMayBeSmi(T1, T0); | 1762 __ LoadClassIdMayBeSmi(T1, T0); |
| 1763 |
| 1764 // Closures are handled in the runtime. |
1697 __ BranchEqual(T1, Immediate(kClosureCid), &fall_through); | 1765 __ BranchEqual(T1, Immediate(kClosureCid), &fall_through); |
| 1766 |
| 1767 __ BranchUnsignedGreaterEqual( |
| 1768 T1, Immediate(kNumPredefinedCids), &use_canonical_type); |
| 1769 |
| 1770 __ BranchNotEqual(T1, Immediate(kDoubleCid), ¬_double); |
| 1771 // Object is a double. |
| 1772 __ LoadIsolate(T1); |
| 1773 __ LoadFromOffset(T1, T1, Isolate::object_store_offset()); |
| 1774 __ LoadFromOffset(V0, T1, ObjectStore::double_type_offset()); |
| 1775 __ Ret(); |
| 1776 |
| 1777 __ Bind(¬_double); |
| 1778 JumpIfNotInteger(assembler, T1, T2, ¬_integer); |
| 1779 // Object is an integer. |
| 1780 __ LoadIsolate(T1); |
| 1781 __ LoadFromOffset(T1, T1, Isolate::object_store_offset()); |
| 1782 __ LoadFromOffset(V0, T1, ObjectStore::int_type_offset()); |
| 1783 __ Ret(); |
| 1784 |
| 1785 __ Bind(¬_integer); |
| 1786 JumpIfNotString(assembler, T1, T2, &use_canonical_type); |
| 1787 // Object is a string. |
| 1788 __ LoadIsolate(T1); |
| 1789 __ LoadFromOffset(T1, T1, Isolate::object_store_offset()); |
| 1790 __ LoadFromOffset(V0, T1, ObjectStore::string_type_offset()); |
| 1791 __ Ret(); |
| 1792 |
| 1793 __ Bind(&use_canonical_type); |
1698 __ LoadClassById(T2, T1); | 1794 __ LoadClassById(T2, T1); |
1699 // T2: class of instance (T0). | |
1700 | |
1701 __ lhu(T1, FieldAddress(T2, Class::num_type_arguments_offset())); | 1795 __ lhu(T1, FieldAddress(T2, Class::num_type_arguments_offset())); |
1702 __ BranchNotEqual(T1, Immediate(0), &fall_through); | 1796 __ BranchNotEqual(T1, Immediate(0), &fall_through); |
1703 | 1797 |
1704 __ lw(V0, FieldAddress(T2, Class::canonical_type_offset())); | 1798 __ lw(V0, FieldAddress(T2, Class::canonical_type_offset())); |
1705 __ BranchEqual(V0, Object::null_object(), &fall_through); | 1799 __ BranchEqual(V0, Object::null_object(), &fall_through); |
1706 __ Ret(); | 1800 __ Ret(); |
1707 | 1801 |
1708 __ Bind(&fall_through); | 1802 __ Bind(&fall_through); |
1709 } | 1803 } |
1710 | 1804 |
1711 | 1805 |
| 1806 void Intrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler) { |
| 1807 Label fall_through, different_cids, equal, not_equal, not_integer; |
| 1808 |
| 1809 __ lw(T0, Address(SP, 0 * kWordSize)); |
| 1810 __ LoadClassIdMayBeSmi(T1, T0); |
| 1811 |
| 1812 // Closures are handled in the runtime. |
| 1813 __ BranchEqual(T1, Immediate(kClosureCid), &fall_through); |
| 1814 |
| 1815 __ lw(T0, Address(SP, 1 * kWordSize)); |
| 1816 __ LoadClassIdMayBeSmi(T2, T0); |
| 1817 |
| 1818 // Check whether class ids match. If class ids don't match objects can still |
| 1819 // have the same runtime type (e.g. multiple string implementation classes |
| 1820 // map to a single String type). |
| 1821 __ BranchNotEqual(T1, T2, &different_cids); |
| 1822 |
| 1823 // Objects have the same class and neither is a closure. |
| 1824 // Check if there are no type arguments. In this case we can return true. |
| 1825 // Otherwise fall through into the runtime to handle comparison. |
| 1826 __ LoadClassById(T2, T1); |
| 1827 __ lhu(T1, FieldAddress(T2, Class::num_type_arguments_offset())); |
| 1828 __ BranchNotEqual(T1, Immediate(0), &fall_through); |
| 1829 |
| 1830 __ Bind(&equal); |
| 1831 __ LoadObject(V0, Bool::True()); |
| 1832 __ Ret(); |
| 1833 |
| 1834 // Class ids are different. Check if we are comparing runtime types of |
| 1835 // two strings (with different representations) or two integers. |
| 1836 __ Bind(&different_cids); |
| 1837 __ BranchUnsignedGreaterEqual( |
| 1838 T1, Immediate(kNumPredefinedCids), ¬_equal); |
| 1839 |
| 1840 // Check if both are integers. |
| 1841 JumpIfNotInteger(assembler, T1, T0, ¬_integer); |
| 1842 JumpIfInteger(assembler, T2, T0, &equal); |
| 1843 __ b(¬_equal); |
| 1844 |
| 1845 __ Bind(¬_integer); |
| 1846 // Check if both are strings. |
| 1847 JumpIfNotString(assembler, T1, T0, ¬_equal); |
| 1848 JumpIfString(assembler, T2, T0, &equal); |
| 1849 |
| 1850 // Neither strings nor integers and have different class ids. |
| 1851 __ Bind(¬_equal); |
| 1852 __ LoadObject(V0, Bool::False()); |
| 1853 __ Ret(); |
| 1854 |
| 1855 __ Bind(&fall_through); |
| 1856 } |
| 1857 |
| 1858 |
1712 void Intrinsifier::String_getHashCode(Assembler* assembler) { | 1859 void Intrinsifier::String_getHashCode(Assembler* assembler) { |
1713 Label fall_through; | 1860 Label fall_through; |
1714 __ lw(T0, Address(SP, 0 * kWordSize)); | 1861 __ lw(T0, Address(SP, 0 * kWordSize)); |
1715 __ lw(V0, FieldAddress(T0, String::hash_offset())); | 1862 __ lw(V0, FieldAddress(T0, String::hash_offset())); |
1716 __ beq(V0, ZR, &fall_through); | 1863 __ beq(V0, ZR, &fall_through); |
1717 __ Ret(); | 1864 __ Ret(); |
1718 __ Bind(&fall_through); // Hash not yet computed. | 1865 __ Bind(&fall_through); // Hash not yet computed. |
1719 } | 1866 } |
1720 | 1867 |
1721 | 1868 |
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2258 __ lw(T0, Address(V0, TimelineStream::enabled_offset())); | 2405 __ lw(T0, Address(V0, TimelineStream::enabled_offset())); |
2259 __ LoadObject(V0, Bool::True()); | 2406 __ LoadObject(V0, Bool::True()); |
2260 __ LoadObject(V1, Bool::False()); | 2407 __ LoadObject(V1, Bool::False()); |
2261 __ Ret(); | 2408 __ Ret(); |
2262 __ delay_slot()->movz(V0, V1, T0); // V0 = (T0 == 0) ? V1 : V0. | 2409 __ delay_slot()->movz(V0, V1, T0); // V0 = (T0 == 0) ? V1 : V0. |
2263 } | 2410 } |
2264 | 2411 |
2265 } // namespace dart | 2412 } // namespace dart |
2266 | 2413 |
2267 #endif // defined TARGET_ARCH_MIPS | 2414 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |