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

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

Issue 304703002: Split GuardField into GuardFieldType and GuardFieldLength instructions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 6 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.cc ('k') | runtime/vm/intermediate_language_arm64.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_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/cpu.h" 10 #include "vm/cpu.h"
(...skipping 1581 matching lines...) Expand 10 before | Expand all | Expand 10 after
1592 const DRegister value_reg = EvenDRegisterOf(locs()->in(2).fpu_reg()); 1592 const DRegister value_reg = EvenDRegisterOf(locs()->in(2).fpu_reg());
1593 __ vstmd(IA, index.reg(), value_reg, 2); 1593 __ vstmd(IA, index.reg(), value_reg, 2);
1594 break; 1594 break;
1595 } 1595 }
1596 default: 1596 default:
1597 UNREACHABLE(); 1597 UNREACHABLE();
1598 } 1598 }
1599 } 1599 }
1600 1600
1601 1601
1602 LocationSummary* GuardFieldInstr::MakeLocationSummary(Isolate* isolate, 1602 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Isolate* isolate,
1603 bool opt) const { 1603 bool opt) const {
1604 const intptr_t kNumInputs = 1; 1604 const intptr_t kNumInputs = 1;
1605 LocationSummary* summary = new(isolate) LocationSummary( 1605 LocationSummary* summary = new(isolate) LocationSummary(
1606 isolate, kNumInputs, 0, LocationSummary::kNoCall); 1606 isolate, kNumInputs, 0, LocationSummary::kNoCall);
1607 summary->set_in(0, Location::RequiresRegister()); 1607 summary->set_in(0, Location::RequiresRegister());
1608 const bool field_has_length = field().needs_length_check(); 1608
1609 summary->AddTemp(Location::RequiresRegister()); 1609 const intptr_t value_cid = value()->Type()->ToCid();
1610 summary->AddTemp(Location::RequiresRegister()); 1610 const intptr_t field_cid = field().guarded_cid();
1611 const bool need_field_temp_reg = 1611
1612 field_has_length || (field().guarded_cid() == kIllegalCid); 1612 const bool emit_full_guard =
1613 if (need_field_temp_reg) { 1613 !opt || (field_cid == kIllegalCid);
1614
1615 const bool needs_value_cid_temp_reg = emit_full_guard ||
1616 ((value_cid == kDynamicCid) && (field_cid != kSmiCid));
1617
1618 const bool needs_field_temp_reg = emit_full_guard;
1619
1620 if (needs_value_cid_temp_reg) {
1614 summary->AddTemp(Location::RequiresRegister()); 1621 summary->AddTemp(Location::RequiresRegister());
1615 } 1622 }
1623
1624 if (needs_field_temp_reg) {
1625 summary->AddTemp(Location::RequiresRegister());
1626 }
1627
1616 return summary; 1628 return summary;
1617 } 1629 }
1618 1630
1619 1631
1620 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1632 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1633 const intptr_t value_cid = value()->Type()->ToCid();
1621 const intptr_t field_cid = field().guarded_cid(); 1634 const intptr_t field_cid = field().guarded_cid();
1622 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; 1635 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
1623 const intptr_t field_length = field().guarded_list_length();
1624 const bool field_has_length = field().needs_length_check();
1625 const bool needs_field_temp_reg =
1626 field_has_length || (field().guarded_cid() == kIllegalCid);
1627 if (field_has_length) {
1628 // Currently, we should only see final fields that remember length.
1629 ASSERT(field().is_final());
1630 }
1631 1636
1632 if (field_cid == kDynamicCid) { 1637 if (field_cid == kDynamicCid) {
1633 ASSERT(!compiler->is_optimizing()); 1638 ASSERT(!compiler->is_optimizing());
1634 return; // Nothing to emit. 1639 return; // Nothing to emit.
1635 } 1640 }
1636 1641
1637 const intptr_t value_cid = value()->Type()->ToCid(); 1642 const bool emit_full_guard =
1643 !compiler->is_optimizing() || (field_cid == kIllegalCid);
1644
1645 const bool needs_value_cid_temp_reg = emit_full_guard ||
1646 ((value_cid == kDynamicCid) && (field_cid != kSmiCid));
1647
1648 const bool needs_field_temp_reg = emit_full_guard;
1638 1649
1639 const Register value_reg = locs()->in(0).reg(); 1650 const Register value_reg = locs()->in(0).reg();
1640 1651
1641 const Register value_cid_reg = locs()->temp(0).reg(); 1652 const Register value_cid_reg = needs_value_cid_temp_reg ?
1653 locs()->temp(0).reg() : kNoRegister;
1642 1654
1643 const Register temp_reg = locs()->temp(1).reg(); 1655 const Register field_reg = needs_field_temp_reg ?
1644
1645 Register field_reg = needs_field_temp_reg ?
1646 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; 1656 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister;
1647 1657
1648 Label ok, fail_label; 1658 Label ok, fail_label;
1649 1659
1650 Label* deopt = compiler->is_optimizing() ? 1660 Label* deopt = compiler->is_optimizing() ?
1651 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; 1661 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
1652 1662
1653 Label* fail = (deopt != NULL) ? deopt : &fail_label; 1663 Label* fail = (deopt != NULL) ? deopt : &fail_label;
1654 1664
1655 if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) { 1665 if (emit_full_guard) {
1656 if (!compiler->is_optimizing() && (field_reg == kNoRegister)) {
1657 // Currently we can't have different location summaries for optimized
1658 // and non-optimized code. So instead we manually pick up a register
1659 // that is known to be free because we know how non-optimizing compiler
1660 // allocates registers.
1661 field_reg = R2;
1662 ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg));
1663 }
1664
1665 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); 1666 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
1666 1667
1667 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); 1668 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
1668 FieldAddress field_nullability_operand( 1669 FieldAddress field_nullability_operand(
1669 field_reg, Field::is_nullable_offset()); 1670 field_reg, Field::is_nullable_offset());
1670 FieldAddress field_length_operand(
1671 field_reg, Field::guarded_list_length_offset());
1672
1673 ASSERT(value_cid_reg != kNoRegister);
1674 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
1675 1671
1676 if (value_cid == kDynamicCid) { 1672 if (value_cid == kDynamicCid) {
1677 LoadValueCid(compiler, value_cid_reg, value_reg); 1673 LoadValueCid(compiler, value_cid_reg, value_reg);
1678 Label skip_length_check;
1679 __ ldr(IP, field_cid_operand); 1674 __ ldr(IP, field_cid_operand);
1680 __ cmp(value_cid_reg, Operand(IP)); 1675 __ cmp(value_cid_reg, Operand(IP));
1681 __ b(&skip_length_check, NE); 1676 __ b(&ok, EQ);
1682 if (field_has_length) {
1683 ASSERT(temp_reg != kNoRegister);
1684 // Field guard may have remembered list length, check it.
1685 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1686 __ ldr(temp_reg,
1687 FieldAddress(value_reg, Array::length_offset()));
1688 __ CompareImmediate(temp_reg, Smi::RawValue(field_length));
1689 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1690 __ ldr(temp_reg,
1691 FieldAddress(value_reg, TypedData::length_offset()));
1692 __ CompareImmediate(temp_reg, Smi::RawValue(field_length));
1693 } else {
1694 ASSERT(field_cid == kIllegalCid);
1695 ASSERT(field_length == Field::kUnknownFixedLength);
1696 // At compile time we do not know the type of the field nor its
1697 // length. At execution time we may have set the class id and
1698 // list length so we compare the guarded length with the
1699 // list length here, without this check the list length could change
1700 // without triggering a deoptimization.
1701 Label check_array, length_compared, no_fixed_length;
1702 // If length is negative the length guard is either disabled or
1703 // has not been initialized, either way it is safe to skip the
1704 // length check.
1705 __ ldr(IP, field_length_operand);
1706 __ CompareImmediate(IP, 0);
1707 __ b(&skip_length_check, LT);
1708 __ CompareImmediate(value_cid_reg, kNullCid);
1709 __ b(&no_fixed_length, EQ);
1710 // Check for typed data array.
1711 __ CompareImmediate(value_cid_reg, kTypedDataInt32x4ArrayCid);
1712 __ b(&no_fixed_length, GT);
1713 __ CompareImmediate(value_cid_reg, kTypedDataInt8ArrayCid);
1714 // Could still be a regular array.
1715 __ b(&check_array, LT);
1716 __ ldr(temp_reg,
1717 FieldAddress(value_reg, TypedData::length_offset()));
1718 __ ldr(IP, field_length_operand);
1719 __ cmp(temp_reg, Operand(IP));
1720 __ b(&length_compared);
1721 // Check for regular array.
1722 __ Bind(&check_array);
1723 __ CompareImmediate(value_cid_reg, kImmutableArrayCid);
1724 __ b(&no_fixed_length, GT);
1725 __ CompareImmediate(value_cid_reg, kArrayCid);
1726 __ b(&no_fixed_length, LT);
1727 __ ldr(temp_reg,
1728 FieldAddress(value_reg, Array::length_offset()));
1729 __ ldr(IP, field_length_operand);
1730 __ cmp(temp_reg, Operand(IP));
1731 __ b(&length_compared);
1732 __ Bind(&no_fixed_length);
1733 __ b(fail);
1734 __ Bind(&length_compared);
1735 // Following branch cannot not occur, fall through.
1736 }
1737 __ b(fail, NE);
1738 }
1739 __ Bind(&skip_length_check);
1740 __ ldr(IP, field_nullability_operand); 1677 __ ldr(IP, field_nullability_operand);
1741 __ cmp(value_cid_reg, Operand(IP)); 1678 __ cmp(value_cid_reg, Operand(IP));
1742 } else if (value_cid == kNullCid) { 1679 } else if (value_cid == kNullCid) {
1743 __ ldr(value_cid_reg, field_nullability_operand); 1680 __ ldr(value_cid_reg, field_nullability_operand);
1744 __ CompareImmediate(value_cid_reg, value_cid); 1681 __ CompareImmediate(value_cid_reg, value_cid);
1745 } else { 1682 } else {
1746 Label skip_length_check;
1747 __ ldr(value_cid_reg, field_cid_operand); 1683 __ ldr(value_cid_reg, field_cid_operand);
1748 __ CompareImmediate(value_cid_reg, value_cid); 1684 __ CompareImmediate(value_cid_reg, value_cid);
1749 __ b(&skip_length_check, NE);
1750 if (field_has_length) {
1751 ASSERT(value_cid_reg != kNoRegister);
1752 ASSERT(temp_reg != kNoRegister);
1753 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1754 __ ldr(temp_reg,
1755 FieldAddress(value_reg, Array::length_offset()));
1756 __ CompareImmediate(temp_reg, Smi::RawValue(field_length));
1757 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1758 __ ldr(temp_reg,
1759 FieldAddress(value_reg, TypedData::length_offset()));
1760 __ CompareImmediate(temp_reg, Smi::RawValue(field_length));
1761 } else if (field_cid != kIllegalCid) {
1762 ASSERT(field_cid != value_cid);
1763 ASSERT(field_length >= 0);
1764 // Field has a known class id and length. At compile time it is
1765 // known that the value's class id is not a fixed length list.
1766 __ b(fail);
1767 } else {
1768 ASSERT(field_cid == kIllegalCid);
1769 ASSERT(field_length == Field::kUnknownFixedLength);
1770 // Following jump cannot not occur, fall through.
1771 }
1772 __ b(fail, NE);
1773 }
1774 // Not identical, possibly null.
1775 __ Bind(&skip_length_check);
1776 } 1685 }
1777 __ b(&ok, EQ); 1686 __ b(&ok, EQ);
1778 1687
1779 __ ldr(IP, field_cid_operand); 1688 // Check if the tracked state of the guarded field can be initialized
1780 __ CompareImmediate(IP, kIllegalCid); 1689 // inline. If the field needs length check we fall through to runtime
1781 __ b(fail, NE); 1690 // which is responsible for computing offset of the length field
1691 // based on the class id.
1692 // Length guard will be emitted separately when needed via GuardFieldLength
1693 // instruction after GuardFieldClass.
1694 if (!field().needs_length_check()) {
1695 // Uninitialized field can be handled inline. Check if the
1696 // field is still unitialized.
1697 __ ldr(IP, field_cid_operand);
1698 __ CompareImmediate(IP, kIllegalCid);
1699 __ b(fail, NE);
1782 1700
1783 if (value_cid == kDynamicCid) { 1701 if (value_cid == kDynamicCid) {
1784 __ str(value_cid_reg, field_cid_operand); 1702 __ str(value_cid_reg, field_cid_operand);
1785 __ str(value_cid_reg, field_nullability_operand); 1703 __ str(value_cid_reg, field_nullability_operand);
1786 if (field_has_length) { 1704 } else {
1787 Label check_array, length_set, no_fixed_length; 1705 __ LoadImmediate(IP, value_cid);
1788 __ CompareImmediate(value_cid_reg, kNullCid); 1706 __ str(IP, field_cid_operand);
1789 __ b(&no_fixed_length, EQ); 1707 __ str(IP, field_nullability_operand);
1790 // Check for typed data array.
1791 __ CompareImmediate(value_cid_reg, kTypedDataInt32x4ArrayCid);
1792 __ b(&no_fixed_length, GT);
1793 __ CompareImmediate(value_cid_reg, kTypedDataInt8ArrayCid);
1794 // Could still be a regular array.
1795 __ b(&check_array, LT);
1796 // Destroy value_cid_reg (safe because we are finished with it).
1797 __ ldr(value_cid_reg,
1798 FieldAddress(value_reg, TypedData::length_offset()));
1799 __ str(value_cid_reg, field_length_operand);
1800 __ b(&length_set); // Updated field length typed data array.
1801 // Check for regular array.
1802 __ Bind(&check_array);
1803 __ CompareImmediate(value_cid_reg, kImmutableArrayCid);
1804 __ b(&no_fixed_length, GT);
1805 __ CompareImmediate(value_cid_reg, kArrayCid);
1806 __ b(&no_fixed_length, LT);
1807 // Destroy value_cid_reg (safe because we are finished with it).
1808 __ ldr(value_cid_reg,
1809 FieldAddress(value_reg, Array::length_offset()));
1810 __ str(value_cid_reg, field_length_operand);
1811 // Updated field length from regular array.
1812 __ b(&length_set);
1813 __ Bind(&no_fixed_length);
1814 __ LoadImmediate(IP, Smi::RawValue(Field::kNoFixedLength));
1815 __ str(IP, field_length_operand);
1816 __ Bind(&length_set);
1817 } 1708 }
1818 } else { 1709
1819 __ LoadImmediate(IP, value_cid); 1710 if (deopt == NULL) {
1820 __ str(IP, field_cid_operand); 1711 ASSERT(!compiler->is_optimizing());
1821 __ str(IP, field_nullability_operand); 1712 __ b(&ok);
1822 if (field_has_length) {
1823 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1824 // Destroy value_cid_reg (safe because we are finished with it).
1825 __ ldr(value_cid_reg,
1826 FieldAddress(value_reg, Array::length_offset()));
1827 __ str(value_cid_reg, field_length_operand);
1828 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1829 // Destroy value_cid_reg (safe because we are finished with it).
1830 __ ldr(value_cid_reg,
1831 FieldAddress(value_reg, TypedData::length_offset()));
1832 __ str(value_cid_reg, field_length_operand);
1833 } else {
1834 __ LoadImmediate(IP, Smi::RawValue(Field::kNoFixedLength));
1835 __ str(IP, field_length_operand);
1836 }
1837 } 1713 }
1838 } 1714 }
1839 1715
1840 if (deopt == NULL) { 1716 if (deopt == NULL) {
1841 ASSERT(!compiler->is_optimizing()); 1717 ASSERT(!compiler->is_optimizing());
1842 __ b(&ok);
1843 __ Bind(fail); 1718 __ Bind(fail);
1844 1719
1845 __ ldr(IP, FieldAddress(field_reg, Field::guarded_cid_offset())); 1720 __ ldr(IP, FieldAddress(field_reg, Field::guarded_cid_offset()));
1846 __ CompareImmediate(IP, kDynamicCid); 1721 __ CompareImmediate(IP, kDynamicCid);
1847 __ b(&ok, EQ); 1722 __ b(&ok, EQ);
1848 1723
1849 __ Push(field_reg); 1724 __ Push(field_reg);
1850 __ Push(value_reg); 1725 __ Push(value_reg);
1851 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); 1726 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
1852 __ Drop(2); // Drop the field and the value. 1727 __ Drop(2); // Drop the field and the value.
1853 } 1728 }
1854 } else { 1729 } else {
1855 ASSERT(compiler->is_optimizing()); 1730 ASSERT(compiler->is_optimizing());
1856 ASSERT(deopt != NULL); 1731 ASSERT(deopt != NULL);
1732
1857 // Field guard class has been initialized and is known. 1733 // Field guard class has been initialized and is known.
1858 if (field_reg != kNoRegister) {
1859 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
1860 }
1861 if (value_cid == kDynamicCid) { 1734 if (value_cid == kDynamicCid) {
1862 // Field's guarded class id is fixed by value's class id is not known. 1735 // Field's guarded class id is fixed by value's class id is not known.
1863 __ tst(value_reg, Operand(kSmiTagMask)); 1736 __ tst(value_reg, Operand(kSmiTagMask));
1864 1737
1865 if (field_cid != kSmiCid) { 1738 if (field_cid != kSmiCid) {
1866 __ b(fail, EQ); 1739 __ b(fail, EQ);
1867 __ LoadClassId(value_cid_reg, value_reg); 1740 __ LoadClassId(value_cid_reg, value_reg);
1868 __ CompareImmediate(value_cid_reg, field_cid); 1741 __ CompareImmediate(value_cid_reg, field_cid);
1869 } 1742 }
1870 1743
1871 if (field_has_length) {
1872 __ b(fail, NE);
1873 // Classes are same, perform guarded list length check.
1874 ASSERT(field_reg != kNoRegister);
1875 ASSERT(value_cid_reg != kNoRegister);
1876 FieldAddress field_length_operand(
1877 field_reg, Field::guarded_list_length_offset());
1878 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1879 // Destroy value_cid_reg (safe because we are finished with it).
1880 __ ldr(value_cid_reg,
1881 FieldAddress(value_reg, Array::length_offset()));
1882 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1883 // Destroy value_cid_reg (safe because we are finished with it).
1884 __ ldr(value_cid_reg,
1885 FieldAddress(value_reg, TypedData::length_offset()));
1886 }
1887 __ ldr(IP, field_length_operand);
1888 __ cmp(value_cid_reg, Operand(IP));
1889 }
1890
1891 if (field().is_nullable() && (field_cid != kNullCid)) { 1744 if (field().is_nullable() && (field_cid != kNullCid)) {
1892 __ b(&ok, EQ); 1745 __ b(&ok, EQ);
1893 __ CompareImmediate(value_reg, 1746 if (field_cid != kSmiCid) {
1894 reinterpret_cast<intptr_t>(Object::null())); 1747 __ CompareImmediate(value_cid_reg, kNullCid);
1748 } else {
1749 __ CompareImmediate(value_reg,
1750 reinterpret_cast<intptr_t>(Object::null()));
1751 }
1895 } 1752 }
1896 __ b(fail, NE); 1753 __ b(fail, NE);
1897 } else { 1754 } else {
1898 // Both value's and field's class id is known. 1755 // Both value's and field's class id is known.
1899 if ((value_cid != field_cid) && (value_cid != nullability)) { 1756 ASSERT((value_cid != field_cid) && (value_cid != nullability));
1900 __ b(fail); 1757 __ b(fail);
1901 } else if (field_has_length && (value_cid == field_cid)) {
1902 ASSERT(value_cid_reg != kNoRegister);
1903 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1904 // Destroy value_cid_reg (safe because we are finished with it).
1905 __ ldr(value_cid_reg,
1906 FieldAddress(value_reg, Array::length_offset()));
1907 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1908 // Destroy value_cid_reg (safe because we are finished with it).
1909 __ ldr(value_cid_reg,
1910 FieldAddress(value_reg, TypedData::length_offset()));
1911 }
1912 __ CompareImmediate(value_cid_reg, field_length);
1913 __ b(fail, NE);
1914 } else {
1915 UNREACHABLE();
1916 }
1917 } 1758 }
1918 } 1759 }
1919 __ Bind(&ok); 1760 __ Bind(&ok);
1920 } 1761 }
1921 1762
1922 1763
1764 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Isolate* isolate,
1765 bool opt) const {
1766 const intptr_t kNumInputs = 1;
1767 LocationSummary* summary = new(isolate) LocationSummary(
1768 isolate, kNumInputs, 0, LocationSummary::kNoCall);
1769 summary->set_in(0, Location::RequiresRegister());
1770
1771 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) {
1772 // We need temporaries for field object, length offset and expected length.
1773 summary->AddTemp(Location::RequiresRegister());
1774 summary->AddTemp(Location::RequiresRegister());
1775 summary->AddTemp(Location::RequiresRegister());
1776 } else {
1777 // TODO(vegorov): can use TMP when length is small enough to fit into
1778 // immediate.
1779 summary->AddTemp(Location::RequiresRegister());
1780 }
1781
1782 return summary;
1783 }
1784
1785
1786 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1787 if (field().guarded_list_length() == Field::kNoFixedLength) {
1788 ASSERT(!compiler->is_optimizing());
1789 return; // Nothing to emit.
1790 }
1791
1792 Label* deopt = compiler->is_optimizing() ?
1793 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
1794
1795 const Register value_reg = locs()->in(0).reg();
1796
1797 if (!compiler->is_optimizing() ||
1798 (field().guarded_list_length() == Field::kUnknownFixedLength)) {
1799 const Register field_reg = locs()->temp(0).reg();
1800 const Register offset_reg = locs()->temp(1).reg();
1801 const Register length_reg = locs()->temp(2).reg();
1802
1803 Label ok;
1804
1805 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
1806
1807 __ ldrsb(offset_reg, FieldAddress(field_reg,
1808 Field::guarded_list_length_in_object_offset_offset()));
1809 __ ldr(length_reg, FieldAddress(field_reg,
1810 Field::guarded_list_length_offset()));
1811
1812 __ tst(offset_reg, Operand(offset_reg));
1813 __ b(&ok, MI);
1814
1815 // Load the length from the value. GuardFieldClass already verified that
1816 // value's class matches guarded class id of the field.
1817 // offset_reg contains offset already corrected by -kHeapObjectTag that is
1818 // why we use Address instead of FieldAddress.
1819 __ ldr(IP, Address(value_reg, offset_reg));
1820 __ cmp(length_reg, Operand(IP));
1821
1822 if (deopt == NULL) {
1823 __ b(&ok, EQ);
1824
1825 __ Push(field_reg);
1826 __ Push(value_reg);
1827 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
1828 __ Drop(2); // Drop the field and the value.
1829 } else {
1830 __ b(deopt, NE);
1831 }
1832
1833 __ Bind(&ok);
1834 } else {
1835 ASSERT(compiler->is_optimizing());
1836 ASSERT(field().guarded_list_length() >= 0);
1837 ASSERT(field().guarded_list_length_in_object_offset() !=
1838 Field::kUnknownLengthOffset);
1839
1840 const Register length_reg = locs()->temp(0).reg();
1841
1842 __ ldr(length_reg,
1843 FieldAddress(value_reg,
1844 field().guarded_list_length_in_object_offset()));
1845 __ CompareImmediate(length_reg,
1846 Smi::RawValue(field().guarded_list_length()));
1847 __ b(deopt, NE);
1848 }
1849 }
1850
1851
1923 class StoreInstanceFieldSlowPath : public SlowPathCode { 1852 class StoreInstanceFieldSlowPath : public SlowPathCode {
1924 public: 1853 public:
1925 StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction, 1854 StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction,
1926 const Class& cls) 1855 const Class& cls)
1927 : instruction_(instruction), cls_(cls) { } 1856 : instruction_(instruction), cls_(cls) { }
1928 1857
1929 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { 1858 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
1930 __ Comment("StoreInstanceFieldSlowPath"); 1859 __ Comment("StoreInstanceFieldSlowPath");
1931 __ Bind(entry_label()); 1860 __ Bind(entry_label());
1932 1861
(...skipping 4469 matching lines...) Expand 10 before | Expand all | Expand 10 after
6402 compiler->GenerateCall(token_pos(), 6331 compiler->GenerateCall(token_pos(),
6403 &label, 6332 &label,
6404 PcDescriptors::kOther, 6333 PcDescriptors::kOther,
6405 locs()); 6334 locs());
6406 __ Drop(ArgumentCount()); // Discard arguments. 6335 __ Drop(ArgumentCount()); // Discard arguments.
6407 } 6336 }
6408 6337
6409 } // namespace dart 6338 } // namespace dart
6410 6339
6411 #endif // defined TARGET_ARCH_ARM 6340 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.cc ('k') | runtime/vm/intermediate_language_arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698