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