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

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 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/assembler_arm.h ('k') | runtime/vm/code_patcher_arm.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" 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"
11 #include "vm/runtime_entry.h" 11 #include "vm/runtime_entry.h"
12 #include "vm/simulator.h" 12 #include "vm/simulator.h"
13 #include "vm/stack_frame.h" 13 #include "vm/stack_frame.h"
14 #include "vm/stub_code.h" 14 #include "vm/stub_code.h"
15 15
(...skipping 1618 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(reg != SP);
1688 ASSERT(reg != PC);
1689 ASSERT((*used & (1 << reg)) == 0);
1690 *used |= (1 << reg);
1691 return reg;
1692 }
1693
1694
1695 Register AllocateRegister(RegList* used) {
1696 const RegList free = ~*used;
1697 return (free == 0) ?
1698 kNoRegister :
1699 UseRegister(static_cast<Register>(Utils::CountTrailingZeros(free)), used);
1700 }
1701
1702
1703 void Assembler::VerifiedWrite(const Address& address, Register new_value) {
1704 if (VerifiedMemory::enabled()) {
1705 ASSERT(address.mode() == Address::Offset ||
1706 address.mode() == Address::NegOffset);
1707 // Allocate temporary registers (and check for register collisions).
1708 RegList used = 0;
1709 UseRegister(new_value, &used);
1710 Register base = UseRegister(address.rn(), &used);
1711 if (address.rm() != kNoRegister) UseRegister(address.rm(), &used);
1712 Register old_value = AllocateRegister(&used);
1713 Register shadow_value = AllocateRegister(&used);
1714 PushList(used);
1715 // Verify old value.
1716 ldr(old_value, address);
1717 Operand shadow_offset(GetVerifiedMemoryShadow());
1718 add(base, base, shadow_offset);
1719 ldr(shadow_value, address);
1720 cmp(old_value, Operand(shadow_value));
1721 Label ok;
1722 b(&ok);
1723 Stop("Write barrier verification failed");
1724 Bind(&ok);
1725 // Write new value.
1726 str(new_value, address);
1727 sub(base, base, shadow_offset);
1728 str(new_value, address);
1729 PopList(used);
1730 } else {
1731 str(new_value, address);
1732 }
1733 }
1734
1735
1644 void Assembler::StoreIntoObject(Register object, 1736 void Assembler::StoreIntoObject(Register object,
1645 const Address& dest, 1737 const Address& dest,
1646 Register value, 1738 Register value,
1647 bool can_value_be_smi) { 1739 bool can_value_be_smi) {
1648 ASSERT(object != value); 1740 ASSERT(object != value);
1649 str(value, dest); 1741 VerifiedWrite(dest, value);
1650 Label done; 1742 Label done;
1651 if (can_value_be_smi) { 1743 if (can_value_be_smi) {
1652 StoreIntoObjectFilter(object, value, &done); 1744 StoreIntoObjectFilter(object, value, &done);
1653 } else { 1745 } else {
1654 StoreIntoObjectFilterNoSmi(object, value, &done); 1746 StoreIntoObjectFilterNoSmi(object, value, &done);
1655 } 1747 }
1656 // A store buffer update is required. 1748 // A store buffer update is required.
1657 RegList regs = (1 << LR); 1749 RegList regs = (1 << LR);
1658 if (value != R0) { 1750 if (value != R0) {
1659 regs |= (1 << R0); // Preserve R0. 1751 regs |= (1 << R0); // Preserve R0.
(...skipping 20 matching lines...) Expand all
1680 } else { 1772 } else {
1681 AddImmediate(IP, object, offset - kHeapObjectTag); 1773 AddImmediate(IP, object, offset - kHeapObjectTag);
1682 StoreIntoObject(object, Address(IP), value, can_value_be_smi); 1774 StoreIntoObject(object, Address(IP), value, can_value_be_smi);
1683 } 1775 }
1684 } 1776 }
1685 1777
1686 1778
1687 void Assembler::StoreIntoObjectNoBarrier(Register object, 1779 void Assembler::StoreIntoObjectNoBarrier(Register object,
1688 const Address& dest, 1780 const Address& dest,
1689 Register value) { 1781 Register value) {
1690 str(value, dest); 1782 VerifiedWrite(dest, value);
1691 #if defined(DEBUG) 1783 #if defined(DEBUG)
1692 Label done; 1784 Label done;
1693 StoreIntoObjectFilter(object, value, &done); 1785 StoreIntoObjectFilter(object, value, &done);
1694 Stop("Store buffer update is required"); 1786 Stop("Store buffer update is required");
1695 Bind(&done); 1787 Bind(&done);
1696 #endif // defined(DEBUG) 1788 #endif // defined(DEBUG)
1697 // No store buffer update. 1789 // No store buffer update.
1698 } 1790 }
1699 1791
1700 1792
(...skipping 10 matching lines...) Expand all
1711 } 1803 }
1712 1804
1713 1805
1714 void Assembler::StoreIntoObjectNoBarrier(Register object, 1806 void Assembler::StoreIntoObjectNoBarrier(Register object,
1715 const Address& dest, 1807 const Address& dest,
1716 const Object& value) { 1808 const Object& value) {
1717 ASSERT(value.IsSmi() || value.InVMHeap() || 1809 ASSERT(value.IsSmi() || value.InVMHeap() ||
1718 (value.IsOld() && value.IsNotTemporaryScopedHandle())); 1810 (value.IsOld() && value.IsNotTemporaryScopedHandle()));
1719 // No store buffer update. 1811 // No store buffer update.
1720 LoadObject(IP, value); 1812 LoadObject(IP, value);
1721 str(IP, dest); 1813 VerifiedWrite(dest, IP);
1722 } 1814 }
1723 1815
1724 1816
1725 void Assembler::StoreIntoObjectNoBarrierOffset(Register object, 1817 void Assembler::StoreIntoObjectNoBarrierOffset(Register object,
1726 int32_t offset, 1818 int32_t offset,
1727 const Object& value) { 1819 const Object& value) {
1728 int32_t ignored = 0; 1820 int32_t ignored = 0;
1729 if (Address::CanHoldStoreOffset(kWord, offset - kHeapObjectTag, &ignored)) { 1821 if (Address::CanHoldStoreOffset(kWord, offset - kHeapObjectTag, &ignored)) {
1730 StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value); 1822 StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value);
1731 } else { 1823 } else {
1732 AddImmediate(IP, object, offset - kHeapObjectTag); 1824 AddImmediate(IP, object, offset - kHeapObjectTag);
1733 StoreIntoObjectNoBarrier(object, Address(IP), value); 1825 StoreIntoObjectNoBarrier(object, Address(IP), value);
1734 } 1826 }
1735 } 1827 }
1736 1828
1737 1829
1738 void Assembler::InitializeFieldsNoBarrier(Register object, 1830 void Assembler::InitializeFieldsNoBarrier(Register object,
1739 Register begin, 1831 Register begin,
1740 Register end, 1832 Register end,
1741 Register value_even, 1833 Register value_even,
1742 Register value_odd) { 1834 Register value_odd) {
1743 ASSERT(value_odd == value_even + 1); 1835 ASSERT(value_odd == value_even + 1);
1744 Label init_loop; 1836 Label init_loop;
1745 Bind(&init_loop); 1837 Bind(&init_loop);
1746 AddImmediate(begin, 2 * kWordSize); 1838 AddImmediate(begin, 2 * kWordSize);
1747 cmp(begin, Operand(end)); 1839 cmp(begin, Operand(end));
1748 strd(value_even, Address(begin, -2 * kWordSize), LS); 1840 WriteShadowedFieldPair(begin, -2 * kWordSize, value_even, value_odd, LS);
1749 b(&init_loop, CC); 1841 b(&init_loop, CC);
1750 str(value_even, Address(begin, -2 * kWordSize), HI); 1842 WriteShadowedField(begin, -2 * kWordSize, value_even, HI);
1751 #if defined(DEBUG) 1843 #if defined(DEBUG)
1752 Label done; 1844 Label done;
1753 StoreIntoObjectFilter(object, value_even, &done); 1845 StoreIntoObjectFilter(object, value_even, &done);
1754 StoreIntoObjectFilter(object, value_odd, &done); 1846 StoreIntoObjectFilter(object, value_odd, &done);
1755 Stop("Store buffer update is required"); 1847 Stop("Store buffer update is required");
1756 Bind(&done); 1848 Bind(&done);
1757 #endif // defined(DEBUG) 1849 #endif // defined(DEBUG)
1758 // No store buffer update. 1850 // No store buffer update.
1759 } 1851 }
1760 1852
1761 1853
1762 void Assembler::InitializeFieldsNoBarrierUnrolled(Register object, 1854 void Assembler::InitializeFieldsNoBarrierUnrolled(Register object,
1763 Register begin, 1855 Register base,
1764 intptr_t count, 1856 intptr_t begin_offset,
1857 intptr_t end_offset,
1765 Register value_even, 1858 Register value_even,
1766 Register value_odd) { 1859 Register value_odd) {
1767 ASSERT(value_odd == value_even + 1); 1860 ASSERT(value_odd == value_even + 1);
1768 intptr_t current_offset = 0; 1861 intptr_t current_offset = begin_offset;
1769 const intptr_t end_offset = count * kWordSize;
1770 while (current_offset + kWordSize < end_offset) { 1862 while (current_offset + kWordSize < end_offset) {
1771 strd(value_even, Address(begin, current_offset)); 1863 WriteShadowedFieldPair(base, current_offset, value_even, value_odd);
1772 current_offset += 2*kWordSize; 1864 current_offset += 2*kWordSize;
1773 } 1865 }
1774 while (current_offset < end_offset) { 1866 while (current_offset < end_offset) {
1775 str(value_even, Address(begin, current_offset)); 1867 WriteShadowedField(base, current_offset, value_even);
1776 current_offset += kWordSize; 1868 current_offset += kWordSize;
1777 } 1869 }
1778 #if defined(DEBUG) 1870 #if defined(DEBUG)
1779 Label done; 1871 Label done;
1780 StoreIntoObjectFilter(object, value_even, &done); 1872 StoreIntoObjectFilter(object, value_even, &done);
1781 StoreIntoObjectFilter(object, value_odd, &done); 1873 StoreIntoObjectFilter(object, value_odd, &done);
1782 Stop("Store buffer update is required"); 1874 Stop("Store buffer update is required");
1783 Bind(&done); 1875 Bind(&done);
1784 #endif // defined(DEBUG) 1876 #endif // defined(DEBUG)
1785 // No store buffer update. 1877 // No store buffer update.
1786 } 1878 }
1787 1879
1788 1880
1881 void Assembler::StoreIntoSmiField(const Address& dest, Register value) {
1882 // TODO(koda): Verify previous value was Smi.
1883 VerifiedWrite(dest, value);
1884 #if defined(DEBUG)
1885 Label done;
1886 tst(value, Operand(kHeapObjectTag));
1887 b(&done, EQ);
1888 Stop("Smi expected");
1889 Bind(&done);
1890 #endif // defined(DEBUG)
1891 }
1892
1893
1789 void Assembler::LoadClassId(Register result, Register object, Condition cond) { 1894 void Assembler::LoadClassId(Register result, Register object, Condition cond) {
1790 ASSERT(RawObject::kClassIdTagPos == 16); 1895 ASSERT(RawObject::kClassIdTagPos == 16);
1791 ASSERT(RawObject::kClassIdTagSize == 16); 1896 ASSERT(RawObject::kClassIdTagSize == 16);
1792 const intptr_t class_id_offset = Object::tags_offset() + 1897 const intptr_t class_id_offset = Object::tags_offset() +
1793 RawObject::kClassIdTagPos / kBitsPerByte; 1898 RawObject::kClassIdTagPos / kBitsPerByte;
1794 ldrh(result, FieldAddress(object, class_id_offset), cond); 1899 ldrh(result, FieldAddress(object, class_id_offset), cond);
1795 } 1900 }
1796 1901
1797 1902
1798 void Assembler::LoadClassById(Register result, Register class_id) { 1903 void Assembler::LoadClassById(Register result, Register class_id) {
(...skipping 1676 matching lines...) Expand 10 before | Expand all | Expand 10 after
3475 3580
3476 3581
3477 const char* Assembler::FpuRegisterName(FpuRegister reg) { 3582 const char* Assembler::FpuRegisterName(FpuRegister reg) {
3478 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); 3583 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters));
3479 return fpu_reg_names[reg]; 3584 return fpu_reg_names[reg];
3480 } 3585 }
3481 3586
3482 } // namespace dart 3587 } // namespace dart
3483 3588
3484 #endif // defined TARGET_ARCH_ARM 3589 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/assembler_arm.h ('k') | runtime/vm/code_patcher_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698