# HG changeset patch # User sjohanss # Date 1420642649 -3600 # Wed Jan 07 15:57:29 2015 +0100 # Node ID 0bfabe254b3990b971043f780701699914c8b3dc # Parent 8c911031c3e725c92d88a13390625835a180d24e 8062063: Usage of UseHugeTLBFS, UseLargePagesInMetaspace and huge SurvivorAlignmentInBytes cause crashes in CMBitMapClosure::do_bit Summary: Making sure committed memory is cleared when re-committed, even if using large pages. Reviewed-by: diff --git a/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp b/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp --- a/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp +++ b/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp @@ -43,9 +43,11 @@ # include "os_bsd.inline.hpp" #endif #include "utilities/bitMap.inline.hpp" +#include "utilities/copy.hpp" G1PageBasedVirtualSpace::G1PageBasedVirtualSpace() : _low_boundary(NULL), - _high_boundary(NULL), _committed(), _page_size(0), _special(false), _executable(false) { + _high_boundary(NULL), _committed(), _page_size(0), _special(false), + _needs_clear_on_commit(), _executable(false) { } bool G1PageBasedVirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t page_size) { @@ -66,6 +68,9 @@ assert(_committed.size() == 0, "virtual space initialized more than once"); uintx size_in_bits = rs.size() / page_size; _committed.resize(size_in_bits, /* in_resource_area */ false); + if (_special) { + _needs_clear_on_commit.resize(size_in_bits, /* in_resource_area */ false); + } return true; } @@ -84,6 +89,7 @@ _executable = false; _page_size = 0; _committed.resize(0, false); + _needs_clear_on_commit.resize(0, false); } size_t G1PageBasedVirtualSpace::committed_size() const { @@ -124,7 +130,17 @@ // We need to make sure to commit all pages covered by the given area. guarantee(is_area_uncommitted(start, size_in_pages), "Specified area is not uncommitted"); - if (!_special) { + if (_special) { + // When the memory is _special it is not really uncommitted. _needs_clear_on_commit + // is used to communicate that the memory needs to be cleared because it is seen by + // others as uncommitted. + for (uintptr_t page_index = start; page_index < start + size_in_pages; page_index++) { + if (_needs_clear_on_commit.at(page_index)) { + Copy::zero_to_bytes((HeapWord*)page_start(page_index), _page_size); + _needs_clear_on_commit.clear_bit(page_index); + } + } + } else { os::commit_memory_or_exit(page_start(start), byte_size_for_pages(size_in_pages), _executable, err_msg("Failed to commit pages from "SIZE_FORMAT" of length "SIZE_FORMAT, start, size_in_pages)); } @@ -140,7 +156,10 @@ MemRegion G1PageBasedVirtualSpace::uncommit(uintptr_t start, size_t size_in_pages) { guarantee(is_area_committed(start, size_in_pages), "checking"); - if (!_special) { + if (_special) { + // Mark that memory needs to be cleared if committed again. + _needs_clear_on_commit.set_range(start, start + size_in_pages); + } else { os::uncommit_memory(page_start(start), byte_size_for_pages(size_in_pages)); } diff --git a/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp b/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp --- a/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp +++ b/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp @@ -49,6 +49,10 @@ // Bitmap used for verification of commit/uncommit operations. BitMap _committed; + // For _special spaces we need to keep track if the memory needs to be cleared + // on commit or not. + BitMap _needs_clear_on_commit; + // Indicates that the entire space has been committed and pinned in memory, // os::commit_memory() or os::uncommit_memory() have no function. bool _special;