| 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 |