< prev index next >

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

Print this page
rev 7618 : 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:
rev 7619 : [mq]: clear-in-listener

@@ -43,11 +43,12 @@
 # include "os_bsd.inline.hpp"
 #endif
 #include "utilities/bitMap.inline.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_zeroing(), _executable(false) {
 }
 
 bool G1PageBasedVirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t page_size) {
   if (!rs.is_reserved()) {
     return false;  // Allocation failed.

@@ -64,10 +65,13 @@
   _page_size = page_size;
 
   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_zeroing.resize(size_in_bits, /* in_resource_area */ false);
+  }
 
   return true;
 }
 
 

@@ -82,10 +86,11 @@
   _high_boundary          = NULL;
   _special                = false;
   _executable             = false;
   _page_size              = 0;
   _committed.resize(0, false);
+  _needs_zeroing.resize(0, false);
 }
 
 size_t G1PageBasedVirtualSpace::committed_size() const {
   return _committed.count_one_bits() * _page_size;
 }

@@ -118,48 +123,58 @@
 
 size_t G1PageBasedVirtualSpace::byte_size_for_pages(size_t num) {
   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.
   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) {
+    // When the memory is _special it is not really uncommitted. _needs_zeroing is
+    // used to keep track if the current committed range contains pages that are all
+    // zeroed or not.
+    if (_needs_zeroing.get_next_one_offset(start,end) < end) {
+      zero_filled = false;
+      _needs_zeroing.clear_range(start, end);
+    }
+  } 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));
   }
-  _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);
   if (AlwaysPreTouch) {
-    os::pretouch_memory((char*)result.start(), (char*)result.end());
+    os::pretouch_memory(page_start(start), page_start(end));
   }
-  return result;
+  return zero_filled;
 }
 
-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");
 
-  if (!_special) {
+  if (_special) {
+    // Mark that memory needs to be cleared if committed again.
+    _needs_zeroing.set_range(start, start + size_in_pages);
+  } else {
     os::uncommit_memory(page_start(start), byte_size_for_pages(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 {
   return _low_boundary <= (const char*) p && (const char*) p < _high_boundary;
 }
 
 #ifndef PRODUCT
 void G1PageBasedVirtualSpace::print_on(outputStream* out) {
   out->print   ("Virtual space:");
-  if (special()) out->print(" (pinned in memory)");
+  if (_special) out->print(" (pinned in memory)");
   out->cr();
   out->print_cr(" - committed: " SIZE_FORMAT, committed_size());
   out->print_cr(" - reserved:  " SIZE_FORMAT, reserved_size());
   out->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]",  p2i(_low_boundary), p2i(_high_boundary));
 }
< prev index next >