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

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

Issue 1409733009: ARM: Fix double use of IP when storing object fields with large offsets. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 1 month 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
« no previous file with comments | « runtime/vm/assembler_arm.h ('k') | no next file » | 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" // NOLINT 5 #include "vm/globals.h" // NOLINT
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/cpu.h" 9 #include "vm/cpu.h"
10 #include "vm/longjump.h" 10 #include "vm/longjump.h"
(...skipping 1706 matching lines...) Expand 10 before | Expand all | Expand 10 after
1717 Operand shadow(GetVerifiedMemoryShadow()); 1717 Operand shadow(GetVerifiedMemoryShadow());
1718 add(base, base, shadow, cond); 1718 add(base, base, shadow, cond);
1719 strd(value_even, value_odd, base, offset, cond); 1719 strd(value_even, value_odd, base, offset, cond);
1720 sub(base, base, shadow, cond); 1720 sub(base, base, shadow, cond);
1721 } 1721 }
1722 strd(value_even, value_odd, base, offset, cond); 1722 strd(value_even, value_odd, base, offset, cond);
1723 } 1723 }
1724 1724
1725 1725
1726 Register UseRegister(Register reg, RegList* used) { 1726 Register UseRegister(Register reg, RegList* used) {
1727 ASSERT(reg != THR);
1727 ASSERT(reg != SP); 1728 ASSERT(reg != SP);
1729 ASSERT(reg != FP);
1728 ASSERT(reg != PC); 1730 ASSERT(reg != PC);
1729 ASSERT((*used & (1 << reg)) == 0); 1731 ASSERT((*used & (1 << reg)) == 0);
1730 *used |= (1 << reg); 1732 *used |= (1 << reg);
1731 return reg; 1733 return reg;
1732 } 1734 }
1733 1735
1734 1736
1735 Register AllocateRegister(RegList* used) { 1737 Register AllocateRegister(RegList* used) {
1736 const RegList free = ~*used; 1738 const RegList free = ~*used;
1737 return (free == 0) ? 1739 return (free == 0) ?
1738 kNoRegister : 1740 kNoRegister :
1739 UseRegister(static_cast<Register>(Utils::CountTrailingZeros(free)), used); 1741 UseRegister(static_cast<Register>(Utils::CountTrailingZeros(free)), used);
1740 } 1742 }
1741 1743
1742 1744
1743 void Assembler::VerifiedWrite(const Address& address, 1745 void Assembler::VerifiedWrite(Register object,
1746 const Address& address,
1744 Register new_value, 1747 Register new_value,
1745 FieldContent old_content) { 1748 FieldContent old_content) {
1746 #if defined(DEBUG) 1749 #if defined(DEBUG)
1747 ASSERT(address.mode() == Address::Offset || 1750 ASSERT(address.mode() == Address::Offset ||
1748 address.mode() == Address::NegOffset); 1751 address.mode() == Address::NegOffset);
1749 // Allocate temporary registers (and check for register collisions). 1752 // Allocate temporary registers (and check for register collisions).
1750 RegList used = 0; 1753 RegList used = 0;
1751 UseRegister(new_value, &used); 1754 UseRegister(new_value, &used);
1752 Register base = UseRegister(address.rn(), &used); 1755 Register base = UseRegister(address.rn(), &used);
1756 if ((object != base) && (object != kNoRegister)) {
Florian Schneider 2015/11/05 01:50:35 I guess not checking (object != base) would be ok,
1757 UseRegister(object, &used);
1758 }
1753 if (address.rm() != kNoRegister) { 1759 if (address.rm() != kNoRegister) {
1754 UseRegister(address.rm(), &used); 1760 UseRegister(address.rm(), &used);
1755 } 1761 }
1756 Register old_value = AllocateRegister(&used); 1762 Register old_value = AllocateRegister(&used);
1757 Register temp = AllocateRegister(&used); 1763 Register temp = AllocateRegister(&used);
1758 PushList(used); 1764 PushList(used);
1759 ldr(old_value, address); 1765 ldr(old_value, address);
1760 // First check that 'old_value' contains 'old_content'. 1766 // First check that 'old_value' contains 'old_content'.
1761 // Smi test. 1767 // Smi test.
1762 tst(old_value, Operand(kHeapObjectTag)); 1768 tst(old_value, Operand(kHeapObjectTag));
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1811 str(new_value, address); 1817 str(new_value, address);
1812 #endif // DEBUG 1818 #endif // DEBUG
1813 } 1819 }
1814 1820
1815 1821
1816 void Assembler::StoreIntoObject(Register object, 1822 void Assembler::StoreIntoObject(Register object,
1817 const Address& dest, 1823 const Address& dest,
1818 Register value, 1824 Register value,
1819 bool can_value_be_smi) { 1825 bool can_value_be_smi) {
1820 ASSERT(object != value); 1826 ASSERT(object != value);
1821 VerifiedWrite(dest, value, kHeapObjectOrSmi); 1827 VerifiedWrite(object, dest, value, kHeapObjectOrSmi);
1822 Label done; 1828 Label done;
1823 if (can_value_be_smi) { 1829 if (can_value_be_smi) {
1824 StoreIntoObjectFilter(object, value, &done); 1830 StoreIntoObjectFilter(object, value, &done);
1825 } else { 1831 } else {
1826 StoreIntoObjectFilterNoSmi(object, value, &done); 1832 StoreIntoObjectFilterNoSmi(object, value, &done);
1827 } 1833 }
1828 // A store buffer update is required. 1834 // A store buffer update is required.
1829 RegList regs = (1 << CODE_REG) | (1 << LR); 1835 RegList regs = (1 << CODE_REG) | (1 << LR);
1830 if (value != R0) { 1836 if (value != R0) {
1831 regs |= (1 << R0); // Preserve R0. 1837 regs |= (1 << R0); // Preserve R0.
(...skipping 22 matching lines...) Expand all
1854 AddImmediate(IP, object, offset - kHeapObjectTag); 1860 AddImmediate(IP, object, offset - kHeapObjectTag);
1855 StoreIntoObject(object, Address(IP), value, can_value_be_smi); 1861 StoreIntoObject(object, Address(IP), value, can_value_be_smi);
1856 } 1862 }
1857 } 1863 }
1858 1864
1859 1865
1860 void Assembler::StoreIntoObjectNoBarrier(Register object, 1866 void Assembler::StoreIntoObjectNoBarrier(Register object,
1861 const Address& dest, 1867 const Address& dest,
1862 Register value, 1868 Register value,
1863 FieldContent old_content) { 1869 FieldContent old_content) {
1864 VerifiedWrite(dest, value, old_content); 1870 VerifiedWrite(object, dest, value, old_content);
1865 #if defined(DEBUG) 1871 #if defined(DEBUG)
1866 Label done; 1872 Label done;
1867 StoreIntoObjectFilter(object, value, &done); 1873 StoreIntoObjectFilter(object, value, &done);
1868 Stop("Store buffer update is required"); 1874 Stop("Store buffer update is required");
1869 Bind(&done); 1875 Bind(&done);
1870 #endif // defined(DEBUG) 1876 #endif // defined(DEBUG)
1871 // No store buffer update. 1877 // No store buffer update.
1872 } 1878 }
1873 1879
1874 1880
(...skipping 13 matching lines...) Expand all
1888 1894
1889 1895
1890 void Assembler::StoreIntoObjectNoBarrier(Register object, 1896 void Assembler::StoreIntoObjectNoBarrier(Register object,
1891 const Address& dest, 1897 const Address& dest,
1892 const Object& value, 1898 const Object& value,
1893 FieldContent old_content) { 1899 FieldContent old_content) {
1894 ASSERT(value.IsSmi() || value.InVMHeap() || 1900 ASSERT(value.IsSmi() || value.InVMHeap() ||
1895 (value.IsOld() && value.IsNotTemporaryScopedHandle())); 1901 (value.IsOld() && value.IsNotTemporaryScopedHandle()));
1896 // No store buffer update. 1902 // No store buffer update.
1897 LoadObject(IP, value); 1903 LoadObject(IP, value);
1898 VerifiedWrite(dest, IP, old_content); 1904 VerifiedWrite(object, dest, IP, old_content);
1899 } 1905 }
1900 1906
1901 1907
1902 void Assembler::StoreIntoObjectNoBarrierOffset(Register object, 1908 void Assembler::StoreIntoObjectNoBarrierOffset(Register object,
1903 int32_t offset, 1909 int32_t offset,
1904 const Object& value, 1910 const Object& value,
1905 FieldContent old_content) { 1911 FieldContent old_content) {
1906 int32_t ignored = 0; 1912 int32_t ignored = 0;
1907 if (Address::CanHoldStoreOffset(kWord, offset - kHeapObjectTag, &ignored)) { 1913 if (Address::CanHoldStoreOffset(kWord, offset - kHeapObjectTag, &ignored)) {
1908 StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value, 1914 StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value,
1909 old_content); 1915 old_content);
1910 } else { 1916 } else {
1911 AddImmediate(IP, object, offset - kHeapObjectTag); 1917 Register base = object == R9 ? R8 : R9;
1912 StoreIntoObjectNoBarrier(object, Address(IP), value, old_content); 1918 Push(base);
1919 AddImmediate(base, object, offset - kHeapObjectTag);
1920 StoreIntoObjectNoBarrier(object, Address(base), value, old_content);
1921 Pop(base);
1913 } 1922 }
1914 } 1923 }
1915 1924
1916 1925
1917 void Assembler::InitializeFieldsNoBarrier(Register object, 1926 void Assembler::InitializeFieldsNoBarrier(Register object,
1918 Register begin, 1927 Register begin,
1919 Register end, 1928 Register end,
1920 Register value_even, 1929 Register value_even,
1921 Register value_odd) { 1930 Register value_odd) {
1922 ASSERT(value_odd == value_even + 1); 1931 ASSERT(value_odd == value_even + 1);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1966 1975
1967 1976
1968 void Assembler::StoreIntoSmiField(const Address& dest, Register value) { 1977 void Assembler::StoreIntoSmiField(const Address& dest, Register value) {
1969 #if defined(DEBUG) 1978 #if defined(DEBUG)
1970 Label done; 1979 Label done;
1971 tst(value, Operand(kHeapObjectTag)); 1980 tst(value, Operand(kHeapObjectTag));
1972 b(&done, EQ); 1981 b(&done, EQ);
1973 Stop("New value must be Smi."); 1982 Stop("New value must be Smi.");
1974 Bind(&done); 1983 Bind(&done);
1975 #endif // defined(DEBUG) 1984 #endif // defined(DEBUG)
1976 VerifiedWrite(dest, value, kOnlySmi); 1985 VerifiedWrite(kNoRegister, dest, value, kOnlySmi);
1977 } 1986 }
1978 1987
1979 1988
1980 void Assembler::LoadClassId(Register result, Register object, Condition cond) { 1989 void Assembler::LoadClassId(Register result, Register object, Condition cond) {
1981 ASSERT(RawObject::kClassIdTagPos == 16); 1990 ASSERT(RawObject::kClassIdTagPos == 16);
1982 ASSERT(RawObject::kClassIdTagSize == 16); 1991 ASSERT(RawObject::kClassIdTagSize == 16);
1983 const intptr_t class_id_offset = Object::tags_offset() + 1992 const intptr_t class_id_offset = Object::tags_offset() +
1984 RawObject::kClassIdTagPos / kBitsPerByte; 1993 RawObject::kClassIdTagPos / kBitsPerByte;
1985 ldrh(result, FieldAddress(object, class_id_offset), cond); 1994 ldrh(result, FieldAddress(object, class_id_offset), cond);
1986 } 1995 }
(...skipping 1656 matching lines...) Expand 10 before | Expand all | Expand 10 after
3643 3652
3644 3653
3645 const char* Assembler::FpuRegisterName(FpuRegister reg) { 3654 const char* Assembler::FpuRegisterName(FpuRegister reg) {
3646 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); 3655 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters));
3647 return fpu_reg_names[reg]; 3656 return fpu_reg_names[reg];
3648 } 3657 }
3649 3658
3650 } // namespace dart 3659 } // namespace dart
3651 3660
3652 #endif // defined TARGET_ARCH_ARM 3661 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/assembler_arm.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698