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 |
1656 // Return type quickly for simple types (not parameterized and not signature). | 1717 // Return type quickly for simple types (not parameterized and not signature). |
1657 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { | 1718 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { |
1658 Label fall_through; | 1719 Label fall_through, use_canonical_type, not_double, not_integer; |
1659 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1720 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1660 __ LoadClassIdMayBeSmi(R1, R0); | 1721 __ LoadClassIdMayBeSmi(R1, R0); |
| 1722 |
1661 __ CompareImmediate(R1, kClosureCid); | 1723 __ CompareImmediate(R1, kClosureCid); |
1662 __ b(&fall_through, EQ); // Instance is a closure. | 1724 __ b(&fall_through, EQ); // Instance is a closure. |
| 1725 |
| 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); |
1663 __ LoadClassById(R2, R1); | 1752 __ LoadClassById(R2, R1); |
1664 // R2: class of instance (R0). | |
1665 | |
1666 __ ldr(R3, FieldAddress(R2, Class::num_type_arguments_offset()), kHalfword); | 1753 __ ldr(R3, FieldAddress(R2, Class::num_type_arguments_offset()), kHalfword); |
1667 __ CompareImmediate(R3, 0); | 1754 __ CompareImmediate(R3, 0); |
1668 __ b(&fall_through, NE); | 1755 __ b(&fall_through, NE); |
1669 | 1756 |
1670 __ ldr(R0, FieldAddress(R2, Class::canonical_type_offset())); | 1757 __ ldr(R0, FieldAddress(R2, Class::canonical_type_offset())); |
1671 __ CompareObject(R0, Object::null_object()); | 1758 __ CompareObject(R0, Object::null_object()); |
1672 __ b(&fall_through, EQ); | 1759 __ b(&fall_through, EQ); |
1673 __ ret(); | 1760 __ ret(); |
1674 | 1761 |
1675 __ Bind(&fall_through); | 1762 __ Bind(&fall_through); |
1676 } | 1763 } |
1677 | 1764 |
1678 | 1765 |
| 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 |
1679 void Intrinsifier::String_getHashCode(Assembler* assembler) { | 1821 void Intrinsifier::String_getHashCode(Assembler* assembler) { |
1680 Label fall_through; | 1822 Label fall_through; |
1681 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1823 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1682 __ ldr(R0, FieldAddress(R0, String::hash_offset())); | 1824 __ ldr(R0, FieldAddress(R0, String::hash_offset())); |
1683 __ CompareRegisters(R0, ZR); | 1825 __ CompareRegisters(R0, ZR); |
1684 __ b(&fall_through, EQ); | 1826 __ b(&fall_through, EQ); |
1685 __ ret(); | 1827 __ ret(); |
1686 // Hash not yet computed. | 1828 // Hash not yet computed. |
1687 __ Bind(&fall_through); | 1829 __ Bind(&fall_through); |
1688 } | 1830 } |
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2225 __ cmp(R0, Operand(0)); | 2367 __ cmp(R0, Operand(0)); |
2226 __ LoadObject(R0, Bool::False()); | 2368 __ LoadObject(R0, Bool::False()); |
2227 __ LoadObject(TMP, Bool::True()); | 2369 __ LoadObject(TMP, Bool::True()); |
2228 __ csel(R0, TMP, R0, NE); | 2370 __ csel(R0, TMP, R0, NE); |
2229 __ ret(); | 2371 __ ret(); |
2230 } | 2372 } |
2231 | 2373 |
2232 } // namespace dart | 2374 } // namespace dart |
2233 | 2375 |
2234 #endif // defined TARGET_ARCH_ARM64 | 2376 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |