Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/s390/macro-assembler-s390.cc

Issue 2601563002: S390: Optimize allocate sequence (Closed)
Patch Set: Created 3 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/s390/disasm-s390.cc ('k') | src/s390/simulator-s390.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/s390/disasm-s390.cc ('k') | src/s390/simulator-s390.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698