8067785: Using AlwaysPreTouch does not always touch all pages

Reviewed-by: pliden, drwhite
This commit is contained in:
Stefan Karlsson 2016-04-19 08:12:28 +02:00
parent 7ced38a6b5
commit 66777c3399

View file

@ -751,6 +751,29 @@ bool VirtualSpace::contains(const void* p) const {
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 @@ bool VirtualSpace::contains(const void* p) const {
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 @@ bool VirtualSpace::expand_by(size_t bytes, bool pre_touch) {
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 @@ bool VirtualSpace::expand_by(size_t bytes, bool pre_touch) {
// 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);)
return false;
} else {
_upper_high += upper_needs;
}
}
if (pre_touch || AlwaysPreTouch) {
os::pretouch_memory(previous_high, unaligned_new_high);
if (upper_needs > 0) {
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;
}
_upper_high += upper_needs;
}
_high += bytes;