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 | |
1643 // Return type quickly for simple types (not parameterized and not signature). | 1582 // Return type quickly for simple types (not parameterized and not signature). |
1644 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { | 1583 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { |
1645 Label fall_through, use_canonical_type, not_double, not_integer; | 1584 Label fall_through; |
1646 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1585 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1647 __ LoadClassIdMayBeSmi(R1, R0); | 1586 __ LoadClassIdMayBeSmi(R1, R0); |
1648 | |
1649 __ CompareImmediate(R1, kClosureCid); | 1587 __ CompareImmediate(R1, kClosureCid); |
1650 __ b(&fall_through, EQ); // Instance is a closure. | 1588 __ b(&fall_through, EQ); // Instance is a closure. |
| 1589 __ LoadClassById(R2, R1); |
| 1590 // R2: class of instance (R0). |
1651 | 1591 |
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); | |
1678 __ LoadClassById(R2, R1); | |
1679 __ ldrh(R3, FieldAddress(R2, Class::num_type_arguments_offset())); | 1592 __ ldrh(R3, FieldAddress(R2, Class::num_type_arguments_offset())); |
1680 __ CompareImmediate(R3, 0); | 1593 __ CompareImmediate(R3, 0); |
1681 __ b(&fall_through, NE); | 1594 __ b(&fall_through, NE); |
1682 | 1595 |
1683 __ ldr(R0, FieldAddress(R2, Class::canonical_type_offset())); | 1596 __ ldr(R0, FieldAddress(R2, Class::canonical_type_offset())); |
1684 __ CompareObject(R0, Object::null_object()); | 1597 __ CompareObject(R0, Object::null_object()); |
1685 __ b(&fall_through, EQ); | 1598 __ b(&fall_through, EQ); |
1686 __ Ret(); | 1599 __ Ret(); |
1687 | 1600 |
1688 __ Bind(&fall_through); | 1601 __ Bind(&fall_through); |
1689 } | 1602 } |
1690 | 1603 |
1691 | 1604 |
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 | |
1747 void Intrinsifier::String_getHashCode(Assembler* assembler) { | 1605 void Intrinsifier::String_getHashCode(Assembler* assembler) { |
1748 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1606 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1749 __ ldr(R0, FieldAddress(R0, String::hash_offset())); | 1607 __ ldr(R0, FieldAddress(R0, String::hash_offset())); |
1750 __ cmp(R0, Operand(0)); | 1608 __ cmp(R0, Operand(0)); |
1751 __ bx(LR, NE); // Hash not yet computed. | 1609 __ bx(LR, NE); // Hash not yet computed. |
1752 } | 1610 } |
1753 | 1611 |
1754 | 1612 |
1755 void GenerateSubstringMatchesSpecialization(Assembler* assembler, | 1613 void GenerateSubstringMatchesSpecialization(Assembler* assembler, |
1756 intptr_t receiver_cid, | 1614 intptr_t receiver_cid, |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2295 __ ldr(R0, Address(R0, TimelineStream::enabled_offset())); | 2153 __ ldr(R0, Address(R0, TimelineStream::enabled_offset())); |
2296 __ cmp(R0, Operand(0)); | 2154 __ cmp(R0, Operand(0)); |
2297 __ LoadObject(R0, Bool::True(), NE); | 2155 __ LoadObject(R0, Bool::True(), NE); |
2298 __ LoadObject(R0, Bool::False(), EQ); | 2156 __ LoadObject(R0, Bool::False(), EQ); |
2299 __ Ret(); | 2157 __ Ret(); |
2300 } | 2158 } |
2301 | 2159 |
2302 } // namespace dart | 2160 } // namespace dart |
2303 | 2161 |
2304 #endif // defined TARGET_ARCH_ARM | 2162 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |