src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp

Print this page
rev 4204 : 7163191: G1: introduce a "heap spanning table" abstraction
Summary: Add a heap spanning table and employ it for the heap region sequence table.
Reviewed-by:


1748 bool G1CollectedHeap::expand(size_t expand_bytes) {
1749   size_t old_mem_size = _g1_storage.committed_size();
1750   size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes);
1751   aligned_expand_bytes = align_size_up(aligned_expand_bytes,
1752                                        HeapRegion::GrainBytes);
1753   ergo_verbose2(ErgoHeapSizing,
1754                 "expand the heap",
1755                 ergo_format_byte("requested expansion amount")
1756                 ergo_format_byte("attempted expansion amount"),
1757                 expand_bytes, aligned_expand_bytes);
1758 
1759   // First commit the memory.
1760   HeapWord* old_end = (HeapWord*) _g1_storage.high();
1761   bool successful = _g1_storage.expand_by(aligned_expand_bytes);
1762   if (successful) {
1763     // Then propagate this update to the necessary data structures.
1764     HeapWord* new_end = (HeapWord*) _g1_storage.high();
1765     update_committed_space(old_end, new_end);
1766 
1767     FreeRegionList expansion_list("Local Expansion List");
1768     MemRegion mr = _hrs.expand_by(old_end, new_end, &expansion_list);
1769     assert(mr.start() == old_end, "post-condition");
1770     // mr might be a smaller region than what was requested if
1771     // expand_by() was unable to allocate the HeapRegion instances
1772     assert(mr.end() <= new_end, "post-condition");
1773 
1774     size_t actual_expand_bytes = mr.byte_size();
1775     assert(actual_expand_bytes <= aligned_expand_bytes, "post-condition");
1776     assert(actual_expand_bytes == expansion_list.total_capacity_bytes(),
1777            "post-condition");
1778     if (actual_expand_bytes < aligned_expand_bytes) {
1779       // We could not expand _hrs to the desired size. In this case we
1780       // need to shrink the committed space accordingly.
1781       assert(mr.end() < new_end, "invariant");
1782 
1783       size_t diff_bytes = aligned_expand_bytes - actual_expand_bytes;
1784       // First uncommit the memory.
1785       _g1_storage.shrink_by(diff_bytes);
1786       // Then propagate this update to the necessary data structures.
1787       update_committed_space(new_end, mr.end());
1788     }


1803                   "did not expand the heap",
1804                   ergo_format_reason("heap expansion operation failed"));
1805     // The expansion of the virtual storage space was unsuccessful.
1806     // Let's see if it was because we ran out of swap.
1807     if (G1ExitOnExpansionFailure &&
1808         _g1_storage.uncommitted_size() >= aligned_expand_bytes) {
1809       // We had head room...
1810       vm_exit_out_of_memory(aligned_expand_bytes, "G1 heap expansion");
1811     }
1812   }
1813   return successful;
1814 }
1815 
1816 void G1CollectedHeap::shrink_helper(size_t shrink_bytes) {
1817   size_t old_mem_size = _g1_storage.committed_size();
1818   size_t aligned_shrink_bytes =
1819     ReservedSpace::page_align_size_down(shrink_bytes);
1820   aligned_shrink_bytes = align_size_down(aligned_shrink_bytes,
1821                                          HeapRegion::GrainBytes);
1822   uint num_regions_deleted = 0;
1823   MemRegion mr = _hrs.shrink_by(aligned_shrink_bytes, &num_regions_deleted);


1824   HeapWord* old_end = (HeapWord*) _g1_storage.high();
1825   assert(mr.end() == old_end, "post-condition");
1826 
1827   ergo_verbose3(ErgoHeapSizing,
1828                 "shrink the heap",
1829                 ergo_format_byte("requested shrinking amount")
1830                 ergo_format_byte("aligned shrinking amount")
1831                 ergo_format_byte("attempted shrinking amount"),
1832                 shrink_bytes, aligned_shrink_bytes, mr.byte_size());
1833   if (mr.byte_size() > 0) {
1834     if (_hr_printer.is_active()) {
1835       HeapWord* curr = mr.end();
1836       while (curr > mr.start()) {
1837         HeapWord* curr_end = curr;
1838         curr -= HeapRegion::GrainWords;
1839         _hr_printer.uncommit(curr, curr_end);
1840       }
1841       assert(curr == mr.start(), "post-condition");
1842     }
1843 


2022   } else {
2023     vm_exit_during_initialization("G1 requires a mod ref bs.");
2024     return JNI_ENOMEM;
2025   }
2026 
2027   // Also create a G1 rem set.
2028   if (mr_bs()->is_a(BarrierSet::CardTableModRef)) {
2029     _g1_rem_set = new G1RemSet(this, (CardTableModRefBS*)mr_bs());
2030   } else {
2031     vm_exit_during_initialization("G1 requires a cardtable mod ref bs.");
2032     return JNI_ENOMEM;
2033   }
2034 
2035   // Carve out the G1 part of the heap.
2036 
2037   ReservedSpace g1_rs   = heap_rs.first_part(max_byte_size);
2038   _g1_reserved = MemRegion((HeapWord*)g1_rs.base(),
2039                            g1_rs.size()/HeapWordSize);
2040 
2041   _g1_storage.initialize(g1_rs, 0);
2042   _g1_committed = MemRegion((HeapWord*)_g1_storage.low(), (size_t) 0);
2043   _hrs.initialize((HeapWord*) _g1_reserved.start(),
2044                   (HeapWord*) _g1_reserved.end(),
2045                   _expansion_regions);


2046 
2047   // 6843694 - ensure that the maximum region index can fit
2048   // in the remembered set structures.
2049   const uint max_region_idx = (1U << (sizeof(RegionIdx_t)*BitsPerByte-1)) - 1;
2050   guarantee((max_regions() - 1) <= max_region_idx, "too many regions");
2051 
2052   size_t max_cards_per_region = ((size_t)1 << (sizeof(CardIdx_t)*BitsPerByte-1)) - 1;
2053   guarantee(HeapRegion::CardsPerRegion > 0, "make sure it's initialized");
2054   guarantee(HeapRegion::CardsPerRegion < max_cards_per_region,
2055             "too many cards per region");
2056 
2057   HeapRegionSet::set_unrealistically_long_length(max_regions() + 1);
2058 
2059   _bot_shared = new G1BlockOffsetSharedArray(_reserved,
2060                                              heap_word_size(init_byte_size));
2061 
2062   _g1h = this;
2063 
2064    _in_cset_fast_test_length = max_regions();
2065    _in_cset_fast_test_base =




1748 bool G1CollectedHeap::expand(size_t expand_bytes) {
1749   size_t old_mem_size = _g1_storage.committed_size();
1750   size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes);
1751   aligned_expand_bytes = align_size_up(aligned_expand_bytes,
1752                                        HeapRegion::GrainBytes);
1753   ergo_verbose2(ErgoHeapSizing,
1754                 "expand the heap",
1755                 ergo_format_byte("requested expansion amount")
1756                 ergo_format_byte("attempted expansion amount"),
1757                 expand_bytes, aligned_expand_bytes);
1758 
1759   // First commit the memory.
1760   HeapWord* old_end = (HeapWord*) _g1_storage.high();
1761   bool successful = _g1_storage.expand_by(aligned_expand_bytes);
1762   if (successful) {
1763     // Then propagate this update to the necessary data structures.
1764     HeapWord* new_end = (HeapWord*) _g1_storage.high();
1765     update_committed_space(old_end, new_end);
1766 
1767     FreeRegionList expansion_list("Local Expansion List");
1768     MemRegion mr = _hrs.expand_to(new_end, &expansion_list);
1769     assert(mr.start() == old_end, "post-condition");
1770     // mr might be a smaller region than what was requested if
1771     // expand_by() was unable to allocate the HeapRegion instances
1772     assert(mr.end() <= new_end, "post-condition");
1773 
1774     size_t actual_expand_bytes = mr.byte_size();
1775     assert(actual_expand_bytes <= aligned_expand_bytes, "post-condition");
1776     assert(actual_expand_bytes == expansion_list.total_capacity_bytes(),
1777            "post-condition");
1778     if (actual_expand_bytes < aligned_expand_bytes) {
1779       // We could not expand _hrs to the desired size. In this case we
1780       // need to shrink the committed space accordingly.
1781       assert(mr.end() < new_end, "invariant");
1782 
1783       size_t diff_bytes = aligned_expand_bytes - actual_expand_bytes;
1784       // First uncommit the memory.
1785       _g1_storage.shrink_by(diff_bytes);
1786       // Then propagate this update to the necessary data structures.
1787       update_committed_space(new_end, mr.end());
1788     }


1803                   "did not expand the heap",
1804                   ergo_format_reason("heap expansion operation failed"));
1805     // The expansion of the virtual storage space was unsuccessful.
1806     // Let's see if it was because we ran out of swap.
1807     if (G1ExitOnExpansionFailure &&
1808         _g1_storage.uncommitted_size() >= aligned_expand_bytes) {
1809       // We had head room...
1810       vm_exit_out_of_memory(aligned_expand_bytes, "G1 heap expansion");
1811     }
1812   }
1813   return successful;
1814 }
1815 
1816 void G1CollectedHeap::shrink_helper(size_t shrink_bytes) {
1817   size_t old_mem_size = _g1_storage.committed_size();
1818   size_t aligned_shrink_bytes =
1819     ReservedSpace::page_align_size_down(shrink_bytes);
1820   aligned_shrink_bytes = align_size_down(aligned_shrink_bytes,
1821                                          HeapRegion::GrainBytes);
1822   uint num_regions_deleted = 0;
1823   HeapWord* desired_new_end =
1824         (HeapWord*) _g1_storage.high() - (aligned_shrink_bytes / HeapWordSize);
1825   MemRegion mr = _hrs.shrink_to(desired_new_end, &num_regions_deleted);
1826   HeapWord* old_end = (HeapWord*) _g1_storage.high();
1827   assert(mr.end() == old_end, "post-condition");
1828 
1829   ergo_verbose3(ErgoHeapSizing,
1830                 "shrink the heap",
1831                 ergo_format_byte("requested shrinking amount")
1832                 ergo_format_byte("aligned shrinking amount")
1833                 ergo_format_byte("attempted shrinking amount"),
1834                 shrink_bytes, aligned_shrink_bytes, mr.byte_size());
1835   if (mr.byte_size() > 0) {
1836     if (_hr_printer.is_active()) {
1837       HeapWord* curr = mr.end();
1838       while (curr > mr.start()) {
1839         HeapWord* curr_end = curr;
1840         curr -= HeapRegion::GrainWords;
1841         _hr_printer.uncommit(curr, curr_end);
1842       }
1843       assert(curr == mr.start(), "post-condition");
1844     }
1845 


2024   } else {
2025     vm_exit_during_initialization("G1 requires a mod ref bs.");
2026     return JNI_ENOMEM;
2027   }
2028 
2029   // Also create a G1 rem set.
2030   if (mr_bs()->is_a(BarrierSet::CardTableModRef)) {
2031     _g1_rem_set = new G1RemSet(this, (CardTableModRefBS*)mr_bs());
2032   } else {
2033     vm_exit_during_initialization("G1 requires a cardtable mod ref bs.");
2034     return JNI_ENOMEM;
2035   }
2036 
2037   // Carve out the G1 part of the heap.
2038 
2039   ReservedSpace g1_rs   = heap_rs.first_part(max_byte_size);
2040   _g1_reserved = MemRegion((HeapWord*)g1_rs.base(),
2041                            g1_rs.size()/HeapWordSize);
2042 
2043   _g1_storage.initialize(g1_rs, 0);
2044   _g1_committed = MemRegion((HeapWord*) _g1_storage.low(), (size_t) 0);
2045   _hrs.initialize((HeapWord*) _g1_reserved.start(),
2046                   (HeapWord*) _g1_reserved.end());
2047   assert(_hrs.max_length() == _expansion_regions,
2048          err_msg("max length: %u expansion regions: %u",
2049                  _hrs.max_length(), _expansion_regions));
2050 
2051   // 6843694 - ensure that the maximum region index can fit
2052   // in the remembered set structures.
2053   const uint max_region_idx = (1U << (sizeof(RegionIdx_t)*BitsPerByte-1)) - 1;
2054   guarantee((max_regions() - 1) <= max_region_idx, "too many regions");
2055 
2056   size_t max_cards_per_region = ((size_t)1 << (sizeof(CardIdx_t)*BitsPerByte-1)) - 1;
2057   guarantee(HeapRegion::CardsPerRegion > 0, "make sure it's initialized");
2058   guarantee(HeapRegion::CardsPerRegion < max_cards_per_region,
2059             "too many cards per region");
2060 
2061   HeapRegionSet::set_unrealistically_long_length(max_regions() + 1);
2062 
2063   _bot_shared = new G1BlockOffsetSharedArray(_reserved,
2064                                              heap_word_size(init_byte_size));
2065 
2066   _g1h = this;
2067 
2068    _in_cset_fast_test_length = max_regions();
2069    _in_cset_fast_test_base =