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

Side by Side Diff: runtime/vm/intermediate_language_mips.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_MIPS. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS.
6 #if defined(TARGET_ARCH_MIPS) 6 #if defined(TARGET_ARCH_MIPS)
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 1575 matching lines...) Expand 10 before | Expand all | Expand 10 after
1586 summary->AddTemp(Location::RequiresRegister()); 1586 summary->AddTemp(Location::RequiresRegister());
1587 } 1587 }
1588 return summary; 1588 return summary;
1589 } 1589 }
1590 1590
1591 1591
1592 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1592 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1593 __ TraceSimMsg("GuardFieldInstr"); 1593 __ TraceSimMsg("GuardFieldInstr");
1594 const intptr_t field_cid = field().guarded_cid(); 1594 const intptr_t field_cid = field().guarded_cid();
1595 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; 1595 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
1596 const intptr_t field_length = field().guarded_list_length(); 1596 const intptr_t field_length = Smi::RawValue(field().guarded_list_length());
1597 const bool field_has_length = field().needs_length_check(); 1597 const bool field_has_length = field().needs_length_check();
1598 const bool needs_value_temp_reg = 1598 const bool needs_value_temp_reg =
1599 (field_has_length || ((value()->Type()->ToCid() == kDynamicCid) && 1599 (field_has_length || ((value()->Type()->ToCid() == kDynamicCid) &&
1600 (field().guarded_cid() != kSmiCid))); 1600 (field().guarded_cid() != kSmiCid)));
1601 const bool needs_field_temp_reg = 1601 const bool needs_field_temp_reg =
1602 field_has_length || (field().guarded_cid() == kIllegalCid); 1602 field_has_length || (field().guarded_cid() == kIllegalCid);
1603 if (field_has_length) { 1603 if (field_has_length) {
1604 // Currently, we should only see final fields that remember length. 1604 // Currently, we should only see final fields that remember length.
1605 ASSERT(field().is_final()); 1605 ASSERT(field().is_final());
1606 } 1606 }
(...skipping 26 matching lines...) Expand all
1633 if (!compiler->is_optimizing() && (field_reg == kNoRegister)) { 1633 if (!compiler->is_optimizing() && (field_reg == kNoRegister)) {
1634 // Currently we can't have different location summaries for optimized 1634 // Currently we can't have different location summaries for optimized
1635 // and non-optimized code. So instead we manually pick up a register 1635 // and non-optimized code. So instead we manually pick up a register
1636 // that is known to be free because we know how non-optimizing compiler 1636 // that is known to be free because we know how non-optimizing compiler
1637 // allocates registers. 1637 // allocates registers.
1638 field_reg = A0; 1638 field_reg = A0;
1639 ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg)); 1639 ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg));
1640 } 1640 }
1641 1641
1642 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); 1642 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
1643 1643 int32_t raw_no_fixed_length = Smi::RawValue(Field::kNoFixedLength);
1644 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); 1644 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
1645 FieldAddress field_nullability_operand( 1645 FieldAddress field_nullability_operand(
1646 field_reg, Field::is_nullable_offset()); 1646 field_reg, Field::is_nullable_offset());
1647 FieldAddress field_length_operand( 1647 FieldAddress field_length_operand(
1648 field_reg, Field::guarded_list_length_offset()); 1648 field_reg, Field::guarded_list_length_offset());
1649 1649
1650 if (value_cid == kDynamicCid) { 1650 if (value_cid == kDynamicCid) {
1651 if (value_cid_reg == kNoRegister) { 1651 if (value_cid_reg == kNoRegister) {
1652 ASSERT(!compiler->is_optimizing()); 1652 ASSERT(!compiler->is_optimizing());
1653 value_cid_reg = A1; 1653 value_cid_reg = A1;
(...skipping 11 matching lines...) Expand all
1665 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { 1665 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1666 __ lw(TMP, FieldAddress(value_reg, Array::length_offset())); 1666 __ lw(TMP, FieldAddress(value_reg, Array::length_offset()));
1667 __ LoadImmediate(CMPRES1, field_length); 1667 __ LoadImmediate(CMPRES1, field_length);
1668 __ subu(CMPRES1, TMP, CMPRES1); 1668 __ subu(CMPRES1, TMP, CMPRES1);
1669 } else if (RawObject::IsTypedDataClassId(field_cid)) { 1669 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1670 __ lw(TMP, FieldAddress(value_reg, TypedData::length_offset())); 1670 __ lw(TMP, FieldAddress(value_reg, TypedData::length_offset()));
1671 __ LoadImmediate(CMPRES1, field_length); 1671 __ LoadImmediate(CMPRES1, field_length);
1672 __ subu(CMPRES1, TMP, CMPRES1); 1672 __ subu(CMPRES1, TMP, CMPRES1);
1673 } else { 1673 } else {
1674 ASSERT(field_cid == kIllegalCid); 1674 ASSERT(field_cid == kIllegalCid);
1675 __ LoadImmediate(CMPRES1, 0x1); 1675 Label check_array, local_exit, local_fail;
1676 __ BranchEqual(value_cid_reg, kNullCid, &local_fail);
1677 // Check for typed data array.
1678 __ BranchSignedGreater(value_cid_reg, kTypedDataFloat32x4ArrayCid,
1679 &local_fail);
1680 __ BranchSignedLess(value_cid_reg, kTypedDataInt8ArrayCid,
1681 &check_array);
1682 __ lw(TMP, FieldAddress(value_reg, TypedData::length_offset()));
1683 __ lw(CMPRES1, field_length_operand);
1684 __ subu(CMPRES1, TMP, CMPRES1);
1685 __ b(&local_exit);
1686 // Check for regular array.
1687 __ Bind(&check_array);
1688 __ BranchSignedGreater(value_cid_reg, kImmutableArrayCid,
1689 &local_fail);
1690 __ BranchSignedLess(value_cid_reg, kArrayCid, &local_fail);
1691 __ lw(TMP, FieldAddress(value_reg, Array::length_offset()));
1692 __ lw(CMPRES1, field_length_operand);
1693 __ subu(CMPRES1, TMP, CMPRES1);
1694 __ b(&local_exit);
1695
1696 __ Bind(&local_fail);
1697 // TODO(regis): TMP1 may conflict. Revisit.
1698 __ LoadImmediate(TMP1, raw_no_fixed_length);
1699 __ sw(TMP1, field_length_operand);
1700
1701 __ Bind(&local_exit);
1676 } 1702 }
1677 __ bne(CMPRES1, ZR, fail); 1703 __ bne(CMPRES1, ZR, fail);
1678 } 1704 }
1679 __ Bind(&skip_length_check); 1705 __ Bind(&skip_length_check);
1680 __ lw(TMP1, field_nullability_operand); 1706 __ lw(TMP1, field_nullability_operand);
1681 __ subu(CMPRES, value_cid_reg, TMP1); 1707 __ subu(CMPRES, value_cid_reg, TMP1);
1682 } else if (value_cid == kNullCid) { 1708 } else if (value_cid == kNullCid) {
1683 // TODO(regis): TMP1 may conflict. Revisit. 1709 // TODO(regis): TMP1 may conflict. Revisit.
1684 __ lw(TMP1, field_nullability_operand); 1710 __ lw(TMP1, field_nullability_operand);
1685 __ LoadImmediate(CMPRES, value_cid); 1711 __ LoadImmediate(CMPRES, value_cid);
1686 __ subu(CMPRES, TMP1, CMPRES); 1712 __ subu(CMPRES, TMP1, CMPRES);
1687 } else { 1713 } else {
1688 Label skip_length_check; 1714 Label skip_length_check;
1689 // TODO(regis): TMP1 may conflict. Revisit. 1715 // TODO(regis): TMP1 may conflict. Revisit.
1690 __ lw(TMP1, field_cid_operand); 1716 __ lw(TMP1, field_cid_operand);
1691 __ LoadImmediate(CMPRES, value_cid); 1717 __ LoadImmediate(CMPRES, value_cid);
1692 __ subu(CMPRES, TMP1, CMPRES); 1718 __ subu(CMPRES, TMP1, CMPRES);
1693 __ bne(CMPRES, ZR, &skip_length_check); 1719 __ bne(CMPRES, ZR, &skip_length_check);
1694 // Insert length check. 1720 // Insert length check.
1695 if (field_has_length) { 1721 if (field_has_length) {
1696 if (value_cid_reg == kNoRegister) { 1722 if (value_cid_reg == kNoRegister) {
1697 ASSERT(!compiler->is_optimizing()); 1723 ASSERT(!compiler->is_optimizing());
1698 value_cid_reg = A1; 1724 value_cid_reg = A1;
1699 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg)); 1725 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
1700 } 1726 }
1701 ASSERT(value_cid_reg != kNoRegister); 1727 ASSERT(value_cid_reg != kNoRegister);
1702 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { 1728 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1703 __ lw(TMP, FieldAddress(value_reg, Array::length_offset())); 1729 __ lw(TMP, FieldAddress(value_reg, Array::length_offset()));
1704 __ LoadImmediate(CMPRES, field_length); 1730 __ LoadImmediate(CMPRES, field_length);
1705 __ subu(CMPRES, TMP, CMPRES); 1731 __ subu(CMPRES, TMP, CMPRES);
1706 } else if (RawObject::IsTypedDataClassId(field_cid)) { 1732 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1707 __ lw(TMP, FieldAddress(value_reg, TypedData::length_offset())); 1733 __ lw(TMP, FieldAddress(value_reg, TypedData::length_offset()));
1708 __ LoadImmediate(CMPRES, field_length); 1734 __ LoadImmediate(CMPRES, field_length);
1709 __ subu(CMPRES, TMP, CMPRES); 1735 __ subu(CMPRES, TMP, CMPRES);
1710 } else { 1736 } else {
1711 ASSERT(field_cid == kIllegalCid); 1737 ASSERT(field_cid == kIllegalCid);
1712 __ LoadImmediate(CMPRES, 0x1);
1713 } 1738 }
1739 __ bne(CMPRES, ZR, fail);
1714 } 1740 }
1715 __ Bind(&skip_length_check); 1741 __ Bind(&skip_length_check);
1716 } 1742 }
1717 __ beq(CMPRES, ZR, &ok); 1743 __ beq(CMPRES, ZR, &ok);
1718 1744
1719 __ lw(CMPRES1, field_cid_operand); 1745 __ lw(CMPRES1, field_cid_operand);
1720 __ BranchNotEqual(CMPRES1, kIllegalCid, fail); 1746 __ BranchNotEqual(CMPRES1, kIllegalCid, fail);
1721 1747
1722 if (value_cid == kDynamicCid) { 1748 if (value_cid == kDynamicCid) {
1723 __ sw(value_cid_reg, field_cid_operand); 1749 __ sw(value_cid_reg, field_cid_operand);
(...skipping 17 matching lines...) Expand all
1741 &local_fail); 1767 &local_fail);
1742 __ BranchSignedLess(value_cid_reg, kArrayCid, &local_fail); 1768 __ BranchSignedLess(value_cid_reg, kArrayCid, &local_fail);
1743 // Destroy value_cid_reg (safe because we are finished with it). 1769 // Destroy value_cid_reg (safe because we are finished with it).
1744 __ lw(value_cid_reg, 1770 __ lw(value_cid_reg,
1745 FieldAddress(value_reg, Array::length_offset())); 1771 FieldAddress(value_reg, Array::length_offset()));
1746 __ sw(value_cid_reg, field_length_operand); 1772 __ sw(value_cid_reg, field_length_operand);
1747 __ b(&local_exit); // Updated field length from regular array. 1773 __ b(&local_exit); // Updated field length from regular array.
1748 1774
1749 __ Bind(&local_fail); 1775 __ Bind(&local_fail);
1750 // TODO(regis): TMP1 may conflict. Revisit. 1776 // TODO(regis): TMP1 may conflict. Revisit.
1751 __ LoadImmediate(TMP1, Field::kNoFixedLength); 1777 __ LoadImmediate(TMP1, raw_no_fixed_length);
1752 __ sw(TMP1, field_length_operand); 1778 __ sw(TMP1, field_length_operand);
1753 1779
1754 __ Bind(&local_exit); 1780 __ Bind(&local_exit);
1755 } 1781 }
1756 } else { 1782 } else {
1757 if (value_cid_reg == kNoRegister) { 1783 if (value_cid_reg == kNoRegister) {
1758 ASSERT(!compiler->is_optimizing()); 1784 ASSERT(!compiler->is_optimizing());
1759 value_cid_reg = A1; 1785 value_cid_reg = A1;
1760 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg)); 1786 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
1761 } 1787 }
1762 ASSERT(value_cid_reg != kNoRegister); 1788 ASSERT(value_cid_reg != kNoRegister);
1763 ASSERT(field_reg != kNoRegister); 1789 ASSERT(field_reg != kNoRegister);
1764 __ LoadImmediate(TMP1, value_cid); 1790 __ LoadImmediate(TMP1, value_cid);
1765 __ sw(TMP1, field_cid_operand); 1791 __ sw(TMP1, field_cid_operand);
1766 __ sw(TMP1, field_nullability_operand); 1792 __ sw(TMP1, field_nullability_operand);
1767 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) { 1793 if (field_has_length) {
1768 // Destroy value_cid_reg (safe because we are finished with it). 1794 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1769 __ lw(value_cid_reg, 1795 // Destroy value_cid_reg (safe because we are finished with it).
1770 FieldAddress(value_reg, Array::length_offset())); 1796 __ lw(value_cid_reg,
1771 __ sw(value_cid_reg, field_length_operand); 1797 FieldAddress(value_reg, Array::length_offset()));
1772 } else if (RawObject::IsTypedDataClassId(value_cid)) { 1798 __ sw(value_cid_reg, field_length_operand);
1773 // Destroy value_cid_reg (safe because we are finished with it). 1799 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1774 __ lw(value_cid_reg, 1800 // Destroy value_cid_reg (safe because we are finished with it).
1775 FieldAddress(value_reg, TypedData::length_offset())); 1801 __ lw(value_cid_reg,
1776 __ sw(value_cid_reg, field_length_operand); 1802 FieldAddress(value_reg, TypedData::length_offset()));
1777 } else { 1803 __ sw(value_cid_reg, field_length_operand);
1778 // Destroy value_cid_reg (safe because we are finished with it). 1804 } else {
1779 __ LoadImmediate(value_cid_reg, Field::kNoFixedLength); 1805 // Destroy value_cid_reg (safe because we are finished with it).
1780 __ sw(value_cid_reg, field_length_operand); 1806 __ LoadImmediate(value_cid_reg, raw_no_fixed_length);
1807 __ sw(value_cid_reg, field_length_operand);
1808 }
1781 } 1809 }
1782 } 1810 }
1783
1784 if (!ok_is_fall_through) { 1811 if (!ok_is_fall_through) {
1785 __ b(&ok); 1812 __ b(&ok);
1786 } 1813 }
1787 } else { 1814 } else {
1788 if (field_reg != kNoRegister) { 1815 if (field_reg != kNoRegister) {
1789 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); 1816 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
1790 } 1817 }
1791 if (value_cid == kDynamicCid) { 1818 if (value_cid == kDynamicCid) {
1792 // Field's guarded class id is fixed by value's class id is not known. 1819 // Field's guarded class id is fixed by value's class id is not known.
1793 __ andi(CMPRES, value_reg, Immediate(kSmiTagMask)); 1820 __ andi(CMPRES, value_reg, Immediate(kSmiTagMask));
(...skipping 2279 matching lines...) Expand 10 before | Expand all | Expand 10 after
4073 compiler->GenerateCall(token_pos(), 4100 compiler->GenerateCall(token_pos(),
4074 &label, 4101 &label,
4075 PcDescriptors::kOther, 4102 PcDescriptors::kOther,
4076 locs()); 4103 locs());
4077 __ Drop(2); // Discard type arguments and receiver. 4104 __ Drop(2); // Discard type arguments and receiver.
4078 } 4105 }
4079 4106
4080 } // namespace dart 4107 } // namespace dart
4081 4108
4082 #endif // defined TARGET_ARCH_MIPS 4109 #endif // defined TARGET_ARCH_MIPS
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698