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 |