1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/runtime/virtualspace.cpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,704 @@ 1.4 +/* 1.5 + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "incls/_precompiled.incl" 1.29 +#include "incls/_virtualspace.cpp.incl" 1.30 + 1.31 + 1.32 +// ReservedSpace 1.33 +ReservedSpace::ReservedSpace(size_t size) { 1.34 + initialize(size, 0, false, NULL); 1.35 +} 1.36 + 1.37 +ReservedSpace::ReservedSpace(size_t size, size_t alignment, 1.38 + bool large, char* requested_address) { 1.39 + initialize(size, alignment, large, requested_address); 1.40 +} 1.41 + 1.42 +char * 1.43 +ReservedSpace::align_reserved_region(char* addr, const size_t len, 1.44 + const size_t prefix_size, 1.45 + const size_t prefix_align, 1.46 + const size_t suffix_size, 1.47 + const size_t suffix_align) 1.48 +{ 1.49 + assert(addr != NULL, "sanity"); 1.50 + const size_t required_size = prefix_size + suffix_size; 1.51 + assert(len >= required_size, "len too small"); 1.52 + 1.53 + const size_t s = size_t(addr); 1.54 + const size_t beg_ofs = s + prefix_size & suffix_align - 1; 1.55 + const size_t beg_delta = beg_ofs == 0 ? 0 : suffix_align - beg_ofs; 1.56 + 1.57 + if (len < beg_delta + required_size) { 1.58 + return NULL; // Cannot do proper alignment. 1.59 + } 1.60 + const size_t end_delta = len - (beg_delta + required_size); 1.61 + 1.62 + if (beg_delta != 0) { 1.63 + os::release_memory(addr, beg_delta); 1.64 + } 1.65 + 1.66 + if (end_delta != 0) { 1.67 + char* release_addr = (char*) (s + beg_delta + required_size); 1.68 + os::release_memory(release_addr, end_delta); 1.69 + } 1.70 + 1.71 + return (char*) (s + beg_delta); 1.72 +} 1.73 + 1.74 +char* ReservedSpace::reserve_and_align(const size_t reserve_size, 1.75 + const size_t prefix_size, 1.76 + const size_t prefix_align, 1.77 + const size_t suffix_size, 1.78 + const size_t suffix_align) 1.79 +{ 1.80 + assert(reserve_size > prefix_size + suffix_size, "should not be here"); 1.81 + 1.82 + char* raw_addr = os::reserve_memory(reserve_size, NULL, prefix_align); 1.83 + if (raw_addr == NULL) return NULL; 1.84 + 1.85 + char* result = align_reserved_region(raw_addr, reserve_size, prefix_size, 1.86 + prefix_align, suffix_size, 1.87 + suffix_align); 1.88 + if (result == NULL && !os::release_memory(raw_addr, reserve_size)) { 1.89 + fatal("os::release_memory failed"); 1.90 + } 1.91 + 1.92 +#ifdef ASSERT 1.93 + if (result != NULL) { 1.94 + const size_t raw = size_t(raw_addr); 1.95 + const size_t res = size_t(result); 1.96 + assert(res >= raw, "alignment decreased start addr"); 1.97 + assert(res + prefix_size + suffix_size <= raw + reserve_size, 1.98 + "alignment increased end addr"); 1.99 + assert((res & prefix_align - 1) == 0, "bad alignment of prefix"); 1.100 + assert((res + prefix_size & suffix_align - 1) == 0, 1.101 + "bad alignment of suffix"); 1.102 + } 1.103 +#endif 1.104 + 1.105 + return result; 1.106 +} 1.107 + 1.108 +ReservedSpace::ReservedSpace(const size_t prefix_size, 1.109 + const size_t prefix_align, 1.110 + const size_t suffix_size, 1.111 + const size_t suffix_align) 1.112 +{ 1.113 + assert(prefix_size != 0, "sanity"); 1.114 + assert(prefix_align != 0, "sanity"); 1.115 + assert(suffix_size != 0, "sanity"); 1.116 + assert(suffix_align != 0, "sanity"); 1.117 + assert((prefix_size & prefix_align - 1) == 0, 1.118 + "prefix_size not divisible by prefix_align"); 1.119 + assert((suffix_size & suffix_align - 1) == 0, 1.120 + "suffix_size not divisible by suffix_align"); 1.121 + assert((suffix_align & prefix_align - 1) == 0, 1.122 + "suffix_align not divisible by prefix_align"); 1.123 + 1.124 + // On systems where the entire region has to be reserved and committed up 1.125 + // front, the compound alignment normally done by this method is unnecessary. 1.126 + const bool try_reserve_special = UseLargePages && 1.127 + prefix_align == os::large_page_size(); 1.128 + if (!os::can_commit_large_page_memory() && try_reserve_special) { 1.129 + initialize(prefix_size + suffix_size, prefix_align, true); 1.130 + return; 1.131 + } 1.132 + 1.133 + _base = NULL; 1.134 + _size = 0; 1.135 + _alignment = 0; 1.136 + _special = false; 1.137 + 1.138 + // Optimistically try to reserve the exact size needed. 1.139 + const size_t size = prefix_size + suffix_size; 1.140 + char* addr = os::reserve_memory(size, NULL, prefix_align); 1.141 + if (addr == NULL) return; 1.142 + 1.143 + // Check whether the result has the needed alignment (unlikely unless 1.144 + // prefix_align == suffix_align). 1.145 + const size_t ofs = size_t(addr) + prefix_size & suffix_align - 1; 1.146 + if (ofs != 0) { 1.147 + // Wrong alignment. Release, allocate more space and do manual alignment. 1.148 + // 1.149 + // On most operating systems, another allocation with a somewhat larger size 1.150 + // will return an address "close to" that of the previous allocation. The 1.151 + // result is often the same address (if the kernel hands out virtual 1.152 + // addresses from low to high), or an address that is offset by the increase 1.153 + // in size. Exploit that to minimize the amount of extra space requested. 1.154 + if (!os::release_memory(addr, size)) { 1.155 + fatal("os::release_memory failed"); 1.156 + } 1.157 + 1.158 + const size_t extra = MAX2(ofs, suffix_align - ofs); 1.159 + addr = reserve_and_align(size + extra, prefix_size, prefix_align, 1.160 + suffix_size, suffix_align); 1.161 + if (addr == NULL) { 1.162 + // Try an even larger region. If this fails, address space is exhausted. 1.163 + addr = reserve_and_align(size + suffix_align, prefix_size, 1.164 + prefix_align, suffix_size, suffix_align); 1.165 + } 1.166 + } 1.167 + 1.168 + _base = addr; 1.169 + _size = size; 1.170 + _alignment = prefix_align; 1.171 +} 1.172 + 1.173 +void ReservedSpace::initialize(size_t size, size_t alignment, bool large, 1.174 + char* requested_address) { 1.175 + const size_t granularity = os::vm_allocation_granularity(); 1.176 + assert((size & granularity - 1) == 0, 1.177 + "size not aligned to os::vm_allocation_granularity()"); 1.178 + assert((alignment & granularity - 1) == 0, 1.179 + "alignment not aligned to os::vm_allocation_granularity()"); 1.180 + assert(alignment == 0 || is_power_of_2((intptr_t)alignment), 1.181 + "not a power of 2"); 1.182 + 1.183 + _base = NULL; 1.184 + _size = 0; 1.185 + _special = false; 1.186 + _alignment = 0; 1.187 + if (size == 0) { 1.188 + return; 1.189 + } 1.190 + 1.191 + // If OS doesn't support demand paging for large page memory, we need 1.192 + // to use reserve_memory_special() to reserve and pin the entire region. 1.193 + bool special = large && !os::can_commit_large_page_memory(); 1.194 + char* base = NULL; 1.195 + 1.196 + if (special) { 1.197 + // It's not hard to implement reserve_memory_special() such that it can 1.198 + // allocate at fixed address, but there seems no use of this feature 1.199 + // for now, so it's not implemented. 1.200 + assert(requested_address == NULL, "not implemented"); 1.201 + 1.202 + base = os::reserve_memory_special(size); 1.203 + 1.204 + if (base != NULL) { 1.205 + // Check alignment constraints 1.206 + if (alignment > 0) { 1.207 + assert((uintptr_t) base % alignment == 0, 1.208 + "Large pages returned a non-aligned address"); 1.209 + } 1.210 + _special = true; 1.211 + } else { 1.212 + // failed; try to reserve regular memory below 1.213 + } 1.214 + } 1.215 + 1.216 + if (base == NULL) { 1.217 + // Optimistically assume that the OSes returns an aligned base pointer. 1.218 + // When reserving a large address range, most OSes seem to align to at 1.219 + // least 64K. 1.220 + 1.221 + // If the memory was requested at a particular address, use 1.222 + // os::attempt_reserve_memory_at() to avoid over mapping something 1.223 + // important. If available space is not detected, return NULL. 1.224 + 1.225 + if (requested_address != 0) { 1.226 + base = os::attempt_reserve_memory_at(size, requested_address); 1.227 + } else { 1.228 + base = os::reserve_memory(size, NULL, alignment); 1.229 + } 1.230 + 1.231 + if (base == NULL) return; 1.232 + 1.233 + // Check alignment constraints 1.234 + if (alignment > 0 && ((size_t)base & alignment - 1) != 0) { 1.235 + // Base not aligned, retry 1.236 + if (!os::release_memory(base, size)) fatal("os::release_memory failed"); 1.237 + // Reserve size large enough to do manual alignment and 1.238 + // increase size to a multiple of the desired alignment 1.239 + size = align_size_up(size, alignment); 1.240 + size_t extra_size = size + alignment; 1.241 + char* extra_base = os::reserve_memory(extra_size, NULL, alignment); 1.242 + if (extra_base == NULL) return; 1.243 + // Do manual alignement 1.244 + base = (char*) align_size_up((uintptr_t) extra_base, alignment); 1.245 + assert(base >= extra_base, "just checking"); 1.246 + // Release unused areas 1.247 + size_t unused_bottom_size = base - extra_base; 1.248 + size_t unused_top_size = extra_size - size - unused_bottom_size; 1.249 + assert(unused_bottom_size % os::vm_allocation_granularity() == 0, 1.250 + "size not allocation aligned"); 1.251 + assert(unused_top_size % os::vm_allocation_granularity() == 0, 1.252 + "size not allocation aligned"); 1.253 + if (unused_bottom_size > 0) { 1.254 + os::release_memory(extra_base, unused_bottom_size); 1.255 + } 1.256 + if (unused_top_size > 0) { 1.257 + os::release_memory(base + size, unused_top_size); 1.258 + } 1.259 + } 1.260 + } 1.261 + // Done 1.262 + _base = base; 1.263 + _size = size; 1.264 + _alignment = MAX2(alignment, (size_t) os::vm_page_size()); 1.265 + 1.266 + assert(markOopDesc::encode_pointer_as_mark(_base)->decode_pointer() == _base, 1.267 + "area must be distinguisable from marks for mark-sweep"); 1.268 + assert(markOopDesc::encode_pointer_as_mark(&_base[size])->decode_pointer() == &_base[size], 1.269 + "area must be distinguisable from marks for mark-sweep"); 1.270 +} 1.271 + 1.272 + 1.273 +ReservedSpace::ReservedSpace(char* base, size_t size, size_t alignment, 1.274 + bool special) { 1.275 + assert((size % os::vm_allocation_granularity()) == 0, 1.276 + "size not allocation aligned"); 1.277 + _base = base; 1.278 + _size = size; 1.279 + _alignment = alignment; 1.280 + _special = special; 1.281 +} 1.282 + 1.283 + 1.284 +ReservedSpace ReservedSpace::first_part(size_t partition_size, size_t alignment, 1.285 + bool split, bool realloc) { 1.286 + assert(partition_size <= size(), "partition failed"); 1.287 + if (split) { 1.288 + os::split_reserved_memory(_base, _size, partition_size, realloc); 1.289 + } 1.290 + ReservedSpace result(base(), partition_size, alignment, special()); 1.291 + return result; 1.292 +} 1.293 + 1.294 + 1.295 +ReservedSpace 1.296 +ReservedSpace::last_part(size_t partition_size, size_t alignment) { 1.297 + assert(partition_size <= size(), "partition failed"); 1.298 + ReservedSpace result(base() + partition_size, size() - partition_size, 1.299 + alignment, special()); 1.300 + return result; 1.301 +} 1.302 + 1.303 + 1.304 +size_t ReservedSpace::page_align_size_up(size_t size) { 1.305 + return align_size_up(size, os::vm_page_size()); 1.306 +} 1.307 + 1.308 + 1.309 +size_t ReservedSpace::page_align_size_down(size_t size) { 1.310 + return align_size_down(size, os::vm_page_size()); 1.311 +} 1.312 + 1.313 + 1.314 +size_t ReservedSpace::allocation_align_size_up(size_t size) { 1.315 + return align_size_up(size, os::vm_allocation_granularity()); 1.316 +} 1.317 + 1.318 + 1.319 +size_t ReservedSpace::allocation_align_size_down(size_t size) { 1.320 + return align_size_down(size, os::vm_allocation_granularity()); 1.321 +} 1.322 + 1.323 + 1.324 +void ReservedSpace::release() { 1.325 + if (is_reserved()) { 1.326 + if (special()) { 1.327 + os::release_memory_special(_base, _size); 1.328 + } else{ 1.329 + os::release_memory(_base, _size); 1.330 + } 1.331 + _base = NULL; 1.332 + _size = 0; 1.333 + _special = false; 1.334 + } 1.335 +} 1.336 + 1.337 + 1.338 +// VirtualSpace 1.339 + 1.340 +VirtualSpace::VirtualSpace() { 1.341 + _low_boundary = NULL; 1.342 + _high_boundary = NULL; 1.343 + _low = NULL; 1.344 + _high = NULL; 1.345 + _lower_high = NULL; 1.346 + _middle_high = NULL; 1.347 + _upper_high = NULL; 1.348 + _lower_high_boundary = NULL; 1.349 + _middle_high_boundary = NULL; 1.350 + _upper_high_boundary = NULL; 1.351 + _lower_alignment = 0; 1.352 + _middle_alignment = 0; 1.353 + _upper_alignment = 0; 1.354 +} 1.355 + 1.356 + 1.357 +bool VirtualSpace::initialize(ReservedSpace rs, size_t committed_size) { 1.358 + if(!rs.is_reserved()) return false; // allocation failed. 1.359 + assert(_low_boundary == NULL, "VirtualSpace already initialized"); 1.360 + _low_boundary = rs.base(); 1.361 + _high_boundary = low_boundary() + rs.size(); 1.362 + 1.363 + _low = low_boundary(); 1.364 + _high = low(); 1.365 + 1.366 + _special = rs.special(); 1.367 + 1.368 + // When a VirtualSpace begins life at a large size, make all future expansion 1.369 + // and shrinking occur aligned to a granularity of large pages. This avoids 1.370 + // fragmentation of physical addresses that inhibits the use of large pages 1.371 + // by the OS virtual memory system. Empirically, we see that with a 4MB 1.372 + // page size, the only spaces that get handled this way are codecache and 1.373 + // the heap itself, both of which provide a substantial performance 1.374 + // boost in many benchmarks when covered by large pages. 1.375 + // 1.376 + // No attempt is made to force large page alignment at the very top and 1.377 + // bottom of the space if they are not aligned so already. 1.378 + _lower_alignment = os::vm_page_size(); 1.379 + _middle_alignment = os::page_size_for_region(rs.size(), rs.size(), 1); 1.380 + _upper_alignment = os::vm_page_size(); 1.381 + 1.382 + // End of each region 1.383 + _lower_high_boundary = (char*) round_to((intptr_t) low_boundary(), middle_alignment()); 1.384 + _middle_high_boundary = (char*) round_down((intptr_t) high_boundary(), middle_alignment()); 1.385 + _upper_high_boundary = high_boundary(); 1.386 + 1.387 + // High address of each region 1.388 + _lower_high = low_boundary(); 1.389 + _middle_high = lower_high_boundary(); 1.390 + _upper_high = middle_high_boundary(); 1.391 + 1.392 + // commit to initial size 1.393 + if (committed_size > 0) { 1.394 + if (!expand_by(committed_size)) { 1.395 + return false; 1.396 + } 1.397 + } 1.398 + return true; 1.399 +} 1.400 + 1.401 + 1.402 +VirtualSpace::~VirtualSpace() { 1.403 + release(); 1.404 +} 1.405 + 1.406 + 1.407 +void VirtualSpace::release() { 1.408 + (void)os::release_memory(low_boundary(), reserved_size()); 1.409 + _low_boundary = NULL; 1.410 + _high_boundary = NULL; 1.411 + _low = NULL; 1.412 + _high = NULL; 1.413 + _lower_high = NULL; 1.414 + _middle_high = NULL; 1.415 + _upper_high = NULL; 1.416 + _lower_high_boundary = NULL; 1.417 + _middle_high_boundary = NULL; 1.418 + _upper_high_boundary = NULL; 1.419 + _lower_alignment = 0; 1.420 + _middle_alignment = 0; 1.421 + _upper_alignment = 0; 1.422 + _special = false; 1.423 +} 1.424 + 1.425 + 1.426 +size_t VirtualSpace::committed_size() const { 1.427 + return pointer_delta(high(), low(), sizeof(char)); 1.428 +} 1.429 + 1.430 + 1.431 +size_t VirtualSpace::reserved_size() const { 1.432 + return pointer_delta(high_boundary(), low_boundary(), sizeof(char)); 1.433 +} 1.434 + 1.435 + 1.436 +size_t VirtualSpace::uncommitted_size() const { 1.437 + return reserved_size() - committed_size(); 1.438 +} 1.439 + 1.440 + 1.441 +bool VirtualSpace::contains(const void* p) const { 1.442 + return low() <= (const char*) p && (const char*) p < high(); 1.443 +} 1.444 + 1.445 +/* 1.446 + First we need to determine if a particular virtual space is using large 1.447 + pages. This is done at the initialize function and only virtual spaces 1.448 + that are larger than LargePageSizeInBytes use large pages. Once we 1.449 + have determined this, all expand_by and shrink_by calls must grow and 1.450 + shrink by large page size chunks. If a particular request 1.451 + is within the current large page, the call to commit and uncommit memory 1.452 + can be ignored. In the case that the low and high boundaries of this 1.453 + space is not large page aligned, the pages leading to the first large 1.454 + page address and the pages after the last large page address must be 1.455 + allocated with default pages. 1.456 +*/ 1.457 +bool VirtualSpace::expand_by(size_t bytes, bool pre_touch) { 1.458 + if (uncommitted_size() < bytes) return false; 1.459 + 1.460 + if (special()) { 1.461 + // don't commit memory if the entire space is pinned in memory 1.462 + _high += bytes; 1.463 + return true; 1.464 + } 1.465 + 1.466 + char* previous_high = high(); 1.467 + char* unaligned_new_high = high() + bytes; 1.468 + assert(unaligned_new_high <= high_boundary(), 1.469 + "cannot expand by more than upper boundary"); 1.470 + 1.471 + // Calculate where the new high for each of the regions should be. If 1.472 + // the low_boundary() and high_boundary() are LargePageSizeInBytes aligned 1.473 + // then the unaligned lower and upper new highs would be the 1.474 + // lower_high() and upper_high() respectively. 1.475 + char* unaligned_lower_new_high = 1.476 + MIN2(unaligned_new_high, lower_high_boundary()); 1.477 + char* unaligned_middle_new_high = 1.478 + MIN2(unaligned_new_high, middle_high_boundary()); 1.479 + char* unaligned_upper_new_high = 1.480 + MIN2(unaligned_new_high, upper_high_boundary()); 1.481 + 1.482 + // Align the new highs based on the regions alignment. lower and upper 1.483 + // alignment will always be default page size. middle alignment will be 1.484 + // LargePageSizeInBytes if the actual size of the virtual space is in 1.485 + // fact larger than LargePageSizeInBytes. 1.486 + char* aligned_lower_new_high = 1.487 + (char*) round_to((intptr_t) unaligned_lower_new_high, lower_alignment()); 1.488 + char* aligned_middle_new_high = 1.489 + (char*) round_to((intptr_t) unaligned_middle_new_high, middle_alignment()); 1.490 + char* aligned_upper_new_high = 1.491 + (char*) round_to((intptr_t) unaligned_upper_new_high, upper_alignment()); 1.492 + 1.493 + // Determine which regions need to grow in this expand_by call. 1.494 + // If you are growing in the lower region, high() must be in that 1.495 + // region so calcuate the size based on high(). For the middle and 1.496 + // upper regions, determine the starting point of growth based on the 1.497 + // location of high(). By getting the MAX of the region's low address 1.498 + // (or the prevoius region's high address) and high(), we can tell if it 1.499 + // is an intra or inter region growth. 1.500 + size_t lower_needs = 0; 1.501 + if (aligned_lower_new_high > lower_high()) { 1.502 + lower_needs = 1.503 + pointer_delta(aligned_lower_new_high, lower_high(), sizeof(char)); 1.504 + } 1.505 + size_t middle_needs = 0; 1.506 + if (aligned_middle_new_high > middle_high()) { 1.507 + middle_needs = 1.508 + pointer_delta(aligned_middle_new_high, middle_high(), sizeof(char)); 1.509 + } 1.510 + size_t upper_needs = 0; 1.511 + if (aligned_upper_new_high > upper_high()) { 1.512 + upper_needs = 1.513 + pointer_delta(aligned_upper_new_high, upper_high(), sizeof(char)); 1.514 + } 1.515 + 1.516 + // Check contiguity. 1.517 + assert(low_boundary() <= lower_high() && 1.518 + lower_high() <= lower_high_boundary(), 1.519 + "high address must be contained within the region"); 1.520 + assert(lower_high_boundary() <= middle_high() && 1.521 + middle_high() <= middle_high_boundary(), 1.522 + "high address must be contained within the region"); 1.523 + assert(middle_high_boundary() <= upper_high() && 1.524 + upper_high() <= upper_high_boundary(), 1.525 + "high address must be contained within the region"); 1.526 + 1.527 + // Commit regions 1.528 + if (lower_needs > 0) { 1.529 + assert(low_boundary() <= lower_high() && 1.530 + lower_high() + lower_needs <= lower_high_boundary(), 1.531 + "must not expand beyond region"); 1.532 + if (!os::commit_memory(lower_high(), lower_needs)) { 1.533 + debug_only(warning("os::commit_memory failed")); 1.534 + return false; 1.535 + } else { 1.536 + _lower_high += lower_needs; 1.537 + } 1.538 + } 1.539 + if (middle_needs > 0) { 1.540 + assert(lower_high_boundary() <= middle_high() && 1.541 + middle_high() + middle_needs <= middle_high_boundary(), 1.542 + "must not expand beyond region"); 1.543 + if (!os::commit_memory(middle_high(), middle_needs, middle_alignment())) { 1.544 + debug_only(warning("os::commit_memory failed")); 1.545 + return false; 1.546 + } 1.547 + _middle_high += middle_needs; 1.548 + } 1.549 + if (upper_needs > 0) { 1.550 + assert(middle_high_boundary() <= upper_high() && 1.551 + upper_high() + upper_needs <= upper_high_boundary(), 1.552 + "must not expand beyond region"); 1.553 + if (!os::commit_memory(upper_high(), upper_needs)) { 1.554 + debug_only(warning("os::commit_memory failed")); 1.555 + return false; 1.556 + } else { 1.557 + _upper_high += upper_needs; 1.558 + } 1.559 + } 1.560 + 1.561 + if (pre_touch || AlwaysPreTouch) { 1.562 + int vm_ps = os::vm_page_size(); 1.563 + for (char* curr = previous_high; 1.564 + curr < unaligned_new_high; 1.565 + curr += vm_ps) { 1.566 + // Note the use of a write here; originally we tried just a read, but 1.567 + // since the value read was unused, the optimizer removed the read. 1.568 + // If we ever have a concurrent touchahead thread, we'll want to use 1.569 + // a read, to avoid the potential of overwriting data (if a mutator 1.570 + // thread beats the touchahead thread to a page). There are various 1.571 + // ways of making sure this read is not optimized away: for example, 1.572 + // generating the code for a read procedure at runtime. 1.573 + *curr = 0; 1.574 + } 1.575 + } 1.576 + 1.577 + _high += bytes; 1.578 + return true; 1.579 +} 1.580 + 1.581 +// A page is uncommitted if the contents of the entire page is deemed unusable. 1.582 +// Continue to decrement the high() pointer until it reaches a page boundary 1.583 +// in which case that particular page can now be uncommitted. 1.584 +void VirtualSpace::shrink_by(size_t size) { 1.585 + if (committed_size() < size) 1.586 + fatal("Cannot shrink virtual space to negative size"); 1.587 + 1.588 + if (special()) { 1.589 + // don't uncommit if the entire space is pinned in memory 1.590 + _high -= size; 1.591 + return; 1.592 + } 1.593 + 1.594 + char* unaligned_new_high = high() - size; 1.595 + assert(unaligned_new_high >= low_boundary(), "cannot shrink past lower boundary"); 1.596 + 1.597 + // Calculate new unaligned address 1.598 + char* unaligned_upper_new_high = 1.599 + MAX2(unaligned_new_high, middle_high_boundary()); 1.600 + char* unaligned_middle_new_high = 1.601 + MAX2(unaligned_new_high, lower_high_boundary()); 1.602 + char* unaligned_lower_new_high = 1.603 + MAX2(unaligned_new_high, low_boundary()); 1.604 + 1.605 + // Align address to region's alignment 1.606 + char* aligned_upper_new_high = 1.607 + (char*) round_to((intptr_t) unaligned_upper_new_high, upper_alignment()); 1.608 + char* aligned_middle_new_high = 1.609 + (char*) round_to((intptr_t) unaligned_middle_new_high, middle_alignment()); 1.610 + char* aligned_lower_new_high = 1.611 + (char*) round_to((intptr_t) unaligned_lower_new_high, lower_alignment()); 1.612 + 1.613 + // Determine which regions need to shrink 1.614 + size_t upper_needs = 0; 1.615 + if (aligned_upper_new_high < upper_high()) { 1.616 + upper_needs = 1.617 + pointer_delta(upper_high(), aligned_upper_new_high, sizeof(char)); 1.618 + } 1.619 + size_t middle_needs = 0; 1.620 + if (aligned_middle_new_high < middle_high()) { 1.621 + middle_needs = 1.622 + pointer_delta(middle_high(), aligned_middle_new_high, sizeof(char)); 1.623 + } 1.624 + size_t lower_needs = 0; 1.625 + if (aligned_lower_new_high < lower_high()) { 1.626 + lower_needs = 1.627 + pointer_delta(lower_high(), aligned_lower_new_high, sizeof(char)); 1.628 + } 1.629 + 1.630 + // Check contiguity. 1.631 + assert(middle_high_boundary() <= upper_high() && 1.632 + upper_high() <= upper_high_boundary(), 1.633 + "high address must be contained within the region"); 1.634 + assert(lower_high_boundary() <= middle_high() && 1.635 + middle_high() <= middle_high_boundary(), 1.636 + "high address must be contained within the region"); 1.637 + assert(low_boundary() <= lower_high() && 1.638 + lower_high() <= lower_high_boundary(), 1.639 + "high address must be contained within the region"); 1.640 + 1.641 + // Uncommit 1.642 + if (upper_needs > 0) { 1.643 + assert(middle_high_boundary() <= aligned_upper_new_high && 1.644 + aligned_upper_new_high + upper_needs <= upper_high_boundary(), 1.645 + "must not shrink beyond region"); 1.646 + if (!os::uncommit_memory(aligned_upper_new_high, upper_needs)) { 1.647 + debug_only(warning("os::uncommit_memory failed")); 1.648 + return; 1.649 + } else { 1.650 + _upper_high -= upper_needs; 1.651 + } 1.652 + } 1.653 + if (middle_needs > 0) { 1.654 + assert(lower_high_boundary() <= aligned_middle_new_high && 1.655 + aligned_middle_new_high + middle_needs <= middle_high_boundary(), 1.656 + "must not shrink beyond region"); 1.657 + if (!os::uncommit_memory(aligned_middle_new_high, middle_needs)) { 1.658 + debug_only(warning("os::uncommit_memory failed")); 1.659 + return; 1.660 + } else { 1.661 + _middle_high -= middle_needs; 1.662 + } 1.663 + } 1.664 + if (lower_needs > 0) { 1.665 + assert(low_boundary() <= aligned_lower_new_high && 1.666 + aligned_lower_new_high + lower_needs <= lower_high_boundary(), 1.667 + "must not shrink beyond region"); 1.668 + if (!os::uncommit_memory(aligned_lower_new_high, lower_needs)) { 1.669 + debug_only(warning("os::uncommit_memory failed")); 1.670 + return; 1.671 + } else { 1.672 + _lower_high -= lower_needs; 1.673 + } 1.674 + } 1.675 + 1.676 + _high -= size; 1.677 +} 1.678 + 1.679 +#ifndef PRODUCT 1.680 +void VirtualSpace::check_for_contiguity() { 1.681 + // Check contiguity. 1.682 + assert(low_boundary() <= lower_high() && 1.683 + lower_high() <= lower_high_boundary(), 1.684 + "high address must be contained within the region"); 1.685 + assert(lower_high_boundary() <= middle_high() && 1.686 + middle_high() <= middle_high_boundary(), 1.687 + "high address must be contained within the region"); 1.688 + assert(middle_high_boundary() <= upper_high() && 1.689 + upper_high() <= upper_high_boundary(), 1.690 + "high address must be contained within the region"); 1.691 + assert(low() >= low_boundary(), "low"); 1.692 + assert(low_boundary() <= lower_high_boundary(), "lower high boundary"); 1.693 + assert(upper_high_boundary() <= high_boundary(), "upper high boundary"); 1.694 + assert(high() <= upper_high(), "upper high"); 1.695 +} 1.696 + 1.697 +void VirtualSpace::print() { 1.698 + tty->print ("Virtual space:"); 1.699 + if (special()) tty->print(" (pinned in memory)"); 1.700 + tty->cr(); 1.701 + tty->print_cr(" - committed: %ld", committed_size()); 1.702 + tty->print_cr(" - reserved: %ld", reserved_size()); 1.703 + tty->print_cr(" - [low, high]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low(), high()); 1.704 + tty->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low_boundary(), high_boundary()); 1.705 +} 1.706 + 1.707 +#endif