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

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

Issue 730343005: Write-barrier verification on ARM. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 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 | 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" 5 #include "vm/globals.h"
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 1623 matching lines...) Expand 10 before | Expand all | Expand 10 after
1634 // For the value we are only interested in the new/old bit and the tag bit. 1634 // For the value we are only interested in the new/old bit and the tag bit.
1635 // And the new bit with the tag bit. The resulting bit will be 0 for a Smi. 1635 // And the new bit with the tag bit. The resulting bit will be 0 for a Smi.
1636 and_(IP, value, Operand(value, LSL, kObjectAlignmentLog2 - 1)); 1636 and_(IP, value, Operand(value, LSL, kObjectAlignmentLog2 - 1));
1637 // And the result with the negated space bit of the object. 1637 // And the result with the negated space bit of the object.
1638 bic(IP, IP, Operand(object)); 1638 bic(IP, IP, Operand(object));
1639 tst(IP, Operand(kNewObjectAlignmentOffset)); 1639 tst(IP, Operand(kNewObjectAlignmentOffset));
1640 b(no_update, EQ); 1640 b(no_update, EQ);
1641 } 1641 }
1642 1642
1643 1643
1644 Operand Assembler::GetVerifiedMemoryShadow() {
1645 Operand offset;
1646 if (!Operand::CanHold(VerifiedMemory::offset(), &offset)) {
1647 FATAL1("Offset 0x%" Px " not representable", VerifiedMemory::offset());
1648 }
1649 return offset;
1650 }
1651
1652
1653 void Assembler::WriteShadowedField(Register base,
1654 intptr_t offset,
1655 Register value,
1656 Condition cond) {
1657 if (VerifiedMemory::enabled()) {
1658 ASSERT(base != value);
1659 Operand shadow(GetVerifiedMemoryShadow());
1660 add(base, base, shadow, cond);
1661 str(value, Address(base, offset), cond);
1662 sub(base, base, shadow, cond);
1663 }
1664 str(value, Address(base, offset), cond);
1665 }
1666
1667
1668 void Assembler::WriteShadowedFieldPair(Register base,
1669 intptr_t offset,
1670 Register value_even,
1671 Register value_odd,
1672 Condition cond) {
1673 ASSERT(value_odd == value_even + 1);
1674 if (VerifiedMemory::enabled()) {
1675 ASSERT(base != value_even);
1676 ASSERT(base != value_odd);
1677 Operand shadow(GetVerifiedMemoryShadow());
1678 add(base, base, shadow, cond);
1679 strd(value_even, Address(base, offset), cond);
1680 sub(base, base, shadow, cond);
1681 }
1682 strd(value_even, Address(base, offset), cond);
1683 }
1684
1685
1686 Register UseRegister(Register reg, RegList* used) {
1687 ASSERT((*used & (1 << reg)) == 0);
1688 *used |= (1 << reg);
1689 return reg;
1690 }
1691
1692
1693 Register AllocateRegister(RegList* used) {
1694 const RegList free = ~*used;
1695 return (free == 0) ?
1696 kNoRegister :
1697 UseRegister(static_cast<Register>(Utils::CountTrailingZeros(free)), used);
1698 }
1699
1700
1701 void Assembler::VerifiedWrite(const Address& address, Register new_value) {
1702 if (VerifiedMemory::enabled()) {
1703 ASSERT(address.mode() == Address::Offset ||
1704 address.mode() == Address::NegOffset);
1705 // Allocate temporary registers.
1706 RegList used = 0;
1707 UseRegister(new_value, &used);
1708 Register base = UseRegister(address.rn(), &used);
1709 if (address.rm() != kNoRegister) UseRegister(address.rm(), &used);
1710 Register old_value = AllocateRegister(&used);
Ivan Posva 2014/12/08 19:27:56 How do you prevent allocating one of the pre-assig
koda 2014/12/08 22:23:42 Added assertions to UseRegister. This would only b
1711 Register shadow_value = AllocateRegister(&used);
Vyacheslav Egorov (Google) 2014/12/09 11:14:12 I suggest you merge your custom register allocator
koda 2014/12/09 14:38:28 VerifiedWrite needs to be used in lower-level code
1712 PushList(used);
1713 // Verify old value.
1714 ldr(old_value, address);
1715 Operand shadow_offset(GetVerifiedMemoryShadow());
1716 add(base, base, shadow_offset);
1717 ldr(shadow_value, address);
1718 cmp(old_value, Operand(shadow_value));
1719 Label ok;
1720 b(&ok);
1721 Stop("Write barrier verification failed");
1722 Bind(&ok);
1723 // Write new value.
1724 str(new_value, address);
1725 sub(base, base, shadow_offset);
1726 str(new_value, address);
1727 PopList(used);
1728 } else {
1729 str(new_value, address);
1730 }
1731 }
1732
1733
1644 void Assembler::StoreIntoObject(Register object, 1734 void Assembler::StoreIntoObject(Register object,
1645 const Address& dest, 1735 const Address& dest,
1646 Register value, 1736 Register value,
1647 bool can_value_be_smi) { 1737 bool can_value_be_smi) {
1648 ASSERT(object != value); 1738 ASSERT(object != value);
1649 str(value, dest); 1739 VerifiedWrite(dest, value);
1650 Label done; 1740 Label done;
1651 if (can_value_be_smi) { 1741 if (can_value_be_smi) {
1652 StoreIntoObjectFilter(object, value, &done); 1742 StoreIntoObjectFilter(object, value, &done);
1653 } else { 1743 } else {
1654 StoreIntoObjectFilterNoSmi(object, value, &done); 1744 StoreIntoObjectFilterNoSmi(object, value, &done);
1655 } 1745 }
1656 // A store buffer update is required. 1746 // A store buffer update is required.
1657 RegList regs = (1 << LR); 1747 RegList regs = (1 << LR);
1658 if (value != R0) { 1748 if (value != R0) {
1659 regs |= (1 << R0); // Preserve R0. 1749 regs |= (1 << R0); // Preserve R0.
(...skipping 20 matching lines...) Expand all
1680 } else { 1770 } else {
1681 AddImmediate(IP, object, offset - kHeapObjectTag); 1771 AddImmediate(IP, object, offset - kHeapObjectTag);
1682 StoreIntoObject(object, Address(IP), value, can_value_be_smi); 1772 StoreIntoObject(object, Address(IP), value, can_value_be_smi);
1683 } 1773 }
1684 } 1774 }
1685 1775
1686 1776
1687 void Assembler::StoreIntoObjectNoBarrier(Register object, 1777 void Assembler::StoreIntoObjectNoBarrier(Register object,
1688 const Address& dest, 1778 const Address& dest,
1689 Register value) { 1779 Register value) {
1690 str(value, dest); 1780 VerifiedWrite(dest, value);
1691 #if defined(DEBUG) 1781 #if defined(DEBUG)
1692 Label done; 1782 Label done;
1693 StoreIntoObjectFilter(object, value, &done); 1783 StoreIntoObjectFilter(object, value, &done);
1694 Stop("Store buffer update is required"); 1784 Stop("Store buffer update is required");
1695 Bind(&done); 1785 Bind(&done);
1696 #endif // defined(DEBUG) 1786 #endif // defined(DEBUG)
1697 // No store buffer update. 1787 // No store buffer update.
1698 } 1788 }
1699 1789
1700 1790
(...skipping 10 matching lines...) Expand all
1711 } 1801 }
1712 1802
1713 1803
1714 void Assembler::StoreIntoObjectNoBarrier(Register object, 1804 void Assembler::StoreIntoObjectNoBarrier(Register object,
1715 const Address& dest, 1805 const Address& dest,
1716 const Object& value) { 1806 const Object& value) {
1717 ASSERT(value.IsSmi() || value.InVMHeap() || 1807 ASSERT(value.IsSmi() || value.InVMHeap() ||
1718 (value.IsOld() && value.IsNotTemporaryScopedHandle())); 1808 (value.IsOld() && value.IsNotTemporaryScopedHandle()));
1719 // No store buffer update. 1809 // No store buffer update.
1720 LoadObject(IP, value); 1810 LoadObject(IP, value);
1721 str(IP, dest); 1811 VerifiedWrite(dest, IP);
1722 } 1812 }
1723 1813
1724 1814
1725 void Assembler::StoreIntoObjectNoBarrierOffset(Register object, 1815 void Assembler::StoreIntoObjectNoBarrierOffset(Register object,
1726 int32_t offset, 1816 int32_t offset,
1727 const Object& value) { 1817 const Object& value) {
1728 int32_t ignored = 0; 1818 int32_t ignored = 0;
1729 if (Address::CanHoldStoreOffset(kWord, offset - kHeapObjectTag, &ignored)) { 1819 if (Address::CanHoldStoreOffset(kWord, offset - kHeapObjectTag, &ignored)) {
1730 StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value); 1820 StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value);
1731 } else { 1821 } else {
1732 AddImmediate(IP, object, offset - kHeapObjectTag); 1822 AddImmediate(IP, object, offset - kHeapObjectTag);
1733 StoreIntoObjectNoBarrier(object, Address(IP), value); 1823 StoreIntoObjectNoBarrier(object, Address(IP), value);
1734 } 1824 }
1735 } 1825 }
1736 1826
1737 1827
1738 void Assembler::InitializeFieldsNoBarrier(Register object, 1828 void Assembler::InitializeFieldsNoBarrier(Register object,
1739 Register begin, 1829 Register begin,
1740 Register end, 1830 Register end,
1741 Register value_even, 1831 Register value_even,
1742 Register value_odd) { 1832 Register value_odd) {
1743 ASSERT(value_odd == value_even + 1); 1833 ASSERT(value_odd == value_even + 1);
1744 Label init_loop; 1834 Label init_loop;
1745 Bind(&init_loop); 1835 Bind(&init_loop);
1746 AddImmediate(begin, 2 * kWordSize); 1836 AddImmediate(begin, 2 * kWordSize);
1747 cmp(begin, Operand(end)); 1837 cmp(begin, Operand(end));
1748 strd(value_even, Address(begin, -2 * kWordSize), LS); 1838 WriteShadowedFieldPair(begin, -2 * kWordSize, value_even, value_odd, LS);
1749 b(&init_loop, CC); 1839 b(&init_loop, CC);
1750 str(value_even, Address(begin, -2 * kWordSize), HI); 1840 WriteShadowedField(begin, -2 * kWordSize, value_even, HI);
1751 #if defined(DEBUG) 1841 #if defined(DEBUG)
1752 Label done; 1842 Label done;
1753 StoreIntoObjectFilter(object, value_even, &done); 1843 StoreIntoObjectFilter(object, value_even, &done);
1754 StoreIntoObjectFilter(object, value_odd, &done); 1844 StoreIntoObjectFilter(object, value_odd, &done);
1755 Stop("Store buffer update is required"); 1845 Stop("Store buffer update is required");
1756 Bind(&done); 1846 Bind(&done);
1757 #endif // defined(DEBUG) 1847 #endif // defined(DEBUG)
1758 // No store buffer update. 1848 // No store buffer update.
1759 } 1849 }
1760 1850
1761 1851
1762 void Assembler::InitializeFieldsNoBarrierUnrolled(Register object, 1852 void Assembler::InitializeFieldsNoBarrierUnrolled(Register object,
1763 Register begin, 1853 Register base,
1764 intptr_t count, 1854 intptr_t begin_offset,
1855 intptr_t end_offset,
1765 Register value_even, 1856 Register value_even,
1766 Register value_odd) { 1857 Register value_odd) {
1767 ASSERT(value_odd == value_even + 1); 1858 ASSERT(value_odd == value_even + 1);
1768 intptr_t current_offset = 0; 1859 intptr_t current_offset = begin_offset;
1769 const intptr_t end_offset = count * kWordSize;
1770 while (current_offset + kWordSize < end_offset) { 1860 while (current_offset + kWordSize < end_offset) {
1771 strd(value_even, Address(begin, current_offset)); 1861 WriteShadowedFieldPair(base, current_offset, value_even, value_odd);
1772 current_offset += 2*kWordSize; 1862 current_offset += 2*kWordSize;
1773 } 1863 }
1774 while (current_offset < end_offset) { 1864 while (current_offset < end_offset) {
1775 str(value_even, Address(begin, current_offset)); 1865 WriteShadowedField(base, current_offset, value_even);
1776 current_offset += kWordSize; 1866 current_offset += kWordSize;
1777 } 1867 }
1778 #if defined(DEBUG) 1868 #if defined(DEBUG)
1779 Label done; 1869 Label done;
1780 StoreIntoObjectFilter(object, value_even, &done); 1870 StoreIntoObjectFilter(object, value_even, &done);
1781 StoreIntoObjectFilter(object, value_odd, &done); 1871 StoreIntoObjectFilter(object, value_odd, &done);
1782 Stop("Store buffer update is required"); 1872 Stop("Store buffer update is required");
1783 Bind(&done); 1873 Bind(&done);
1784 #endif // defined(DEBUG) 1874 #endif // defined(DEBUG)
1785 // No store buffer update. 1875 // No store buffer update.
1786 } 1876 }
1787 1877
1788 1878
1879 void Assembler::StoreIntoSmiField(const Address& dest, Register value) {
1880 // TODO(koda): Verify previous value was Smi.
1881 VerifiedWrite(dest, value);
1882 #if defined(DEBUG)
1883 Label done;
1884 tst(value, Operand(kHeapObjectTag));
1885 b(&done, EQ);
1886 Stop("Smi expected");
1887 Bind(&done);
1888 #endif // defined(DEBUG)
1889 }
1890
1891
1789 void Assembler::LoadClassId(Register result, Register object, Condition cond) { 1892 void Assembler::LoadClassId(Register result, Register object, Condition cond) {
1790 ASSERT(RawObject::kClassIdTagPos == 16); 1893 ASSERT(RawObject::kClassIdTagPos == 16);
1791 ASSERT(RawObject::kClassIdTagSize == 16); 1894 ASSERT(RawObject::kClassIdTagSize == 16);
1792 const intptr_t class_id_offset = Object::tags_offset() + 1895 const intptr_t class_id_offset = Object::tags_offset() +
1793 RawObject::kClassIdTagPos / kBitsPerByte; 1896 RawObject::kClassIdTagPos / kBitsPerByte;
1794 ldrh(result, FieldAddress(object, class_id_offset), cond); 1897 ldrh(result, FieldAddress(object, class_id_offset), cond);
1795 } 1898 }
1796 1899
1797 1900
1798 void Assembler::LoadClassById(Register result, Register class_id) { 1901 void Assembler::LoadClassById(Register result, Register class_id) {
(...skipping 1674 matching lines...) Expand 10 before | Expand all | Expand 10 after
3473 3576
3474 3577
3475 const char* Assembler::FpuRegisterName(FpuRegister reg) { 3578 const char* Assembler::FpuRegisterName(FpuRegister reg) {
3476 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); 3579 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters));
3477 return fpu_reg_names[reg]; 3580 return fpu_reg_names[reg];
3478 } 3581 }
3479 3582
3480 } // namespace dart 3583 } // namespace dart
3481 3584
3482 #endif // defined TARGET_ARCH_ARM 3585 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698