OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |