Mercurial > hg > graal-jvmci-8
comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @ 10374:87c64c0438fb
6976350: G1: deal with fragmentation while copying objects during GC
Summary: Create G1ParGCAllocBufferContainer to contain two buffers instead of previously using one buffer, in order to hold the first priority buffer longer. Thus, when some large objects hits the value of free space left in the first priority buffer it has an alternative to fit in the second priority buffer while the first priority buffer is given more chances to try allocating smaller objects. Overall, it will improve heap space efficiency.
Reviewed-by: johnc, jmasa, brutisso
Contributed-by: tamao <tao.mao@oracle.com>
author | tamao |
---|---|
date | Mon, 03 Jun 2013 14:37:13 -0700 |
parents | 001ec9515f84 |
children | f2110083203d |
comparison
equal
deleted
inserted
replaced
10372:e72f7eecc96d | 10374:87c64c0438fb |
---|---|
590 // Allocate blocks during garbage collection. Will ensure an | 590 // Allocate blocks during garbage collection. Will ensure an |
591 // allocation region, either by picking one or expanding the | 591 // allocation region, either by picking one or expanding the |
592 // heap, and then allocate a block of the given size. The block | 592 // heap, and then allocate a block of the given size. The block |
593 // may not be a humongous - it must fit into a single heap region. | 593 // may not be a humongous - it must fit into a single heap region. |
594 HeapWord* par_allocate_during_gc(GCAllocPurpose purpose, size_t word_size); | 594 HeapWord* par_allocate_during_gc(GCAllocPurpose purpose, size_t word_size); |
595 | |
596 HeapWord* allocate_during_gc_slow(GCAllocPurpose purpose, | |
597 HeapRegion* alloc_region, | |
598 bool par, | |
599 size_t word_size); | |
600 | 595 |
601 // Ensure that no further allocations can happen in "r", bearing in mind | 596 // Ensure that no further allocations can happen in "r", bearing in mind |
602 // that parallel threads might be attempting allocations. | 597 // that parallel threads might be attempting allocations. |
603 void par_allocate_remaining_space(HeapRegion* r); | 598 void par_allocate_remaining_space(HeapRegion* r); |
604 | 599 |
1731 if (_retired) | 1726 if (_retired) |
1732 return; | 1727 return; |
1733 ParGCAllocBuffer::retire(end_of_gc, retain); | 1728 ParGCAllocBuffer::retire(end_of_gc, retain); |
1734 _retired = true; | 1729 _retired = true; |
1735 } | 1730 } |
1731 | |
1732 bool is_retired() { | |
1733 return _retired; | |
1734 } | |
1735 }; | |
1736 | |
1737 class G1ParGCAllocBufferContainer { | |
1738 protected: | |
1739 static int const _priority_max = 2; | |
1740 G1ParGCAllocBuffer* _priority_buffer[_priority_max]; | |
1741 | |
1742 public: | |
1743 G1ParGCAllocBufferContainer(size_t gclab_word_size) { | |
1744 for (int pr = 0; pr < _priority_max; ++pr) { | |
1745 _priority_buffer[pr] = new G1ParGCAllocBuffer(gclab_word_size); | |
1746 } | |
1747 } | |
1748 | |
1749 ~G1ParGCAllocBufferContainer() { | |
1750 for (int pr = 0; pr < _priority_max; ++pr) { | |
1751 assert(_priority_buffer[pr]->is_retired(), "alloc buffers should all retire at this point."); | |
1752 delete _priority_buffer[pr]; | |
1753 } | |
1754 } | |
1755 | |
1756 HeapWord* allocate(size_t word_sz) { | |
1757 HeapWord* obj; | |
1758 for (int pr = 0; pr < _priority_max; ++pr) { | |
1759 obj = _priority_buffer[pr]->allocate(word_sz); | |
1760 if (obj != NULL) return obj; | |
1761 } | |
1762 return obj; | |
1763 } | |
1764 | |
1765 bool contains(void* addr) { | |
1766 for (int pr = 0; pr < _priority_max; ++pr) { | |
1767 if (_priority_buffer[pr]->contains(addr)) return true; | |
1768 } | |
1769 return false; | |
1770 } | |
1771 | |
1772 void undo_allocation(HeapWord* obj, size_t word_sz) { | |
1773 bool finish_undo; | |
1774 for (int pr = 0; pr < _priority_max; ++pr) { | |
1775 if (_priority_buffer[pr]->contains(obj)) { | |
1776 _priority_buffer[pr]->undo_allocation(obj, word_sz); | |
1777 finish_undo = true; | |
1778 } | |
1779 } | |
1780 if (!finish_undo) ShouldNotReachHere(); | |
1781 } | |
1782 | |
1783 size_t words_remaining() { | |
1784 size_t result = 0; | |
1785 for (int pr = 0; pr < _priority_max; ++pr) { | |
1786 result += _priority_buffer[pr]->words_remaining(); | |
1787 } | |
1788 return result; | |
1789 } | |
1790 | |
1791 size_t words_remaining_in_retired_buffer() { | |
1792 G1ParGCAllocBuffer* retired = _priority_buffer[0]; | |
1793 return retired->words_remaining(); | |
1794 } | |
1795 | |
1796 void flush_stats_and_retire(PLABStats* stats, bool end_of_gc, bool retain) { | |
1797 for (int pr = 0; pr < _priority_max; ++pr) { | |
1798 _priority_buffer[pr]->flush_stats_and_retire(stats, end_of_gc, retain); | |
1799 } | |
1800 } | |
1801 | |
1802 void update(bool end_of_gc, bool retain, HeapWord* buf, size_t word_sz) { | |
1803 G1ParGCAllocBuffer* retired_and_set = _priority_buffer[0]; | |
1804 retired_and_set->retire(end_of_gc, retain); | |
1805 retired_and_set->set_buf(buf); | |
1806 retired_and_set->set_word_size(word_sz); | |
1807 adjust_priority_order(); | |
1808 } | |
1809 | |
1810 private: | |
1811 void adjust_priority_order() { | |
1812 G1ParGCAllocBuffer* retired_and_set = _priority_buffer[0]; | |
1813 | |
1814 int last = _priority_max - 1; | |
1815 for (int pr = 0; pr < last; ++pr) { | |
1816 _priority_buffer[pr] = _priority_buffer[pr + 1]; | |
1817 } | |
1818 _priority_buffer[last] = retired_and_set; | |
1819 } | |
1736 }; | 1820 }; |
1737 | 1821 |
1738 class G1ParScanThreadState : public StackObj { | 1822 class G1ParScanThreadState : public StackObj { |
1739 protected: | 1823 protected: |
1740 G1CollectedHeap* _g1h; | 1824 G1CollectedHeap* _g1h; |
1741 RefToScanQueue* _refs; | 1825 RefToScanQueue* _refs; |
1742 DirtyCardQueue _dcq; | 1826 DirtyCardQueue _dcq; |
1743 CardTableModRefBS* _ct_bs; | 1827 CardTableModRefBS* _ct_bs; |
1744 G1RemSet* _g1_rem; | 1828 G1RemSet* _g1_rem; |
1745 | 1829 |
1746 G1ParGCAllocBuffer _surviving_alloc_buffer; | 1830 G1ParGCAllocBufferContainer _surviving_alloc_buffer; |
1747 G1ParGCAllocBuffer _tenured_alloc_buffer; | 1831 G1ParGCAllocBufferContainer _tenured_alloc_buffer; |
1748 G1ParGCAllocBuffer* _alloc_buffers[GCAllocPurposeCount]; | 1832 G1ParGCAllocBufferContainer* _alloc_buffers[GCAllocPurposeCount]; |
1749 ageTable _age_table; | 1833 ageTable _age_table; |
1750 | 1834 |
1751 size_t _alloc_buffer_waste; | 1835 size_t _alloc_buffer_waste; |
1752 size_t _undo_waste; | 1836 size_t _undo_waste; |
1753 | 1837 |
1807 } | 1891 } |
1808 | 1892 |
1809 RefToScanQueue* refs() { return _refs; } | 1893 RefToScanQueue* refs() { return _refs; } |
1810 ageTable* age_table() { return &_age_table; } | 1894 ageTable* age_table() { return &_age_table; } |
1811 | 1895 |
1812 G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) { | 1896 G1ParGCAllocBufferContainer* alloc_buffer(GCAllocPurpose purpose) { |
1813 return _alloc_buffers[purpose]; | 1897 return _alloc_buffers[purpose]; |
1814 } | 1898 } |
1815 | 1899 |
1816 size_t alloc_buffer_waste() const { return _alloc_buffer_waste; } | 1900 size_t alloc_buffer_waste() const { return _alloc_buffer_waste; } |
1817 size_t undo_waste() const { return _undo_waste; } | 1901 size_t undo_waste() const { return _undo_waste; } |
1837 | 1921 |
1838 HeapWord* allocate_slow(GCAllocPurpose purpose, size_t word_sz) { | 1922 HeapWord* allocate_slow(GCAllocPurpose purpose, size_t word_sz) { |
1839 HeapWord* obj = NULL; | 1923 HeapWord* obj = NULL; |
1840 size_t gclab_word_size = _g1h->desired_plab_sz(purpose); | 1924 size_t gclab_word_size = _g1h->desired_plab_sz(purpose); |
1841 if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) { | 1925 if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) { |
1842 G1ParGCAllocBuffer* alloc_buf = alloc_buffer(purpose); | 1926 G1ParGCAllocBufferContainer* alloc_buf = alloc_buffer(purpose); |
1843 add_to_alloc_buffer_waste(alloc_buf->words_remaining()); | |
1844 alloc_buf->retire(false /* end_of_gc */, false /* retain */); | |
1845 | 1927 |
1846 HeapWord* buf = _g1h->par_allocate_during_gc(purpose, gclab_word_size); | 1928 HeapWord* buf = _g1h->par_allocate_during_gc(purpose, gclab_word_size); |
1847 if (buf == NULL) return NULL; // Let caller handle allocation failure. | 1929 if (buf == NULL) return NULL; // Let caller handle allocation failure. |
1848 // Otherwise. | 1930 |
1849 alloc_buf->set_word_size(gclab_word_size); | 1931 add_to_alloc_buffer_waste(alloc_buf->words_remaining_in_retired_buffer()); |
1850 alloc_buf->set_buf(buf); | 1932 alloc_buf->update(false /* end_of_gc */, false /* retain */, buf, gclab_word_size); |
1851 | 1933 |
1852 obj = alloc_buf->allocate(word_sz); | 1934 obj = alloc_buf->allocate(word_sz); |
1853 assert(obj != NULL, "buffer was definitely big enough..."); | 1935 assert(obj != NULL, "buffer was definitely big enough..."); |
1854 } else { | 1936 } else { |
1855 obj = _g1h->par_allocate_during_gc(purpose, word_sz); | 1937 obj = _g1h->par_allocate_during_gc(purpose, word_sz); |
1957 } else { | 2039 } else { |
1958 deal_with_reference((oop*)ref); | 2040 deal_with_reference((oop*)ref); |
1959 } | 2041 } |
1960 } | 2042 } |
1961 | 2043 |
1962 public: | |
1963 void trim_queue(); | 2044 void trim_queue(); |
1964 }; | 2045 }; |
1965 | 2046 |
1966 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTEDHEAP_HPP | 2047 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTEDHEAP_HPP |