Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: runtime/vm/intermediate_language_ia32.cc

Issue 22915008: Tests for GuardField length check along with bug fixes (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698