Chromium Code Reviews| 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 |