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_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 Loading... | |
| 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, ¬_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(¬_double); | |
| 1633 // If object is an integer (smi, mint or bigint) return int type. | |
| 1634 __ movl(RAX, RCX); | |
| 1635 JumpIfNotInteger(assembler, RAX, ¬_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(¬_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, ¬_equal); | |
| 1704 | |
| 1705 __ movq(RAX, RCX); | |
| 1706 JumpIfNotInteger(assembler, RAX, ¬_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(¬_equal); | |
| 1713 | |
| 1714 __ Bind(¬_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, ¬_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(¬_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 Loading... | |
| 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 |
| OLD | NEW |