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 1659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1670 ASSERT(kSmiTagShift == 1); | 1670 ASSERT(kSmiTagShift == 1); |
1671 __ AddImmediate(R0, R0, TwoByteString::data_offset() - kHeapObjectTag); | 1671 __ AddImmediate(R0, R0, TwoByteString::data_offset() - kHeapObjectTag); |
1672 __ ldr(R0, Address(R0, R1), kUnsignedHalfword); | 1672 __ ldr(R0, Address(R0, R1), kUnsignedHalfword); |
1673 __ SmiTag(R0); | 1673 __ SmiTag(R0); |
1674 __ ret(); | 1674 __ ret(); |
1675 | 1675 |
1676 __ Bind(&fall_through); | 1676 __ Bind(&fall_through); |
1677 } | 1677 } |
1678 | 1678 |
1679 | 1679 |
| 1680 void GenerateSubstringMatchesSpecialization(Assembler* assembler, |
| 1681 intptr_t receiver_cid, |
| 1682 intptr_t other_cid, |
| 1683 Label* return_true, |
| 1684 Label* return_false) { |
| 1685 __ SmiUntag(R1); |
| 1686 __ ldr(R8, FieldAddress(R0, String::length_offset())); // this.length |
| 1687 __ SmiUntag(R8); |
| 1688 __ ldr(R9, FieldAddress(R2, String::length_offset())); // other.length |
| 1689 __ SmiUntag(R9); |
| 1690 |
| 1691 // if (other.length == 0) return true; |
| 1692 __ cmp(R9, Operand(0)); |
| 1693 __ b(return_true, EQ); |
| 1694 |
| 1695 // if (start < 0) return false; |
| 1696 __ cmp(R1, Operand(0)); |
| 1697 __ b(return_false, LT); |
| 1698 |
| 1699 // if (start + other.length > this.length) return false; |
| 1700 __ add(R3, R1, Operand(R9)); |
| 1701 __ cmp(R3, Operand(R8)); |
| 1702 __ b(return_false, GT); |
| 1703 |
| 1704 if (receiver_cid == kOneByteStringCid) { |
| 1705 __ AddImmediate(R0, R0, OneByteString::data_offset() - kHeapObjectTag); |
| 1706 __ add(R0, R0, Operand(R1)); |
| 1707 } else { |
| 1708 ASSERT(receiver_cid == kTwoByteStringCid); |
| 1709 __ AddImmediate(R0, R0, TwoByteString::data_offset() - kHeapObjectTag); |
| 1710 __ add(R0, R0, Operand(R1)); |
| 1711 __ add(R0, R0, Operand(R1)); |
| 1712 } |
| 1713 if (other_cid == kOneByteStringCid) { |
| 1714 __ AddImmediate(R2, R2, OneByteString::data_offset() - kHeapObjectTag); |
| 1715 } else { |
| 1716 ASSERT(other_cid == kTwoByteStringCid); |
| 1717 __ AddImmediate(R2, R2, TwoByteString::data_offset() - kHeapObjectTag); |
| 1718 } |
| 1719 |
| 1720 // i = 0 |
| 1721 __ LoadImmediate(R3, 0); |
| 1722 |
| 1723 // do |
| 1724 Label loop; |
| 1725 __ Bind(&loop); |
| 1726 |
| 1727 // this.codeUnitAt(i + start) |
| 1728 __ ldr(R10, Address(R0, 0), |
| 1729 receiver_cid == kOneByteStringCid ? kUnsignedByte : kUnsignedHalfword); |
| 1730 // other.codeUnitAt(i) |
| 1731 __ ldr(R11, Address(R2, 0), |
| 1732 other_cid == kOneByteStringCid ? kUnsignedByte : kUnsignedHalfword); |
| 1733 __ cmp(R10, Operand(R11)); |
| 1734 __ b(return_false, NE); |
| 1735 |
| 1736 // i++, while (i < len) |
| 1737 __ add(R3, R3, Operand(1)); |
| 1738 __ add(R0, R0, Operand(receiver_cid == kOneByteStringCid ? 1 : 2)); |
| 1739 __ add(R2, R2, Operand(other_cid == kOneByteStringCid ? 1 : 2)); |
| 1740 __ cmp(R3, Operand(R9)); |
| 1741 __ b(&loop, LT); |
| 1742 |
| 1743 __ b(return_true); |
| 1744 } |
| 1745 |
| 1746 |
| 1747 // bool _substringMatches(int start, String other) |
| 1748 // This intrinsic handles a OneByteString or TwoByteString receiver with a |
| 1749 // OneByteString other. |
| 1750 void Intrinsifier::StringBaseSubstringMatches(Assembler* assembler) { |
| 1751 Label fall_through, return_true, return_false, try_two_byte; |
| 1752 __ ldr(R0, Address(SP, 2 * kWordSize)); // this |
| 1753 __ ldr(R1, Address(SP, 1 * kWordSize)); // start |
| 1754 __ ldr(R2, Address(SP, 0 * kWordSize)); // other |
| 1755 |
| 1756 __ tsti(R1, Immediate(kSmiTagMask)); |
| 1757 __ b(&fall_through, NE); // 'start' is not a Smi. |
| 1758 |
| 1759 __ CompareClassId(R2, kOneByteStringCid); |
| 1760 __ b(&fall_through, NE); |
| 1761 |
| 1762 __ CompareClassId(R0, kOneByteStringCid); |
| 1763 __ b(&fall_through, NE); |
| 1764 |
| 1765 GenerateSubstringMatchesSpecialization(assembler, |
| 1766 kOneByteStringCid, |
| 1767 kOneByteStringCid, |
| 1768 &return_true, |
| 1769 &return_false); |
| 1770 |
| 1771 __ Bind(&try_two_byte); |
| 1772 __ CompareClassId(R0, kTwoByteStringCid); |
| 1773 __ b(&fall_through, NE); |
| 1774 |
| 1775 GenerateSubstringMatchesSpecialization(assembler, |
| 1776 kTwoByteStringCid, |
| 1777 kOneByteStringCid, |
| 1778 &return_true, |
| 1779 &return_false); |
| 1780 |
| 1781 __ Bind(&return_true); |
| 1782 __ LoadObject(R0, Bool::True()); |
| 1783 __ ret(); |
| 1784 |
| 1785 __ Bind(&return_false); |
| 1786 __ LoadObject(R0, Bool::False()); |
| 1787 __ ret(); |
| 1788 |
| 1789 __ Bind(&fall_through); |
| 1790 } |
| 1791 |
| 1792 |
1680 void Intrinsifier::StringBaseCharAt(Assembler* assembler) { | 1793 void Intrinsifier::StringBaseCharAt(Assembler* assembler) { |
1681 Label fall_through, try_two_byte_string; | 1794 Label fall_through, try_two_byte_string; |
1682 | 1795 |
1683 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index. | 1796 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index. |
1684 __ ldr(R0, Address(SP, 1 * kWordSize)); // String. | 1797 __ ldr(R0, Address(SP, 1 * kWordSize)); // String. |
1685 __ tsti(R1, Immediate(kSmiTagMask)); | 1798 __ tsti(R1, Immediate(kSmiTagMask)); |
1686 __ b(&fall_through, NE); // Index is not a Smi. | 1799 __ b(&fall_through, NE); // Index is not a Smi. |
1687 // Range check. | 1800 // Range check. |
1688 __ ldr(R2, FieldAddress(R0, String::length_offset())); | 1801 __ ldr(R2, FieldAddress(R0, String::length_offset())); |
1689 __ cmp(R1, Operand(R2)); | 1802 __ cmp(R1, Operand(R2)); |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2085 | 2198 |
2086 void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler) { | 2199 void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler) { |
2087 __ LoadIsolate(R0); | 2200 __ LoadIsolate(R0); |
2088 __ ldr(R0, Address(R0, Isolate::current_tag_offset())); | 2201 __ ldr(R0, Address(R0, Isolate::current_tag_offset())); |
2089 __ ret(); | 2202 __ ret(); |
2090 } | 2203 } |
2091 | 2204 |
2092 } // namespace dart | 2205 } // namespace dart |
2093 | 2206 |
2094 #endif // defined TARGET_ARCH_ARM64 | 2207 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |