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

Side by Side Diff: runtime/vm/intermediate_language_arm.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_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
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 1519 matching lines...) Expand 10 before | Expand all | Expand 10 after
1530 if (need_field_temp_reg) { 1530 if (need_field_temp_reg) {
1531 summary->AddTemp(Location::RequiresRegister()); 1531 summary->AddTemp(Location::RequiresRegister());
1532 } 1532 }
1533 return summary; 1533 return summary;
1534 } 1534 }
1535 1535
1536 1536
1537 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1537 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1538 const intptr_t field_cid = field().guarded_cid(); 1538 const intptr_t field_cid = field().guarded_cid();
1539 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; 1539 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
1540 const intptr_t field_length = field().guarded_list_length(); 1540 const intptr_t field_length = Smi::RawValue(field().guarded_list_length());
srdjan 2013/08/27 17:45:22 It is not a good idea to hang onto tagged value as
Cutch 2013/08/28 12:24:59 Thanks for this.
1541 const bool field_has_length = field().needs_length_check(); 1541 const bool field_has_length = field().needs_length_check();
1542 const bool needs_value_temp_reg = 1542 const bool needs_value_temp_reg =
1543 (field_has_length || ((value()->Type()->ToCid() == kDynamicCid) && 1543 (field_has_length || ((value()->Type()->ToCid() == kDynamicCid) &&
1544 (field().guarded_cid() != kSmiCid))); 1544 (field().guarded_cid() != kSmiCid)));
1545 const bool needs_field_temp_reg = 1545 const bool needs_field_temp_reg =
1546 field_has_length || (field().guarded_cid() == kIllegalCid); 1546 field_has_length || (field().guarded_cid() == kIllegalCid);
1547 if (field_has_length) { 1547 if (field_has_length) {
1548 // Currently, we should only see final fields that remember length. 1548 // Currently, we should only see final fields that remember length.
1549 ASSERT(field().is_final()); 1549 ASSERT(field().is_final());
1550 } 1550 }
(...skipping 28 matching lines...) Expand all
1579 if (!compiler->is_optimizing() && (field_reg == kNoRegister)) { 1579 if (!compiler->is_optimizing() && (field_reg == kNoRegister)) {
1580 // Currently we can't have different location summaries for optimized 1580 // Currently we can't have different location summaries for optimized
1581 // and non-optimized code. So instead we manually pick up a register 1581 // and non-optimized code. So instead we manually pick up a register
1582 // that is known to be free because we know how non-optimizing compiler 1582 // that is known to be free because we know how non-optimizing compiler
1583 // allocates registers. 1583 // allocates registers.
1584 field_reg = R2; 1584 field_reg = R2;
1585 ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg)); 1585 ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg));
1586 } 1586 }
1587 1587
1588 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); 1588 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
1589 1589 int32_t raw_no_fixed_length = Smi::RawValue(Field::kNoFixedLength);
1590 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); 1590 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
1591 FieldAddress field_nullability_operand( 1591 FieldAddress field_nullability_operand(
1592 field_reg, Field::is_nullable_offset()); 1592 field_reg, Field::is_nullable_offset());
1593 FieldAddress field_length_operand( 1593 FieldAddress field_length_operand(
1594 field_reg, Field::guarded_list_length_offset()); 1594 field_reg, Field::guarded_list_length_offset());
1595 1595
1596 if (value_cid_reg == kNoRegister) { 1596 if (value_cid_reg == kNoRegister) {
1597 ASSERT(!compiler->is_optimizing()); 1597 ASSERT(!compiler->is_optimizing());
1598 value_cid_reg = R3; 1598 value_cid_reg = R3;
1599 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg)); 1599 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
(...skipping 11 matching lines...) Expand all
1611 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { 1611 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1612 __ ldr(temp_reg, 1612 __ ldr(temp_reg,
1613 FieldAddress(value_reg, Array::length_offset())); 1613 FieldAddress(value_reg, Array::length_offset()));
1614 __ CompareImmediate(temp_reg, field_length); 1614 __ CompareImmediate(temp_reg, field_length);
1615 } else if (RawObject::IsTypedDataClassId(field_cid)) { 1615 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1616 __ ldr(temp_reg, 1616 __ ldr(temp_reg,
1617 FieldAddress(value_reg, TypedData::length_offset())); 1617 FieldAddress(value_reg, TypedData::length_offset()));
1618 __ CompareImmediate(temp_reg, field_length); 1618 __ CompareImmediate(temp_reg, field_length);
1619 } else { 1619 } else {
1620 ASSERT(field_cid == kIllegalCid); 1620 ASSERT(field_cid == kIllegalCid);
1621 Label check_array, local_exit, local_fail;
1622 __ CompareImmediate(value_cid_reg, kNullCid);
srdjan 2013/08/27 17:45:22 This code seems identical to the one below, please
Cutch 2013/08/28 12:24:59 This code is not identical to the block below. Thi
1623 __ b(&local_fail, EQ);
1624 // Check for typed data array.
1625 __ CompareImmediate(value_cid_reg, kTypedDataFloat32x4ArrayCid);
1626 __ b(&local_fail, GT);
1627 __ CompareImmediate(value_cid_reg, kTypedDataInt8ArrayCid);
1628 __ b(&check_array, LT); // Could still be a regular array.
1629 __ ldr(temp_reg,
1630 FieldAddress(value_reg, TypedData::length_offset()));
1631 __ ldr(IP, field_length_operand);
1632 __ cmp(temp_reg, ShifterOperand(IP));
1633 __ b(&local_exit); // Updated field length typed data array.
1634 // Check for regular array.
1635 __ Bind(&check_array);
1636 __ CompareImmediate(value_cid_reg, kImmutableArrayCid);
1637 __ b(&local_fail, GT);
1638 __ CompareImmediate(value_cid_reg, kArrayCid);
1639 __ b(&local_fail, LT);
1640 __ ldr(temp_reg,
1641 FieldAddress(value_reg, Array::length_offset()));
1642 __ ldr(IP, field_length_operand);
1643 __ cmp(temp_reg, ShifterOperand(IP));
1644 __ b(&local_exit); // Updated field length from regular array.
1645
1646 __ Bind(&local_fail);
1647 __ LoadImmediate(IP, raw_no_fixed_length);
1648 __ str(IP, field_length_operand);
1649
1650 __ Bind(&local_exit);
1621 // Following branch cannot not occur, fall through. 1651 // Following branch cannot not occur, fall through.
1622 } 1652 }
1623 __ b(fail, NE); 1653 __ b(fail, NE);
1624 } 1654 }
1625 __ Bind(&skip_length_check); 1655 __ Bind(&skip_length_check);
1626 __ ldr(IP, field_nullability_operand); 1656 __ ldr(IP, field_nullability_operand);
1627 __ cmp(value_cid_reg, ShifterOperand(IP)); 1657 __ cmp(value_cid_reg, ShifterOperand(IP));
1628 } else if (value_cid == kNullCid) { 1658 } else if (value_cid == kNullCid) {
1629 __ ldr(value_cid_reg, field_nullability_operand); 1659 __ ldr(value_cid_reg, field_nullability_operand);
1630 __ CompareImmediate(value_cid_reg, value_cid); 1660 __ CompareImmediate(value_cid_reg, value_cid);
(...skipping 10 matching lines...) Expand all
1641 FieldAddress(value_reg, Array::length_offset())); 1671 FieldAddress(value_reg, Array::length_offset()));
1642 __ CompareImmediate(temp_reg, field_length); 1672 __ CompareImmediate(temp_reg, field_length);
1643 } else if (RawObject::IsTypedDataClassId(field_cid)) { 1673 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1644 __ ldr(temp_reg, 1674 __ ldr(temp_reg,
1645 FieldAddress(value_reg, TypedData::length_offset())); 1675 FieldAddress(value_reg, TypedData::length_offset()));
1646 __ CompareImmediate(temp_reg, field_length); 1676 __ CompareImmediate(temp_reg, field_length);
1647 } else { 1677 } else {
1648 ASSERT(field_cid == kIllegalCid); 1678 ASSERT(field_cid == kIllegalCid);
1649 // Following jump cannot not occur, fall through. 1679 // Following jump cannot not occur, fall through.
1650 } 1680 }
1681 __ b(fail, NE);
1651 } 1682 }
1652 // Not identical, possibly null. 1683 // Not identical, possibly null.
1653 __ Bind(&skip_length_check); 1684 __ Bind(&skip_length_check);
1654 } 1685 }
1655 __ b(&ok, EQ); 1686 __ b(&ok, EQ);
1656 1687
1657 __ ldr(IP, field_cid_operand); 1688 __ ldr(IP, field_cid_operand);
1658 __ CompareImmediate(IP, kIllegalCid); 1689 __ CompareImmediate(IP, kIllegalCid);
1659 __ b(fail, NE); 1690 __ b(fail, NE);
1660 1691
(...skipping 20 matching lines...) Expand all
1681 __ b(&local_fail, GT); 1712 __ b(&local_fail, GT);
1682 __ CompareImmediate(value_cid_reg, kArrayCid); 1713 __ CompareImmediate(value_cid_reg, kArrayCid);
1683 __ b(&local_fail, LT); 1714 __ b(&local_fail, LT);
1684 // Destroy value_cid_reg (safe because we are finished with it). 1715 // Destroy value_cid_reg (safe because we are finished with it).
1685 __ ldr(value_cid_reg, 1716 __ ldr(value_cid_reg,
1686 FieldAddress(value_reg, Array::length_offset())); 1717 FieldAddress(value_reg, Array::length_offset()));
1687 __ str(value_cid_reg, field_length_operand); 1718 __ str(value_cid_reg, field_length_operand);
1688 __ b(&local_exit); // Updated field length from regular array. 1719 __ b(&local_exit); // Updated field length from regular array.
1689 1720
1690 __ Bind(&local_fail); 1721 __ Bind(&local_fail);
1691 __ LoadImmediate(IP, Field::kNoFixedLength); 1722 __ LoadImmediate(IP, raw_no_fixed_length);
1692 __ str(IP, field_length_operand); 1723 __ str(IP, field_length_operand);
1693 1724
1694 __ Bind(&local_exit); 1725 __ Bind(&local_exit);
1695 } 1726 }
1696 } else { 1727 } else {
1697 __ LoadImmediate(IP, value_cid); 1728 __ LoadImmediate(IP, value_cid);
1698 __ str(IP, field_cid_operand); 1729 __ str(IP, field_cid_operand);
1699 __ str(IP, field_nullability_operand); 1730 __ str(IP, field_nullability_operand);
1700 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) { 1731 if (field_has_length) {
1701 // Destroy value_cid_reg (safe because we are finished with it). 1732 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1702 __ ldr(value_cid_reg, 1733 // Destroy value_cid_reg (safe because we are finished with it).
1703 FieldAddress(value_reg, Array::length_offset())); 1734 __ ldr(value_cid_reg,
1704 __ str(value_cid_reg, field_length_operand); 1735 FieldAddress(value_reg, Array::length_offset()));
1705 } else if (RawObject::IsTypedDataClassId(value_cid)) { 1736 __ str(value_cid_reg, field_length_operand);
1706 // Destroy value_cid_reg (safe because we are finished with it). 1737 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1707 __ ldr(value_cid_reg, 1738 // Destroy value_cid_reg (safe because we are finished with it).
1708 FieldAddress(value_reg, TypedData::length_offset())); 1739 __ ldr(value_cid_reg,
1709 __ str(value_cid_reg, field_length_operand); 1740 FieldAddress(value_reg, TypedData::length_offset()));
1710 } else { 1741 __ str(value_cid_reg, field_length_operand);
1711 __ LoadImmediate(IP, Field::kNoFixedLength); 1742 } else {
1712 __ str(IP, field_length_operand); 1743 __ LoadImmediate(IP, raw_no_fixed_length);
1744 __ str(IP, field_length_operand);
1745 }
1713 } 1746 }
1714 } 1747 }
1715
1716 if (!ok_is_fall_through) { 1748 if (!ok_is_fall_through) {
1717 __ b(&ok); 1749 __ b(&ok);
1718 } 1750 }
1719 } else { 1751 } else {
1720 if (field_reg != kNoRegister) { 1752 if (field_reg != kNoRegister) {
1721 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); 1753 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
1722 } 1754 }
1723 if (value_cid == kDynamicCid) { 1755 if (value_cid == kDynamicCid) {
1724 // Field's guarded class id is fixed by value's class id is not known. 1756 // Field's guarded class id is fixed by value's class id is not known.
1725 __ tst(value_reg, ShifterOperand(kSmiTagMask)); 1757 __ tst(value_reg, ShifterOperand(kSmiTagMask));
(...skipping 2917 matching lines...) Expand 10 before | Expand all | Expand 10 after
4643 compiler->GenerateCall(token_pos(), 4675 compiler->GenerateCall(token_pos(),
4644 &label, 4676 &label,
4645 PcDescriptors::kOther, 4677 PcDescriptors::kOther,
4646 locs()); 4678 locs());
4647 __ Drop(2); // Discard type arguments and receiver. 4679 __ Drop(2); // Discard type arguments and receiver.
4648 } 4680 }
4649 4681
4650 } // namespace dart 4682 } // namespace dart
4651 4683
4652 #endif // defined TARGET_ARCH_ARM 4684 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698