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 |
1576 // Return type quickly for simple types (not parameterized and not signature). | 1630 // Return type quickly for simple types (not parameterized and not signature). |
1577 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { | 1631 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { |
1578 Label fall_through; | 1632 Label fall_through, use_canonical_type, not_integer, not_double; |
1579 __ movq(RAX, Address(RSP, + 1 * kWordSize)); | 1633 __ movq(RAX, Address(RSP, + 1 * kWordSize)); |
1580 __ LoadClassIdMayBeSmi(RCX, RAX); | 1634 __ LoadClassIdMayBeSmi(RCX, RAX); |
1581 | 1635 |
1582 // RCX: untagged cid of instance (RAX). | 1636 // RCX: untagged cid of instance (RAX). |
1583 __ cmpq(RCX, Immediate(kClosureCid)); | 1637 __ cmpq(RCX, Immediate(kClosureCid)); |
1584 __ j(EQUAL, &fall_through, Assembler::kNearJump); // Instance is a closure. | 1638 __ j(EQUAL, &fall_through); // Instance is a closure. |
1585 | 1639 |
| 1640 __ cmpl(RCX, Immediate(kNumPredefinedCids)); |
| 1641 __ j(ABOVE, &use_canonical_type); |
| 1642 |
| 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); |
1586 __ LoadClassById(RDI, RCX); | 1675 __ LoadClassById(RDI, RCX); |
1587 // RDI: class of instance (RAX). | |
1588 | |
1589 __ movzxw(RCX, FieldAddress(RDI, Class::num_type_arguments_offset())); | 1676 __ movzxw(RCX, FieldAddress(RDI, Class::num_type_arguments_offset())); |
1590 __ cmpq(RCX, Immediate(0)); | 1677 __ cmpq(RCX, Immediate(0)); |
1591 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); | 1678 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); |
1592 __ movq(RAX, FieldAddress(RDI, Class::canonical_type_offset())); | 1679 __ movq(RAX, FieldAddress(RDI, Class::canonical_type_offset())); |
1593 __ CompareObject(RAX, Object::null_object()); | 1680 __ CompareObject(RAX, Object::null_object()); |
1594 __ j(EQUAL, &fall_through, Assembler::kNearJump); // Not yet set. | 1681 __ j(EQUAL, &fall_through, Assembler::kNearJump); // Not yet set. |
1595 __ ret(); | 1682 __ ret(); |
1596 | 1683 |
1597 __ Bind(&fall_through); | 1684 __ Bind(&fall_through); |
1598 } | 1685 } |
1599 | 1686 |
1600 | 1687 |
| 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 |
1601 void Intrinsifier::String_getHashCode(Assembler* assembler) { | 1752 void Intrinsifier::String_getHashCode(Assembler* assembler) { |
1602 Label fall_through; | 1753 Label fall_through; |
1603 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. | 1754 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. |
1604 __ movq(RAX, FieldAddress(RAX, String::hash_offset())); | 1755 __ movq(RAX, FieldAddress(RAX, String::hash_offset())); |
1605 __ cmpq(RAX, Immediate(0)); | 1756 __ cmpq(RAX, Immediate(0)); |
1606 __ j(EQUAL, &fall_through, Assembler::kNearJump); | 1757 __ j(EQUAL, &fall_through, Assembler::kNearJump); |
1607 __ ret(); | 1758 __ ret(); |
1608 __ Bind(&fall_through); | 1759 __ Bind(&fall_through); |
1609 // Hash not yet computed. | 1760 // Hash not yet computed. |
1610 } | 1761 } |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2144 __ Bind(&true_label); | 2295 __ Bind(&true_label); |
2145 __ LoadObject(RAX, Bool::True()); | 2296 __ LoadObject(RAX, Bool::True()); |
2146 __ ret(); | 2297 __ ret(); |
2147 } | 2298 } |
2148 | 2299 |
2149 #undef __ | 2300 #undef __ |
2150 | 2301 |
2151 } // namespace dart | 2302 } // namespace dart |
2152 | 2303 |
2153 #endif // defined TARGET_ARCH_X64 | 2304 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |