| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 <assert.h> // For assert | 5 #include <assert.h> // For assert |
| 6 #include <limits.h> // For LONG_MIN, LONG_MAX. | 6 #include <limits.h> // For LONG_MIN, LONG_MAX. |
| 7 | 7 |
| 8 #if V8_TARGET_ARCH_S390 | 8 #if V8_TARGET_ARCH_S390 |
| 9 | 9 |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 1561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1572 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 1572 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
| 1573 ExternalReference allocation_limit = | 1573 ExternalReference allocation_limit = |
| 1574 AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 1574 AllocationUtils::GetAllocationLimitReference(isolate(), flags); |
| 1575 | 1575 |
| 1576 intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address()); | 1576 intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address()); |
| 1577 intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address()); | 1577 intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address()); |
| 1578 DCHECK((limit - top) == kPointerSize); | 1578 DCHECK((limit - top) == kPointerSize); |
| 1579 | 1579 |
| 1580 // Set up allocation top address register. | 1580 // Set up allocation top address register. |
| 1581 Register top_address = scratch1; | 1581 Register top_address = scratch1; |
| 1582 // This code stores a temporary value in ip. This is OK, as the code below | |
| 1583 // does not need ip for implicit literal generation. | |
| 1584 Register alloc_limit = ip; | |
| 1585 Register result_end = scratch2; | 1582 Register result_end = scratch2; |
| 1586 mov(top_address, Operand(allocation_top)); | 1583 mov(top_address, Operand(allocation_top)); |
| 1587 | 1584 |
| 1588 if ((flags & RESULT_CONTAINS_TOP) == 0) { | 1585 if ((flags & RESULT_CONTAINS_TOP) == 0) { |
| 1589 // Load allocation top into result and allocation limit into ip. | 1586 // Load allocation top into result and allocation limit into ip. |
| 1590 LoadP(result, MemOperand(top_address)); | 1587 LoadP(result, MemOperand(top_address)); |
| 1591 LoadP(alloc_limit, MemOperand(top_address, kPointerSize)); | |
| 1592 } else { | 1588 } else { |
| 1593 if (emit_debug_code()) { | 1589 if (emit_debug_code()) { |
| 1594 // Assert that result actually contains top on entry. | 1590 // Assert that result actually contains top on entry. |
| 1595 LoadP(alloc_limit, MemOperand(top_address)); | 1591 CmpP(result, MemOperand(top_address)); |
| 1596 CmpP(result, alloc_limit); | |
| 1597 Check(eq, kUnexpectedAllocationTop); | 1592 Check(eq, kUnexpectedAllocationTop); |
| 1598 } | 1593 } |
| 1599 // Load allocation limit. Result already contains allocation top. | |
| 1600 LoadP(alloc_limit, MemOperand(top_address, limit - top)); | |
| 1601 } | 1594 } |
| 1602 | 1595 |
| 1603 if ((flags & DOUBLE_ALIGNMENT) != 0) { | 1596 if ((flags & DOUBLE_ALIGNMENT) != 0) { |
| 1604 // Align the next allocation. Storing the filler map without checking top is | 1597 // Align the next allocation. Storing the filler map without checking top is |
| 1605 // safe in new-space because the limit of the heap is aligned there. | 1598 // safe in new-space because the limit of the heap is aligned there. |
| 1606 #if V8_TARGET_ARCH_S390X | 1599 #if V8_TARGET_ARCH_S390X |
| 1607 STATIC_ASSERT(kPointerAlignment == kDoubleAlignment); | 1600 STATIC_ASSERT(kPointerAlignment == kDoubleAlignment); |
| 1608 #else | 1601 #else |
| 1609 STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment); | 1602 STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment); |
| 1610 AndP(result_end, result, Operand(kDoubleAlignmentMask)); | 1603 AndP(result_end, result, Operand(kDoubleAlignmentMask)); |
| 1611 Label aligned; | 1604 Label aligned; |
| 1612 beq(&aligned, Label::kNear); | 1605 beq(&aligned, Label::kNear); |
| 1613 if ((flags & PRETENURE) != 0) { | 1606 if ((flags & PRETENURE) != 0) { |
| 1614 CmpLogicalP(result, alloc_limit); | 1607 CmpLogicalP(result, MemOperand(top_address, limit - top)); |
| 1615 bge(gc_required); | 1608 bge(gc_required); |
| 1616 } | 1609 } |
| 1617 mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); | 1610 mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); |
| 1618 StoreW(result_end, MemOperand(result)); | 1611 StoreW(result_end, MemOperand(result)); |
| 1619 AddP(result, result, Operand(kDoubleSize / 2)); | 1612 AddP(result, result, Operand(kDoubleSize / 2)); |
| 1620 bind(&aligned); | 1613 bind(&aligned); |
| 1621 #endif | 1614 #endif |
| 1622 } | 1615 } |
| 1623 | 1616 |
| 1624 // Calculate new top and bail out if new space is exhausted. Use result | 1617 AddP(result_end, result, Operand(object_size)); |
| 1625 // to calculate the new top. | 1618 |
| 1626 SubP(r0, alloc_limit, result); | 1619 // Compare with allocation limit. |
| 1627 if (is_int16(object_size)) { | 1620 CmpLogicalP(result_end, MemOperand(top_address, limit - top)); |
| 1628 CmpP(r0, Operand(object_size)); | 1621 bge(gc_required); |
| 1629 blt(gc_required); | |
| 1630 AddP(result_end, result, Operand(object_size)); | |
| 1631 } else { | |
| 1632 mov(result_end, Operand(object_size)); | |
| 1633 CmpP(r0, result_end); | |
| 1634 blt(gc_required); | |
| 1635 AddP(result_end, result, result_end); | |
| 1636 } | |
| 1637 | 1622 |
| 1638 if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) { | 1623 if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) { |
| 1639 // The top pointer is not updated for allocation folding dominators. | 1624 // The top pointer is not updated for allocation folding dominators. |
| 1640 StoreP(result_end, MemOperand(top_address)); | 1625 StoreP(result_end, MemOperand(top_address)); |
| 1641 } | 1626 } |
| 1642 | 1627 |
| 1628 // Prefetch the allocation_top's next cache line in advance to |
| 1629 // help alleviate potential cache misses. |
| 1630 // Mode 2 - Prefetch the data into a cache line for store access. |
| 1631 pfd(r2, MemOperand(result, 256)); |
| 1632 |
| 1643 // Tag object. | 1633 // Tag object. |
| 1644 AddP(result, result, Operand(kHeapObjectTag)); | 1634 la(result, MemOperand(result, kHeapObjectTag)); |
| 1645 } | 1635 } |
| 1646 | 1636 |
| 1647 void MacroAssembler::Allocate(Register object_size, Register result, | 1637 void MacroAssembler::Allocate(Register object_size, Register result, |
| 1648 Register result_end, Register scratch, | 1638 Register result_end, Register scratch, |
| 1649 Label* gc_required, AllocationFlags flags) { | 1639 Label* gc_required, AllocationFlags flags) { |
| 1650 DCHECK((flags & ALLOCATION_FOLDED) == 0); | 1640 DCHECK((flags & ALLOCATION_FOLDED) == 0); |
| 1651 if (!FLAG_inline_new) { | 1641 if (!FLAG_inline_new) { |
| 1652 if (emit_debug_code()) { | 1642 if (emit_debug_code()) { |
| 1653 // Trash the registers to simulate an allocation failure. | 1643 // Trash the registers to simulate an allocation failure. |
| 1654 LoadImmP(result, Operand(0x7091)); | 1644 LoadImmP(result, Operand(0x7091)); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1669 ExternalReference allocation_top = | 1659 ExternalReference allocation_top = |
| 1670 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 1660 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
| 1671 ExternalReference allocation_limit = | 1661 ExternalReference allocation_limit = |
| 1672 AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 1662 AllocationUtils::GetAllocationLimitReference(isolate(), flags); |
| 1673 intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address()); | 1663 intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address()); |
| 1674 intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address()); | 1664 intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address()); |
| 1675 DCHECK((limit - top) == kPointerSize); | 1665 DCHECK((limit - top) == kPointerSize); |
| 1676 | 1666 |
| 1677 // Set up allocation top address and allocation limit registers. | 1667 // Set up allocation top address and allocation limit registers. |
| 1678 Register top_address = scratch; | 1668 Register top_address = scratch; |
| 1679 // This code stores a temporary value in ip. This is OK, as the code below | |
| 1680 // does not need ip for implicit literal generation. | |
| 1681 Register alloc_limit = ip; | |
| 1682 mov(top_address, Operand(allocation_top)); | 1669 mov(top_address, Operand(allocation_top)); |
| 1683 | 1670 |
| 1684 if ((flags & RESULT_CONTAINS_TOP) == 0) { | 1671 if ((flags & RESULT_CONTAINS_TOP) == 0) { |
| 1685 // Load allocation top into result and allocation limit into alloc_limit.. | 1672 // Load allocation top into result |
| 1686 LoadP(result, MemOperand(top_address)); | 1673 LoadP(result, MemOperand(top_address)); |
| 1687 LoadP(alloc_limit, MemOperand(top_address, kPointerSize)); | |
| 1688 } else { | 1674 } else { |
| 1689 if (emit_debug_code()) { | 1675 if (emit_debug_code()) { |
| 1690 // Assert that result actually contains top on entry. | 1676 // Assert that result actually contains top on entry. |
| 1691 LoadP(alloc_limit, MemOperand(top_address)); | 1677 CmpP(result, MemOperand(top_address)); |
| 1692 CmpP(result, alloc_limit); | |
| 1693 Check(eq, kUnexpectedAllocationTop); | 1678 Check(eq, kUnexpectedAllocationTop); |
| 1694 } | 1679 } |
| 1695 // Load allocation limit. Result already contains allocation top. | |
| 1696 LoadP(alloc_limit, MemOperand(top_address, limit - top)); | |
| 1697 } | 1680 } |
| 1698 | 1681 |
| 1699 if ((flags & DOUBLE_ALIGNMENT) != 0) { | 1682 if ((flags & DOUBLE_ALIGNMENT) != 0) { |
| 1700 // Align the next allocation. Storing the filler map without checking top is | 1683 // Align the next allocation. Storing the filler map without checking top is |
| 1701 // safe in new-space because the limit of the heap is aligned there. | 1684 // safe in new-space because the limit of the heap is aligned there. |
| 1702 #if V8_TARGET_ARCH_S390X | 1685 #if V8_TARGET_ARCH_S390X |
| 1703 STATIC_ASSERT(kPointerAlignment == kDoubleAlignment); | 1686 STATIC_ASSERT(kPointerAlignment == kDoubleAlignment); |
| 1704 #else | 1687 #else |
| 1705 STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment); | 1688 STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment); |
| 1706 AndP(result_end, result, Operand(kDoubleAlignmentMask)); | 1689 AndP(result_end, result, Operand(kDoubleAlignmentMask)); |
| 1707 Label aligned; | 1690 Label aligned; |
| 1708 beq(&aligned, Label::kNear); | 1691 beq(&aligned, Label::kNear); |
| 1709 if ((flags & PRETENURE) != 0) { | 1692 if ((flags & PRETENURE) != 0) { |
| 1710 CmpLogicalP(result, alloc_limit); | 1693 CmpLogicalP(result, MemOperand(top_address, limit - top)); |
| 1711 bge(gc_required); | 1694 bge(gc_required); |
| 1712 } | 1695 } |
| 1713 mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); | 1696 mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); |
| 1714 StoreW(result_end, MemOperand(result)); | 1697 StoreW(result_end, MemOperand(result)); |
| 1715 AddP(result, result, Operand(kDoubleSize / 2)); | 1698 AddP(result, result, Operand(kDoubleSize / 2)); |
| 1716 bind(&aligned); | 1699 bind(&aligned); |
| 1717 #endif | 1700 #endif |
| 1718 } | 1701 } |
| 1719 | 1702 |
| 1720 // Calculate new top and bail out if new space is exhausted. Use result | 1703 // Calculate new top and bail out if new space is exhausted. Use result |
| 1721 // to calculate the new top. Object size may be in words so a shift is | 1704 // to calculate the new top. Object size may be in words so a shift is |
| 1722 // required to get the number of bytes. | 1705 // required to get the number of bytes. |
| 1723 SubP(r0, alloc_limit, result); | |
| 1724 if ((flags & SIZE_IN_WORDS) != 0) { | 1706 if ((flags & SIZE_IN_WORDS) != 0) { |
| 1725 ShiftLeftP(result_end, object_size, Operand(kPointerSizeLog2)); | 1707 ShiftLeftP(result_end, object_size, Operand(kPointerSizeLog2)); |
| 1726 CmpP(r0, result_end); | |
| 1727 blt(gc_required); | |
| 1728 AddP(result_end, result, result_end); | 1708 AddP(result_end, result, result_end); |
| 1729 } else { | 1709 } else { |
| 1730 CmpP(r0, object_size); | |
| 1731 blt(gc_required); | |
| 1732 AddP(result_end, result, object_size); | 1710 AddP(result_end, result, object_size); |
| 1733 } | 1711 } |
| 1712 CmpLogicalP(result_end, MemOperand(top_address, limit - top)); |
| 1713 bge(gc_required); |
| 1734 | 1714 |
| 1735 // Update allocation top. result temporarily holds the new top. | 1715 // Update allocation top. result temporarily holds the new top. |
| 1736 if (emit_debug_code()) { | 1716 if (emit_debug_code()) { |
| 1737 AndP(r0, result_end, Operand(kObjectAlignmentMask)); | 1717 AndP(r0, result_end, Operand(kObjectAlignmentMask)); |
| 1738 Check(eq, kUnalignedAllocationInNewSpace, cr0); | 1718 Check(eq, kUnalignedAllocationInNewSpace, cr0); |
| 1739 } | 1719 } |
| 1740 if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) { | 1720 if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) { |
| 1741 // The top pointer is not updated for allocation folding dominators. | 1721 // The top pointer is not updated for allocation folding dominators. |
| 1742 StoreP(result_end, MemOperand(top_address)); | 1722 StoreP(result_end, MemOperand(top_address)); |
| 1743 } | 1723 } |
| 1744 | 1724 |
| 1725 // Prefetch the allocation_top's next cache line in advance to |
| 1726 // help alleviate potential cache misses. |
| 1727 // Mode 2 - Prefetch the data into a cache line for store access. |
| 1728 pfd(r2, MemOperand(result, 256)); |
| 1729 |
| 1745 // Tag object. | 1730 // Tag object. |
| 1746 AddP(result, result, Operand(kHeapObjectTag)); | 1731 la(result, MemOperand(result, kHeapObjectTag)); |
| 1747 } | 1732 } |
| 1748 | 1733 |
| 1749 void MacroAssembler::FastAllocate(Register object_size, Register result, | 1734 void MacroAssembler::FastAllocate(Register object_size, Register result, |
| 1750 Register result_end, Register scratch, | 1735 Register result_end, Register scratch, |
| 1751 AllocationFlags flags) { | 1736 AllocationFlags flags) { |
| 1752 // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag | 1737 // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag |
| 1753 // is not specified. Other registers must not overlap. | 1738 // is not specified. Other registers must not overlap. |
| 1754 DCHECK(!AreAliased(object_size, result, scratch, ip)); | 1739 DCHECK(!AreAliased(object_size, result, scratch, ip)); |
| 1755 DCHECK(!AreAliased(result_end, result, scratch, ip)); | 1740 DCHECK(!AreAliased(result_end, result, scratch, ip)); |
| 1756 DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end)); | 1741 DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end)); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1788 AddP(result_end, result, object_size); | 1773 AddP(result_end, result, object_size); |
| 1789 } | 1774 } |
| 1790 | 1775 |
| 1791 // Update allocation top. result temporarily holds the new top. | 1776 // Update allocation top. result temporarily holds the new top. |
| 1792 if (emit_debug_code()) { | 1777 if (emit_debug_code()) { |
| 1793 AndP(r0, result_end, Operand(kObjectAlignmentMask)); | 1778 AndP(r0, result_end, Operand(kObjectAlignmentMask)); |
| 1794 Check(eq, kUnalignedAllocationInNewSpace, cr0); | 1779 Check(eq, kUnalignedAllocationInNewSpace, cr0); |
| 1795 } | 1780 } |
| 1796 StoreP(result_end, MemOperand(top_address)); | 1781 StoreP(result_end, MemOperand(top_address)); |
| 1797 | 1782 |
| 1783 // Prefetch the allocation_top's next cache line in advance to |
| 1784 // help alleviate potential cache misses. |
| 1785 // Mode 2 - Prefetch the data into a cache line for store access. |
| 1786 pfd(r2, MemOperand(result, 256)); |
| 1787 |
| 1798 // Tag object. | 1788 // Tag object. |
| 1799 AddP(result, result, Operand(kHeapObjectTag)); | 1789 la(result, MemOperand(result, kHeapObjectTag)); |
| 1800 } | 1790 } |
| 1801 | 1791 |
| 1802 void MacroAssembler::FastAllocate(int object_size, Register result, | 1792 void MacroAssembler::FastAllocate(int object_size, Register result, |
| 1803 Register scratch1, Register scratch2, | 1793 Register scratch1, Register scratch2, |
| 1804 AllocationFlags flags) { | 1794 AllocationFlags flags) { |
| 1805 DCHECK(object_size <= kMaxRegularHeapObjectSize); | 1795 DCHECK(object_size <= kMaxRegularHeapObjectSize); |
| 1806 DCHECK(!AreAliased(result, scratch1, scratch2, ip)); | 1796 DCHECK(!AreAliased(result, scratch1, scratch2, ip)); |
| 1807 | 1797 |
| 1808 // Make object size into bytes. | 1798 // Make object size into bytes. |
| 1809 if ((flags & SIZE_IN_WORDS) != 0) { | 1799 if ((flags & SIZE_IN_WORDS) != 0) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1830 AndP(result_end, result, Operand(kDoubleAlignmentMask)); | 1820 AndP(result_end, result, Operand(kDoubleAlignmentMask)); |
| 1831 Label aligned; | 1821 Label aligned; |
| 1832 beq(&aligned, Label::kNear); | 1822 beq(&aligned, Label::kNear); |
| 1833 mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); | 1823 mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); |
| 1834 StoreW(result_end, MemOperand(result)); | 1824 StoreW(result_end, MemOperand(result)); |
| 1835 AddP(result, result, Operand(kDoubleSize / 2)); | 1825 AddP(result, result, Operand(kDoubleSize / 2)); |
| 1836 bind(&aligned); | 1826 bind(&aligned); |
| 1837 #endif | 1827 #endif |
| 1838 } | 1828 } |
| 1839 | 1829 |
| 1840 // Calculate new top using result. | 1830 if (CpuFeatures::IsSupported(GENERAL_INSTR_EXT) && is_int8(object_size)) { |
| 1841 AddP(result_end, result, Operand(object_size)); | 1831 // Update allocation top. |
| 1832 AddP(MemOperand(top_address), Operand(object_size)); |
| 1833 } else { |
| 1834 // Calculate new top using result. |
| 1835 AddP(result_end, result, Operand(object_size)); |
| 1842 | 1836 |
| 1843 // The top pointer is not updated for allocation folding dominators. | 1837 // Update allocation top. |
| 1844 StoreP(result_end, MemOperand(top_address)); | 1838 StoreP(result_end, MemOperand(top_address)); |
| 1839 } |
| 1840 |
| 1841 // Prefetch the allocation_top's next cache line in advance to |
| 1842 // help alleviate potential cache misses. |
| 1843 // Mode 2 - Prefetch the data into a cache line for store access. |
| 1844 pfd(r2, MemOperand(result, 256)); |
| 1845 | 1845 |
| 1846 // Tag object. | 1846 // Tag object. |
| 1847 AddP(result, result, Operand(kHeapObjectTag)); | 1847 la(result, MemOperand(result, kHeapObjectTag)); |
| 1848 } | 1848 } |
| 1849 | 1849 |
| 1850 void MacroAssembler::CompareObjectType(Register object, Register map, | 1850 void MacroAssembler::CompareObjectType(Register object, Register map, |
| 1851 Register type_reg, InstanceType type) { | 1851 Register type_reg, InstanceType type) { |
| 1852 const Register temp = type_reg.is(no_reg) ? r0 : type_reg; | 1852 const Register temp = type_reg.is(no_reg) ? r0 : type_reg; |
| 1853 | 1853 |
| 1854 LoadP(map, FieldMemOperand(object, HeapObject::kMapOffset)); | 1854 LoadP(map, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 1855 CompareInstanceType(map, temp, type); | 1855 CompareInstanceType(map, temp, type); |
| 1856 } | 1856 } |
| 1857 | 1857 |
| (...skipping 3253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5111 } | 5111 } |
| 5112 if (mag.shift > 0) ShiftRightArith(result, result, Operand(mag.shift)); | 5112 if (mag.shift > 0) ShiftRightArith(result, result, Operand(mag.shift)); |
| 5113 ExtractBit(r0, dividend, 31); | 5113 ExtractBit(r0, dividend, 31); |
| 5114 AddP(result, r0); | 5114 AddP(result, r0); |
| 5115 } | 5115 } |
| 5116 | 5116 |
| 5117 } // namespace internal | 5117 } // namespace internal |
| 5118 } // namespace v8 | 5118 } // namespace v8 |
| 5119 | 5119 |
| 5120 #endif // V8_TARGET_ARCH_S390 | 5120 #endif // V8_TARGET_ARCH_S390 |
| OLD | NEW |