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 1561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1572 void Intrinsifier::ObjectEquals(Assembler* assembler) { | 1572 void Intrinsifier::ObjectEquals(Assembler* assembler) { |
1573 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1573 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1574 __ ldr(R1, Address(SP, 1 * kWordSize)); | 1574 __ ldr(R1, Address(SP, 1 * kWordSize)); |
1575 __ cmp(R0, Operand(R1)); | 1575 __ cmp(R0, Operand(R1)); |
1576 __ LoadObject(R0, Bool::False(), NE); | 1576 __ LoadObject(R0, Bool::False(), NE); |
1577 __ LoadObject(R0, Bool::True(), EQ); | 1577 __ LoadObject(R0, Bool::True(), EQ); |
1578 __ Ret(); | 1578 __ Ret(); |
1579 } | 1579 } |
1580 | 1580 |
1581 | 1581 |
| 1582 static void RangeCheck(Assembler* assembler, |
| 1583 Register val, |
| 1584 Register tmp, |
| 1585 intptr_t low, |
| 1586 intptr_t high, |
| 1587 Condition cc, |
| 1588 Label* target) { |
| 1589 __ AddImmediate(tmp, val, -low); |
| 1590 __ CompareImmediate(tmp, high - low); |
| 1591 __ b(target, cc); |
| 1592 } |
| 1593 |
| 1594 |
| 1595 const Condition kIfNotInRange = HI; |
| 1596 const Condition kIfInRange = LS; |
| 1597 |
| 1598 |
| 1599 static void JumpIfInteger(Assembler* assembler, |
| 1600 Register cid, |
| 1601 Register tmp, |
| 1602 Label* target) { |
| 1603 RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfInRange, target); |
| 1604 } |
| 1605 |
| 1606 |
| 1607 static void JumpIfNotInteger(Assembler* assembler, |
| 1608 Register cid, |
| 1609 Register tmp, |
| 1610 Label* target) { |
| 1611 RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfNotInRange, target); |
| 1612 } |
| 1613 |
| 1614 |
| 1615 static void JumpIfString(Assembler* assembler, |
| 1616 Register cid, |
| 1617 Register tmp, |
| 1618 Label* target) { |
| 1619 RangeCheck(assembler, |
| 1620 cid, |
| 1621 tmp, |
| 1622 kOneByteStringCid, |
| 1623 kExternalTwoByteStringCid, |
| 1624 kIfInRange, |
| 1625 target); |
| 1626 } |
| 1627 |
| 1628 |
| 1629 static void JumpIfNotString(Assembler* assembler, |
| 1630 Register cid, |
| 1631 Register tmp, |
| 1632 Label* target) { |
| 1633 RangeCheck(assembler, |
| 1634 cid, |
| 1635 tmp, |
| 1636 kOneByteStringCid, |
| 1637 kExternalTwoByteStringCid, |
| 1638 kIfNotInRange, |
| 1639 target); |
| 1640 } |
| 1641 |
| 1642 |
1582 // Return type quickly for simple types (not parameterized and not signature). | 1643 // Return type quickly for simple types (not parameterized and not signature). |
1583 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { | 1644 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { |
1584 Label fall_through; | 1645 Label fall_through, use_canonical_type, not_double, not_integer; |
1585 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1646 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1586 __ LoadClassIdMayBeSmi(R1, R0); | 1647 __ LoadClassIdMayBeSmi(R1, R0); |
| 1648 |
1587 __ CompareImmediate(R1, kClosureCid); | 1649 __ CompareImmediate(R1, kClosureCid); |
1588 __ b(&fall_through, EQ); // Instance is a closure. | 1650 __ b(&fall_through, EQ); // Instance is a closure. |
| 1651 |
| 1652 __ CompareImmediate(R1, kNumPredefinedCids); |
| 1653 __ b(&use_canonical_type, HI); |
| 1654 |
| 1655 __ CompareImmediate(R1, kDoubleCid); |
| 1656 __ b(¬_double, NE); |
| 1657 |
| 1658 __ LoadIsolate(R0); |
| 1659 __ LoadFromOffset(kWord, R0, R0, Isolate::object_store_offset()); |
| 1660 __ LoadFromOffset(kWord, R0, R0, ObjectStore::double_type_offset()); |
| 1661 __ Ret(); |
| 1662 |
| 1663 __ Bind(¬_double); |
| 1664 JumpIfNotInteger(assembler, R1, R0, ¬_integer); |
| 1665 __ LoadIsolate(R0); |
| 1666 __ LoadFromOffset(kWord, R0, R0, Isolate::object_store_offset()); |
| 1667 __ LoadFromOffset(kWord, R0, R0, ObjectStore::int_type_offset()); |
| 1668 __ Ret(); |
| 1669 |
| 1670 __ Bind(¬_integer); |
| 1671 JumpIfNotString(assembler, R1, R0, &use_canonical_type); |
| 1672 __ LoadIsolate(R0); |
| 1673 __ LoadFromOffset(kWord, R0, R0, Isolate::object_store_offset()); |
| 1674 __ LoadFromOffset(kWord, R0, R0, ObjectStore::string_type_offset()); |
| 1675 __ Ret(); |
| 1676 |
| 1677 __ Bind(&use_canonical_type); |
1589 __ LoadClassById(R2, R1); | 1678 __ LoadClassById(R2, R1); |
1590 // R2: class of instance (R0). | |
1591 | |
1592 __ ldrh(R3, FieldAddress(R2, Class::num_type_arguments_offset())); | 1679 __ ldrh(R3, FieldAddress(R2, Class::num_type_arguments_offset())); |
1593 __ CompareImmediate(R3, 0); | 1680 __ CompareImmediate(R3, 0); |
1594 __ b(&fall_through, NE); | 1681 __ b(&fall_through, NE); |
1595 | 1682 |
1596 __ ldr(R0, FieldAddress(R2, Class::canonical_type_offset())); | 1683 __ ldr(R0, FieldAddress(R2, Class::canonical_type_offset())); |
1597 __ CompareObject(R0, Object::null_object()); | 1684 __ CompareObject(R0, Object::null_object()); |
1598 __ b(&fall_through, EQ); | 1685 __ b(&fall_through, EQ); |
1599 __ Ret(); | 1686 __ Ret(); |
1600 | 1687 |
1601 __ Bind(&fall_through); | 1688 __ Bind(&fall_through); |
1602 } | 1689 } |
1603 | 1690 |
1604 | 1691 |
| 1692 void Intrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler) { |
| 1693 Label fall_through, different_cids, equal, not_equal, not_integer; |
| 1694 __ ldr(R0, Address(SP, 0 * kWordSize)); |
| 1695 __ LoadClassIdMayBeSmi(R1, R0); |
| 1696 |
| 1697 // Check if left hand size is a closure. Closures are handled in the runtime. |
| 1698 __ CompareImmediate(R1, kClosureCid); |
| 1699 __ b(&fall_through, EQ); |
| 1700 |
| 1701 __ ldr(R0, Address(SP, 1 * kWordSize)); |
| 1702 __ LoadClassIdMayBeSmi(R2, R0); |
| 1703 |
| 1704 // Check whether class ids match. If class ids don't match objects can still |
| 1705 // have the same runtime type (e.g. multiple string implementation classes |
| 1706 // map to a single String type). |
| 1707 __ cmp(R1, Operand(R2)); |
| 1708 __ b(&different_cids, NE); |
| 1709 |
| 1710 // Objects have the same class and neither is a closure. |
| 1711 // Check if there are no type arguments. In this case we can return true. |
| 1712 // Otherwise fall through into the runtime to handle comparison. |
| 1713 __ LoadClassById(R3, R1); |
| 1714 __ ldrh(R3, FieldAddress(R3, Class::num_type_arguments_offset())); |
| 1715 __ CompareImmediate(R3, 0); |
| 1716 __ b(&fall_through, NE); |
| 1717 |
| 1718 __ Bind(&equal); |
| 1719 __ LoadObject(R0, Bool::True()); |
| 1720 __ Ret(); |
| 1721 |
| 1722 // Class ids are different. Check if we are comparing runtime types of |
| 1723 // two strings (with different representations) or two integers. |
| 1724 __ Bind(&different_cids); |
| 1725 __ CompareImmediate(R1, kNumPredefinedCids); |
| 1726 __ b(¬_equal, HI); |
| 1727 |
| 1728 // Check if both are integers. |
| 1729 JumpIfNotInteger(assembler, R1, R0, ¬_integer); |
| 1730 JumpIfInteger(assembler, R2, R0, &equal); |
| 1731 __ b(¬_equal); |
| 1732 |
| 1733 __ Bind(¬_integer); |
| 1734 // Check if both are strings. |
| 1735 JumpIfNotString(assembler, R1, R0, ¬_equal); |
| 1736 JumpIfString(assembler, R2, R0, &equal); |
| 1737 |
| 1738 // Neither strings nor integers and have different class ids. |
| 1739 __ Bind(¬_equal); |
| 1740 __ LoadObject(R0, Bool::False()); |
| 1741 __ Ret(); |
| 1742 |
| 1743 __ Bind(&fall_through); |
| 1744 } |
| 1745 |
| 1746 |
1605 void Intrinsifier::String_getHashCode(Assembler* assembler) { | 1747 void Intrinsifier::String_getHashCode(Assembler* assembler) { |
1606 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1748 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1607 __ ldr(R0, FieldAddress(R0, String::hash_offset())); | 1749 __ ldr(R0, FieldAddress(R0, String::hash_offset())); |
1608 __ cmp(R0, Operand(0)); | 1750 __ cmp(R0, Operand(0)); |
1609 __ bx(LR, NE); // Hash not yet computed. | 1751 __ bx(LR, NE); // Hash not yet computed. |
1610 } | 1752 } |
1611 | 1753 |
1612 | 1754 |
1613 void GenerateSubstringMatchesSpecialization(Assembler* assembler, | 1755 void GenerateSubstringMatchesSpecialization(Assembler* assembler, |
1614 intptr_t receiver_cid, | 1756 intptr_t receiver_cid, |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2153 __ ldr(R0, Address(R0, TimelineStream::enabled_offset())); | 2295 __ ldr(R0, Address(R0, TimelineStream::enabled_offset())); |
2154 __ cmp(R0, Operand(0)); | 2296 __ cmp(R0, Operand(0)); |
2155 __ LoadObject(R0, Bool::True(), NE); | 2297 __ LoadObject(R0, Bool::True(), NE); |
2156 __ LoadObject(R0, Bool::False(), EQ); | 2298 __ LoadObject(R0, Bool::False(), EQ); |
2157 __ Ret(); | 2299 __ Ret(); |
2158 } | 2300 } |
2159 | 2301 |
2160 } // namespace dart | 2302 } // namespace dart |
2161 | 2303 |
2162 #endif // defined TARGET_ARCH_ARM | 2304 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |