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 1622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1633 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1633 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1634 __ ldr(R1, Address(SP, 1 * kWordSize)); | 1634 __ ldr(R1, Address(SP, 1 * kWordSize)); |
1635 __ cmp(R0, Operand(R1)); | 1635 __ cmp(R0, Operand(R1)); |
1636 __ LoadObject(R0, Bool::False()); | 1636 __ LoadObject(R0, Bool::False()); |
1637 __ LoadObject(TMP, Bool::True()); | 1637 __ LoadObject(TMP, Bool::True()); |
1638 __ csel(R0, TMP, R0, EQ); | 1638 __ csel(R0, TMP, R0, EQ); |
1639 __ ret(); | 1639 __ ret(); |
1640 } | 1640 } |
1641 | 1641 |
1642 | 1642 |
1643 static void RangeCheck(Assembler* assembler, | |
1644 Register val, | |
1645 Register tmp, | |
1646 intptr_t low, | |
1647 intptr_t high, | |
1648 Condition cc, | |
1649 Label* target) { | |
1650 __ SubImmediate(tmp, val, low); | |
1651 __ CompareImmediate(tmp, high - low); | |
1652 __ b(target, cc); | |
1653 } | |
1654 | |
1655 | |
1656 const Condition kIfNotInRange = HI; | |
1657 const Condition kIfInRange = LS; | |
1658 | |
1659 | |
1660 static void JumpIfInteger(Assembler* assembler, | |
1661 Register cid, | |
1662 Register tmp, | |
1663 Label* target) { | |
1664 RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfInRange, target); | |
1665 } | |
1666 | |
1667 | |
1668 static void JumpIfNotInteger(Assembler* assembler, | |
1669 Register cid, | |
1670 Register tmp, | |
1671 Label* target) { | |
1672 RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfNotInRange, target); | |
1673 } | |
1674 | |
1675 | |
1676 static void JumpIfString(Assembler* assembler, | |
1677 Register cid, | |
1678 Register tmp, | |
1679 Label* target) { | |
1680 RangeCheck(assembler, | |
1681 cid, | |
1682 tmp, | |
1683 kOneByteStringCid, | |
1684 kExternalTwoByteStringCid, | |
1685 kIfInRange, | |
1686 target); | |
1687 } | |
1688 | |
1689 | |
1690 static void JumpIfNotString(Assembler* assembler, | |
1691 Register cid, | |
1692 Register tmp, | |
1693 Label* target) { | |
1694 RangeCheck(assembler, | |
1695 cid, | |
1696 tmp, | |
1697 kOneByteStringCid, | |
1698 kExternalTwoByteStringCid, | |
1699 kIfNotInRange, | |
1700 target); | |
1701 } | |
1702 | |
1703 | |
1643 // Return type quickly for simple types (not parameterized and not signature). | 1704 // Return type quickly for simple types (not parameterized and not signature). |
1644 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { | 1705 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { |
1645 Label fall_through; | 1706 Label fall_through, use_canonical_type, not_double, not_integer; |
1646 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1707 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1647 __ LoadClassIdMayBeSmi(R1, R0); | 1708 __ LoadClassIdMayBeSmi(R1, R0); |
1709 | |
1648 __ CompareImmediate(R1, kClosureCid); | 1710 __ CompareImmediate(R1, kClosureCid); |
1649 __ b(&fall_through, EQ); // Instance is a closure. | 1711 __ b(&fall_through, EQ); // Instance is a closure. |
1712 | |
1713 __ CompareImmediate(R1, kNumPredefinedCids); | |
1714 __ b(&use_canonical_type, HI); | |
1715 | |
1716 __ CompareImmediate(R1, kDoubleCid); | |
1717 __ b(¬_double, NE); | |
1718 | |
1719 __ LoadIsolate(R0); | |
1720 __ LoadFromOffset(R0, R0, Isolate::object_store_offset()); | |
1721 __ LoadFromOffset(R0, R0, ObjectStore::double_type_offset()); | |
1722 __ ret(); | |
1723 | |
1724 __ Bind(¬_double); | |
1725 JumpIfNotInteger(assembler, R1, R0, ¬_integer); | |
1726 __ LoadIsolate(R0); | |
1727 __ LoadFromOffset(R0, R0, Isolate::object_store_offset()); | |
1728 __ LoadFromOffset(R0, R0, ObjectStore::int_type_offset()); | |
1729 __ ret(); | |
1730 | |
1731 __ Bind(¬_integer); | |
1732 JumpIfNotString(assembler, R1, R0, &use_canonical_type); | |
1733 __ LoadIsolate(R0); | |
1734 __ LoadFromOffset(R0, R0, Isolate::object_store_offset()); | |
1735 __ LoadFromOffset(R0, R0, ObjectStore::string_type_offset()); | |
1736 __ ret(); | |
1737 | |
1738 __ Bind(&use_canonical_type); | |
1650 __ LoadClassById(R2, R1); | 1739 __ LoadClassById(R2, R1); |
1651 // R2: class of instance (R0). | |
1652 | |
1653 __ ldr(R3, FieldAddress(R2, Class::num_type_arguments_offset()), kHalfword); | 1740 __ ldr(R3, FieldAddress(R2, Class::num_type_arguments_offset()), kHalfword); |
1654 __ CompareImmediate(R3, 0); | 1741 __ CompareImmediate(R3, 0); |
1655 __ b(&fall_through, NE); | 1742 __ b(&fall_through, NE); |
1656 | 1743 |
1657 __ ldr(R0, FieldAddress(R2, Class::canonical_type_offset())); | 1744 __ ldr(R0, FieldAddress(R2, Class::canonical_type_offset())); |
1658 __ CompareObject(R0, Object::null_object()); | 1745 __ CompareObject(R0, Object::null_object()); |
1659 __ b(&fall_through, EQ); | 1746 __ b(&fall_through, EQ); |
1660 __ ret(); | 1747 __ ret(); |
1661 | 1748 |
1662 __ Bind(&fall_through); | 1749 __ Bind(&fall_through); |
1663 } | 1750 } |
1664 | 1751 |
1665 | 1752 |
1753 void Intrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler) { | |
1754 Label fall_through, different_cids, equal, not_equal, not_integer; | |
1755 __ ldr(R0, Address(SP, 0 * kWordSize)); | |
1756 __ LoadClassIdMayBeSmi(R1, R0); | |
1757 | |
1758 // Check if left hand size is a closure. Closures are handled in the runtime. | |
1759 __ CompareImmediate(R1, kClosureCid); | |
1760 __ b(&fall_through, EQ); | |
1761 | |
1762 __ ldr(R0, Address(SP, 1 * kWordSize)); | |
1763 __ LoadClassIdMayBeSmi(R2, R0); | |
1764 | |
1765 // Check whether class ids match. If class ids don't match objects can still | |
1766 // have the same runtime type (e.g. multiple string implementation classes | |
1767 // map to a single String type). | |
1768 __ cmp(R1, Operand(R2)); | |
1769 __ b(&different_cids, NE); | |
1770 | |
1771 // Objects have the same class and neither is a closure. | |
1772 // Check if there are no type arguments. In this case we can return true. | |
1773 // Otherwise fall through into the runtime to handle comparison. | |
1774 __ LoadClassById(R3, R1); | |
1775 __ ldr(R3, FieldAddress(R3, Class::num_type_arguments_offset()), kHalfword); | |
regis
2016/10/08 09:10:37
ditto
Vyacheslav Egorov (Google)
2016/10/24 20:23:03
Acknowledged.
| |
1776 __ CompareImmediate(R3, 0); | |
1777 __ b(&fall_through, NE); | |
1778 | |
1779 __ Bind(&equal); | |
1780 __ LoadObject(R0, Bool::True()); | |
1781 __ ret(); | |
1782 | |
1783 // Class ids are different. Check if we are comparing runtime types of | |
1784 // two strings (with different representations) or two integers. | |
1785 __ Bind(&different_cids); | |
1786 __ CompareImmediate(R1, kNumPredefinedCids); | |
1787 __ b(¬_equal, HI); | |
1788 | |
1789 // Check if both are integers. | |
1790 JumpIfNotInteger(assembler, R1, R0, ¬_integer); | |
1791 JumpIfInteger(assembler, R2, R0, &equal); | |
1792 __ b(¬_equal); | |
1793 | |
1794 __ Bind(¬_integer); | |
1795 // Check if both are strings. | |
1796 JumpIfNotString(assembler, R1, R0, ¬_equal); | |
1797 JumpIfString(assembler, R2, R0, &equal); | |
1798 | |
1799 // Neither strings nor integers and have different class ids. | |
1800 __ Bind(¬_equal); | |
1801 __ LoadObject(R0, Bool::False()); | |
1802 __ ret(); | |
1803 | |
1804 __ Bind(&fall_through); | |
1805 } | |
1806 | |
1807 | |
1666 void Intrinsifier::String_getHashCode(Assembler* assembler) { | 1808 void Intrinsifier::String_getHashCode(Assembler* assembler) { |
1667 Label fall_through; | 1809 Label fall_through; |
1668 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1810 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1669 __ ldr(R0, FieldAddress(R0, String::hash_offset())); | 1811 __ ldr(R0, FieldAddress(R0, String::hash_offset())); |
1670 __ CompareRegisters(R0, ZR); | 1812 __ CompareRegisters(R0, ZR); |
1671 __ b(&fall_through, EQ); | 1813 __ b(&fall_through, EQ); |
1672 __ ret(); | 1814 __ ret(); |
1673 // Hash not yet computed. | 1815 // Hash not yet computed. |
1674 __ Bind(&fall_through); | 1816 __ Bind(&fall_through); |
1675 } | 1817 } |
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2212 __ cmp(R0, Operand(0)); | 2354 __ cmp(R0, Operand(0)); |
2213 __ LoadObject(R0, Bool::False()); | 2355 __ LoadObject(R0, Bool::False()); |
2214 __ LoadObject(TMP, Bool::True()); | 2356 __ LoadObject(TMP, Bool::True()); |
2215 __ csel(R0, TMP, R0, NE); | 2357 __ csel(R0, TMP, R0, NE); |
2216 __ ret(); | 2358 __ ret(); |
2217 } | 2359 } |
2218 | 2360 |
2219 } // namespace dart | 2361 } // namespace dart |
2220 | 2362 |
2221 #endif // defined TARGET_ARCH_ARM64 | 2363 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |