Chromium Code Reviews| 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" // 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 1682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1693 | 1693 |
| 1694 | 1694 |
| 1695 Register AllocateRegister(RegList* used) { | 1695 Register AllocateRegister(RegList* used) { |
| 1696 const RegList free = ~*used; | 1696 const RegList free = ~*used; |
| 1697 return (free == 0) ? | 1697 return (free == 0) ? |
| 1698 kNoRegister : | 1698 kNoRegister : |
| 1699 UseRegister(static_cast<Register>(Utils::CountTrailingZeros(free)), used); | 1699 UseRegister(static_cast<Register>(Utils::CountTrailingZeros(free)), used); |
| 1700 } | 1700 } |
| 1701 | 1701 |
| 1702 | 1702 |
| 1703 void Assembler::VerifiedWrite(const Address& address, Register new_value) { | 1703 void Assembler::VerifiedWrite(const Address& address, |
| 1704 Register new_value, | |
| 1705 FieldContent old_content) { | |
| 1706 #if defined(DEBUG) | |
| 1707 ASSERT(address.mode() == Address::Offset || | |
| 1708 address.mode() == Address::NegOffset); | |
| 1709 // Allocate temporary registers (and check for register collisions). | |
| 1710 RegList used = 0; | |
| 1711 UseRegister(new_value, &used); | |
| 1712 Register base = UseRegister(address.rn(), &used); | |
| 1713 if (address.rm() != kNoRegister) UseRegister(address.rm(), &used); | |
|
Ivan Posva
2015/01/16 06:34:48
{
}
koda
2015/01/16 16:24:32
Done.
| |
| 1714 Register old_value = AllocateRegister(&used); | |
| 1715 Register temp = AllocateRegister(&used); | |
| 1716 PushList(used); | |
| 1717 ldr(old_value, address); | |
| 1718 // First check that 'old_value' contains 'old_content'. | |
| 1719 // Smi test. | |
| 1720 tst(old_value, Operand(kHeapObjectTag)); | |
| 1721 Label ok; | |
| 1722 switch (old_content) { | |
| 1723 case kOnlySmi: | |
| 1724 b(&ok, EQ); // Smi is OK. | |
| 1725 Stop("Expected smi."); | |
| 1726 break; | |
| 1727 case kHeapObjectOrSmi: | |
| 1728 b(&ok, EQ); // Smi is OK. | |
| 1729 // Non-smi case: Verify object pointer is word-aligned when untagged. | |
| 1730 COMPILE_ASSERT(kHeapObjectTag == 1); | |
| 1731 tst(old_value, Operand((kWordSize - 1) - kHeapObjectTag)); | |
| 1732 b(&ok, EQ); | |
| 1733 Stop("Expected heap object or Smi"); | |
| 1734 break; | |
| 1735 case kEmptyOrSmiOrNull: | |
| 1736 b(&ok, EQ); // Smi is OK. | |
| 1737 // Non-smi case: Check for the special zap word or null. | |
| 1738 // Note: Cannot use CompareImmediate, since IP may be in use. | |
| 1739 LoadImmediate(temp, Heap::kZap32Bits); | |
| 1740 cmp(old_value, Operand(temp)); | |
| 1741 b(&ok, EQ); | |
| 1742 LoadImmediate(temp, reinterpret_cast<uint32_t>(Object::null())); | |
| 1743 cmp(old_value, Operand(temp)); | |
| 1744 b(&ok, EQ); | |
| 1745 Stop("Expected zapped, Smi or null"); | |
| 1746 break; | |
| 1747 default: | |
| 1748 UNREACHABLE(); | |
| 1749 } | |
| 1750 Bind(&ok); | |
| 1704 if (VerifiedMemory::enabled()) { | 1751 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()); | 1752 Operand shadow_offset(GetVerifiedMemoryShadow()); |
| 1753 // Adjust the address to shadow. | |
| 1718 add(base, base, shadow_offset); | 1754 add(base, base, shadow_offset); |
| 1719 ldr(shadow_value, address); | 1755 ldr(temp, address); |
| 1720 cmp(old_value, Operand(shadow_value)); | 1756 cmp(old_value, Operand(temp)); |
| 1721 Label ok; | 1757 Label match; |
| 1722 b(&ok); | 1758 b(&match, EQ); |
| 1723 Stop("Write barrier verification failed"); | 1759 Stop("Write barrier verification failed"); |
| 1724 Bind(&ok); | 1760 Bind(&match); |
| 1725 // Write new value. | 1761 // Write new value in shadow. |
| 1726 str(new_value, address); | 1762 str(new_value, address); |
| 1763 // Restore original address. | |
| 1727 sub(base, base, shadow_offset); | 1764 sub(base, base, shadow_offset); |
| 1728 str(new_value, address); | |
| 1729 PopList(used); | |
| 1730 } else { | |
| 1731 str(new_value, address); | |
| 1732 } | 1765 } |
| 1766 str(new_value, address); | |
| 1767 PopList(used); | |
| 1768 #else | |
| 1769 str(new_value, address); | |
| 1770 #endif // DEBUG | |
| 1733 } | 1771 } |
| 1734 | 1772 |
| 1735 | 1773 |
| 1736 void Assembler::StoreIntoObject(Register object, | 1774 void Assembler::StoreIntoObject(Register object, |
| 1737 const Address& dest, | 1775 const Address& dest, |
| 1738 Register value, | 1776 Register value, |
| 1739 bool can_value_be_smi) { | 1777 bool can_value_be_smi) { |
| 1740 ASSERT(object != value); | 1778 ASSERT(object != value); |
| 1741 VerifiedWrite(dest, value); | 1779 VerifiedWrite(dest, value, kHeapObjectOrSmi); |
| 1742 Label done; | 1780 Label done; |
| 1743 if (can_value_be_smi) { | 1781 if (can_value_be_smi) { |
| 1744 StoreIntoObjectFilter(object, value, &done); | 1782 StoreIntoObjectFilter(object, value, &done); |
| 1745 } else { | 1783 } else { |
| 1746 StoreIntoObjectFilterNoSmi(object, value, &done); | 1784 StoreIntoObjectFilterNoSmi(object, value, &done); |
| 1747 } | 1785 } |
| 1748 // A store buffer update is required. | 1786 // A store buffer update is required. |
| 1749 RegList regs = (1 << LR); | 1787 RegList regs = (1 << LR); |
| 1750 if (value != R0) { | 1788 if (value != R0) { |
| 1751 regs |= (1 << R0); // Preserve R0. | 1789 regs |= (1 << R0); // Preserve R0. |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1771 object, FieldAddress(object, offset), value, can_value_be_smi); | 1809 object, FieldAddress(object, offset), value, can_value_be_smi); |
| 1772 } else { | 1810 } else { |
| 1773 AddImmediate(IP, object, offset - kHeapObjectTag); | 1811 AddImmediate(IP, object, offset - kHeapObjectTag); |
| 1774 StoreIntoObject(object, Address(IP), value, can_value_be_smi); | 1812 StoreIntoObject(object, Address(IP), value, can_value_be_smi); |
| 1775 } | 1813 } |
| 1776 } | 1814 } |
| 1777 | 1815 |
| 1778 | 1816 |
| 1779 void Assembler::StoreIntoObjectNoBarrier(Register object, | 1817 void Assembler::StoreIntoObjectNoBarrier(Register object, |
| 1780 const Address& dest, | 1818 const Address& dest, |
| 1781 Register value) { | 1819 Register value, |
| 1782 VerifiedWrite(dest, value); | 1820 FieldContent old_content) { |
| 1821 VerifiedWrite(dest, value, old_content); | |
| 1783 #if defined(DEBUG) | 1822 #if defined(DEBUG) |
| 1784 Label done; | 1823 Label done; |
| 1785 StoreIntoObjectFilter(object, value, &done); | 1824 StoreIntoObjectFilter(object, value, &done); |
| 1786 Stop("Store buffer update is required"); | 1825 Stop("Store buffer update is required"); |
| 1787 Bind(&done); | 1826 Bind(&done); |
| 1788 #endif // defined(DEBUG) | 1827 #endif // defined(DEBUG) |
| 1789 // No store buffer update. | 1828 // No store buffer update. |
| 1790 } | 1829 } |
| 1791 | 1830 |
| 1792 | 1831 |
| 1793 void Assembler::StoreIntoObjectNoBarrierOffset(Register object, | 1832 void Assembler::StoreIntoObjectNoBarrierOffset(Register object, |
| 1794 int32_t offset, | 1833 int32_t offset, |
| 1795 Register value) { | 1834 Register value, |
| 1835 FieldContent old_content) { | |
| 1796 int32_t ignored = 0; | 1836 int32_t ignored = 0; |
| 1797 if (Address::CanHoldStoreOffset(kWord, offset - kHeapObjectTag, &ignored)) { | 1837 if (Address::CanHoldStoreOffset(kWord, offset - kHeapObjectTag, &ignored)) { |
| 1798 StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value); | 1838 StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value, |
| 1839 old_content); | |
| 1799 } else { | 1840 } else { |
| 1800 AddImmediate(IP, object, offset - kHeapObjectTag); | 1841 AddImmediate(IP, object, offset - kHeapObjectTag); |
| 1801 StoreIntoObjectNoBarrier(object, Address(IP), value); | 1842 StoreIntoObjectNoBarrier(object, Address(IP), value, old_content); |
| 1802 } | 1843 } |
| 1803 } | 1844 } |
| 1804 | 1845 |
| 1805 | 1846 |
| 1806 void Assembler::StoreIntoObjectNoBarrier(Register object, | 1847 void Assembler::StoreIntoObjectNoBarrier(Register object, |
| 1807 const Address& dest, | 1848 const Address& dest, |
| 1808 const Object& value) { | 1849 const Object& value, |
| 1850 FieldContent old_content) { | |
| 1809 ASSERT(value.IsSmi() || value.InVMHeap() || | 1851 ASSERT(value.IsSmi() || value.InVMHeap() || |
| 1810 (value.IsOld() && value.IsNotTemporaryScopedHandle())); | 1852 (value.IsOld() && value.IsNotTemporaryScopedHandle())); |
| 1811 // No store buffer update. | 1853 // No store buffer update. |
| 1812 LoadObject(IP, value); | 1854 LoadObject(IP, value); |
| 1813 VerifiedWrite(dest, IP); | 1855 VerifiedWrite(dest, IP, old_content); |
| 1814 } | 1856 } |
| 1815 | 1857 |
| 1816 | 1858 |
| 1817 void Assembler::StoreIntoObjectNoBarrierOffset(Register object, | 1859 void Assembler::StoreIntoObjectNoBarrierOffset(Register object, |
| 1818 int32_t offset, | 1860 int32_t offset, |
| 1819 const Object& value) { | 1861 const Object& value, |
| 1862 FieldContent old_content) { | |
| 1820 int32_t ignored = 0; | 1863 int32_t ignored = 0; |
| 1821 if (Address::CanHoldStoreOffset(kWord, offset - kHeapObjectTag, &ignored)) { | 1864 if (Address::CanHoldStoreOffset(kWord, offset - kHeapObjectTag, &ignored)) { |
| 1822 StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value); | 1865 StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value, |
| 1866 old_content); | |
| 1823 } else { | 1867 } else { |
| 1824 AddImmediate(IP, object, offset - kHeapObjectTag); | 1868 AddImmediate(IP, object, offset - kHeapObjectTag); |
| 1825 StoreIntoObjectNoBarrier(object, Address(IP), value); | 1869 StoreIntoObjectNoBarrier(object, Address(IP), value, old_content); |
| 1826 } | 1870 } |
| 1827 } | 1871 } |
| 1828 | 1872 |
| 1829 | 1873 |
| 1830 void Assembler::InitializeFieldsNoBarrier(Register object, | 1874 void Assembler::InitializeFieldsNoBarrier(Register object, |
| 1831 Register begin, | 1875 Register begin, |
| 1832 Register end, | 1876 Register end, |
| 1833 Register value_even, | 1877 Register value_even, |
| 1834 Register value_odd) { | 1878 Register value_odd) { |
| 1835 ASSERT(value_odd == value_even + 1); | 1879 ASSERT(value_odd == value_even + 1); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1872 StoreIntoObjectFilter(object, value_even, &done); | 1916 StoreIntoObjectFilter(object, value_even, &done); |
| 1873 StoreIntoObjectFilter(object, value_odd, &done); | 1917 StoreIntoObjectFilter(object, value_odd, &done); |
| 1874 Stop("Store buffer update is required"); | 1918 Stop("Store buffer update is required"); |
| 1875 Bind(&done); | 1919 Bind(&done); |
| 1876 #endif // defined(DEBUG) | 1920 #endif // defined(DEBUG) |
| 1877 // No store buffer update. | 1921 // No store buffer update. |
| 1878 } | 1922 } |
| 1879 | 1923 |
| 1880 | 1924 |
| 1881 void Assembler::StoreIntoSmiField(const Address& dest, Register value) { | 1925 void Assembler::StoreIntoSmiField(const Address& dest, Register value) { |
| 1882 // TODO(koda): Verify previous value was Smi. | |
| 1883 VerifiedWrite(dest, value); | |
| 1884 #if defined(DEBUG) | 1926 #if defined(DEBUG) |
| 1885 Label done; | 1927 Label done; |
| 1886 tst(value, Operand(kHeapObjectTag)); | 1928 tst(value, Operand(kHeapObjectTag)); |
| 1887 b(&done, EQ); | 1929 b(&done, EQ); |
| 1888 Stop("Smi expected"); | 1930 Stop("New value must be Smi."); |
| 1889 Bind(&done); | 1931 Bind(&done); |
| 1890 #endif // defined(DEBUG) | 1932 #endif // defined(DEBUG) |
| 1933 VerifiedWrite(dest, value, kOnlySmi); | |
| 1891 } | 1934 } |
| 1892 | 1935 |
| 1893 | 1936 |
| 1894 void Assembler::LoadClassId(Register result, Register object, Condition cond) { | 1937 void Assembler::LoadClassId(Register result, Register object, Condition cond) { |
| 1895 ASSERT(RawObject::kClassIdTagPos == 16); | 1938 ASSERT(RawObject::kClassIdTagPos == 16); |
| 1896 ASSERT(RawObject::kClassIdTagSize == 16); | 1939 ASSERT(RawObject::kClassIdTagSize == 16); |
| 1897 const intptr_t class_id_offset = Object::tags_offset() + | 1940 const intptr_t class_id_offset = Object::tags_offset() + |
| 1898 RawObject::kClassIdTagPos / kBitsPerByte; | 1941 RawObject::kClassIdTagPos / kBitsPerByte; |
| 1899 ldrh(result, FieldAddress(object, class_id_offset), cond); | 1942 ldrh(result, FieldAddress(object, class_id_offset), cond); |
| 1900 } | 1943 } |
| (...skipping 1720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3621 | 3664 |
| 3622 | 3665 |
| 3623 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 3666 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
| 3624 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); | 3667 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); |
| 3625 return fpu_reg_names[reg]; | 3668 return fpu_reg_names[reg]; |
| 3626 } | 3669 } |
| 3627 | 3670 |
| 3628 } // namespace dart | 3671 } // namespace dart |
| 3629 | 3672 |
| 3630 #endif // defined TARGET_ARCH_ARM | 3673 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |