OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
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 1579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1590 ASSERT(kSmiTagShift == 1); | 1590 ASSERT(kSmiTagShift == 1); |
1591 __ AddImmediate(R0, TwoByteString::data_offset() - kHeapObjectTag); | 1591 __ AddImmediate(R0, TwoByteString::data_offset() - kHeapObjectTag); |
1592 __ ldrh(R0, Address(R0, R1)); | 1592 __ ldrh(R0, Address(R0, R1)); |
1593 __ SmiTag(R0); | 1593 __ SmiTag(R0); |
1594 __ Ret(); | 1594 __ Ret(); |
1595 | 1595 |
1596 __ Bind(&fall_through); | 1596 __ Bind(&fall_through); |
1597 } | 1597 } |
1598 | 1598 |
1599 | 1599 |
| 1600 void GenerateSubstringMatchesSpecialization(Assembler* assembler, |
| 1601 intptr_t receiver_cid, |
| 1602 intptr_t other_cid, |
| 1603 Label* return_true, |
| 1604 Label* return_false) { |
| 1605 __ SmiUntag(R1); |
| 1606 __ ldr(R8, FieldAddress(R0, String::length_offset())); // this.length |
| 1607 __ SmiUntag(R8); |
| 1608 __ ldr(R9, FieldAddress(R2, String::length_offset())); // other.length |
| 1609 __ SmiUntag(R9); |
| 1610 |
| 1611 // if (other.length == 0) return true; |
| 1612 __ cmp(R9, Operand(0)); |
| 1613 __ b(return_true, EQ); |
| 1614 |
| 1615 // if (start < 0) return false; |
| 1616 __ cmp(R1, Operand(0)); |
| 1617 __ b(return_false, LT); |
| 1618 |
| 1619 // if (start + other.length > this.length) return false; |
| 1620 __ add(R3, R1, Operand(R9)); |
| 1621 __ cmp(R3, Operand(R8)); |
| 1622 __ b(return_false, GT); |
| 1623 |
| 1624 if (receiver_cid == kOneByteStringCid) { |
| 1625 __ AddImmediate(R0, R0, OneByteString::data_offset() - kHeapObjectTag); |
| 1626 __ add(R0, R0, Operand(R1)); |
| 1627 } else { |
| 1628 ASSERT(receiver_cid == kTwoByteStringCid); |
| 1629 __ AddImmediate(R0, R0, TwoByteString::data_offset() - kHeapObjectTag); |
| 1630 __ add(R0, R0, Operand(R1)); |
| 1631 __ add(R0, R0, Operand(R1)); |
| 1632 } |
| 1633 if (other_cid == kOneByteStringCid) { |
| 1634 __ AddImmediate(R2, R2, OneByteString::data_offset() - kHeapObjectTag); |
| 1635 } else { |
| 1636 ASSERT(other_cid == kTwoByteStringCid); |
| 1637 __ AddImmediate(R2, R2, TwoByteString::data_offset() - kHeapObjectTag); |
| 1638 } |
| 1639 |
| 1640 // i = 0 |
| 1641 __ LoadImmediate(R3, 0); |
| 1642 |
| 1643 // do |
| 1644 Label loop; |
| 1645 __ Bind(&loop); |
| 1646 |
| 1647 if (receiver_cid == kOneByteStringCid) { |
| 1648 __ ldrb(R4, Address(R0, 0)); // this.codeUnitAt(i + start) |
| 1649 } else { |
| 1650 __ ldrh(R4, Address(R0, 0)); // this.codeUnitAt(i + start) |
| 1651 } |
| 1652 if (other_cid == kOneByteStringCid) { |
| 1653 __ ldrb(NOTFP, Address(R2, 0)); // other.codeUnitAt(i) |
| 1654 } else { |
| 1655 __ ldrh(NOTFP, Address(R2, 0)); // other.codeUnitAt(i) |
| 1656 } |
| 1657 __ cmp(R4, Operand(NOTFP)); |
| 1658 __ b(return_false, NE); |
| 1659 |
| 1660 // i++, while (i < len) |
| 1661 __ AddImmediate(R3, R3, 1); |
| 1662 __ AddImmediate(R0, R0, receiver_cid == kOneByteStringCid ? 1 : 2); |
| 1663 __ AddImmediate(R2, R2, other_cid == kOneByteStringCid ? 1 : 2); |
| 1664 __ cmp(R3, Operand(R9)); |
| 1665 __ b(&loop, LT); |
| 1666 |
| 1667 __ b(return_true); |
| 1668 } |
| 1669 |
| 1670 |
| 1671 // bool _substringMatches(int start, String other) |
| 1672 // This intrinsic handles a OneByteString or TwoByteString receiver with a |
| 1673 // OneByteString other. |
| 1674 void Intrinsifier::StringBaseSubstringMatches(Assembler* assembler) { |
| 1675 Label fall_through, return_true, return_false, try_two_byte; |
| 1676 __ ldr(R0, Address(SP, 2 * kWordSize)); // this |
| 1677 __ ldr(R1, Address(SP, 1 * kWordSize)); // start |
| 1678 __ ldr(R2, Address(SP, 0 * kWordSize)); // other |
| 1679 __ Push(R4); // Make ARGS_DESC_REG available. |
| 1680 |
| 1681 __ tst(R1, Operand(kSmiTagMask)); |
| 1682 __ b(&fall_through, NE); // 'start' is not a Smi. |
| 1683 |
| 1684 __ CompareClassId(R2, kOneByteStringCid, R3); |
| 1685 __ b(&fall_through, NE); |
| 1686 |
| 1687 __ CompareClassId(R0, kOneByteStringCid, R3); |
| 1688 __ b(&try_two_byte, NE); |
| 1689 |
| 1690 GenerateSubstringMatchesSpecialization(assembler, |
| 1691 kOneByteStringCid, |
| 1692 kOneByteStringCid, |
| 1693 &return_true, |
| 1694 &return_false); |
| 1695 |
| 1696 __ Bind(&try_two_byte); |
| 1697 __ CompareClassId(R0, kTwoByteStringCid, R3); |
| 1698 __ b(&fall_through, NE); |
| 1699 |
| 1700 GenerateSubstringMatchesSpecialization(assembler, |
| 1701 kTwoByteStringCid, |
| 1702 kOneByteStringCid, |
| 1703 &return_true, |
| 1704 &return_false); |
| 1705 |
| 1706 __ Bind(&return_true); |
| 1707 __ Pop(R4); |
| 1708 __ LoadObject(R0, Bool::True()); |
| 1709 __ Ret(); |
| 1710 |
| 1711 __ Bind(&return_false); |
| 1712 __ Pop(R4); |
| 1713 __ LoadObject(R0, Bool::False()); |
| 1714 __ Ret(); |
| 1715 |
| 1716 __ Bind(&fall_through); |
| 1717 __ Pop(R4); |
| 1718 } |
| 1719 |
| 1720 |
1600 void Intrinsifier::StringBaseCharAt(Assembler* assembler) { | 1721 void Intrinsifier::StringBaseCharAt(Assembler* assembler) { |
1601 Label fall_through, try_two_byte_string; | 1722 Label fall_through, try_two_byte_string; |
1602 | 1723 |
1603 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index. | 1724 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index. |
1604 __ ldr(R0, Address(SP, 1 * kWordSize)); // String. | 1725 __ ldr(R0, Address(SP, 1 * kWordSize)); // String. |
1605 __ tst(R1, Operand(kSmiTagMask)); | 1726 __ tst(R1, Operand(kSmiTagMask)); |
1606 __ b(&fall_through, NE); // Index is not a Smi. | 1727 __ b(&fall_through, NE); // Index is not a Smi. |
1607 // Range check. | 1728 // Range check. |
1608 __ ldr(R2, FieldAddress(R0, String::length_offset())); | 1729 __ ldr(R2, FieldAddress(R0, String::length_offset())); |
1609 __ cmp(R1, Operand(R2)); | 1730 __ cmp(R1, Operand(R2)); |
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2003 | 2124 |
2004 void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler) { | 2125 void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler) { |
2005 __ LoadIsolate(R0); | 2126 __ LoadIsolate(R0); |
2006 __ ldr(R0, Address(R0, Isolate::current_tag_offset())); | 2127 __ ldr(R0, Address(R0, Isolate::current_tag_offset())); |
2007 __ Ret(); | 2128 __ Ret(); |
2008 } | 2129 } |
2009 | 2130 |
2010 } // namespace dart | 2131 } // namespace dart |
2011 | 2132 |
2012 #endif // defined TARGET_ARCH_ARM | 2133 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |