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 1555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1566 __ cmpq(RAX, Address(RSP, + kReceiverOffset * kWordSize)); | 1566 __ cmpq(RAX, Address(RSP, + kReceiverOffset * kWordSize)); |
1567 __ j(EQUAL, &is_true, Assembler::kNearJump); | 1567 __ j(EQUAL, &is_true, Assembler::kNearJump); |
1568 __ LoadObject(RAX, Bool::False()); | 1568 __ LoadObject(RAX, Bool::False()); |
1569 __ ret(); | 1569 __ ret(); |
1570 __ Bind(&is_true); | 1570 __ Bind(&is_true); |
1571 __ LoadObject(RAX, Bool::True()); | 1571 __ LoadObject(RAX, Bool::True()); |
1572 __ ret(); | 1572 __ ret(); |
1573 } | 1573 } |
1574 | 1574 |
1575 | 1575 |
1576 static void RangeCheck(Assembler* assembler, | |
1577 Register reg, | |
1578 intptr_t low, | |
1579 intptr_t high, | |
1580 Condition cc, | |
1581 Label* target) { | |
1582 __ subq(reg, Immediate(low)); | |
1583 __ cmpq(reg, Immediate(high - low)); | |
1584 __ j(cc, target); | |
1585 } | |
1586 | |
1587 | |
1588 const Condition kIfNotInRange = ABOVE; | |
1589 const Condition kIfInRange = BELOW_EQUAL; | |
1590 | |
1591 | |
1592 static void JumpIfInteger(Assembler* assembler, | |
1593 Register cid, | |
1594 Label* target) { | |
1595 RangeCheck(assembler, cid, kSmiCid, kBigintCid, kIfInRange, target); | |
1596 } | |
1597 | |
1598 | |
1599 static void JumpIfNotInteger(Assembler* assembler, | |
1600 Register cid, | |
1601 Label* target) { | |
1602 RangeCheck(assembler, cid, kSmiCid, kBigintCid, kIfNotInRange, target); | |
1603 } | |
1604 | |
1605 | |
1606 static void JumpIfString(Assembler* assembler, | |
1607 Register cid, | |
1608 Label* target) { | |
1609 RangeCheck(assembler, | |
1610 cid, | |
1611 kOneByteStringCid, | |
1612 kExternalTwoByteStringCid, | |
1613 kIfInRange, | |
1614 target); | |
1615 } | |
1616 | |
1617 | |
1618 static void JumpIfNotString(Assembler* assembler, | |
1619 Register cid, | |
1620 Label* target) { | |
1621 RangeCheck(assembler, | |
1622 cid, | |
1623 kOneByteStringCid, | |
1624 kExternalTwoByteStringCid, | |
1625 kIfNotInRange, | |
1626 target); | |
1627 } | |
1628 | |
1629 | |
1630 // Return type quickly for simple types (not parameterized and not signature). | 1576 // Return type quickly for simple types (not parameterized and not signature). |
1631 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { | 1577 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { |
1632 Label fall_through, use_canonical_type, not_integer, not_double; | 1578 Label fall_through; |
1633 __ movq(RAX, Address(RSP, + 1 * kWordSize)); | 1579 __ movq(RAX, Address(RSP, + 1 * kWordSize)); |
1634 __ LoadClassIdMayBeSmi(RCX, RAX); | 1580 __ LoadClassIdMayBeSmi(RCX, RAX); |
1635 | 1581 |
1636 // RCX: untagged cid of instance (RAX). | 1582 // RCX: untagged cid of instance (RAX). |
1637 __ cmpq(RCX, Immediate(kClosureCid)); | 1583 __ cmpq(RCX, Immediate(kClosureCid)); |
1638 __ j(EQUAL, &fall_through); // Instance is a closure. | 1584 __ j(EQUAL, &fall_through, Assembler::kNearJump); // Instance is a closure. |
1639 | 1585 |
1640 __ cmpl(RCX, Immediate(kNumPredefinedCids)); | 1586 __ LoadClassById(RDI, RCX); |
1641 __ j(ABOVE, &use_canonical_type); | 1587 // RDI: class of instance (RAX). |
1642 | 1588 |
1643 // If object is a instance of _Double return double type. | |
1644 __ cmpl(RCX, Immediate(kDoubleCid)); | |
1645 __ j(NOT_EQUAL, ¬_double); | |
1646 | |
1647 __ LoadIsolate(RAX); | |
1648 __ movq(RAX, Address(RAX, Isolate::object_store_offset())); | |
1649 __ movq(RAX, Address(RAX, ObjectStore::double_type_offset())); | |
1650 __ ret(); | |
1651 | |
1652 __ Bind(¬_double); | |
1653 // If object is an integer (smi, mint or bigint) return int type. | |
1654 __ movl(RAX, RCX); | |
1655 JumpIfNotInteger(assembler, RAX, ¬_integer); | |
1656 | |
1657 __ LoadIsolate(RAX); | |
1658 __ movq(RAX, Address(RAX, Isolate::object_store_offset())); | |
1659 __ movq(RAX, Address(RAX, ObjectStore::int_type_offset())); | |
1660 __ ret(); | |
1661 | |
1662 __ Bind(¬_integer); | |
1663 // If object is a string (one byte, two byte or external variants) return | |
1664 // string type. | |
1665 __ movq(RAX, RCX); | |
1666 JumpIfNotString(assembler, RAX, &use_canonical_type); | |
1667 | |
1668 __ LoadIsolate(RAX); | |
1669 __ movq(RAX, Address(RAX, Isolate::object_store_offset())); | |
1670 __ movq(RAX, Address(RAX, ObjectStore::string_type_offset())); | |
1671 __ ret(); | |
1672 | |
1673 // Object is neither double, nor integer, nor string. | |
1674 __ Bind(&use_canonical_type); | |
1675 __ LoadClassById(RDI, RCX); | |
1676 __ movzxw(RCX, FieldAddress(RDI, Class::num_type_arguments_offset())); | 1589 __ movzxw(RCX, FieldAddress(RDI, Class::num_type_arguments_offset())); |
1677 __ cmpq(RCX, Immediate(0)); | 1590 __ cmpq(RCX, Immediate(0)); |
1678 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); | 1591 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); |
1679 __ movq(RAX, FieldAddress(RDI, Class::canonical_type_offset())); | 1592 __ movq(RAX, FieldAddress(RDI, Class::canonical_type_offset())); |
1680 __ CompareObject(RAX, Object::null_object()); | 1593 __ CompareObject(RAX, Object::null_object()); |
1681 __ j(EQUAL, &fall_through, Assembler::kNearJump); // Not yet set. | 1594 __ j(EQUAL, &fall_through, Assembler::kNearJump); // Not yet set. |
1682 __ ret(); | 1595 __ ret(); |
1683 | 1596 |
1684 __ Bind(&fall_through); | 1597 __ Bind(&fall_through); |
1685 } | 1598 } |
1686 | 1599 |
1687 | 1600 |
1688 void Intrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler) { | |
1689 Label fall_through, different_cids, equal, not_equal, not_integer; | |
1690 | |
1691 __ movq(RAX, Address(RSP, + 1 * kWordSize)); | |
1692 __ LoadClassIdMayBeSmi(RCX, RAX); | |
1693 | |
1694 // Check if left hand size is a closure. Closures are handled in the runtime. | |
1695 __ cmpq(RCX, Immediate(kClosureCid)); | |
1696 __ j(EQUAL, &fall_through); | |
1697 | |
1698 __ movq(RAX, Address(RSP, + 2 * kWordSize)); | |
1699 __ LoadClassIdMayBeSmi(RDX, RAX); | |
1700 | |
1701 // Check whether class ids match. If class ids don't match objects can still | |
1702 // have the same runtime type (e.g. multiple string implementation classes | |
1703 // map to a single String type). | |
1704 __ cmpq(RCX, RDX); | |
1705 __ j(NOT_EQUAL, &different_cids); | |
1706 | |
1707 // Objects have the same class and neither is a closure. | |
1708 // Check if there are no type arguments. In this case we can return true. | |
1709 // Otherwise fall through into the runtime to handle comparison. | |
1710 __ LoadClassById(RDI, RCX); | |
1711 __ movzxw(RCX, FieldAddress(RDI, Class::num_type_arguments_offset())); | |
1712 __ cmpq(RCX, Immediate(0)); | |
1713 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); | |
1714 | |
1715 __ Bind(&equal); | |
1716 __ LoadObject(RAX, Bool::True()); | |
1717 __ ret(); | |
1718 | |
1719 // Class ids are different. Check if we are comparing runtime types of | |
1720 // two strings (with different representations) or two integers. | |
1721 __ Bind(&different_cids); | |
1722 __ cmpq(RCX, Immediate(kNumPredefinedCids)); | |
1723 __ j(ABOVE_EQUAL, ¬_equal); | |
1724 | |
1725 __ movq(RAX, RCX); | |
1726 JumpIfNotInteger(assembler, RAX, ¬_integer); | |
1727 | |
1728 // First object is an integer. Check if the second is an integer too. | |
1729 // Otherwise types are unequal because only integers have the same runtime | |
1730 // type as other integers. | |
1731 JumpIfInteger(assembler, RDX, &equal); | |
1732 __ jmp(¬_equal); | |
1733 | |
1734 __ Bind(¬_integer); | |
1735 // Check if the first object is a string. If it is not then | |
1736 // objects don't have the same runtime type because they have | |
1737 // different class ids and they are not strings or integers. | |
1738 JumpIfNotString(assembler, RCX, ¬_equal); | |
1739 // First object is a string. Check if the second is a string too. | |
1740 JumpIfString(assembler, RDX, &equal); | |
1741 // Strings only have the same runtime type as other strings. | |
1742 // Fall-through to the not equal case. | |
1743 | |
1744 __ Bind(¬_equal); | |
1745 __ LoadObject(RAX, Bool::False()); | |
1746 __ ret(); | |
1747 | |
1748 __ Bind(&fall_through); | |
1749 } | |
1750 | |
1751 | |
1752 void Intrinsifier::String_getHashCode(Assembler* assembler) { | 1601 void Intrinsifier::String_getHashCode(Assembler* assembler) { |
1753 Label fall_through; | 1602 Label fall_through; |
1754 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. | 1603 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. |
1755 __ movq(RAX, FieldAddress(RAX, String::hash_offset())); | 1604 __ movq(RAX, FieldAddress(RAX, String::hash_offset())); |
1756 __ cmpq(RAX, Immediate(0)); | 1605 __ cmpq(RAX, Immediate(0)); |
1757 __ j(EQUAL, &fall_through, Assembler::kNearJump); | 1606 __ j(EQUAL, &fall_through, Assembler::kNearJump); |
1758 __ ret(); | 1607 __ ret(); |
1759 __ Bind(&fall_through); | 1608 __ Bind(&fall_through); |
1760 // Hash not yet computed. | 1609 // Hash not yet computed. |
1761 } | 1610 } |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2295 __ Bind(&true_label); | 2144 __ Bind(&true_label); |
2296 __ LoadObject(RAX, Bool::True()); | 2145 __ LoadObject(RAX, Bool::True()); |
2297 __ ret(); | 2146 __ ret(); |
2298 } | 2147 } |
2299 | 2148 |
2300 #undef __ | 2149 #undef __ |
2301 | 2150 |
2302 } // namespace dart | 2151 } // namespace dart |
2303 | 2152 |
2304 #endif // defined TARGET_ARCH_X64 | 2153 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |