Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(134)

Side by Side Diff: runtime/vm/intrinsifier_arm.cc

Issue 2379733002: Recognize and optimize a.runtimeType == b.runtimeType pattern. (Closed)
Patch Set: port to all arch, make AOT opt non-speculative Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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(&not_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(&not_double);
1639 JumpIfNotInteger(assembler, R1, R0, &not_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(&not_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(&not_equal, HI);
1702
1703 // Check if both are integers.
1704 JumpIfNotInteger(assembler, R1, R0, &not_integer);
1705 JumpIfInteger(assembler, R2, R0, &equal);
1706 __ b(&not_equal);
1707
1708 __ Bind(&not_integer);
1709 // Check if both are strings.
1710 JumpIfNotString(assembler, R1, R0, &not_equal);
1711 JumpIfString(assembler, R2, R0, &equal);
1712
1713 // Neither strings nor integers and have different class ids.
1714 __ Bind(&not_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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698