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())); | |
regis
2016/10/08 09:10:37
ditto
Vyacheslav Egorov (Google)
2016/10/24 20:23:03
Acknowledged.
| |
1692 __ cmpq(RCX, Immediate(0)); | |
1693 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); | |
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 |