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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 1594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1605 field_has_length || (field().guarded_cid() == kIllegalCid); | 1605 field_has_length || (field().guarded_cid() == kIllegalCid); |
| 1606 if (field_has_length) { | 1606 if (field_has_length) { |
| 1607 // Currently, we should only see final fields that remember length. | 1607 // Currently, we should only see final fields that remember length. |
| 1608 ASSERT(field().is_final()); | 1608 ASSERT(field().is_final()); |
| 1609 } | 1609 } |
| 1610 | 1610 |
| 1611 if (field_cid == kDynamicCid) { | 1611 if (field_cid == kDynamicCid) { |
| 1612 ASSERT(!compiler->is_optimizing()); | 1612 ASSERT(!compiler->is_optimizing()); |
| 1613 return; // Nothing to emit. | 1613 return; // Nothing to emit. |
| 1614 } | 1614 } |
| 1615 | |
| 1616 const intptr_t value_cid = value()->Type()->ToCid(); | 1615 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1617 | 1616 |
| 1618 Register value_reg = locs()->in(0).reg(); | 1617 Register value_reg = locs()->in(0).reg(); |
| 1619 | 1618 |
| 1620 Register value_cid_reg = needs_value_temp_reg ? | 1619 Register value_cid_reg = needs_value_temp_reg ? |
| 1621 locs()->temp(0).reg() : kNoRegister; | 1620 locs()->temp(0).reg() : kNoRegister; |
| 1622 | 1621 |
| 1623 Register field_reg = needs_field_temp_reg ? | 1622 Register field_reg = needs_field_temp_reg ? |
| 1624 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; | 1623 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; |
| 1625 | 1624 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 1651 field_reg, Field::guarded_list_length_offset()); | 1650 field_reg, Field::guarded_list_length_offset()); |
| 1652 | 1651 |
| 1653 if (value_cid == kDynamicCid) { | 1652 if (value_cid == kDynamicCid) { |
| 1654 if (value_cid_reg == kNoRegister) { | 1653 if (value_cid_reg == kNoRegister) { |
| 1655 ASSERT(!compiler->is_optimizing()); | 1654 ASSERT(!compiler->is_optimizing()); |
| 1656 value_cid_reg = EDX; | 1655 value_cid_reg = EDX; |
| 1657 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg)); | 1656 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg)); |
| 1658 } | 1657 } |
| 1659 | 1658 |
| 1660 LoadValueCid(compiler, value_cid_reg, value_reg); | 1659 LoadValueCid(compiler, value_cid_reg, value_reg); |
| 1661 | |
| 1662 Label skip_length_check; | 1660 Label skip_length_check; |
| 1663 __ cmpl(value_cid_reg, field_cid_operand); | 1661 __ cmpl(value_cid_reg, field_cid_operand); |
| 1664 // Value CID != Field guard CID, skip length check. | 1662 // Value CID != Field guard CID, skip length check. |
| 1665 __ j(NOT_EQUAL, &skip_length_check); | 1663 __ j(NOT_EQUAL, &skip_length_check); |
| 1666 if (field_has_length) { | 1664 if (field_has_length) { |
| 1667 // Field guard may have remembered list length, check it. | 1665 // Field guard may have remembered list length, check it. |
| 1668 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { | 1666 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { |
| 1669 __ pushl(value_cid_reg); | 1667 __ pushl(value_cid_reg); |
| 1670 __ movl(value_cid_reg, | 1668 __ movl(value_cid_reg, |
| 1671 FieldAddress(value_reg, Array::length_offset())); | 1669 FieldAddress(value_reg, Array::length_offset())); |
| 1672 __ cmpl(value_cid_reg, Immediate(field_length)); | 1670 __ cmpl(value_cid_reg, Immediate(Smi::RawValue(field_length))); |
| 1673 __ popl(value_cid_reg); | 1671 __ popl(value_cid_reg); |
| 1674 } else if (RawObject::IsTypedDataClassId(field_cid)) { | 1672 } else if (RawObject::IsTypedDataClassId(field_cid)) { |
| 1675 __ pushl(value_cid_reg); | 1673 __ pushl(value_cid_reg); |
| 1676 __ movl(value_cid_reg, | 1674 __ movl(value_cid_reg, |
| 1677 FieldAddress(value_reg, TypedData::length_offset())); | 1675 FieldAddress(value_reg, TypedData::length_offset())); |
| 1678 __ cmpl(value_cid_reg, Immediate(field_length)); | 1676 __ cmpl(value_cid_reg, Immediate(Smi::RawValue(field_length))); |
| 1679 __ popl(value_cid_reg); | 1677 __ popl(value_cid_reg); |
| 1680 } else { | 1678 } else { |
| 1681 ASSERT(field_cid == kIllegalCid); | 1679 ASSERT(field_cid == kIllegalCid); |
| 1682 // Following jump cannot not occur, fall through. | 1680 Label check_array, local_exit, local_fail; |
|
srdjan
2013/08/28 16:00:55
Optional: maybe rename the labels to be self-expla
srdjan
2013/08/28 16:00:55
Please remind me how can field_cid be kIllegalCid
Cutch
2013/08/28 19:20:36
field_cid is kIllegalCid and field_length is kUnkn
Cutch
2013/08/29 08:27:17
Done.
| |
| 1681 // Check field guard. | |
| 1682 __ cmpl(value_cid_reg, Immediate(kNullCid)); | |
| 1683 __ j(EQUAL, &local_fail); | |
| 1684 // Check for typed data array. | |
| 1685 __ cmpl(value_cid_reg, Immediate(kTypedDataFloat32x4ArrayCid)); | |
| 1686 __ j(GREATER, &local_fail); // Not a typed array or a regular array. | |
| 1687 __ cmpl(value_cid_reg, Immediate(kTypedDataInt8ArrayCid)); | |
| 1688 __ j(LESS, &check_array); // Could still be a regular array. | |
| 1689 __ pushl(value_cid_reg); | |
| 1690 __ movl(value_cid_reg, | |
| 1691 FieldAddress(value_reg, TypedData::length_offset())); | |
| 1692 __ cmpl(field_length_operand, value_cid_reg); | |
|
srdjan
2013/08/28 16:00:55
Eliminate push-pop, use cmpl(field_length, FieldAd
Cutch
2013/08/29 08:27:17
We do not know field_length at compile time, I've
srdjan
2013/08/29 16:05:25
I see: field_length_operand is an address, not a r
| |
| 1693 __ popl(value_cid_reg); | |
| 1694 __ jmp(&local_exit); | |
| 1695 // Check for regular array. | |
| 1696 __ Bind(&check_array); | |
| 1697 __ cmpl(value_cid_reg, Immediate(kImmutableArrayCid)); | |
| 1698 __ j(GREATER, &local_fail); | |
| 1699 __ cmpl(value_cid_reg, Immediate(kArrayCid)); | |
| 1700 __ j(LESS, &local_fail); | |
| 1701 __ pushl(value_cid_reg); | |
| 1702 __ movl(value_cid_reg, | |
| 1703 FieldAddress(value_reg, Array::length_offset())); | |
| 1704 __ cmpl(field_length_operand, value_cid_reg); | |
|
srdjan
2013/08/28 16:00:55
Use __ cmpl(field_length_operand, FieldAddress(...
Cutch
2013/08/29 08:27:17
field_length_operand is a FieldAddress there is no
| |
| 1705 __ popl(value_cid_reg); | |
| 1706 __ jmp(&local_exit); | |
| 1707 | |
| 1708 __ Bind(&local_fail); | |
| 1709 __ movl(field_length_operand, | |
| 1710 Immediate(Smi::RawValue(Field::kNoFixedLength))); | |
| 1711 | |
| 1712 __ Bind(&local_exit); | |
| 1683 } | 1713 } |
| 1684 __ j(NOT_EQUAL, fail); | 1714 __ j(NOT_EQUAL, fail); |
| 1685 } | 1715 } |
| 1686 __ Bind(&skip_length_check); | 1716 __ Bind(&skip_length_check); |
| 1687 __ cmpl(value_cid_reg, field_nullability_operand); | 1717 __ cmpl(value_cid_reg, field_nullability_operand); |
| 1688 } else if (value_cid == kNullCid) { | 1718 } else if (value_cid == kNullCid) { |
| 1689 // Value in graph known to be null. | 1719 // Value in graph known to be null. |
| 1690 // Compare with null. | 1720 // Compare with null. |
| 1691 __ cmpl(field_nullability_operand, Immediate(value_cid)); | 1721 __ cmpl(field_nullability_operand, Immediate(value_cid)); |
| 1692 } else { | 1722 } else { |
| 1693 // Value in graph known to be non-null. | 1723 // Value in graph known to be non-null. |
| 1694 Label skip_length_check; | 1724 Label skip_length_check; |
| 1695 // Compare class id with guard field class id. | 1725 // Compare class id with guard field class id. |
| 1696 __ cmpl(field_cid_operand, Immediate(value_cid)); | 1726 __ cmpl(field_cid_operand, Immediate(value_cid)); |
| 1697 // If not equal, skip over length check. | 1727 // If not equal, skip over length check. |
| 1698 __ j(NOT_EQUAL, &skip_length_check); | 1728 __ j(NOT_EQUAL, &skip_length_check); |
| 1699 // Insert length check. | 1729 // Insert length check. |
| 1700 if (field_has_length) { | 1730 if (field_has_length) { |
| 1701 if (value_cid_reg == kNoRegister) { | 1731 if (value_cid_reg == kNoRegister) { |
| 1702 ASSERT(!compiler->is_optimizing()); | 1732 ASSERT(!compiler->is_optimizing()); |
| 1703 value_cid_reg = EDX; | 1733 value_cid_reg = EDX; |
| 1704 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg)); | 1734 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg)); |
| 1705 } | 1735 } |
| 1706 ASSERT(value_cid_reg != kNoRegister); | 1736 ASSERT(value_cid_reg != kNoRegister); |
| 1707 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { | 1737 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) { |
| 1708 __ pushl(value_cid_reg); | 1738 __ pushl(value_cid_reg); |
| 1709 __ movl(value_cid_reg, | 1739 __ movl(value_cid_reg, |
| 1710 FieldAddress(value_reg, Array::length_offset())); | 1740 FieldAddress(value_reg, Array::length_offset())); |
| 1711 __ cmpl(value_cid_reg, Immediate(field_length)); | 1741 __ cmpl(value_cid_reg, Immediate(Smi::RawValue(field_length))); |
|
srdjan
2013/08/28 16:00:55
Eliminate push/pop by using __cmpl(FieldAddress(..
Cutch
2013/08/29 08:27:17
Done.
| |
| 1712 __ popl(value_cid_reg); | 1742 __ popl(value_cid_reg); |
| 1713 } else if (RawObject::IsTypedDataClassId(field_cid)) { | 1743 } else if (RawObject::IsTypedDataClassId(value_cid)) { |
| 1714 __ pushl(value_cid_reg); | 1744 __ pushl(value_cid_reg); |
| 1715 __ movl(value_cid_reg, | 1745 __ movl(value_cid_reg, |
| 1716 FieldAddress(value_reg, TypedData::length_offset())); | 1746 FieldAddress(value_reg, TypedData::length_offset())); |
| 1717 __ cmpl(value_cid_reg, Immediate(field_length)); | 1747 __ cmpl(value_cid_reg, Immediate(Smi::RawValue(field_length))); |
|
srdjan
2013/08/28 16:00:55
Eliminate push/pop
Cutch
2013/08/29 08:27:17
Done.
| |
| 1718 __ popl(value_cid_reg); | 1748 __ popl(value_cid_reg); |
| 1719 } else { | 1749 } else { |
| 1720 ASSERT(field_cid == kIllegalCid); | 1750 ASSERT(field_cid == kIllegalCid); |
| 1721 // Following jump cannot not occur, fall through. | 1751 // Following jump cannot not occur, fall through. |
| 1722 } | 1752 } |
| 1753 __ j(NOT_EQUAL, fail); | |
| 1723 } | 1754 } |
| 1724 // Not identical, possibly null. | 1755 // Not identical, possibly null. |
| 1725 __ Bind(&skip_length_check); | 1756 __ Bind(&skip_length_check); |
| 1726 } | 1757 } |
| 1727 // Jump when class id guard and list length guard are okay. | 1758 // Jump when class id guard and list length guard are okay. |
| 1728 __ j(EQUAL, &ok); | 1759 __ j(EQUAL, &ok); |
| 1729 | 1760 |
| 1730 | |
| 1731 // Check if guard field is uninitialized. | 1761 // Check if guard field is uninitialized. |
| 1732 __ cmpl(field_cid_operand, Immediate(kIllegalCid)); | 1762 __ cmpl(field_cid_operand, Immediate(kIllegalCid)); |
| 1733 // Jump to failure path when guard field has been initialized and | 1763 // Jump to failure path when guard field has been initialized and |
| 1734 // the field and value class ids do not not match. | 1764 // the field and value class ids do not not match. |
| 1735 __ j(NOT_EQUAL, fail); | 1765 __ j(NOT_EQUAL, fail); |
| 1736 | 1766 |
| 1737 // At this point the field guard is being initialized for the first time. | 1767 // At this point the field guard is being initialized for the first time. |
| 1738 if (value_cid == kDynamicCid) { | 1768 if (value_cid == kDynamicCid) { |
| 1739 // Do not know value's class id. | 1769 // Do not know value's class id. |
| 1740 __ movl(field_cid_operand, value_cid_reg); | 1770 __ movl(field_cid_operand, value_cid_reg); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1759 __ j(GREATER, &local_fail); | 1789 __ j(GREATER, &local_fail); |
| 1760 __ cmpl(value_cid_reg, Immediate(kArrayCid)); | 1790 __ cmpl(value_cid_reg, Immediate(kArrayCid)); |
| 1761 __ j(LESS, &local_fail); | 1791 __ j(LESS, &local_fail); |
| 1762 // Destroy value_cid_reg (safe because we are finished with it). | 1792 // Destroy value_cid_reg (safe because we are finished with it). |
| 1763 __ movl(value_cid_reg, | 1793 __ movl(value_cid_reg, |
| 1764 FieldAddress(value_reg, Array::length_offset())); | 1794 FieldAddress(value_reg, Array::length_offset())); |
| 1765 __ movl(field_length_operand, value_cid_reg); | 1795 __ movl(field_length_operand, value_cid_reg); |
| 1766 __ jmp(&local_exit); // Updated field length from regular array. | 1796 __ jmp(&local_exit); // Updated field length from regular array. |
| 1767 | 1797 |
| 1768 __ Bind(&local_fail); | 1798 __ Bind(&local_fail); |
| 1769 __ movl(field_length_operand, Immediate(Field::kNoFixedLength)); | 1799 __ movl(field_length_operand, |
| 1800 Immediate(Smi::RawValue(Field::kNoFixedLength))); | |
| 1770 | 1801 |
| 1771 __ Bind(&local_exit); | 1802 __ Bind(&local_exit); |
| 1772 } | 1803 } |
| 1773 } else { | 1804 } else { |
| 1774 if (value_cid_reg == kNoRegister) { | 1805 if (value_cid_reg == kNoRegister) { |
| 1775 ASSERT(!compiler->is_optimizing()); | 1806 ASSERT(!compiler->is_optimizing()); |
| 1776 value_cid_reg = EDX; | 1807 value_cid_reg = EDX; |
| 1777 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg)); | 1808 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg)); |
| 1778 } | 1809 } |
| 1779 ASSERT(value_cid_reg != kNoRegister); | 1810 ASSERT(value_cid_reg != kNoRegister); |
| 1780 ASSERT(field_reg != kNoRegister); | 1811 ASSERT(field_reg != kNoRegister); |
| 1781 __ movl(field_cid_operand, Immediate(value_cid)); | 1812 __ movl(field_cid_operand, Immediate(value_cid)); |
| 1782 __ movl(field_nullability_operand, Immediate(value_cid)); | 1813 __ movl(field_nullability_operand, Immediate(value_cid)); |
| 1783 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) { | 1814 if (field_has_length) { |
| 1784 // Destroy value_cid_reg (safe because we are finished with it). | 1815 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) { |
| 1785 __ movl(value_cid_reg, | 1816 // Destroy value_cid_reg (safe because we are finished with it). |
| 1786 FieldAddress(value_reg, Array::length_offset())); | 1817 __ movl(value_cid_reg, |
| 1787 __ movl(field_length_operand, value_cid_reg); | 1818 FieldAddress(value_reg, Array::length_offset())); |
| 1788 } else if (RawObject::IsTypedDataClassId(value_cid)) { | 1819 __ movl(field_length_operand, value_cid_reg); |
| 1789 // Destroy value_cid_reg (safe because we are finished with it). | 1820 } else if (RawObject::IsTypedDataClassId(value_cid)) { |
| 1790 __ movl(value_cid_reg, | 1821 // Destroy value_cid_reg (safe because we are finished with it). |
| 1791 FieldAddress(value_reg, TypedData::length_offset())); | 1822 __ movl(value_cid_reg, |
| 1792 __ movl(field_length_operand, value_cid_reg); | 1823 FieldAddress(value_reg, TypedData::length_offset())); |
| 1793 } else { | 1824 __ movl(field_length_operand, value_cid_reg); |
| 1794 __ movl(field_length_operand, Immediate(Field::kNoFixedLength)); | 1825 } else { |
| 1826 __ movl(field_length_operand, | |
| 1827 Immediate(Smi::RawValue(Field::kNoFixedLength))); | |
| 1828 } | |
| 1795 } | 1829 } |
| 1796 } | 1830 } |
| 1797 | 1831 |
| 1798 if (!ok_is_fall_through) { | 1832 if (!ok_is_fall_through) { |
| 1799 __ jmp(&ok); | 1833 __ jmp(&ok); |
| 1800 } | 1834 } |
| 1801 } else { | 1835 } else { |
| 1802 // Field guard class has been initialized and is known. | 1836 // Field guard class has been initialized and is known. |
| 1803 | |
| 1804 if (field_reg != kNoRegister) { | 1837 if (field_reg != kNoRegister) { |
| 1805 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); | 1838 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); |
| 1806 } | 1839 } |
| 1807 | 1840 |
| 1808 if (value_cid == kDynamicCid) { | 1841 if (value_cid == kDynamicCid) { |
| 1809 // Value's class id is not known. | 1842 // Value's class id is not known. |
| 1810 __ testl(value_reg, Immediate(kSmiTagMask)); | 1843 __ testl(value_reg, Immediate(kSmiTagMask)); |
| 1811 | 1844 |
| 1812 if (field_cid != kSmiCid) { | 1845 if (field_cid != kSmiCid) { |
| 1813 __ j(ZERO, fail); | 1846 __ j(ZERO, fail); |
| (...skipping 3441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5255 PcDescriptors::kOther, | 5288 PcDescriptors::kOther, |
| 5256 locs()); | 5289 locs()); |
| 5257 __ Drop(2); // Discard type arguments and receiver. | 5290 __ Drop(2); // Discard type arguments and receiver. |
| 5258 } | 5291 } |
| 5259 | 5292 |
| 5260 } // namespace dart | 5293 } // namespace dart |
| 5261 | 5294 |
| 5262 #undef __ | 5295 #undef __ |
| 5263 | 5296 |
| 5264 #endif // defined TARGET_ARCH_IA32 | 5297 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |