--- old/src/share/vm/runtime/virtualspace.cpp Thu May 23 14:13:52 2013 +++ new/src/share/vm/runtime/virtualspace.cpp Thu May 23 14:13:52 2013 @@ -81,17 +81,41 @@ const size_t end_delta = len - (beg_delta + required_size); if (beg_delta != 0) { - os::release_memory(addr, beg_delta); + os::release_or_uncommit_partial_region(addr, beg_delta); } if (end_delta != 0) { char* release_addr = (char*) (s + beg_delta + required_size); - os::release_memory(release_addr, end_delta); + 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, @@ -110,6 +134,10 @@ 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); @@ -127,8 +155,10 @@ } // Helper method. -static bool failed_to_reserve_as_requested(char* base, char* requested_address, - const size_t size, bool special) +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 @@ -147,9 +177,7 @@ fatal("os::release_memory_special failed"); } } else { - if (!os::release_memory(base, size)) { - fatal("os::release_memory failed"); - } + release_memory(base, size); } } return true; @@ -177,6 +205,8 @@ 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; @@ -224,9 +254,7 @@ // 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"); - } + release_memory(addr, size); const size_t extra = MAX2(ofs, suffix_align - ofs); addr = reserve_and_align(size + extra, adjusted_prefix_size, prefix_align, @@ -265,6 +293,8 @@ 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. @@ -340,7 +370,8 @@ // 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"); + release_memory(base, size); + // Make sure that size is aligned size = align_size_up(size, alignment); base = os::reserve_memory_aligned(size, alignment); @@ -378,6 +409,7 @@ "size not allocation aligned"); _base = base; _size = size; + set_raw_base_and_size(NULL, 0); _alignment = alignment; _noaccess_prefix = 0; _special = special; @@ -433,7 +465,7 @@ if (special()) { os::release_memory_special(real_base, real_size); } else{ - os::release_memory(real_base, real_size); + release_memory(real_base, real_size); } _base = NULL; _size = 0;