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 1536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1547 void Intrinsifier::ObjectEquals(Assembler* assembler) { | 1547 void Intrinsifier::ObjectEquals(Assembler* assembler) { |
1548 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1548 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1549 __ ldr(R1, Address(SP, 1 * kWordSize)); | 1549 __ ldr(R1, Address(SP, 1 * kWordSize)); |
1550 __ cmp(R0, Operand(R1)); | 1550 __ cmp(R0, Operand(R1)); |
1551 __ LoadObject(R0, Bool::False(), NE); | 1551 __ LoadObject(R0, Bool::False(), NE); |
1552 __ LoadObject(R0, Bool::True(), EQ); | 1552 __ LoadObject(R0, Bool::True(), EQ); |
1553 __ Ret(); | 1553 __ Ret(); |
1554 } | 1554 } |
1555 | 1555 |
1556 | 1556 |
1557 static void RangeCheck(Assembler* assembler, | |
1558 Register val, | |
1559 Register tmp, | |
1560 intptr_t low, | |
1561 intptr_t high, | |
1562 Condition cc, | |
1563 Label* target) { | |
1564 __ SubImmediate(tmp, val, low); | |
1565 __ CompareImmediate(tmp, high - low); | |
1566 __ b(target, cc); | |
1567 } | |
1568 | |
1569 | |
1570 const Condition kIfNotInRange = HI; | |
1571 const Condition kIfInRange = LS; | |
1572 | |
1573 | |
1574 static void JumpIfInteger(Assembler* assembler, | |
1575 Register cid, | |
1576 Register tmp, | |
1577 Label* target) { | |
1578 RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfInRange, target); | |
1579 } | |
1580 | |
1581 | |
1582 static void JumpIfNotInteger(Assembler* assembler, | |
1583 Register cid, | |
1584 Register tmp, | |
1585 Label* target) { | |
1586 RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfNotInRange, target); | |
1587 } | |
1588 | |
1589 | |
1590 static void JumpIfString(Assembler* assembler, | |
1591 Register cid, | |
1592 Register tmp, | |
1593 Label* target) { | |
1594 RangeCheck(assembler, | |
1595 cid, | |
1596 tmp, | |
1597 kOneByteStringCid, | |
1598 kExternalTwoByteStringCid, | |
1599 kIfInRange, | |
1600 target); | |
1601 } | |
1602 | |
1603 | |
1604 static void JumpIfNotString(Assembler* assembler, | |
1605 Register cid, | |
1606 Register tmp, | |
1607 Label* target) { | |
1608 RangeCheck(assembler, | |
1609 cid, | |
1610 tmp, | |
1611 kOneByteStringCid, | |
1612 kExternalTwoByteStringCid, | |
1613 kIfNotInRange, | |
1614 target); | |
1615 } | |
1616 | |
1617 | |
1557 // Return type quickly for simple types (not parameterized and not signature). | 1618 // Return type quickly for simple types (not parameterized and not signature). |
1558 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { | 1619 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { |
1559 Label fall_through; | 1620 Label fall_through, use_canonical_type, not_double, not_integer; |
1560 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1621 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1561 __ LoadClassIdMayBeSmi(R1, R0); | 1622 __ LoadClassIdMayBeSmi(R1, R0); |
1623 | |
1562 __ CompareImmediate(R1, kClosureCid); | 1624 __ CompareImmediate(R1, kClosureCid); |
1563 __ b(&fall_through, EQ); // Instance is a closure. | 1625 __ b(&fall_through, EQ); // Instance is a closure. |
1626 | |
1627 __ CompareImmediate(R1, kNumPredefinedCids); | |
1628 __ b(&use_canonical_type, HI); | |
1629 | |
1630 __ CompareImmediate(R1, kDoubleCid); | |
1631 __ b(¬_double, NE); | |
1632 | |
1633 __ LoadIsolate(R0); | |
1634 __ LoadFromOffset(kWord, R0, R0, Isolate::object_store_offset()); | |
1635 __ LoadFromOffset(kWord, R0, R0, ObjectStore::double_type_offset()); | |
1636 __ Ret(); | |
1637 | |
1638 __ Bind(¬_double); | |
1639 JumpIfNotInteger(assembler, R1, R0, ¬_integer); | |
1640 __ LoadIsolate(R0); | |
1641 __ LoadFromOffset(kWord, R0, R0, Isolate::object_store_offset()); | |
1642 __ LoadFromOffset(kWord, R0, R0, ObjectStore::int_type_offset()); | |
1643 __ Ret(); | |
1644 | |
1645 __ Bind(¬_integer); | |
1646 JumpIfNotString(assembler, R1, R0, &use_canonical_type); | |
1647 __ LoadIsolate(R0); | |
1648 __ LoadFromOffset(kWord, R0, R0, Isolate::object_store_offset()); | |
1649 __ LoadFromOffset(kWord, R0, R0, ObjectStore::string_type_offset()); | |
1650 __ Ret(); | |
1651 | |
1652 __ Bind(&use_canonical_type); | |
1564 __ LoadClassById(R2, R1); | 1653 __ LoadClassById(R2, R1); |
1565 // R2: class of instance (R0). | |
1566 | |
1567 __ ldrh(R3, FieldAddress(R2, Class::num_type_arguments_offset())); | 1654 __ ldrh(R3, FieldAddress(R2, Class::num_type_arguments_offset())); |
1568 __ CompareImmediate(R3, 0); | 1655 __ CompareImmediate(R3, 0); |
1569 __ b(&fall_through, NE); | 1656 __ b(&fall_through, NE); |
1570 | 1657 |
1571 __ ldr(R0, FieldAddress(R2, Class::canonical_type_offset())); | 1658 __ ldr(R0, FieldAddress(R2, Class::canonical_type_offset())); |
1572 __ CompareObject(R0, Object::null_object()); | 1659 __ CompareObject(R0, Object::null_object()); |
1573 __ b(&fall_through, EQ); | 1660 __ b(&fall_through, EQ); |
1574 __ Ret(); | 1661 __ Ret(); |
1575 | 1662 |
1576 __ Bind(&fall_through); | 1663 __ Bind(&fall_through); |
1577 } | 1664 } |
1578 | 1665 |
1579 | 1666 |
1667 void Intrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler) { | |
1668 Label fall_through, different_cids, equal, not_equal, not_integer; | |
1669 __ ldr(R0, Address(SP, 0 * kWordSize)); | |
1670 __ LoadClassIdMayBeSmi(R1, R0); | |
1671 | |
1672 // Check if left hand size is a closure. Closures are handled in the runtime. | |
1673 __ CompareImmediate(R1, kClosureCid); | |
1674 __ b(&fall_through, EQ); | |
1675 | |
1676 __ ldr(R0, Address(SP, 1 * kWordSize)); | |
1677 __ LoadClassIdMayBeSmi(R2, R0); | |
1678 | |
1679 // Check whether class ids match. If class ids don't match objects can still | |
1680 // have the same runtime type (e.g. multiple string implementation classes | |
1681 // map to a single String type). | |
1682 __ cmp(R1, Operand(R2)); | |
1683 __ b(&different_cids, NE); | |
1684 | |
1685 // Objects have the same class and neither is a closure. | |
1686 // Check if there are no type arguments. In this case we can return true. | |
1687 // Otherwise fall through into the runtime to handle comparison. | |
1688 __ LoadClassById(R3, R1); | |
1689 __ ldrh(R3, FieldAddress(R3, Class::num_type_arguments_offset())); | |
regis
2016/10/08 09:10:37
You would cover more cases by checking the number
Vyacheslav Egorov (Google)
2016/10/24 20:23:03
Nice idea, thanks! This can be a further improveme
| |
1690 __ CompareImmediate(R3, 0); | |
1691 __ b(&fall_through, NE); | |
1692 | |
1693 __ Bind(&equal); | |
1694 __ LoadObject(R0, Bool::True()); | |
1695 __ Ret(); | |
1696 | |
1697 // Class ids are different. Check if we are comparing runtime types of | |
1698 // two strings (with different representations) or two integers. | |
1699 __ Bind(&different_cids); | |
1700 __ CompareImmediate(R1, kNumPredefinedCids); | |
1701 __ b(¬_equal, HI); | |
1702 | |
1703 // Check if both are integers. | |
1704 JumpIfNotInteger(assembler, R1, R0, ¬_integer); | |
1705 JumpIfInteger(assembler, R2, R0, &equal); | |
1706 __ b(¬_equal); | |
1707 | |
1708 __ Bind(¬_integer); | |
1709 // Check if both are strings. | |
1710 JumpIfNotString(assembler, R1, R0, ¬_equal); | |
1711 JumpIfString(assembler, R2, R0, &equal); | |
1712 | |
1713 // Neither strings nor integers and have different class ids. | |
1714 __ Bind(¬_equal); | |
1715 __ LoadObject(R0, Bool::False()); | |
1716 __ Ret(); | |
1717 | |
1718 __ Bind(&fall_through); | |
1719 } | |
1720 | |
1721 | |
1580 void Intrinsifier::String_getHashCode(Assembler* assembler) { | 1722 void Intrinsifier::String_getHashCode(Assembler* assembler) { |
1581 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1723 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1582 __ ldr(R0, FieldAddress(R0, String::hash_offset())); | 1724 __ ldr(R0, FieldAddress(R0, String::hash_offset())); |
1583 __ cmp(R0, Operand(0)); | 1725 __ cmp(R0, Operand(0)); |
1584 __ bx(LR, NE); // Hash not yet computed. | 1726 __ bx(LR, NE); // Hash not yet computed. |
1585 } | 1727 } |
1586 | 1728 |
1587 | 1729 |
1588 void GenerateSubstringMatchesSpecialization(Assembler* assembler, | 1730 void GenerateSubstringMatchesSpecialization(Assembler* assembler, |
1589 intptr_t receiver_cid, | 1731 intptr_t receiver_cid, |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2128 __ ldr(R0, Address(R0, TimelineStream::enabled_offset())); | 2270 __ ldr(R0, Address(R0, TimelineStream::enabled_offset())); |
2129 __ cmp(R0, Operand(0)); | 2271 __ cmp(R0, Operand(0)); |
2130 __ LoadObject(R0, Bool::True(), NE); | 2272 __ LoadObject(R0, Bool::True(), NE); |
2131 __ LoadObject(R0, Bool::False(), EQ); | 2273 __ LoadObject(R0, Bool::False(), EQ); |
2132 __ Ret(); | 2274 __ Ret(); |
2133 } | 2275 } |
2134 | 2276 |
2135 } // namespace dart | 2277 } // namespace dart |
2136 | 2278 |
2137 #endif // defined TARGET_ARCH_ARM | 2279 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |