提交 85c9dee2 编写于 作者: S sjohanss

8062063: Usage of UseHugeTLBFS, UseLargePagesInMetaspace and huge...

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: jwilhelm, tschatzl
上级 346d6763
...@@ -45,7 +45,8 @@ ...@@ -45,7 +45,8 @@
#include "utilities/bitMap.inline.hpp" #include "utilities/bitMap.inline.hpp"
G1PageBasedVirtualSpace::G1PageBasedVirtualSpace() : _low_boundary(NULL), 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),
_dirty(), _executable(false) {
} }
bool G1PageBasedVirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t page_size) { bool G1PageBasedVirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t page_size) {
...@@ -66,6 +67,9 @@ bool G1PageBasedVirtualSpace::initialize_with_granularity(ReservedSpace rs, size ...@@ -66,6 +67,9 @@ bool G1PageBasedVirtualSpace::initialize_with_granularity(ReservedSpace rs, size
assert(_committed.size() == 0, "virtual space initialized more than once"); assert(_committed.size() == 0, "virtual space initialized more than once");
uintx size_in_bits = rs.size() / page_size; uintx size_in_bits = rs.size() / page_size;
_committed.resize(size_in_bits, /* in_resource_area */ false); _committed.resize(size_in_bits, /* in_resource_area */ false);
if (_special) {
_dirty.resize(size_in_bits, /* in_resource_area */ false);
}
return true; return true;
} }
...@@ -84,6 +88,7 @@ void G1PageBasedVirtualSpace::release() { ...@@ -84,6 +88,7 @@ void G1PageBasedVirtualSpace::release() {
_executable = false; _executable = false;
_page_size = 0; _page_size = 0;
_committed.resize(0, false); _committed.resize(0, false);
_dirty.resize(0, false);
} }
size_t G1PageBasedVirtualSpace::committed_size() const { size_t G1PageBasedVirtualSpace::committed_size() const {
...@@ -120,31 +125,40 @@ size_t G1PageBasedVirtualSpace::byte_size_for_pages(size_t num) { ...@@ -120,31 +125,40 @@ size_t G1PageBasedVirtualSpace::byte_size_for_pages(size_t num) {
return num * _page_size; return num * _page_size;
} }
MemRegion G1PageBasedVirtualSpace::commit(uintptr_t start, size_t size_in_pages) { bool G1PageBasedVirtualSpace::commit(uintptr_t start, size_t size_in_pages) {
// We need to make sure to commit all pages covered by the given area. // 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"); guarantee(is_area_uncommitted(start, size_in_pages), "Specified area is not uncommitted");
if (!_special) { bool zero_filled = true;
uintptr_t end = start + size_in_pages;
if (_special) {
// Check for dirty pages and update zero_filled if any found.
if (_dirty.get_next_one_offset(start,end) < end) {
zero_filled = false;
_dirty.clear_range(start, end);
}
} else {
os::commit_memory_or_exit(page_start(start), byte_size_for_pages(size_in_pages), _executable, 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)); err_msg("Failed to commit pages from "SIZE_FORMAT" of length "SIZE_FORMAT, start, size_in_pages));
} }
_committed.set_range(start, start + size_in_pages); _committed.set_range(start, end);
MemRegion result((HeapWord*)page_start(start), byte_size_for_pages(size_in_pages) / HeapWordSize); return zero_filled;
return result;
} }
MemRegion G1PageBasedVirtualSpace::uncommit(uintptr_t start, size_t size_in_pages) { void G1PageBasedVirtualSpace::uncommit(uintptr_t start, size_t size_in_pages) {
guarantee(is_area_committed(start, size_in_pages), "checking"); guarantee(is_area_committed(start, size_in_pages), "checking");
if (!_special) { if (_special) {
// Mark that memory is dirty. If committed again the memory might
// need to be cleared explicitly.
_dirty.set_range(start, start + size_in_pages);
} else {
os::uncommit_memory(page_start(start), byte_size_for_pages(size_in_pages)); os::uncommit_memory(page_start(start), byte_size_for_pages(size_in_pages));
} }
_committed.clear_range(start, start + size_in_pages); _committed.clear_range(start, start + size_in_pages);
MemRegion result((HeapWord*)page_start(start), byte_size_for_pages(size_in_pages) / HeapWordSize);
return result;
} }
bool G1PageBasedVirtualSpace::contains(const void* p) const { bool G1PageBasedVirtualSpace::contains(const void* p) const {
...@@ -154,7 +168,7 @@ bool G1PageBasedVirtualSpace::contains(const void* p) const { ...@@ -154,7 +168,7 @@ bool G1PageBasedVirtualSpace::contains(const void* p) const {
#ifndef PRODUCT #ifndef PRODUCT
void G1PageBasedVirtualSpace::print_on(outputStream* out) { void G1PageBasedVirtualSpace::print_on(outputStream* out) {
out->print ("Virtual space:"); out->print ("Virtual space:");
if (special()) out->print(" (pinned in memory)"); if (_special) out->print(" (pinned in memory)");
out->cr(); out->cr();
out->print_cr(" - committed: " SIZE_FORMAT, committed_size()); out->print_cr(" - committed: " SIZE_FORMAT, committed_size());
out->print_cr(" - reserved: " SIZE_FORMAT, reserved_size()); out->print_cr(" - reserved: " SIZE_FORMAT, reserved_size());
......
...@@ -49,6 +49,12 @@ class G1PageBasedVirtualSpace VALUE_OBJ_CLASS_SPEC { ...@@ -49,6 +49,12 @@ class G1PageBasedVirtualSpace VALUE_OBJ_CLASS_SPEC {
// Bitmap used for verification of commit/uncommit operations. // Bitmap used for verification of commit/uncommit operations.
BitMap _committed; BitMap _committed;
// Bitmap used to keep track of which pages are dirty or not for _special
// spaces. This is needed because for those spaces the underlying memory
// will only be zero filled the first time it is committed. Calls to commit
// will use this bitmap and return whether or not the memory is zero filled.
BitMap _dirty;
// Indicates that the entire space has been committed and pinned in memory, // Indicates that the entire space has been committed and pinned in memory,
// os::commit_memory() or os::uncommit_memory() have no function. // os::commit_memory() or os::uncommit_memory() have no function.
bool _special; bool _special;
...@@ -71,12 +77,11 @@ class G1PageBasedVirtualSpace VALUE_OBJ_CLASS_SPEC { ...@@ -71,12 +77,11 @@ class G1PageBasedVirtualSpace VALUE_OBJ_CLASS_SPEC {
public: public:
// Commit the given area of pages starting at start being size_in_pages large. // Commit the given area of pages starting at start being size_in_pages large.
MemRegion commit(uintptr_t start, size_t size_in_pages); // Returns true if the given area is zero filled upon completion.
bool commit(uintptr_t start, size_t size_in_pages);
// Uncommit the given area of pages starting at start being size_in_pages large. // Uncommit the given area of pages starting at start being size_in_pages large.
MemRegion uncommit(uintptr_t start, size_t size_in_pages); void uncommit(uintptr_t start, size_t size_in_pages);
bool special() const { return _special; }
// Initialization // Initialization
G1PageBasedVirtualSpace(); G1PageBasedVirtualSpace();
......
...@@ -67,9 +67,9 @@ class G1RegionsLargerThanCommitSizeMapper : public G1RegionToSpaceMapper { ...@@ -67,9 +67,9 @@ class G1RegionsLargerThanCommitSizeMapper : public G1RegionToSpaceMapper {
} }
virtual void commit_regions(uintptr_t start_idx, size_t num_regions) { virtual void commit_regions(uintptr_t start_idx, size_t num_regions) {
_storage.commit(start_idx * _pages_per_region, num_regions * _pages_per_region); bool zero_filled = _storage.commit(start_idx * _pages_per_region, num_regions * _pages_per_region);
_commit_map.set_range(start_idx, start_idx + num_regions); _commit_map.set_range(start_idx, start_idx + num_regions);
fire_on_commit(start_idx, num_regions, true); fire_on_commit(start_idx, num_regions, zero_filled);
} }
virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) { virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) {
...@@ -117,8 +117,7 @@ class G1RegionsSmallerThanCommitSizeMapper : public G1RegionToSpaceMapper { ...@@ -117,8 +117,7 @@ class G1RegionsSmallerThanCommitSizeMapper : public G1RegionToSpaceMapper {
uint old_refcount = _refcounts.get_by_index(idx); uint old_refcount = _refcounts.get_by_index(idx);
bool zero_filled = false; bool zero_filled = false;
if (old_refcount == 0) { if (old_refcount == 0) {
_storage.commit(idx, 1); zero_filled = _storage.commit(idx, 1);
zero_filled = true;
} }
_refcounts.set_by_index(idx, old_refcount + 1); _refcounts.set_by_index(idx, old_refcount + 1);
_commit_map.set_bit(i); _commit_map.set_bit(i);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册