| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 } else { | 368 } else { |
| 369 usat(dst, satpos, src, cond); | 369 usat(dst, satpos, src, cond); |
| 370 } | 370 } |
| 371 } | 371 } |
| 372 | 372 |
| 373 | 373 |
| 374 void MacroAssembler::LoadRoot(Register destination, | 374 void MacroAssembler::LoadRoot(Register destination, |
| 375 Heap::RootListIndex index, | 375 Heap::RootListIndex index, |
| 376 Condition cond) { | 376 Condition cond) { |
| 377 if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) && | 377 if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) && |
| 378 !Heap::RootCanBeWrittenAfterInitialization(index) && | 378 isolate()->heap()->RootCanBeTreatedAsConstant(index) && |
| 379 !predictable_code_size()) { | 379 !predictable_code_size()) { |
| 380 Handle<Object> root(isolate()->heap()->roots_array_start()[index], | 380 // The CPU supports fast immediate values, and this root will never |
| 381 isolate()); | 381 // change. We will load it as a relocatable immediate value. |
| 382 if (!isolate()->heap()->InNewSpace(*root)) { | 382 Handle<Object> root(&isolate()->heap()->roots_array_start()[index]); |
| 383 // The CPU supports fast immediate values, and this root will never | 383 mov(destination, Operand(root), LeaveCC, cond); |
| 384 // change. We will load it as a relocatable immediate value. | 384 return; |
| 385 mov(destination, Operand(root), LeaveCC, cond); | |
| 386 return; | |
| 387 } | |
| 388 } | 385 } |
| 389 ldr(destination, MemOperand(kRootRegister, index << kPointerSizeLog2), cond); | 386 ldr(destination, MemOperand(kRootRegister, index << kPointerSizeLog2), cond); |
| 390 } | 387 } |
| 391 | 388 |
| 392 | 389 |
| 393 void MacroAssembler::StoreRoot(Register source, | 390 void MacroAssembler::StoreRoot(Register source, |
| 394 Heap::RootListIndex index, | 391 Heap::RootListIndex index, |
| 395 Condition cond) { | 392 Condition cond) { |
| 396 str(source, MemOperand(kRootRegister, index << kPointerSizeLog2), cond); | 393 str(source, MemOperand(kRootRegister, index << kPointerSizeLog2), cond); |
| 397 } | 394 } |
| (...skipping 1300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1698 ExternalReference allocation_limit = | 1695 ExternalReference allocation_limit = |
| 1699 AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 1696 AllocationUtils::GetAllocationLimitReference(isolate(), flags); |
| 1700 | 1697 |
| 1701 intptr_t top = | 1698 intptr_t top = |
| 1702 reinterpret_cast<intptr_t>(allocation_top.address()); | 1699 reinterpret_cast<intptr_t>(allocation_top.address()); |
| 1703 intptr_t limit = | 1700 intptr_t limit = |
| 1704 reinterpret_cast<intptr_t>(allocation_limit.address()); | 1701 reinterpret_cast<intptr_t>(allocation_limit.address()); |
| 1705 ASSERT((limit - top) == kPointerSize); | 1702 ASSERT((limit - top) == kPointerSize); |
| 1706 ASSERT(result.code() < ip.code()); | 1703 ASSERT(result.code() < ip.code()); |
| 1707 | 1704 |
| 1708 // Set up allocation top address and object size registers. | 1705 // Set up allocation top address register. |
| 1709 Register topaddr = scratch1; | 1706 Register topaddr = scratch1; |
| 1710 Register obj_size_reg = scratch2; | |
| 1711 mov(topaddr, Operand(allocation_top)); | 1707 mov(topaddr, Operand(allocation_top)); |
| 1712 Operand obj_size_operand = Operand(object_size); | |
| 1713 if (!obj_size_operand.is_single_instruction(this)) { | |
| 1714 // We are about to steal IP, so we need to load this value first | |
| 1715 mov(obj_size_reg, obj_size_operand); | |
| 1716 } | |
| 1717 | 1708 |
| 1718 // This code stores a temporary value in ip. This is OK, as the code below | 1709 // This code stores a temporary value in ip. This is OK, as the code below |
| 1719 // does not need ip for implicit literal generation. | 1710 // does not need ip for implicit literal generation. |
| 1720 if ((flags & RESULT_CONTAINS_TOP) == 0) { | 1711 if ((flags & RESULT_CONTAINS_TOP) == 0) { |
| 1721 // Load allocation top into result and allocation limit into ip. | 1712 // Load allocation top into result and allocation limit into ip. |
| 1722 ldm(ia, topaddr, result.bit() | ip.bit()); | 1713 ldm(ia, topaddr, result.bit() | ip.bit()); |
| 1723 } else { | 1714 } else { |
| 1724 if (emit_debug_code()) { | 1715 if (emit_debug_code()) { |
| 1725 // Assert that result actually contains top on entry. ip is used | 1716 // Assert that result actually contains top on entry. ip is used |
| 1726 // immediately below so this use of ip does not cause difference with | 1717 // immediately below so this use of ip does not cause difference with |
| 1727 // respect to register content between debug and release mode. | 1718 // respect to register content between debug and release mode. |
| 1728 ldr(ip, MemOperand(topaddr)); | 1719 ldr(ip, MemOperand(topaddr)); |
| 1729 cmp(result, ip); | 1720 cmp(result, ip); |
| 1730 Check(eq, kUnexpectedAllocationTop); | 1721 Check(eq, kUnexpectedAllocationTop); |
| 1731 } | 1722 } |
| 1732 // Load allocation limit into ip. Result already contains allocation top. | 1723 // Load allocation limit into ip. Result already contains allocation top. |
| 1733 ldr(ip, MemOperand(topaddr, limit - top)); | 1724 ldr(ip, MemOperand(topaddr, limit - top)); |
| 1734 } | 1725 } |
| 1735 | 1726 |
| 1736 if ((flags & DOUBLE_ALIGNMENT) != 0) { | 1727 if ((flags & DOUBLE_ALIGNMENT) != 0) { |
| 1737 // Align the next allocation. Storing the filler map without checking top is | 1728 // Align the next allocation. Storing the filler map without checking top is |
| 1738 // always safe because the limit of the heap is always aligned. | 1729 // safe in new-space because the limit of the heap is aligned there. |
| 1739 ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0); | 1730 ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0); |
| 1740 ASSERT(kPointerAlignment * 2 == kDoubleAlignment); | 1731 STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment); |
| 1741 and_(scratch2, result, Operand(kDoubleAlignmentMask), SetCC); | 1732 and_(scratch2, result, Operand(kDoubleAlignmentMask), SetCC); |
| 1742 Label aligned; | 1733 Label aligned; |
| 1743 b(eq, &aligned); | 1734 b(eq, &aligned); |
| 1735 if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { |
| 1736 cmp(result, Operand(ip)); |
| 1737 b(hs, gc_required); |
| 1738 } |
| 1744 mov(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); | 1739 mov(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); |
| 1745 str(scratch2, MemOperand(result, kDoubleSize / 2, PostIndex)); | 1740 str(scratch2, MemOperand(result, kDoubleSize / 2, PostIndex)); |
| 1746 bind(&aligned); | 1741 bind(&aligned); |
| 1747 } | 1742 } |
| 1748 | 1743 |
| 1749 // Calculate new top and bail out if new space is exhausted. Use result | 1744 // Calculate new top and bail out if new space is exhausted. Use result |
| 1750 // to calculate the new top. | 1745 // to calculate the new top. We must preserve the ip register at this |
| 1751 if (obj_size_operand.is_single_instruction(this)) { | 1746 // point, so we cannot just use add(). |
| 1752 // We can add the size as an immediate | 1747 ASSERT(object_size > 0); |
| 1753 add(scratch2, result, obj_size_operand, SetCC); | 1748 Register source = result; |
| 1754 } else { | 1749 Condition cond = al; |
| 1755 // Doesn't fit in an immediate, we have to use the register | 1750 int shift = 0; |
| 1756 add(scratch2, result, obj_size_reg, SetCC); | 1751 while (object_size != 0) { |
| 1752 if (((object_size >> shift) & 0x03) == 0) { |
| 1753 shift += 2; |
| 1754 } else { |
| 1755 int bits = object_size & (0xff << shift); |
| 1756 object_size -= bits; |
| 1757 shift += 8; |
| 1758 Operand bits_operand(bits); |
| 1759 ASSERT(bits_operand.is_single_instruction(this)); |
| 1760 add(scratch2, source, bits_operand, SetCC, cond); |
| 1761 source = scratch2; |
| 1762 cond = cc; |
| 1763 } |
| 1757 } | 1764 } |
| 1758 b(cs, gc_required); | 1765 b(cs, gc_required); |
| 1759 cmp(scratch2, Operand(ip)); | 1766 cmp(scratch2, Operand(ip)); |
| 1760 b(hi, gc_required); | 1767 b(hi, gc_required); |
| 1761 str(scratch2, MemOperand(topaddr)); | 1768 str(scratch2, MemOperand(topaddr)); |
| 1762 | 1769 |
| 1763 // Tag object if requested. | 1770 // Tag object if requested. |
| 1764 if ((flags & TAG_OBJECT) != 0) { | 1771 if ((flags & TAG_OBJECT) != 0) { |
| 1765 add(result, result, Operand(kHeapObjectTag)); | 1772 add(result, result, Operand(kHeapObjectTag)); |
| 1766 } | 1773 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1826 ldr(ip, MemOperand(topaddr)); | 1833 ldr(ip, MemOperand(topaddr)); |
| 1827 cmp(result, ip); | 1834 cmp(result, ip); |
| 1828 Check(eq, kUnexpectedAllocationTop); | 1835 Check(eq, kUnexpectedAllocationTop); |
| 1829 } | 1836 } |
| 1830 // Load allocation limit into ip. Result already contains allocation top. | 1837 // Load allocation limit into ip. Result already contains allocation top. |
| 1831 ldr(ip, MemOperand(topaddr, limit - top)); | 1838 ldr(ip, MemOperand(topaddr, limit - top)); |
| 1832 } | 1839 } |
| 1833 | 1840 |
| 1834 if ((flags & DOUBLE_ALIGNMENT) != 0) { | 1841 if ((flags & DOUBLE_ALIGNMENT) != 0) { |
| 1835 // Align the next allocation. Storing the filler map without checking top is | 1842 // Align the next allocation. Storing the filler map without checking top is |
| 1836 // always safe because the limit of the heap is always aligned. | 1843 // safe in new-space because the limit of the heap is aligned there. |
| 1837 ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0); | 1844 ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0); |
| 1838 ASSERT(kPointerAlignment * 2 == kDoubleAlignment); | 1845 ASSERT(kPointerAlignment * 2 == kDoubleAlignment); |
| 1839 and_(scratch2, result, Operand(kDoubleAlignmentMask), SetCC); | 1846 and_(scratch2, result, Operand(kDoubleAlignmentMask), SetCC); |
| 1840 Label aligned; | 1847 Label aligned; |
| 1841 b(eq, &aligned); | 1848 b(eq, &aligned); |
| 1849 if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { |
| 1850 cmp(result, Operand(ip)); |
| 1851 b(hs, gc_required); |
| 1852 } |
| 1842 mov(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); | 1853 mov(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); |
| 1843 str(scratch2, MemOperand(result, kDoubleSize / 2, PostIndex)); | 1854 str(scratch2, MemOperand(result, kDoubleSize / 2, PostIndex)); |
| 1844 bind(&aligned); | 1855 bind(&aligned); |
| 1845 } | 1856 } |
| 1846 | 1857 |
| 1847 // Calculate new top and bail out if new space is exhausted. Use result | 1858 // Calculate new top and bail out if new space is exhausted. Use result |
| 1848 // to calculate the new top. Object size may be in words so a shift is | 1859 // to calculate the new top. Object size may be in words so a shift is |
| 1849 // required to get the number of bytes. | 1860 // required to get the number of bytes. |
| 1850 if ((flags & SIZE_IN_WORDS) != 0) { | 1861 if ((flags & SIZE_IN_WORDS) != 0) { |
| 1851 add(scratch2, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC); | 1862 add(scratch2, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC); |
| (...skipping 2025 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3877 void CodePatcher::EmitCondition(Condition cond) { | 3888 void CodePatcher::EmitCondition(Condition cond) { |
| 3878 Instr instr = Assembler::instr_at(masm_.pc_); | 3889 Instr instr = Assembler::instr_at(masm_.pc_); |
| 3879 instr = (instr & ~kCondMask) | cond; | 3890 instr = (instr & ~kCondMask) | cond; |
| 3880 masm_.emit(instr); | 3891 masm_.emit(instr); |
| 3881 } | 3892 } |
| 3882 | 3893 |
| 3883 | 3894 |
| 3884 } } // namespace v8::internal | 3895 } } // namespace v8::internal |
| 3885 | 3896 |
| 3886 #endif // V8_TARGET_ARCH_ARM | 3897 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |