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

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
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | runtime/vm/intermediate_language_mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 1521 matching lines...) Expand 10 before | Expand all | Expand 10 after
1532 field_has_length || (field().guarded_cid() == kIllegalCid); 1532 field_has_length || (field().guarded_cid() == kIllegalCid);
1533 if (field_has_length) { 1533 if (field_has_length) {
1534 // Currently, we should only see final fields that remember length. 1534 // Currently, we should only see final fields that remember length.
1535 ASSERT(field().is_final()); 1535 ASSERT(field().is_final());
1536 } 1536 }
1537 1537
1538 if (field_cid == kDynamicCid) { 1538 if (field_cid == kDynamicCid) {
1539 ASSERT(!compiler->is_optimizing()); 1539 ASSERT(!compiler->is_optimizing());
1540 return; // Nothing to emit. 1540 return; // Nothing to emit.
1541 } 1541 }
1542
1543 const intptr_t value_cid = value()->Type()->ToCid(); 1542 const intptr_t value_cid = value()->Type()->ToCid();
1544 1543
1545 Register value_reg = locs()->in(0).reg(); 1544 Register value_reg = locs()->in(0).reg();
1546 1545
1547 Register value_cid_reg = needs_value_temp_reg ? 1546 Register value_cid_reg = needs_value_temp_reg ?
1548 locs()->temp(0).reg() : kNoRegister; 1547 locs()->temp(0).reg() : kNoRegister;
1549 1548
1550 Register field_reg = needs_field_temp_reg ? 1549 Register field_reg = needs_field_temp_reg ?
1551 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; 1550 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister;
1552 1551
(...skipping 25 matching lines...) Expand all
1578 field_reg, Field::guarded_list_length_offset()); 1577 field_reg, Field::guarded_list_length_offset());
1579 1578
1580 if (value_cid == kDynamicCid) { 1579 if (value_cid == kDynamicCid) {
1581 if (value_cid_reg == kNoRegister) { 1580 if (value_cid_reg == kNoRegister) {
1582 ASSERT(!compiler->is_optimizing()); 1581 ASSERT(!compiler->is_optimizing());
1583 value_cid_reg = EDX; 1582 value_cid_reg = EDX;
1584 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg)); 1583 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
1585 } 1584 }
1586 1585
1587 LoadValueCid(compiler, value_cid_reg, value_reg); 1586 LoadValueCid(compiler, value_cid_reg, value_reg);
1588
1589 Label skip_length_check; 1587 Label skip_length_check;
1590 __ cmpl(value_cid_reg, field_cid_operand); 1588 __ cmpl(value_cid_reg, field_cid_operand);
1591 // Value CID != Field guard CID, skip length check. 1589 // Value CID != Field guard CID, skip length check.
1592 __ j(NOT_EQUAL, &skip_length_check); 1590 __ j(NOT_EQUAL, &skip_length_check);
1593 if (field_has_length) { 1591 if (field_has_length) {
1594 // Field guard may have remembered list length, check it. 1592 // Field guard may have remembered list length, check it.
1595 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { 1593 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1596 __ pushl(value_cid_reg); 1594 __ pushl(value_cid_reg);
1597 __ movl(value_cid_reg, 1595 __ movl(value_cid_reg,
1598 FieldAddress(value_reg, Array::length_offset())); 1596 FieldAddress(value_reg, Array::length_offset()));
1599 __ cmpl(value_cid_reg, Immediate(field_length)); 1597 __ cmpl(value_cid_reg, Immediate(Smi::RawValue(field_length)));
1600 __ popl(value_cid_reg); 1598 __ popl(value_cid_reg);
1601 } else if (RawObject::IsTypedDataClassId(field_cid)) { 1599 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1602 __ pushl(value_cid_reg); 1600 __ pushl(value_cid_reg);
1603 __ movl(value_cid_reg, 1601 __ movl(value_cid_reg,
1604 FieldAddress(value_reg, TypedData::length_offset())); 1602 FieldAddress(value_reg, TypedData::length_offset()));
1605 __ cmpl(value_cid_reg, Immediate(field_length)); 1603 __ cmpl(value_cid_reg, Immediate(Smi::RawValue(field_length)));
1606 __ popl(value_cid_reg); 1604 __ popl(value_cid_reg);
1607 } else { 1605 } else {
1608 ASSERT(field_cid == kIllegalCid); 1606 ASSERT(field_cid == kIllegalCid);
1609 // Following jump cannot not occur, fall through. 1607 ASSERT(field_length == Field::kUnknownFixedLength);
1608 // At compile time we do not know the type of the field nor its
1609 // length. At execution time we may have set the class id and
1610 // list length so we compare the guarded length with the
1611 // list length here, without this check the list length could change
1612 // without triggering a deoptimization.
1613 Label check_array, length_compared, no_fixed_length;
1614 __ cmpl(value_cid_reg, Immediate(kNullCid));
1615 __ j(EQUAL, &no_fixed_length, Assembler::kNearJump);
1616 // Check for typed data array.
1617 __ cmpl(value_cid_reg, Immediate(kTypedDataFloat32x4ArrayCid));
1618 // Not a typed array or a regular array.
1619 __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
1620 __ cmpl(value_cid_reg, Immediate(kTypedDataInt8ArrayCid));
1621 // Could still be a regular array.
1622 __ j(LESS, &check_array, Assembler::kNearJump);
1623 __ pushl(value_cid_reg);
1624 __ movl(value_cid_reg,
1625 FieldAddress(value_reg, TypedData::length_offset()));
1626 __ cmpl(field_length_operand, value_cid_reg);
1627 __ popl(value_cid_reg);
1628 __ jmp(&length_compared, Assembler::kNearJump);
1629 // Check for regular array.
1630 __ Bind(&check_array);
1631 __ cmpl(value_cid_reg, Immediate(kImmutableArrayCid));
1632 __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
1633 __ cmpl(value_cid_reg, Immediate(kArrayCid));
1634 __ j(LESS, &no_fixed_length, Assembler::kNearJump);
1635 __ pushl(value_cid_reg);
1636 __ movl(value_cid_reg,
1637 FieldAddress(value_reg, Array::length_offset()));
1638 __ cmpl(field_length_operand, value_cid_reg);
1639 __ popl(value_cid_reg);
1640 __ jmp(&length_compared, Assembler::kNearJump);
1641 __ Bind(&no_fixed_length);
1642 __ jmp(fail);
1643 __ Bind(&length_compared);
1610 } 1644 }
1611 __ j(NOT_EQUAL, fail); 1645 __ j(NOT_EQUAL, fail);
1612 } 1646 }
1613 __ Bind(&skip_length_check); 1647 __ Bind(&skip_length_check);
1614 __ cmpl(value_cid_reg, field_nullability_operand); 1648 __ cmpl(value_cid_reg, field_nullability_operand);
1615 } else if (value_cid == kNullCid) { 1649 } else if (value_cid == kNullCid) {
1616 // Value in graph known to be null. 1650 // Value in graph known to be null.
1617 // Compare with null. 1651 // Compare with null.
1618 __ cmpl(field_nullability_operand, Immediate(value_cid)); 1652 __ cmpl(field_nullability_operand, Immediate(value_cid));
1619 } else { 1653 } else {
1620 // Value in graph known to be non-null. 1654 // Value in graph known to be non-null.
1621 Label skip_length_check; 1655 Label skip_length_check;
1622 // Compare class id with guard field class id. 1656 // Compare class id with guard field class id.
1623 __ cmpl(field_cid_operand, Immediate(value_cid)); 1657 __ cmpl(field_cid_operand, Immediate(value_cid));
1624 // If not equal, skip over length check. 1658 // If not equal, skip over length check.
1625 __ j(NOT_EQUAL, &skip_length_check); 1659 __ j(NOT_EQUAL, &skip_length_check);
1626 // Insert length check. 1660 // Insert length check.
1627 if (field_has_length) { 1661 if (field_has_length) {
1628 if (value_cid_reg == kNoRegister) {
1629 ASSERT(!compiler->is_optimizing());
1630 value_cid_reg = EDX;
1631 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
1632 }
1633 ASSERT(value_cid_reg != kNoRegister); 1662 ASSERT(value_cid_reg != kNoRegister);
1634 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { 1663 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1635 __ pushl(value_cid_reg); 1664 __ cmpl(FieldAddress(value_reg, Array::length_offset()),
1636 __ movl(value_cid_reg, 1665 Immediate(Smi::RawValue(field_length)));
1637 FieldAddress(value_reg, Array::length_offset())); 1666 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1638 __ cmpl(value_cid_reg, Immediate(field_length)); 1667 __ cmpl(FieldAddress(value_reg, TypedData::length_offset()),
1639 __ popl(value_cid_reg); 1668 Immediate(Smi::RawValue(field_length)));
1640 } else if (RawObject::IsTypedDataClassId(field_cid)) { 1669 } else if (field_cid != kIllegalCid) {
1641 __ pushl(value_cid_reg); 1670 ASSERT(field_cid != value_cid);
1642 __ movl(value_cid_reg, 1671 ASSERT(field_length >= 0);
1643 FieldAddress(value_reg, TypedData::length_offset())); 1672 // Field has a known class id and length. At compile time it is
1644 __ cmpl(value_cid_reg, Immediate(field_length)); 1673 // known that the value's class id is not a fixed length list.
1645 __ popl(value_cid_reg); 1674 __ jmp(fail);
1646 } else { 1675 } else {
1647 ASSERT(field_cid == kIllegalCid); 1676 ASSERT(field_cid == kIllegalCid);
1677 ASSERT(field_length == Field::kUnknownFixedLength);
1648 // Following jump cannot not occur, fall through. 1678 // Following jump cannot not occur, fall through.
1649 } 1679 }
1680 __ j(NOT_EQUAL, fail);
1650 } 1681 }
1651 // Not identical, possibly null. 1682 // Not identical, possibly null.
1652 __ Bind(&skip_length_check); 1683 __ Bind(&skip_length_check);
1653 } 1684 }
1654 // Jump when class id guard and list length guard are okay. 1685 // Jump when class id guard and list length guard are okay.
1655 __ j(EQUAL, &ok); 1686 __ j(EQUAL, &ok);
1656 1687
1657
1658 // Check if guard field is uninitialized. 1688 // Check if guard field is uninitialized.
1659 __ cmpl(field_cid_operand, Immediate(kIllegalCid)); 1689 __ cmpl(field_cid_operand, Immediate(kIllegalCid));
1660 // Jump to failure path when guard field has been initialized and 1690 // Jump to failure path when guard field has been initialized and
1661 // the field and value class ids do not not match. 1691 // the field and value class ids do not not match.
1662 __ j(NOT_EQUAL, fail); 1692 __ j(NOT_EQUAL, fail);
1663 1693
1664 // At this point the field guard is being initialized for the first time. 1694 // At this point the field guard is being initialized for the first time.
1665 if (value_cid == kDynamicCid) { 1695 if (value_cid == kDynamicCid) {
1666 // Do not know value's class id. 1696 // Do not know value's class id.
1667 __ movl(field_cid_operand, value_cid_reg); 1697 __ movl(field_cid_operand, value_cid_reg);
1668 __ movl(field_nullability_operand, value_cid_reg); 1698 __ movl(field_nullability_operand, value_cid_reg);
1669 if (field_has_length) { 1699 if (field_has_length) {
1670 Label check_array, local_exit, local_fail; 1700 Label check_array, length_set, no_fixed_length;
1671 __ cmpl(value_cid_reg, Immediate(kNullCid)); 1701 __ cmpl(value_cid_reg, Immediate(kNullCid));
1672 __ j(EQUAL, &local_fail); 1702 __ j(EQUAL, &no_fixed_length, Assembler::kNearJump);
1673 // Check for typed data array. 1703 // Check for typed data array.
1674 __ cmpl(value_cid_reg, Immediate(kTypedDataFloat32x4ArrayCid)); 1704 __ cmpl(value_cid_reg, Immediate(kTypedDataFloat32x4ArrayCid));
1675 __ j(GREATER, &local_fail); // Not a typed array or a regular array. 1705 // Not a typed array or a regular array.
1706 __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
1676 __ cmpl(value_cid_reg, Immediate(kTypedDataInt8ArrayCid)); 1707 __ cmpl(value_cid_reg, Immediate(kTypedDataInt8ArrayCid));
1677 __ j(LESS, &check_array); // Could still be a regular array. 1708 // Could still be a regular array.
1709 __ j(LESS, &check_array, Assembler::kNearJump);
1678 // Destroy value_cid_reg (safe because we are finished with it). 1710 // Destroy value_cid_reg (safe because we are finished with it).
1679 __ movl(value_cid_reg, 1711 __ movl(value_cid_reg,
1680 FieldAddress(value_reg, TypedData::length_offset())); 1712 FieldAddress(value_reg, TypedData::length_offset()));
1681 __ movl(field_length_operand, value_cid_reg); 1713 __ movl(field_length_operand, value_cid_reg);
1682 __ jmp(&local_exit); // Updated field length typed data array. 1714 // Updated field length typed data array.
1715 __ jmp(&length_set, Assembler::kNearJump);
1683 // Check for regular array. 1716 // Check for regular array.
1684 __ Bind(&check_array); 1717 __ Bind(&check_array);
1685 __ cmpl(value_cid_reg, Immediate(kImmutableArrayCid)); 1718 __ cmpl(value_cid_reg, Immediate(kImmutableArrayCid));
1686 __ j(GREATER, &local_fail); 1719 __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
1687 __ cmpl(value_cid_reg, Immediate(kArrayCid)); 1720 __ cmpl(value_cid_reg, Immediate(kArrayCid));
1688 __ j(LESS, &local_fail); 1721 __ j(LESS, &no_fixed_length, Assembler::kNearJump);
1689 // Destroy value_cid_reg (safe because we are finished with it). 1722 // Destroy value_cid_reg (safe because we are finished with it).
1690 __ movl(value_cid_reg, 1723 __ movl(value_cid_reg,
1691 FieldAddress(value_reg, Array::length_offset())); 1724 FieldAddress(value_reg, Array::length_offset()));
1692 __ movl(field_length_operand, value_cid_reg); 1725 __ movl(field_length_operand, value_cid_reg);
1693 __ jmp(&local_exit); // Updated field length from regular array. 1726 // Updated field length from regular array.
1694 1727 __ jmp(&length_set, Assembler::kNearJump);
1695 __ Bind(&local_fail); 1728 __ Bind(&no_fixed_length);
1696 __ movl(field_length_operand, Immediate(Field::kNoFixedLength)); 1729 __ movl(field_length_operand,
1697 1730 Immediate(Smi::RawValue(Field::kNoFixedLength)));
1698 __ Bind(&local_exit); 1731 __ Bind(&length_set);
1699 } 1732 }
1700 } else { 1733 } else {
1701 if (value_cid_reg == kNoRegister) {
1702 ASSERT(!compiler->is_optimizing());
1703 value_cid_reg = EDX;
1704 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
1705 }
1706 ASSERT(value_cid_reg != kNoRegister);
1707 ASSERT(field_reg != kNoRegister); 1734 ASSERT(field_reg != kNoRegister);
1708 __ movl(field_cid_operand, Immediate(value_cid)); 1735 __ movl(field_cid_operand, Immediate(value_cid));
1709 __ movl(field_nullability_operand, Immediate(value_cid)); 1736 __ movl(field_nullability_operand, Immediate(value_cid));
1710 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) { 1737 if (field_has_length) {
1711 // Destroy value_cid_reg (safe because we are finished with it). 1738 ASSERT(value_cid_reg != kNoRegister);
1712 __ movl(value_cid_reg, 1739 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1713 FieldAddress(value_reg, Array::length_offset())); 1740 // Destroy value_cid_reg (safe because we are finished with it).
1714 __ movl(field_length_operand, value_cid_reg); 1741 __ movl(value_cid_reg,
1715 } else if (RawObject::IsTypedDataClassId(value_cid)) { 1742 FieldAddress(value_reg, Array::length_offset()));
1716 // Destroy value_cid_reg (safe because we are finished with it). 1743 __ movl(field_length_operand, value_cid_reg);
1717 __ movl(value_cid_reg, 1744 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1718 FieldAddress(value_reg, TypedData::length_offset())); 1745 // Destroy value_cid_reg (safe because we are finished with it).
1719 __ movl(field_length_operand, value_cid_reg); 1746 __ movl(value_cid_reg,
1720 } else { 1747 FieldAddress(value_reg, TypedData::length_offset()));
1721 __ movl(field_length_operand, Immediate(Field::kNoFixedLength)); 1748 __ movl(field_length_operand, value_cid_reg);
1749 } else {
1750 __ movl(field_length_operand,
1751 Immediate(Smi::RawValue(Field::kNoFixedLength)));
1752 }
1722 } 1753 }
1723 } 1754 }
1724 1755
1725 if (!ok_is_fall_through) { 1756 if (!ok_is_fall_through) {
1726 __ jmp(&ok); 1757 __ jmp(&ok);
1727 } 1758 }
1728 } else { 1759 } else {
1729 // Field guard class has been initialized and is known. 1760 // Field guard class has been initialized and is known.
1730
1731 if (field_reg != kNoRegister) { 1761 if (field_reg != kNoRegister) {
1732 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); 1762 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
1733 } 1763 }
1734 1764
1735 if (value_cid == kDynamicCid) { 1765 if (value_cid == kDynamicCid) {
1736 // Value's class id is not known. 1766 // Value's class id is not known.
1737 __ testl(value_reg, Immediate(kSmiTagMask)); 1767 __ testl(value_reg, Immediate(kSmiTagMask));
1738 1768
1739 if (field_cid != kSmiCid) { 1769 if (field_cid != kSmiCid) {
1740 __ j(ZERO, fail); 1770 __ j(ZERO, fail);
(...skipping 3451 matching lines...) Expand 10 before | Expand all | Expand 10 after
5192 PcDescriptors::kOther, 5222 PcDescriptors::kOther,
5193 locs()); 5223 locs());
5194 __ Drop(2); // Discard type arguments and receiver. 5224 __ Drop(2); // Discard type arguments and receiver.
5195 } 5225 }
5196 5226
5197 } // namespace dart 5227 } // namespace dart
5198 5228
5199 #undef __ 5229 #undef __
5200 5230
5201 #endif // defined TARGET_ARCH_IA32 5231 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | runtime/vm/intermediate_language_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698