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

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

Issue 2379733002: Recognize and optimize a.runtimeType == b.runtimeType pattern. (Closed)
Patch Set: Support polymorphic inlining of Object.get:runtimeType 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_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
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 1535 matching lines...) Expand 10 before | Expand all | Expand 10 after
1546 __ cmpq(RAX, Address(RSP, + kReceiverOffset * kWordSize)); 1546 __ cmpq(RAX, Address(RSP, + kReceiverOffset * kWordSize));
1547 __ j(EQUAL, &is_true, Assembler::kNearJump); 1547 __ j(EQUAL, &is_true, Assembler::kNearJump);
1548 __ LoadObject(RAX, Bool::False()); 1548 __ LoadObject(RAX, Bool::False());
1549 __ ret(); 1549 __ ret();
1550 __ Bind(&is_true); 1550 __ Bind(&is_true);
1551 __ LoadObject(RAX, Bool::True()); 1551 __ LoadObject(RAX, Bool::True());
1552 __ ret(); 1552 __ ret();
1553 } 1553 }
1554 1554
1555 1555
1556 static void RangeCheck(Assembler* assembler,
1557 Register reg,
1558 intptr_t low,
1559 intptr_t high,
1560 Condition cc,
1561 Label* target) {
1562 __ subq(reg, Immediate(low));
1563 __ cmpq(reg, Immediate(high - low));
1564 __ j(cc, target);
1565 }
1566
1567
1568 const Condition kIfNotInRange = ABOVE;
1569 const Condition kIfInRange = BELOW_EQUAL;
1570
1571
1572 static void JumpIfInteger(Assembler* assembler,
1573 Register cid,
1574 Label* target) {
1575 RangeCheck(assembler, cid, kSmiCid, kBigintCid, kIfInRange, target);
1576 }
1577
1578
1579 static void JumpIfNotInteger(Assembler* assembler,
1580 Register cid,
1581 Label* target) {
1582 RangeCheck(assembler, cid, kSmiCid, kBigintCid, kIfNotInRange, target);
1583 }
1584
1585
1586 static void JumpIfString(Assembler* assembler,
1587 Register cid,
1588 Label* target) {
1589 RangeCheck(assembler,
1590 cid,
1591 kOneByteStringCid,
1592 kExternalTwoByteStringCid,
1593 kIfInRange,
1594 target);
1595 }
1596
1597
1598 static void JumpIfNotString(Assembler* assembler,
1599 Register cid,
1600 Label* target) {
1601 RangeCheck(assembler,
1602 cid,
1603 kOneByteStringCid,
1604 kExternalTwoByteStringCid,
1605 kIfNotInRange,
1606 target);
1607 }
1608
1609
1556 // Return type quickly for simple types (not parameterized and not signature). 1610 // Return type quickly for simple types (not parameterized and not signature).
1557 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { 1611 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) {
1558 Label fall_through; 1612 Label fall_through, use_canonical_type, not_integer, not_double;
1559 __ movq(RAX, Address(RSP, + 1 * kWordSize)); 1613 __ movq(RAX, Address(RSP, + 1 * kWordSize));
1560 __ LoadClassIdMayBeSmi(RCX, RAX); 1614 __ LoadClassIdMayBeSmi(RCX, RAX);
1561 1615
1562 // RCX: untagged cid of instance (RAX). 1616 // RCX: untagged cid of instance (RAX).
1563 __ cmpq(RCX, Immediate(kClosureCid)); 1617 __ cmpq(RCX, Immediate(kClosureCid));
1564 __ j(EQUAL, &fall_through, Assembler::kNearJump); // Instance is a closure. 1618 __ j(EQUAL, &fall_through); // Instance is a closure.
1565 1619
1620 __ cmpl(RCX, Immediate(kNumPredefinedCids));
1621 __ j(ABOVE, &use_canonical_type);
1622
1623 // If object is a instance of _Double return double type.
1624 __ cmpl(RCX, Immediate(kDoubleCid));
1625 __ j(NOT_EQUAL, &not_double);
1626
1627 __ LoadIsolate(RAX);
1628 __ movq(RAX, Address(RAX, Isolate::object_store_offset()));
1629 __ movq(RAX, Address(RAX, ObjectStore::double_type_offset()));
1630 __ ret();
1631
1632 __ Bind(&not_double);
1633 // If object is an integer (smi, mint or bigint) return int type.
1634 __ movl(RAX, RCX);
1635 JumpIfNotInteger(assembler, RAX, &not_integer);
1636
1637 __ LoadIsolate(RAX);
1638 __ movq(RAX, Address(RAX, Isolate::object_store_offset()));
1639 __ movq(RAX, Address(RAX, ObjectStore::int_type_offset()));
1640 __ ret();
1641
1642 __ Bind(&not_integer);
1643 // If object is a string (one byte, two byte or external variants) return
1644 // string type.
1645 __ movq(RAX, RCX);
1646 JumpIfNotString(assembler, RAX, &use_canonical_type);
1647
1648 __ LoadIsolate(RAX);
1649 __ movq(RAX, Address(RAX, Isolate::object_store_offset()));
1650 __ movq(RAX, Address(RAX, ObjectStore::string_type_offset()));
1651 __ ret();
1652
1653 // Object is neither double, nor integer, nor string.
1654 __ Bind(&use_canonical_type);
1566 __ LoadClassById(RDI, RCX); 1655 __ LoadClassById(RDI, RCX);
1567 // RDI: class of instance (RAX).
1568
1569 __ movzxw(RCX, FieldAddress(RDI, Class::num_type_arguments_offset())); 1656 __ movzxw(RCX, FieldAddress(RDI, Class::num_type_arguments_offset()));
1570 __ cmpq(RCX, Immediate(0)); 1657 __ cmpq(RCX, Immediate(0));
1571 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); 1658 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
1572 __ movq(RAX, FieldAddress(RDI, Class::canonical_type_offset())); 1659 __ movq(RAX, FieldAddress(RDI, Class::canonical_type_offset()));
1573 __ CompareObject(RAX, Object::null_object()); 1660 __ CompareObject(RAX, Object::null_object());
1574 __ j(EQUAL, &fall_through, Assembler::kNearJump); // Not yet set. 1661 __ j(EQUAL, &fall_through, Assembler::kNearJump); // Not yet set.
1575 __ ret(); 1662 __ ret();
1576 1663
1577 __ Bind(&fall_through); 1664 __ Bind(&fall_through);
1578 } 1665 }
1579 1666
1580 1667
1668 void Intrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler) {
1669 Label fall_through, different_cids, equal, not_equal, not_integer;
1670
1671 __ movq(RAX, Address(RSP, + 1 * kWordSize));
1672 __ LoadClassIdMayBeSmi(RCX, RAX);
1673
1674 // Check if left hand size is a closure. Closures are handled in the runtime.
1675 __ cmpq(RCX, Immediate(kClosureCid));
1676 __ j(EQUAL, &fall_through);
1677
1678 __ movq(RAX, Address(RSP, + 2 * kWordSize));
1679 __ LoadClassIdMayBeSmi(RDX, RAX);
1680
1681 // Check whether class ids match. If class ids don't match objects can still
1682 // have the same runtime type (e.g. multiple string implementation classes
1683 // map to a single String type).
1684 __ cmpq(RCX, RDX);
1685 __ j(NOT_EQUAL, &different_cids);
1686
1687 // Objects have the same class and neither is a closure.
1688 // Check if there are no type arguments. In this case we can return true.
1689 // Otherwise fall through into the runtime to handle comparison.
1690 __ LoadClassById(RDI, RCX);
1691 __ movzxw(RCX, FieldAddress(RDI, Class::num_type_arguments_offset()));
1692 __ cmpq(RCX, Immediate(0));
1693 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
Florian Schneider 2016/09/29 18:03:29 Idea: To make the comparison with parameterized cl
Vyacheslav Egorov (Google) 2016/09/30 09:56:28 Yes, that would be neat, but I think it's not that
Florian Schneider 2016/09/30 17:42:56 Agreed.
1694
1695 __ Bind(&equal);
1696 __ LoadObject(RAX, Bool::True());
1697 __ ret();
1698
1699 // Class ids are different. Check if we are comparing runtime types of
1700 // two strings (with different representations) or two integers.
1701 __ Bind(&different_cids);
1702 __ cmpq(RCX, Immediate(kNumPredefinedCids));
1703 __ j(ABOVE_EQUAL, &not_equal);
1704
1705 __ movq(RAX, RCX);
1706 JumpIfNotInteger(assembler, RAX, &not_integer);
1707
1708 // First object is an integer. Check if the second is an integer too.
1709 // Otherwise types are unequal because only integers have the same runtime
1710 // type as other integers.
1711 JumpIfInteger(assembler, RDX, &equal);
1712 __ jmp(&not_equal);
1713
1714 __ Bind(&not_integer);
1715 // Check if the first object is a string. If it is not then
1716 // objects don't have the same runtime type because they have
1717 // different class ids and they are not strings or integers.
1718 JumpIfNotString(assembler, RCX, &not_equal);
1719 // First object is a string. Check if the second is a string too.
1720 JumpIfString(assembler, RDX, &equal);
1721 // Strings only have the same runtime type as other strings.
1722 // Fall-through to the not equal case.
1723
1724 __ Bind(&not_equal);
1725 __ LoadObject(RAX, Bool::False());
1726 __ ret();
1727
1728 __ Bind(&fall_through);
1729 }
1730
1731
1581 void Intrinsifier::String_getHashCode(Assembler* assembler) { 1732 void Intrinsifier::String_getHashCode(Assembler* assembler) {
1582 Label fall_through; 1733 Label fall_through;
1583 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. 1734 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object.
1584 __ movq(RAX, FieldAddress(RAX, String::hash_offset())); 1735 __ movq(RAX, FieldAddress(RAX, String::hash_offset()));
1585 __ cmpq(RAX, Immediate(0)); 1736 __ cmpq(RAX, Immediate(0));
1586 __ j(EQUAL, &fall_through, Assembler::kNearJump); 1737 __ j(EQUAL, &fall_through, Assembler::kNearJump);
1587 __ ret(); 1738 __ ret();
1588 __ Bind(&fall_through); 1739 __ Bind(&fall_through);
1589 // Hash not yet computed. 1740 // Hash not yet computed.
1590 } 1741 }
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after
2124 __ Bind(&true_label); 2275 __ Bind(&true_label);
2125 __ LoadObject(RAX, Bool::True()); 2276 __ LoadObject(RAX, Bool::True());
2126 __ ret(); 2277 __ ret();
2127 } 2278 }
2128 2279
2129 #undef __ 2280 #undef __
2130 2281
2131 } // namespace dart 2282 } // namespace dart
2132 2283
2133 #endif // defined TARGET_ARCH_X64 2284 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698