src/share/vm/runtime/virtualspace.cpp
Print this page
rev 4525 : 8014611: reserve_and_align() assumptions are invalid on windows
Summary: also reviewed by ron.durbin@oracle.com, thomas.schatzl@oracle.com
Reviewed-by: dcubed, brutisso
*** 79,99 ****
return NULL; // Cannot do proper alignment.
}
const size_t end_delta = len - (beg_delta + required_size);
if (beg_delta != 0) {
! os::release_memory(addr, beg_delta);
}
if (end_delta != 0) {
char* release_addr = (char*) (s + beg_delta + required_size);
! os::release_memory(release_addr, end_delta);
}
return (char*) (s + beg_delta);
}
char* ReservedSpace::reserve_and_align(const size_t reserve_size,
const size_t prefix_size,
const size_t prefix_align,
const size_t suffix_size,
const size_t suffix_align)
--- 79,123 ----
return NULL; // Cannot do proper alignment.
}
const size_t end_delta = len - (beg_delta + required_size);
if (beg_delta != 0) {
! os::release_or_uncommit_partial_region(addr, beg_delta);
}
if (end_delta != 0) {
char* release_addr = (char*) (s + beg_delta + required_size);
! os::release_or_uncommit_partial_region(release_addr, end_delta);
}
return (char*) (s + beg_delta);
}
+ void ReservedSpace::set_raw_base_and_size(char * const raw_base,
+ size_t raw_size) {
+ assert(raw_base == NULL || !os::can_release_partial_region(), "sanity");
+ _raw_base = raw_base;
+ _raw_size = raw_size;
+ }
+
+ // On some systems (e.g., windows), the address returned by os::reserve_memory()
+ // is the only addr that can be passed to os::release_memory(). If alignment
+ // was done by this class, that original address is _raw_base.
+ void ReservedSpace::release_memory(char* default_addr, size_t default_size) {
+ bool ok;
+ if (_raw_base == NULL) {
+ ok = os::release_memory(default_addr, default_size);
+ } else {
+ assert(!os::can_release_partial_region(), "sanity");
+ ok = os::release_memory(_raw_base, _raw_size);
+ }
+ if (!ok) {
+ fatal("os::release_memory failed");
+ }
+ set_raw_base_and_size(NULL, 0);
+ }
+
char* ReservedSpace::reserve_and_align(const size_t reserve_size,
const size_t prefix_size,
const size_t prefix_align,
const size_t suffix_size,
const size_t suffix_align)
*** 108,117 ****
--- 132,145 ----
suffix_align);
if (result == NULL && !os::release_memory(raw_addr, reserve_size)) {
fatal("os::release_memory failed");
}
+ if (!os::can_release_partial_region()) {
+ set_raw_base_and_size(raw_addr, reserve_size);
+ }
+
#ifdef ASSERT
if (result != NULL) {
const size_t raw = size_t(raw_addr);
const size_t res = size_t(result);
assert(res >= raw, "alignment decreased start addr");
*** 125,136 ****
return result;
}
// Helper method.
! static bool failed_to_reserve_as_requested(char* base, char* requested_address,
! const size_t size, bool special)
{
if (base == requested_address || requested_address == NULL)
return false; // did not fail
if (base != NULL) {
--- 153,166 ----
return result;
}
// Helper method.
! bool ReservedSpace::failed_to_reserve_as_requested(char* base,
! char* requested_address,
! const size_t size,
! bool special)
{
if (base == requested_address || requested_address == NULL)
return false; // did not fail
if (base != NULL) {
*** 145,159 ****
if (special) {
if (!os::release_memory_special(base, size)) {
fatal("os::release_memory_special failed");
}
} else {
! if (!os::release_memory(base, size)) {
! fatal("os::release_memory failed");
}
}
- }
return true;
}
ReservedSpace::ReservedSpace(const size_t prefix_size,
const size_t prefix_align,
--- 175,187 ----
if (special) {
if (!os::release_memory_special(base, size)) {
fatal("os::release_memory_special failed");
}
} else {
! release_memory(base, size);
}
}
return true;
}
ReservedSpace::ReservedSpace(const size_t prefix_size,
const size_t prefix_align,
*** 175,184 ****
--- 203,214 ----
// Assert that if noaccess_prefix is used, it is the same as prefix_align.
assert(noaccess_prefix == 0 ||
noaccess_prefix == prefix_align, "noaccess prefix wrong");
+ set_raw_base_and_size(NULL, 0);
+
// Add in noaccess_prefix to prefix_size;
const size_t adjusted_prefix_size = prefix_size + noaccess_prefix;
const size_t size = adjusted_prefix_size + suffix_size;
// On systems where the entire region has to be reserved and committed up
*** 222,234 ****
// On most operating systems, another allocation with a somewhat larger size
// will return an address "close to" that of the previous allocation. The
// result is often the same address (if the kernel hands out virtual
// addresses from low to high), or an address that is offset by the increase
// in size. Exploit that to minimize the amount of extra space requested.
! if (!os::release_memory(addr, size)) {
! fatal("os::release_memory failed");
! }
const size_t extra = MAX2(ofs, suffix_align - ofs);
addr = reserve_and_align(size + extra, adjusted_prefix_size, prefix_align,
suffix_size, suffix_align);
if (addr == NULL) {
--- 252,262 ----
// On most operating systems, another allocation with a somewhat larger size
// will return an address "close to" that of the previous allocation. The
// result is often the same address (if the kernel hands out virtual
// addresses from low to high), or an address that is offset by the increase
// in size. Exploit that to minimize the amount of extra space requested.
! release_memory(addr, size);
const size_t extra = MAX2(ofs, suffix_align - ofs);
addr = reserve_and_align(size + extra, adjusted_prefix_size, prefix_align,
suffix_size, suffix_align);
if (addr == NULL) {
*** 263,272 ****
--- 291,302 ----
assert((alignment & (granularity - 1)) == 0,
"alignment not aligned to os::vm_allocation_granularity()");
assert(alignment == 0 || is_power_of_2((intptr_t)alignment),
"not a power of 2");
+ set_raw_base_and_size(NULL, 0);
+
alignment = MAX2(alignment, (size_t)os::vm_page_size());
// Assert that if noaccess_prefix is used, it is the same as alignment.
assert(noaccess_prefix == 0 ||
noaccess_prefix == alignment, "noaccess prefix wrong");
*** 338,348 ****
if (base == NULL) return;
// Check alignment constraints
if ((((size_t)base + noaccess_prefix) & (alignment - 1)) != 0) {
// Base not aligned, retry
! if (!os::release_memory(base, size)) fatal("os::release_memory failed");
// Make sure that size is aligned
size = align_size_up(size, alignment);
base = os::reserve_memory_aligned(size, alignment);
if (requested_address != 0 &&
--- 368,379 ----
if (base == NULL) return;
// Check alignment constraints
if ((((size_t)base + noaccess_prefix) & (alignment - 1)) != 0) {
// Base not aligned, retry
! release_memory(base, size);
!
// Make sure that size is aligned
size = align_size_up(size, alignment);
base = os::reserve_memory_aligned(size, alignment);
if (requested_address != 0 &&
*** 376,385 ****
--- 407,417 ----
bool special, bool executable) {
assert((size % os::vm_allocation_granularity()) == 0,
"size not allocation aligned");
_base = base;
_size = size;
+ set_raw_base_and_size(NULL, 0);
_alignment = alignment;
_noaccess_prefix = 0;
_special = special;
_executable = executable;
}
*** 431,441 ****
char *real_base = _base - _noaccess_prefix;
const size_t real_size = _size + _noaccess_prefix;
if (special()) {
os::release_memory_special(real_base, real_size);
} else{
! os::release_memory(real_base, real_size);
}
_base = NULL;
_size = 0;
_noaccess_prefix = 0;
_special = false;
--- 463,473 ----
char *real_base = _base - _noaccess_prefix;
const size_t real_size = _size + _noaccess_prefix;
if (special()) {
os::release_memory_special(real_base, real_size);
} else{
! release_memory(real_base, real_size);
}
_base = NULL;
_size = 0;
_noaccess_prefix = 0;
_special = false;