diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index f29814efed610..4e575c233db98 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -2187,7 +2187,8 @@ bool FileMapInfo::map_heap_region_impl() { } // allocate from java heap - if (!G1CollectedHeap::heap()->alloc_archive_regions(_mapped_heap_memregion)) { + uint regions_committed; + if (!G1CollectedHeap::heap()->alloc_archive_regions(_mapped_heap_memregion, regions_committed)) { log_info(cds)("Unable to allocate region, java heap range is already in use."); return false; } @@ -2199,7 +2200,7 @@ bool FileMapInfo::map_heap_region_impl() { addr, _mapped_heap_memregion.byte_size(), r->read_only(), r->allow_exec()); if (base == nullptr || base != addr) { - dealloc_heap_region(); + dealloc_heap_region(regions_committed); log_info(cds)("UseSharedSpaces: Unable to map at required address in java heap. " INTPTR_FORMAT ", size = " SIZE_FORMAT " bytes", p2i(addr), _mapped_heap_memregion.byte_size()); @@ -2208,7 +2209,7 @@ bool FileMapInfo::map_heap_region_impl() { r->set_mapped_base(base); if (VerifySharedSpaces && !r->check_region_crc()) { - dealloc_heap_region(); + dealloc_heap_region(regions_committed); log_info(cds)("mapped heap region is corrupt"); return false; } @@ -2251,8 +2252,8 @@ void FileMapInfo::fixup_mapped_heap_region() { } // dealloc the archive regions from java heap -void FileMapInfo::dealloc_heap_region() { - G1CollectedHeap::heap()->dealloc_archive_regions(_mapped_heap_memregion); +void FileMapInfo::dealloc_heap_region(uint regions_committed) { + G1CollectedHeap::heap()->dealloc_archive_regions(_mapped_heap_memregion, regions_committed); } #endif // INCLUDE_CDS_JAVA_HEAP diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index 160f598796dfc..d773dfa70c77f 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -548,7 +548,7 @@ class FileMapInfo : public CHeapObj<mtInternal> { bool validate_boot_class_paths() NOT_CDS_RETURN_(false); bool validate_app_class_paths(int shared_app_paths_len) NOT_CDS_RETURN_(false); bool map_heap_region_impl() NOT_CDS_JAVA_HEAP_RETURN_(false); - void dealloc_heap_region() NOT_CDS_JAVA_HEAP_RETURN; + void dealloc_heap_region(uint regions_committed) NOT_CDS_JAVA_HEAP_RETURN; bool can_use_heap_region(); bool load_heap_region() NOT_CDS_JAVA_HEAP_RETURN_(false); bool map_heap_region() NOT_CDS_JAVA_HEAP_RETURN_(false); diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index eeaa54cee853a..353111ee58543 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -532,7 +532,7 @@ void G1CollectedHeap::iterate_regions_in_range(MemRegion range, const Func& func } } -bool G1CollectedHeap::alloc_archive_regions(MemRegion range) { +bool G1CollectedHeap::alloc_archive_regions(MemRegion range, uint& regions_committed) { assert(!is_init_completed(), "Expect to be called at JVM init time"); MutexLocker x(Heap_lock); @@ -547,7 +547,6 @@ bool G1CollectedHeap::alloc_archive_regions(MemRegion range) { HeapWord* start_address = range.start(); size_t word_size = range.word_size(); HeapWord* last_address = range.last(); - size_t commits = 0; guarantee(reserved.contains(start_address) && reserved.contains(last_address), "MemRegion outside of heap [" PTR_FORMAT ", " PTR_FORMAT "]", @@ -555,15 +554,16 @@ bool G1CollectedHeap::alloc_archive_regions(MemRegion range) { // Perform the actual region allocation, exiting if it fails. // Then note how much new space we have allocated. - if (!_hrm.allocate_containing_regions(range, &commits, workers())) { + regions_committed = 0; + uint regions_allocated = 0; + if (!_hrm.allocate_containing_regions(range, ®ions_committed, ®ions_allocated, workers())) { return false; } increase_used(word_size * HeapWordSize); - if (commits != 0) { - log_debug(gc, ergo, heap)("Attempt heap expansion (allocate archive regions). Total size: " SIZE_FORMAT "B", - HeapRegion::GrainWords * HeapWordSize * commits); - } + log_debug(gc, ergo, heap)("Allocate CDS archive regions. Allocated %u Committed %u", + regions_allocated, regions_committed); + // Mark each G1 region touched by the range as old, add it to // the old set, and set top. @@ -591,11 +591,11 @@ void G1CollectedHeap::populate_archive_regions_bot_part(MemRegion range) { }); } -void G1CollectedHeap::dealloc_archive_regions(MemRegion range) { +void G1CollectedHeap::dealloc_archive_regions(MemRegion range, uint regions_committed) { assert(!is_init_completed(), "Expect to be called at JVM init time"); MemRegion reserved = _hrm.reserved(); size_t size_used = 0; - uint shrink_count = 0; + uint regions_freed = 0; // Free the G1 regions that are within the specified range. MutexLocker x(Heap_lock); @@ -607,21 +607,27 @@ void G1CollectedHeap::dealloc_archive_regions(MemRegion range) { p2i(start_address), p2i(last_address)); size_used += range.byte_size(); - // Free, empty and uncommit regions with CDS archive content. + // Free, empty and optionally uncommit regions with CDS archive content. + uint shrink_count = 0; auto dealloc_archive_region = [&] (HeapRegion* r, bool is_last) { guarantee(r->is_old(), "Expected old region at index %u", r->hrm_index()); _old_set.remove(r); - r->set_free(); - r->set_top(r->bottom()); - _hrm.shrink_at(r->hrm_index(), 1); - shrink_count++; + free_region(r, nullptr); + regions_freed++; + if (regions_committed > shrink_count) { + _hrm.shrink_at(r->hrm_index(), 1); + shrink_count++; + } else { + _hrm.insert_into_free_list(r); + hr_printer()->cleanup(r); + } }; iterate_regions_in_range(range, dealloc_archive_region); - if (shrink_count != 0) { - log_debug(gc, ergo, heap)("Attempt heap shrinking (CDS archive regions). Total size: " SIZE_FORMAT "B", - HeapRegion::GrainWords * HeapWordSize * shrink_count); + log_debug(gc, ergo, heap)("Deallocate CDS archive regions. Freed %u Uncommitted %u regions.", + regions_freed, regions_committed); + if (regions_committed != 0) { // Explicit uncommit. uncommit_regions(shrink_count); } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index e1b95bf616df9..d02b5e32406f6 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -714,7 +714,7 @@ class G1CollectedHeap : public CollectedHeap { // Commit the appropriate G1 region(s) containing the specified range // and mark them as 'old' region(s). - bool alloc_archive_regions(MemRegion range); + bool alloc_archive_regions(MemRegion range, uint& regions_committed); // Populate the G1BlockOffsetTablePart for archived regions with the given // memory range. @@ -724,7 +724,7 @@ class G1CollectedHeap : public CollectedHeap { // which had been allocated by alloc_archive_regions. This should be called // at JVM init time if the archive heap's contents cannot be used (e.g., if // CRC check fails). - void dealloc_archive_regions(MemRegion range); + void dealloc_archive_regions(MemRegion range, uint regions_committed); private: diff --git a/src/hotspot/share/gc/g1/heapRegionManager.cpp b/src/hotspot/share/gc/g1/heapRegionManager.cpp index fc445142bd57b..5dbd604ec03bb 100644 --- a/src/hotspot/share/gc/g1/heapRegionManager.cpp +++ b/src/hotspot/share/gc/g1/heapRegionManager.cpp @@ -551,8 +551,9 @@ uint HeapRegionManager::find_highest_free(bool* expanded) { return G1_NO_HRM_INDEX; } -bool HeapRegionManager::allocate_containing_regions(MemRegion range, size_t* commit_count, WorkerThreads* pretouch_workers) { - size_t commits = 0; +bool HeapRegionManager::allocate_containing_regions(MemRegion range, uint* commit_count, uint* allocate_count, WorkerThreads* pretouch_workers) { + uint commits = 0; + uint allocated = 0; uint start_index = (uint)_regions.get_index_by_address(range.start()); uint last_index = (uint)_regions.get_index_by_address(range.last()); @@ -567,10 +568,12 @@ bool HeapRegionManager::allocate_containing_regions(MemRegion range, size_t* com if (!curr_region->is_free()) { return false; } + allocated++; } allocate_free_regions_starting_at(start_index, (last_index - start_index) + 1); *commit_count = commits; + *allocate_count = allocated; return true; } diff --git a/src/hotspot/share/gc/g1/heapRegionManager.hpp b/src/hotspot/share/gc/g1/heapRegionManager.hpp index ad985e1f85249..c1ef34e8b5872 100644 --- a/src/hotspot/share/gc/g1/heapRegionManager.hpp +++ b/src/hotspot/share/gc/g1/heapRegionManager.hpp @@ -263,8 +263,9 @@ class HeapRegionManager: public CHeapObj<mtGC> { // Allocate the regions that contain the address range specified, committing the // regions if necessary. Return false if any of the regions is already committed - // and not free, and return the number of regions newly committed in commit_count. - bool allocate_containing_regions(MemRegion range, size_t* commit_count, WorkerThreads* pretouch_workers); + // and not free, and return the number of regions newly committed in commit_count, + // allocated in allocate_count. + bool allocate_containing_regions(MemRegion range, uint* commit_count, uint* allocate_count, WorkerThreads* pretouch_workers); // Apply blk->do_heap_region() on all committed regions in address order, // terminating the iteration early if do_heap_region() returns true.