8067785: Using AlwaysPreTouch does not always touch all pages
authorstefank
Tue, 19 Apr 2016 08:12:28 +0200
changeset 37984 5e9b81de0fce
parent 37511 2cd9b35e0eda
child 37986 a46da3f49efe
8067785: Using AlwaysPreTouch does not always touch all pages Reviewed-by: pliden, drwhite
hotspot/src/share/vm/memory/virtualspace.cpp
--- a/hotspot/src/share/vm/memory/virtualspace.cpp	Mon Apr 18 22:40:47 2016 +0200
+++ b/hotspot/src/share/vm/memory/virtualspace.cpp	Tue Apr 19 08:12:28 2016 +0200
@@ -751,6 +751,29 @@
   return low() <= (const char*) p && (const char*) p < high();
 }
 
+static void pretouch_expanded_memory(void* start, void* end) {
+  assert(is_ptr_aligned(start, os::vm_page_size()), "Unexpected alignment");
+  assert(is_ptr_aligned(end,   os::vm_page_size()), "Unexpected alignment");
+
+  os::pretouch_memory(start, end);
+}
+
+static bool commit_expanded(char* start, size_t size, size_t alignment, bool pre_touch, bool executable) {
+  if (os::commit_memory(start, size, alignment, executable)) {
+    if (pre_touch || AlwaysPreTouch) {
+      pretouch_expanded_memory(start, start + size);
+    }
+    return true;
+  }
+
+  debug_only(warning(
+      "INFO: os::commit_memory(" PTR_FORMAT ", " PTR_FORMAT
+      " size=" SIZE_FORMAT ", executable=%d) failed",
+      p2i(start), p2i(start + size), size, executable);)
+
+  return false;
+}
+
 /*
    First we need to determine if a particular virtual space is using large
    pages.  This is done at the initialize function and only virtual spaces
@@ -764,7 +787,9 @@
    allocated with default pages.
 */
 bool VirtualSpace::expand_by(size_t bytes, bool pre_touch) {
-  if (uncommitted_size() < bytes) return false;
+  if (uncommitted_size() < bytes) {
+    return false;
+  }
 
   if (special()) {
     // don't commit memory if the entire space is pinned in memory
@@ -774,30 +799,23 @@
 
   char* previous_high = high();
   char* unaligned_new_high = high() + bytes;
-  assert(unaligned_new_high <= high_boundary(),
-         "cannot expand by more than upper boundary");
+  assert(unaligned_new_high <= high_boundary(), "cannot expand by more than upper boundary");
 
   // Calculate where the new high for each of the regions should be.  If
   // the low_boundary() and high_boundary() are LargePageSizeInBytes aligned
   // then the unaligned lower and upper new highs would be the
   // lower_high() and upper_high() respectively.
-  char* unaligned_lower_new_high =
-    MIN2(unaligned_new_high, lower_high_boundary());
-  char* unaligned_middle_new_high =
-    MIN2(unaligned_new_high, middle_high_boundary());
-  char* unaligned_upper_new_high =
-    MIN2(unaligned_new_high, upper_high_boundary());
+  char* unaligned_lower_new_high =  MIN2(unaligned_new_high, lower_high_boundary());
+  char* unaligned_middle_new_high = MIN2(unaligned_new_high, middle_high_boundary());
+  char* unaligned_upper_new_high =  MIN2(unaligned_new_high, upper_high_boundary());
 
   // Align the new highs based on the regions alignment.  lower and upper
   // alignment will always be default page size.  middle alignment will be
   // LargePageSizeInBytes if the actual size of the virtual space is in
   // fact larger than LargePageSizeInBytes.
-  char* aligned_lower_new_high =
-    (char*) round_to((intptr_t) unaligned_lower_new_high, lower_alignment());
-  char* aligned_middle_new_high =
-    (char*) round_to((intptr_t) unaligned_middle_new_high, middle_alignment());
-  char* aligned_upper_new_high =
-    (char*) round_to((intptr_t) unaligned_upper_new_high, upper_alignment());
+  char* aligned_lower_new_high =  (char*) round_to((intptr_t) unaligned_lower_new_high, lower_alignment());
+  char* aligned_middle_new_high = (char*) round_to((intptr_t) unaligned_middle_new_high, middle_alignment());
+  char* aligned_upper_new_high =  (char*) round_to((intptr_t) unaligned_upper_new_high, upper_alignment());
 
   // Determine which regions need to grow in this expand_by call.
   // If you are growing in the lower region, high() must be in that
@@ -808,75 +826,48 @@
   // is an intra or inter region growth.
   size_t lower_needs = 0;
   if (aligned_lower_new_high > lower_high()) {
-    lower_needs =
-      pointer_delta(aligned_lower_new_high, lower_high(), sizeof(char));
+    lower_needs = pointer_delta(aligned_lower_new_high, lower_high(), sizeof(char));
   }
   size_t middle_needs = 0;
   if (aligned_middle_new_high > middle_high()) {
-    middle_needs =
-      pointer_delta(aligned_middle_new_high, middle_high(), sizeof(char));
+    middle_needs = pointer_delta(aligned_middle_new_high, middle_high(), sizeof(char));
   }
   size_t upper_needs = 0;
   if (aligned_upper_new_high > upper_high()) {
-    upper_needs =
-      pointer_delta(aligned_upper_new_high, upper_high(), sizeof(char));
+    upper_needs = pointer_delta(aligned_upper_new_high, upper_high(), sizeof(char));
   }
 
   // Check contiguity.
-  assert(low_boundary() <= lower_high() &&
-         lower_high() <= lower_high_boundary(),
+  assert(low_boundary() <= lower_high() && lower_high() <= lower_high_boundary(),
          "high address must be contained within the region");
-  assert(lower_high_boundary() <= middle_high() &&
-         middle_high() <= middle_high_boundary(),
+  assert(lower_high_boundary() <= middle_high() && middle_high() <= middle_high_boundary(),
          "high address must be contained within the region");
-  assert(middle_high_boundary() <= upper_high() &&
-         upper_high() <= upper_high_boundary(),
+  assert(middle_high_boundary() <= upper_high() && upper_high() <= upper_high_boundary(),
          "high address must be contained within the region");
 
   // Commit regions
   if (lower_needs > 0) {
-    assert(low_boundary() <= lower_high() &&
-           lower_high() + lower_needs <= lower_high_boundary(),
-           "must not expand beyond region");
-    if (!os::commit_memory(lower_high(), lower_needs, _executable)) {
-      debug_only(warning("INFO: os::commit_memory(" PTR_FORMAT
-                         ", lower_needs=" SIZE_FORMAT ", %d) failed",
-                         p2i(lower_high()), lower_needs, _executable);)
+    assert(lower_high() + lower_needs <= lower_high_boundary(), "must not expand beyond region");
+    if (!commit_expanded(lower_high(), lower_needs, _lower_alignment, pre_touch, _executable)) {
       return false;
-    } else {
-      _lower_high += lower_needs;
     }
+    _lower_high += lower_needs;
   }
+
   if (middle_needs > 0) {
-    assert(lower_high_boundary() <= middle_high() &&
-           middle_high() + middle_needs <= middle_high_boundary(),
-           "must not expand beyond region");
-    if (!os::commit_memory(middle_high(), middle_needs, middle_alignment(),
-                           _executable)) {
-      debug_only(warning("INFO: os::commit_memory(" PTR_FORMAT
-                         ", middle_needs=" SIZE_FORMAT ", " SIZE_FORMAT
-                         ", %d) failed", p2i(middle_high()), middle_needs,
-                         middle_alignment(), _executable);)
+    assert(middle_high() + middle_needs <= middle_high_boundary(), "must not expand beyond region");
+    if (!commit_expanded(middle_high(), middle_needs, _middle_alignment, pre_touch, _executable)) {
       return false;
     }
     _middle_high += middle_needs;
   }
+
   if (upper_needs > 0) {
-    assert(middle_high_boundary() <= upper_high() &&
-           upper_high() + upper_needs <= upper_high_boundary(),
-           "must not expand beyond region");
-    if (!os::commit_memory(upper_high(), upper_needs, _executable)) {
-      debug_only(warning("INFO: os::commit_memory(" PTR_FORMAT
-                         ", upper_needs=" SIZE_FORMAT ", %d) failed",
-                         p2i(upper_high()), upper_needs, _executable);)
+    assert(upper_high() + upper_needs <= upper_high_boundary(), "must not expand beyond region");
+    if (!commit_expanded(upper_high(), upper_needs, _upper_alignment, pre_touch, _executable)) {
       return false;
-    } else {
-      _upper_high += upper_needs;
     }
-  }
-
-  if (pre_touch || AlwaysPreTouch) {
-    os::pretouch_memory(previous_high, unaligned_new_high);
+    _upper_high += upper_needs;
   }
 
   _high += bytes;