OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
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 1635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1646 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1646 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1647 __ ldr(R1, Address(SP, 1 * kWordSize)); | 1647 __ ldr(R1, Address(SP, 1 * kWordSize)); |
1648 __ cmp(R0, Operand(R1)); | 1648 __ cmp(R0, Operand(R1)); |
1649 __ LoadObject(R0, Bool::False()); | 1649 __ LoadObject(R0, Bool::False()); |
1650 __ LoadObject(TMP, Bool::True()); | 1650 __ LoadObject(TMP, Bool::True()); |
1651 __ csel(R0, TMP, R0, EQ); | 1651 __ csel(R0, TMP, R0, EQ); |
1652 __ ret(); | 1652 __ ret(); |
1653 } | 1653 } |
1654 | 1654 |
1655 | 1655 |
1656 static void RangeCheck(Assembler* assembler, | |
1657 Register val, | |
1658 Register tmp, | |
1659 intptr_t low, | |
1660 intptr_t high, | |
1661 Condition cc, | |
1662 Label* target) { | |
1663 __ AddImmediate(tmp, val, -low); | |
1664 __ CompareImmediate(tmp, high - low); | |
1665 __ b(target, cc); | |
1666 } | |
1667 | |
1668 | |
1669 const Condition kIfNotInRange = HI; | |
1670 const Condition kIfInRange = LS; | |
1671 | |
1672 | |
1673 static void JumpIfInteger(Assembler* assembler, | |
1674 Register cid, | |
1675 Register tmp, | |
1676 Label* target) { | |
1677 RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfInRange, target); | |
1678 } | |
1679 | |
1680 | |
1681 static void JumpIfNotInteger(Assembler* assembler, | |
1682 Register cid, | |
1683 Register tmp, | |
1684 Label* target) { | |
1685 RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfNotInRange, target); | |
1686 } | |
1687 | |
1688 | |
1689 static void JumpIfString(Assembler* assembler, | |
1690 Register cid, | |
1691 Register tmp, | |
1692 Label* target) { | |
1693 RangeCheck(assembler, | |
1694 cid, | |
1695 tmp, | |
1696 kOneByteStringCid, | |
1697 kExternalTwoByteStringCid, | |
1698 kIfInRange, | |
1699 target); | |
1700 } | |
1701 | |
1702 | |
1703 static void JumpIfNotString(Assembler* assembler, | |
1704 Register cid, | |
1705 Register tmp, | |
1706 Label* target) { | |
1707 RangeCheck(assembler, | |
1708 cid, | |
1709 tmp, | |
1710 kOneByteStringCid, | |
1711 kExternalTwoByteStringCid, | |
1712 kIfNotInRange, | |
1713 target); | |
1714 } | |
1715 | |
1716 | |
1717 // Return type quickly for simple types (not parameterized and not signature). | 1656 // Return type quickly for simple types (not parameterized and not signature). |
1718 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { | 1657 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { |
1719 Label fall_through, use_canonical_type, not_double, not_integer; | 1658 Label fall_through; |
1720 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1659 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1721 __ LoadClassIdMayBeSmi(R1, R0); | 1660 __ LoadClassIdMayBeSmi(R1, R0); |
1722 | |
1723 __ CompareImmediate(R1, kClosureCid); | 1661 __ CompareImmediate(R1, kClosureCid); |
1724 __ b(&fall_through, EQ); // Instance is a closure. | 1662 __ b(&fall_through, EQ); // Instance is a closure. |
| 1663 __ LoadClassById(R2, R1); |
| 1664 // R2: class of instance (R0). |
1725 | 1665 |
1726 __ CompareImmediate(R1, kNumPredefinedCids); | |
1727 __ b(&use_canonical_type, HI); | |
1728 | |
1729 __ CompareImmediate(R1, kDoubleCid); | |
1730 __ b(¬_double, NE); | |
1731 | |
1732 __ LoadIsolate(R0); | |
1733 __ LoadFromOffset(R0, R0, Isolate::object_store_offset()); | |
1734 __ LoadFromOffset(R0, R0, ObjectStore::double_type_offset()); | |
1735 __ ret(); | |
1736 | |
1737 __ Bind(¬_double); | |
1738 JumpIfNotInteger(assembler, R1, R0, ¬_integer); | |
1739 __ LoadIsolate(R0); | |
1740 __ LoadFromOffset(R0, R0, Isolate::object_store_offset()); | |
1741 __ LoadFromOffset(R0, R0, ObjectStore::int_type_offset()); | |
1742 __ ret(); | |
1743 | |
1744 __ Bind(¬_integer); | |
1745 JumpIfNotString(assembler, R1, R0, &use_canonical_type); | |
1746 __ LoadIsolate(R0); | |
1747 __ LoadFromOffset(R0, R0, Isolate::object_store_offset()); | |
1748 __ LoadFromOffset(R0, R0, ObjectStore::string_type_offset()); | |
1749 __ ret(); | |
1750 | |
1751 __ Bind(&use_canonical_type); | |
1752 __ LoadClassById(R2, R1); | |
1753 __ ldr(R3, FieldAddress(R2, Class::num_type_arguments_offset()), kHalfword); | 1666 __ ldr(R3, FieldAddress(R2, Class::num_type_arguments_offset()), kHalfword); |
1754 __ CompareImmediate(R3, 0); | 1667 __ CompareImmediate(R3, 0); |
1755 __ b(&fall_through, NE); | 1668 __ b(&fall_through, NE); |
1756 | 1669 |
1757 __ ldr(R0, FieldAddress(R2, Class::canonical_type_offset())); | 1670 __ ldr(R0, FieldAddress(R2, Class::canonical_type_offset())); |
1758 __ CompareObject(R0, Object::null_object()); | 1671 __ CompareObject(R0, Object::null_object()); |
1759 __ b(&fall_through, EQ); | 1672 __ b(&fall_through, EQ); |
1760 __ ret(); | 1673 __ ret(); |
1761 | 1674 |
1762 __ Bind(&fall_through); | 1675 __ Bind(&fall_through); |
1763 } | 1676 } |
1764 | 1677 |
1765 | 1678 |
1766 void Intrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler) { | |
1767 Label fall_through, different_cids, equal, not_equal, not_integer; | |
1768 __ ldr(R0, Address(SP, 0 * kWordSize)); | |
1769 __ LoadClassIdMayBeSmi(R1, R0); | |
1770 | |
1771 // Check if left hand size is a closure. Closures are handled in the runtime. | |
1772 __ CompareImmediate(R1, kClosureCid); | |
1773 __ b(&fall_through, EQ); | |
1774 | |
1775 __ ldr(R0, Address(SP, 1 * kWordSize)); | |
1776 __ LoadClassIdMayBeSmi(R2, R0); | |
1777 | |
1778 // Check whether class ids match. If class ids don't match objects can still | |
1779 // have the same runtime type (e.g. multiple string implementation classes | |
1780 // map to a single String type). | |
1781 __ cmp(R1, Operand(R2)); | |
1782 __ b(&different_cids, NE); | |
1783 | |
1784 // Objects have the same class and neither is a closure. | |
1785 // Check if there are no type arguments. In this case we can return true. | |
1786 // Otherwise fall through into the runtime to handle comparison. | |
1787 __ LoadClassById(R3, R1); | |
1788 __ ldr(R3, FieldAddress(R3, Class::num_type_arguments_offset()), kHalfword); | |
1789 __ CompareImmediate(R3, 0); | |
1790 __ b(&fall_through, NE); | |
1791 | |
1792 __ Bind(&equal); | |
1793 __ LoadObject(R0, Bool::True()); | |
1794 __ ret(); | |
1795 | |
1796 // Class ids are different. Check if we are comparing runtime types of | |
1797 // two strings (with different representations) or two integers. | |
1798 __ Bind(&different_cids); | |
1799 __ CompareImmediate(R1, kNumPredefinedCids); | |
1800 __ b(¬_equal, HI); | |
1801 | |
1802 // Check if both are integers. | |
1803 JumpIfNotInteger(assembler, R1, R0, ¬_integer); | |
1804 JumpIfInteger(assembler, R2, R0, &equal); | |
1805 __ b(¬_equal); | |
1806 | |
1807 __ Bind(¬_integer); | |
1808 // Check if both are strings. | |
1809 JumpIfNotString(assembler, R1, R0, ¬_equal); | |
1810 JumpIfString(assembler, R2, R0, &equal); | |
1811 | |
1812 // Neither strings nor integers and have different class ids. | |
1813 __ Bind(¬_equal); | |
1814 __ LoadObject(R0, Bool::False()); | |
1815 __ ret(); | |
1816 | |
1817 __ Bind(&fall_through); | |
1818 } | |
1819 | |
1820 | |
1821 void Intrinsifier::String_getHashCode(Assembler* assembler) { | 1679 void Intrinsifier::String_getHashCode(Assembler* assembler) { |
1822 Label fall_through; | 1680 Label fall_through; |
1823 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1681 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1824 __ ldr(R0, FieldAddress(R0, String::hash_offset())); | 1682 __ ldr(R0, FieldAddress(R0, String::hash_offset())); |
1825 __ CompareRegisters(R0, ZR); | 1683 __ CompareRegisters(R0, ZR); |
1826 __ b(&fall_through, EQ); | 1684 __ b(&fall_through, EQ); |
1827 __ ret(); | 1685 __ ret(); |
1828 // Hash not yet computed. | 1686 // Hash not yet computed. |
1829 __ Bind(&fall_through); | 1687 __ Bind(&fall_through); |
1830 } | 1688 } |
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2367 __ cmp(R0, Operand(0)); | 2225 __ cmp(R0, Operand(0)); |
2368 __ LoadObject(R0, Bool::False()); | 2226 __ LoadObject(R0, Bool::False()); |
2369 __ LoadObject(TMP, Bool::True()); | 2227 __ LoadObject(TMP, Bool::True()); |
2370 __ csel(R0, TMP, R0, NE); | 2228 __ csel(R0, TMP, R0, NE); |
2371 __ ret(); | 2229 __ ret(); |
2372 } | 2230 } |
2373 | 2231 |
2374 } // namespace dart | 2232 } // namespace dart |
2375 | 2233 |
2376 #endif // defined TARGET_ARCH_ARM64 | 2234 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |