Chromium Code Reviews| 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 |