OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <limits.h> // For LONG_MIN, LONG_MAX. | 5 #include <limits.h> // For LONG_MIN, LONG_MAX. |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/base/division-by-constant.h" | 10 #include "src/base/division-by-constant.h" |
(...skipping 1742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1753 b(hi, gc_required); | 1753 b(hi, gc_required); |
1754 str(scratch2, MemOperand(topaddr)); | 1754 str(scratch2, MemOperand(topaddr)); |
1755 | 1755 |
1756 // Tag object if requested. | 1756 // Tag object if requested. |
1757 if ((flags & TAG_OBJECT) != 0) { | 1757 if ((flags & TAG_OBJECT) != 0) { |
1758 add(result, result, Operand(kHeapObjectTag)); | 1758 add(result, result, Operand(kHeapObjectTag)); |
1759 } | 1759 } |
1760 } | 1760 } |
1761 | 1761 |
1762 | 1762 |
1763 void MacroAssembler::Allocate(Register object_size, | 1763 void MacroAssembler::Allocate(Register object_size, Register result, |
1764 Register result, | 1764 Register result_end, Register scratch, |
1765 Register scratch1, | 1765 Label* gc_required, AllocationFlags flags) { |
1766 Register scratch2, | |
1767 Label* gc_required, | |
1768 AllocationFlags flags) { | |
1769 if (!FLAG_inline_new) { | 1766 if (!FLAG_inline_new) { |
1770 if (emit_debug_code()) { | 1767 if (emit_debug_code()) { |
1771 // Trash the registers to simulate an allocation failure. | 1768 // Trash the registers to simulate an allocation failure. |
1772 mov(result, Operand(0x7091)); | 1769 mov(result, Operand(0x7091)); |
1773 mov(scratch1, Operand(0x7191)); | 1770 mov(scratch, Operand(0x7191)); |
1774 mov(scratch2, Operand(0x7291)); | 1771 mov(result_end, Operand(0x7291)); |
1775 } | 1772 } |
1776 jmp(gc_required); | 1773 jmp(gc_required); |
1777 return; | 1774 return; |
1778 } | 1775 } |
1779 | 1776 |
1780 // Assert that the register arguments are different and that none of | 1777 // Assert that the register arguments are different and that none of |
1781 // them are ip. ip is used explicitly in the code generated below. | 1778 // them are ip. ip is used explicitly in the code generated below. |
1782 DCHECK(!result.is(scratch1)); | 1779 DCHECK(!result.is(scratch)); |
1783 DCHECK(!result.is(scratch2)); | 1780 DCHECK(!result.is(result_end)); |
1784 DCHECK(!scratch1.is(scratch2)); | 1781 DCHECK(!scratch.is(result_end)); |
1785 DCHECK(!object_size.is(ip)); | 1782 DCHECK(!object_size.is(ip)); |
1786 DCHECK(!result.is(ip)); | 1783 DCHECK(!result.is(ip)); |
1787 DCHECK(!scratch1.is(ip)); | 1784 DCHECK(!scratch.is(ip)); |
1788 DCHECK(!scratch2.is(ip)); | 1785 DCHECK(!result_end.is(ip)); |
1789 | 1786 |
1790 // Check relative positions of allocation top and limit addresses. | 1787 // Check relative positions of allocation top and limit addresses. |
1791 // The values must be adjacent in memory to allow the use of LDM. | 1788 // The values must be adjacent in memory to allow the use of LDM. |
1792 // Also, assert that the registers are numbered such that the values | 1789 // Also, assert that the registers are numbered such that the values |
1793 // are loaded in the correct order. | 1790 // are loaded in the correct order. |
1794 ExternalReference allocation_top = | 1791 ExternalReference allocation_top = |
1795 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 1792 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
1796 ExternalReference allocation_limit = | 1793 ExternalReference allocation_limit = |
1797 AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 1794 AllocationUtils::GetAllocationLimitReference(isolate(), flags); |
1798 intptr_t top = | 1795 intptr_t top = |
1799 reinterpret_cast<intptr_t>(allocation_top.address()); | 1796 reinterpret_cast<intptr_t>(allocation_top.address()); |
1800 intptr_t limit = | 1797 intptr_t limit = |
1801 reinterpret_cast<intptr_t>(allocation_limit.address()); | 1798 reinterpret_cast<intptr_t>(allocation_limit.address()); |
1802 DCHECK((limit - top) == kPointerSize); | 1799 DCHECK((limit - top) == kPointerSize); |
1803 DCHECK(result.code() < ip.code()); | 1800 DCHECK(result.code() < ip.code()); |
1804 | 1801 |
1805 // Set up allocation top address. | 1802 // Set up allocation top address. |
1806 Register topaddr = scratch1; | 1803 Register topaddr = scratch; |
1807 mov(topaddr, Operand(allocation_top)); | 1804 mov(topaddr, Operand(allocation_top)); |
1808 | 1805 |
1809 // This code stores a temporary value in ip. This is OK, as the code below | 1806 // This code stores a temporary value in ip. This is OK, as the code below |
1810 // does not need ip for implicit literal generation. | 1807 // does not need ip for implicit literal generation. |
1811 if ((flags & RESULT_CONTAINS_TOP) == 0) { | 1808 if ((flags & RESULT_CONTAINS_TOP) == 0) { |
1812 // Load allocation top into result and allocation limit into ip. | 1809 // Load allocation top into result and allocation limit into ip. |
1813 ldm(ia, topaddr, result.bit() | ip.bit()); | 1810 ldm(ia, topaddr, result.bit() | ip.bit()); |
1814 } else { | 1811 } else { |
1815 if (emit_debug_code()) { | 1812 if (emit_debug_code()) { |
1816 // Assert that result actually contains top on entry. ip is used | 1813 // Assert that result actually contains top on entry. ip is used |
1817 // immediately below so this use of ip does not cause difference with | 1814 // immediately below so this use of ip does not cause difference with |
1818 // respect to register content between debug and release mode. | 1815 // respect to register content between debug and release mode. |
1819 ldr(ip, MemOperand(topaddr)); | 1816 ldr(ip, MemOperand(topaddr)); |
1820 cmp(result, ip); | 1817 cmp(result, ip); |
1821 Check(eq, kUnexpectedAllocationTop); | 1818 Check(eq, kUnexpectedAllocationTop); |
1822 } | 1819 } |
1823 // Load allocation limit into ip. Result already contains allocation top. | 1820 // Load allocation limit into ip. Result already contains allocation top. |
1824 ldr(ip, MemOperand(topaddr, limit - top)); | 1821 ldr(ip, MemOperand(topaddr, limit - top)); |
1825 } | 1822 } |
1826 | 1823 |
1827 if ((flags & DOUBLE_ALIGNMENT) != 0) { | 1824 if ((flags & DOUBLE_ALIGNMENT) != 0) { |
1828 // Align the next allocation. Storing the filler map without checking top is | 1825 // Align the next allocation. Storing the filler map without checking top is |
1829 // safe in new-space because the limit of the heap is aligned there. | 1826 // safe in new-space because the limit of the heap is aligned there. |
1830 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); | 1827 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); |
1831 and_(scratch2, result, Operand(kDoubleAlignmentMask), SetCC); | 1828 and_(result_end, result, Operand(kDoubleAlignmentMask), SetCC); |
1832 Label aligned; | 1829 Label aligned; |
1833 b(eq, &aligned); | 1830 b(eq, &aligned); |
1834 if ((flags & PRETENURE) != 0) { | 1831 if ((flags & PRETENURE) != 0) { |
1835 cmp(result, Operand(ip)); | 1832 cmp(result, Operand(ip)); |
1836 b(hs, gc_required); | 1833 b(hs, gc_required); |
1837 } | 1834 } |
1838 mov(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); | 1835 mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); |
1839 str(scratch2, MemOperand(result, kDoubleSize / 2, PostIndex)); | 1836 str(result_end, MemOperand(result, kDoubleSize / 2, PostIndex)); |
1840 bind(&aligned); | 1837 bind(&aligned); |
1841 } | 1838 } |
1842 | 1839 |
1843 // Calculate new top and bail out if new space is exhausted. Use result | 1840 // Calculate new top and bail out if new space is exhausted. Use result |
1844 // to calculate the new top. Object size may be in words so a shift is | 1841 // to calculate the new top. Object size may be in words so a shift is |
1845 // required to get the number of bytes. | 1842 // required to get the number of bytes. |
1846 if ((flags & SIZE_IN_WORDS) != 0) { | 1843 if ((flags & SIZE_IN_WORDS) != 0) { |
1847 add(scratch2, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC); | 1844 add(result_end, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC); |
1848 } else { | 1845 } else { |
1849 add(scratch2, result, Operand(object_size), SetCC); | 1846 add(result_end, result, Operand(object_size), SetCC); |
1850 } | 1847 } |
1851 b(cs, gc_required); | 1848 b(cs, gc_required); |
1852 cmp(scratch2, Operand(ip)); | 1849 cmp(result_end, Operand(ip)); |
1853 b(hi, gc_required); | 1850 b(hi, gc_required); |
1854 | 1851 |
1855 // Update allocation top. result temporarily holds the new top. | 1852 // Update allocation top. result temporarily holds the new top. |
1856 if (emit_debug_code()) { | 1853 if (emit_debug_code()) { |
1857 tst(scratch2, Operand(kObjectAlignmentMask)); | 1854 tst(result_end, Operand(kObjectAlignmentMask)); |
1858 Check(eq, kUnalignedAllocationInNewSpace); | 1855 Check(eq, kUnalignedAllocationInNewSpace); |
1859 } | 1856 } |
1860 str(scratch2, MemOperand(topaddr)); | 1857 str(result_end, MemOperand(topaddr)); |
1861 | 1858 |
1862 // Tag object if requested. | 1859 // Tag object if requested. |
1863 if ((flags & TAG_OBJECT) != 0) { | 1860 if ((flags & TAG_OBJECT) != 0) { |
1864 add(result, result, Operand(kHeapObjectTag)); | 1861 add(result, result, Operand(kHeapObjectTag)); |
1865 } | 1862 } |
1866 } | 1863 } |
1867 | 1864 |
1868 | 1865 |
1869 void MacroAssembler::AllocateTwoByteString(Register result, | 1866 void MacroAssembler::AllocateTwoByteString(Register result, |
1870 Register length, | 1867 Register length, |
(...skipping 1144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3015 b(eq, &done); | 3012 b(eq, &done); |
3016 bind(&byte_loop_1); | 3013 bind(&byte_loop_1); |
3017 ldrb(scratch, MemOperand(src, 1, PostIndex)); | 3014 ldrb(scratch, MemOperand(src, 1, PostIndex)); |
3018 strb(scratch, MemOperand(dst, 1, PostIndex)); | 3015 strb(scratch, MemOperand(dst, 1, PostIndex)); |
3019 sub(length, length, Operand(1), SetCC); | 3016 sub(length, length, Operand(1), SetCC); |
3020 b(ne, &byte_loop_1); | 3017 b(ne, &byte_loop_1); |
3021 bind(&done); | 3018 bind(&done); |
3022 } | 3019 } |
3023 | 3020 |
3024 | 3021 |
3025 void MacroAssembler::InitializeFieldsWithFiller(Register start_offset, | 3022 void MacroAssembler::InitializeFieldsWithFiller(Register current_address, |
3026 Register end_offset, | 3023 Register end_address, |
3027 Register filler) { | 3024 Register filler) { |
3028 Label loop, entry; | 3025 Label loop, entry; |
3029 b(&entry); | 3026 b(&entry); |
3030 bind(&loop); | 3027 bind(&loop); |
3031 str(filler, MemOperand(start_offset, kPointerSize, PostIndex)); | 3028 str(filler, MemOperand(current_address, kPointerSize, PostIndex)); |
3032 bind(&entry); | 3029 bind(&entry); |
3033 cmp(start_offset, end_offset); | 3030 cmp(current_address, end_address); |
3034 b(lo, &loop); | 3031 b(lo, &loop); |
3035 } | 3032 } |
3036 | 3033 |
3037 | 3034 |
3038 void MacroAssembler::CheckFor32DRegs(Register scratch) { | 3035 void MacroAssembler::CheckFor32DRegs(Register scratch) { |
3039 mov(scratch, Operand(ExternalReference::cpu_features())); | 3036 mov(scratch, Operand(ExternalReference::cpu_features())); |
3040 ldr(scratch, MemOperand(scratch)); | 3037 ldr(scratch, MemOperand(scratch)); |
3041 tst(scratch, Operand(1u << VFP32DREGS)); | 3038 tst(scratch, Operand(1u << VFP32DREGS)); |
3042 } | 3039 } |
3043 | 3040 |
(...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3723 } | 3720 } |
3724 } | 3721 } |
3725 if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift)); | 3722 if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift)); |
3726 add(result, result, Operand(dividend, LSR, 31)); | 3723 add(result, result, Operand(dividend, LSR, 31)); |
3727 } | 3724 } |
3728 | 3725 |
3729 } // namespace internal | 3726 } // namespace internal |
3730 } // namespace v8 | 3727 } // namespace v8 |
3731 | 3728 |
3732 #endif // V8_TARGET_ARCH_ARM | 3729 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |