src/share/vm/runtime/virtualspace.cpp

Tue, 29 May 2018 20:20:25 +0800

author
aoqi
date
Tue, 29 May 2018 20:20:25 +0800
changeset 9122
024be04bb151
parent 7994
04ff2f6cd0eb
child 9138
b56ab8e56604
permissions
-rw-r--r--

Merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 *
aoqi@0 23 */
aoqi@0 24
aoqi@0 25 #include "precompiled.hpp"
aoqi@0 26 #include "oops/markOop.hpp"
aoqi@0 27 #include "oops/oop.inline.hpp"
aoqi@0 28 #include "runtime/virtualspace.hpp"
aoqi@0 29 #include "services/memTracker.hpp"
aoqi@0 30 #ifdef TARGET_OS_FAMILY_linux
aoqi@0 31 # include "os_linux.inline.hpp"
aoqi@0 32 #endif
aoqi@0 33 #ifdef TARGET_OS_FAMILY_solaris
aoqi@0 34 # include "os_solaris.inline.hpp"
aoqi@0 35 #endif
aoqi@0 36 #ifdef TARGET_OS_FAMILY_windows
aoqi@0 37 # include "os_windows.inline.hpp"
aoqi@0 38 #endif
aoqi@0 39 #ifdef TARGET_OS_FAMILY_aix
aoqi@0 40 # include "os_aix.inline.hpp"
aoqi@0 41 #endif
aoqi@0 42 #ifdef TARGET_OS_FAMILY_bsd
aoqi@0 43 # include "os_bsd.inline.hpp"
aoqi@0 44 #endif
aoqi@0 45
aoqi@0 46 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
aoqi@0 47
aoqi@0 48 // ReservedSpace
aoqi@0 49
aoqi@0 50 // Dummy constructor
aoqi@0 51 ReservedSpace::ReservedSpace() : _base(NULL), _size(0), _noaccess_prefix(0),
aoqi@0 52 _alignment(0), _special(false), _executable(false) {
aoqi@0 53 }
aoqi@0 54
tschatzl@7782 55 ReservedSpace::ReservedSpace(size_t size, size_t preferred_page_size) {
tschatzl@7782 56 bool has_preferred_page_size = preferred_page_size != 0;
ehelin@7780 57 // Want to use large pages where possible and pad with small pages.
tschatzl@7782 58 size_t page_size = has_preferred_page_size ? preferred_page_size : os::page_size_for_region_unaligned(size, 1);
aoqi@0 59 bool large_pages = page_size != (size_t)os::vm_page_size();
tschatzl@7781 60 size_t alignment;
tschatzl@7782 61 if (large_pages && has_preferred_page_size) {
tschatzl@7781 62 alignment = MAX2(page_size, (size_t)os::vm_allocation_granularity());
tschatzl@7781 63 // ReservedSpace initialization requires size to be aligned to the given
tschatzl@7781 64 // alignment. Align the size up.
tschatzl@7781 65 size = align_size_up(size, alignment);
tschatzl@7781 66 } else {
tschatzl@7781 67 // Don't force the alignment to be large page aligned,
tschatzl@7781 68 // since that will waste memory.
tschatzl@7781 69 alignment = os::vm_allocation_granularity();
tschatzl@7781 70 }
aoqi@0 71 initialize(size, alignment, large_pages, NULL, 0, false);
aoqi@0 72 }
aoqi@0 73
aoqi@0 74 ReservedSpace::ReservedSpace(size_t size, size_t alignment,
aoqi@0 75 bool large,
aoqi@0 76 char* requested_address,
aoqi@0 77 const size_t noaccess_prefix) {
aoqi@0 78 initialize(size+noaccess_prefix, alignment, large, requested_address,
aoqi@0 79 noaccess_prefix, false);
aoqi@0 80 }
aoqi@0 81
aoqi@0 82 ReservedSpace::ReservedSpace(size_t size, size_t alignment,
aoqi@0 83 bool large,
aoqi@0 84 bool executable) {
aoqi@0 85 initialize(size, alignment, large, NULL, 0, executable);
aoqi@0 86 }
aoqi@0 87
aoqi@0 88 // Helper method.
aoqi@0 89 static bool failed_to_reserve_as_requested(char* base, char* requested_address,
aoqi@0 90 const size_t size, bool special)
aoqi@0 91 {
aoqi@0 92 if (base == requested_address || requested_address == NULL)
aoqi@0 93 return false; // did not fail
aoqi@0 94
aoqi@0 95 if (base != NULL) {
aoqi@0 96 // Different reserve address may be acceptable in other cases
aoqi@0 97 // but for compressed oops heap should be at requested address.
aoqi@0 98 assert(UseCompressedOops, "currently requested address used only for compressed oops");
aoqi@0 99 if (PrintCompressedOopsMode) {
aoqi@0 100 tty->cr();
aoqi@0 101 tty->print_cr("Reserved memory not at requested address: " PTR_FORMAT " vs " PTR_FORMAT, base, requested_address);
aoqi@0 102 }
aoqi@0 103 // OS ignored requested address. Try different address.
aoqi@0 104 if (special) {
aoqi@0 105 if (!os::release_memory_special(base, size)) {
aoqi@0 106 fatal("os::release_memory_special failed");
aoqi@0 107 }
aoqi@0 108 } else {
aoqi@0 109 if (!os::release_memory(base, size)) {
aoqi@0 110 fatal("os::release_memory failed");
aoqi@0 111 }
aoqi@0 112 }
aoqi@0 113 }
aoqi@0 114 return true;
aoqi@0 115 }
aoqi@0 116
aoqi@0 117 void ReservedSpace::initialize(size_t size, size_t alignment, bool large,
aoqi@0 118 char* requested_address,
aoqi@0 119 const size_t noaccess_prefix,
aoqi@0 120 bool executable) {
aoqi@0 121 const size_t granularity = os::vm_allocation_granularity();
aoqi@0 122 assert((size & (granularity - 1)) == 0,
aoqi@0 123 "size not aligned to os::vm_allocation_granularity()");
aoqi@0 124 assert((alignment & (granularity - 1)) == 0,
aoqi@0 125 "alignment not aligned to os::vm_allocation_granularity()");
aoqi@0 126 assert(alignment == 0 || is_power_of_2((intptr_t)alignment),
aoqi@0 127 "not a power of 2");
aoqi@0 128
aoqi@0 129 alignment = MAX2(alignment, (size_t)os::vm_page_size());
aoqi@0 130
aoqi@0 131 // Assert that if noaccess_prefix is used, it is the same as alignment.
aoqi@0 132 assert(noaccess_prefix == 0 ||
aoqi@0 133 noaccess_prefix == alignment, "noaccess prefix wrong");
aoqi@0 134
aoqi@0 135 _base = NULL;
aoqi@0 136 _size = 0;
aoqi@0 137 _special = false;
aoqi@0 138 _executable = executable;
aoqi@0 139 _alignment = 0;
aoqi@0 140 _noaccess_prefix = 0;
aoqi@0 141 if (size == 0) {
aoqi@0 142 return;
aoqi@0 143 }
aoqi@0 144
aoqi@0 145 // If OS doesn't support demand paging for large page memory, we need
aoqi@0 146 // to use reserve_memory_special() to reserve and pin the entire region.
aoqi@0 147 bool special = large && !os::can_commit_large_page_memory();
aoqi@0 148 char* base = NULL;
aoqi@0 149
fujie@371 150 #ifdef MIPS64
fujie@371 151 static int code_cache_init_flag = 1;
fujie@389 152 if (UseCodeCacheAllocOpt && code_cache_init_flag && executable) {
fujie@371 153 code_cache_init_flag = 0;
fujie@371 154 requested_address = (char*) (5 * os::Linux::page_size());
fujie@371 155 }
fujie@371 156 #endif
fujie@371 157
aoqi@0 158 if (requested_address != 0) {
aoqi@0 159 requested_address -= noaccess_prefix; // adjust requested address
aoqi@0 160 assert(requested_address != NULL, "huge noaccess prefix?");
aoqi@0 161 }
aoqi@0 162
aoqi@0 163 if (special) {
aoqi@0 164
aoqi@0 165 base = os::reserve_memory_special(size, alignment, requested_address, executable);
aoqi@0 166
aoqi@0 167 if (base != NULL) {
aoqi@0 168 if (failed_to_reserve_as_requested(base, requested_address, size, true)) {
aoqi@0 169 // OS ignored requested address. Try different address.
aoqi@0 170 return;
aoqi@0 171 }
aoqi@0 172 // Check alignment constraints.
aoqi@0 173 assert((uintptr_t) base % alignment == 0,
aoqi@0 174 err_msg("Large pages returned a non-aligned address, base: "
aoqi@0 175 PTR_FORMAT " alignment: " PTR_FORMAT,
aoqi@0 176 base, (void*)(uintptr_t)alignment));
aoqi@0 177 _special = true;
aoqi@0 178 } else {
aoqi@0 179 // failed; try to reserve regular memory below
aoqi@0 180 if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) ||
aoqi@0 181 !FLAG_IS_DEFAULT(LargePageSizeInBytes))) {
aoqi@0 182 if (PrintCompressedOopsMode) {
aoqi@0 183 tty->cr();
aoqi@0 184 tty->print_cr("Reserve regular memory without large pages.");
aoqi@0 185 }
aoqi@0 186 }
aoqi@0 187 }
aoqi@0 188 }
aoqi@0 189
aoqi@0 190 if (base == NULL) {
aoqi@0 191 // Optimistically assume that the OSes returns an aligned base pointer.
aoqi@0 192 // When reserving a large address range, most OSes seem to align to at
aoqi@0 193 // least 64K.
aoqi@0 194
aoqi@0 195 // If the memory was requested at a particular address, use
aoqi@0 196 // os::attempt_reserve_memory_at() to avoid over mapping something
aoqi@0 197 // important. If available space is not detected, return NULL.
aoqi@0 198
aoqi@0 199 if (requested_address != 0) {
aoqi@0 200 base = os::attempt_reserve_memory_at(size, requested_address);
aoqi@0 201 if (failed_to_reserve_as_requested(base, requested_address, size, false)) {
aoqi@0 202 // OS ignored requested address. Try different address.
aoqi@0 203 base = NULL;
aoqi@0 204 }
aoqi@0 205 } else {
aoqi@0 206 base = os::reserve_memory(size, NULL, alignment);
aoqi@0 207 }
aoqi@0 208
aoqi@0 209 if (base == NULL) return;
aoqi@0 210
aoqi@0 211 // Check alignment constraints
aoqi@0 212 if ((((size_t)base + noaccess_prefix) & (alignment - 1)) != 0) {
aoqi@0 213 // Base not aligned, retry
aoqi@0 214 if (!os::release_memory(base, size)) fatal("os::release_memory failed");
aoqi@0 215 // Make sure that size is aligned
aoqi@0 216 size = align_size_up(size, alignment);
aoqi@0 217 base = os::reserve_memory_aligned(size, alignment);
aoqi@0 218
aoqi@0 219 if (requested_address != 0 &&
aoqi@0 220 failed_to_reserve_as_requested(base, requested_address, size, false)) {
aoqi@0 221 // As a result of the alignment constraints, the allocated base differs
aoqi@0 222 // from the requested address. Return back to the caller who can
aoqi@0 223 // take remedial action (like try again without a requested address).
aoqi@0 224 assert(_base == NULL, "should be");
aoqi@0 225 return;
aoqi@0 226 }
aoqi@0 227 }
aoqi@0 228 }
aoqi@0 229 // Done
aoqi@0 230 _base = base;
aoqi@0 231 _size = size;
aoqi@0 232 _alignment = alignment;
aoqi@0 233 _noaccess_prefix = noaccess_prefix;
aoqi@0 234
aoqi@0 235 // Assert that if noaccess_prefix is used, it is the same as alignment.
aoqi@0 236 assert(noaccess_prefix == 0 ||
aoqi@0 237 noaccess_prefix == _alignment, "noaccess prefix wrong");
aoqi@0 238
aoqi@0 239 assert(markOopDesc::encode_pointer_as_mark(_base)->decode_pointer() == _base,
aoqi@0 240 "area must be distinguisable from marks for mark-sweep");
aoqi@0 241 assert(markOopDesc::encode_pointer_as_mark(&_base[size])->decode_pointer() == &_base[size],
aoqi@0 242 "area must be distinguisable from marks for mark-sweep");
aoqi@0 243 }
aoqi@0 244
aoqi@0 245
aoqi@0 246 ReservedSpace::ReservedSpace(char* base, size_t size, size_t alignment,
aoqi@0 247 bool special, bool executable) {
aoqi@0 248 assert((size % os::vm_allocation_granularity()) == 0,
aoqi@0 249 "size not allocation aligned");
aoqi@0 250 _base = base;
aoqi@0 251 _size = size;
aoqi@0 252 _alignment = alignment;
aoqi@0 253 _noaccess_prefix = 0;
aoqi@0 254 _special = special;
aoqi@0 255 _executable = executable;
aoqi@0 256 }
aoqi@0 257
aoqi@0 258
aoqi@0 259 ReservedSpace ReservedSpace::first_part(size_t partition_size, size_t alignment,
aoqi@0 260 bool split, bool realloc) {
aoqi@0 261 assert(partition_size <= size(), "partition failed");
aoqi@0 262 if (split) {
aoqi@0 263 os::split_reserved_memory(base(), size(), partition_size, realloc);
aoqi@0 264 }
aoqi@0 265 ReservedSpace result(base(), partition_size, alignment, special(),
aoqi@0 266 executable());
aoqi@0 267 return result;
aoqi@0 268 }
aoqi@0 269
aoqi@0 270
aoqi@0 271 ReservedSpace
aoqi@0 272 ReservedSpace::last_part(size_t partition_size, size_t alignment) {
aoqi@0 273 assert(partition_size <= size(), "partition failed");
aoqi@0 274 ReservedSpace result(base() + partition_size, size() - partition_size,
aoqi@0 275 alignment, special(), executable());
aoqi@0 276 return result;
aoqi@0 277 }
aoqi@0 278
aoqi@0 279
aoqi@0 280 size_t ReservedSpace::page_align_size_up(size_t size) {
aoqi@0 281 return align_size_up(size, os::vm_page_size());
aoqi@0 282 }
aoqi@0 283
aoqi@0 284
aoqi@0 285 size_t ReservedSpace::page_align_size_down(size_t size) {
aoqi@0 286 return align_size_down(size, os::vm_page_size());
aoqi@0 287 }
aoqi@0 288
aoqi@0 289
aoqi@0 290 size_t ReservedSpace::allocation_align_size_up(size_t size) {
aoqi@0 291 return align_size_up(size, os::vm_allocation_granularity());
aoqi@0 292 }
aoqi@0 293
aoqi@0 294
aoqi@0 295 size_t ReservedSpace::allocation_align_size_down(size_t size) {
aoqi@0 296 return align_size_down(size, os::vm_allocation_granularity());
aoqi@0 297 }
aoqi@0 298
aoqi@0 299
aoqi@0 300 void ReservedSpace::release() {
aoqi@0 301 if (is_reserved()) {
aoqi@0 302 char *real_base = _base - _noaccess_prefix;
aoqi@0 303 const size_t real_size = _size + _noaccess_prefix;
aoqi@0 304 if (special()) {
aoqi@0 305 os::release_memory_special(real_base, real_size);
aoqi@0 306 } else{
aoqi@0 307 os::release_memory(real_base, real_size);
aoqi@0 308 }
aoqi@0 309 _base = NULL;
aoqi@0 310 _size = 0;
aoqi@0 311 _noaccess_prefix = 0;
aoqi@0 312 _special = false;
aoqi@0 313 _executable = false;
aoqi@0 314 }
aoqi@0 315 }
aoqi@0 316
aoqi@0 317 void ReservedSpace::protect_noaccess_prefix(const size_t size) {
aoqi@0 318 assert( (_noaccess_prefix != 0) == (UseCompressedOops && _base != NULL &&
aoqi@0 319 (Universe::narrow_oop_base() != NULL) &&
aoqi@0 320 Universe::narrow_oop_use_implicit_null_checks()),
aoqi@0 321 "noaccess_prefix should be used only with non zero based compressed oops");
aoqi@0 322
aoqi@0 323 // If there is no noaccess prefix, return.
aoqi@0 324 if (_noaccess_prefix == 0) return;
aoqi@0 325
aoqi@0 326 assert(_noaccess_prefix >= (size_t)os::vm_page_size(),
aoqi@0 327 "must be at least page size big");
aoqi@0 328
aoqi@0 329 // Protect memory at the base of the allocated region.
aoqi@0 330 // If special, the page was committed (only matters on windows)
aoqi@0 331 if (!os::protect_memory(_base, _noaccess_prefix, os::MEM_PROT_NONE,
aoqi@0 332 _special)) {
aoqi@0 333 fatal("cannot protect protection page");
aoqi@0 334 }
aoqi@0 335 if (PrintCompressedOopsMode) {
aoqi@0 336 tty->cr();
aoqi@0 337 tty->print_cr("Protected page at the reserved heap base: " PTR_FORMAT " / " INTX_FORMAT " bytes", _base, _noaccess_prefix);
aoqi@0 338 }
aoqi@0 339
aoqi@0 340 _base += _noaccess_prefix;
aoqi@0 341 _size -= _noaccess_prefix;
aoqi@0 342 assert((size == _size) && ((uintptr_t)_base % _alignment == 0),
aoqi@0 343 "must be exactly of required size and alignment");
aoqi@0 344 }
aoqi@0 345
aoqi@0 346 ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment,
aoqi@0 347 bool large, char* requested_address) :
aoqi@0 348 ReservedSpace(size, alignment, large,
aoqi@0 349 requested_address,
aoqi@0 350 (UseCompressedOops && (Universe::narrow_oop_base() != NULL) &&
aoqi@0 351 Universe::narrow_oop_use_implicit_null_checks()) ?
aoqi@0 352 lcm(os::vm_page_size(), alignment) : 0) {
aoqi@0 353 if (base() > 0) {
aoqi@0 354 MemTracker::record_virtual_memory_type((address)base(), mtJavaHeap);
aoqi@0 355 }
aoqi@0 356
aoqi@0 357 // Only reserved space for the java heap should have a noaccess_prefix
aoqi@0 358 // if using compressed oops.
aoqi@0 359 protect_noaccess_prefix(size);
aoqi@0 360 }
aoqi@0 361
aoqi@0 362 // Reserve space for code segment. Same as Java heap only we mark this as
aoqi@0 363 // executable.
aoqi@0 364 ReservedCodeSpace::ReservedCodeSpace(size_t r_size,
aoqi@0 365 size_t rs_align,
aoqi@0 366 bool large) :
aoqi@0 367 ReservedSpace(r_size, rs_align, large, /*executable*/ true) {
aoqi@0 368 MemTracker::record_virtual_memory_type((address)base(), mtCode);
aoqi@0 369 }
aoqi@0 370
aoqi@0 371 // VirtualSpace
aoqi@0 372
aoqi@0 373 VirtualSpace::VirtualSpace() {
aoqi@0 374 _low_boundary = NULL;
aoqi@0 375 _high_boundary = NULL;
aoqi@0 376 _low = NULL;
aoqi@0 377 _high = NULL;
aoqi@0 378 _lower_high = NULL;
aoqi@0 379 _middle_high = NULL;
aoqi@0 380 _upper_high = NULL;
aoqi@0 381 _lower_high_boundary = NULL;
aoqi@0 382 _middle_high_boundary = NULL;
aoqi@0 383 _upper_high_boundary = NULL;
aoqi@0 384 _lower_alignment = 0;
aoqi@0 385 _middle_alignment = 0;
aoqi@0 386 _upper_alignment = 0;
aoqi@0 387 _special = false;
aoqi@0 388 _executable = false;
aoqi@0 389 }
aoqi@0 390
aoqi@0 391
aoqi@0 392 bool VirtualSpace::initialize(ReservedSpace rs, size_t committed_size) {
ehelin@7780 393 const size_t max_commit_granularity = os::page_size_for_region_unaligned(rs.size(), 1);
aoqi@0 394 return initialize_with_granularity(rs, committed_size, max_commit_granularity);
aoqi@0 395 }
aoqi@0 396
aoqi@0 397 bool VirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t committed_size, size_t max_commit_granularity) {
aoqi@0 398 if(!rs.is_reserved()) return false; // allocation failed.
aoqi@0 399 assert(_low_boundary == NULL, "VirtualSpace already initialized");
aoqi@0 400 assert(max_commit_granularity > 0, "Granularity must be non-zero.");
aoqi@0 401
aoqi@0 402 _low_boundary = rs.base();
aoqi@0 403 _high_boundary = low_boundary() + rs.size();
aoqi@0 404
aoqi@0 405 _low = low_boundary();
aoqi@0 406 _high = low();
aoqi@0 407
aoqi@0 408 _special = rs.special();
aoqi@0 409 _executable = rs.executable();
aoqi@0 410
aoqi@0 411 // When a VirtualSpace begins life at a large size, make all future expansion
aoqi@0 412 // and shrinking occur aligned to a granularity of large pages. This avoids
aoqi@0 413 // fragmentation of physical addresses that inhibits the use of large pages
aoqi@0 414 // by the OS virtual memory system. Empirically, we see that with a 4MB
aoqi@0 415 // page size, the only spaces that get handled this way are codecache and
aoqi@0 416 // the heap itself, both of which provide a substantial performance
aoqi@0 417 // boost in many benchmarks when covered by large pages.
aoqi@0 418 //
aoqi@0 419 // No attempt is made to force large page alignment at the very top and
aoqi@0 420 // bottom of the space if they are not aligned so already.
aoqi@0 421 _lower_alignment = os::vm_page_size();
aoqi@0 422 _middle_alignment = max_commit_granularity;
aoqi@0 423 _upper_alignment = os::vm_page_size();
aoqi@0 424
aoqi@0 425 // End of each region
aoqi@0 426 _lower_high_boundary = (char*) round_to((intptr_t) low_boundary(), middle_alignment());
aoqi@0 427 _middle_high_boundary = (char*) round_down((intptr_t) high_boundary(), middle_alignment());
aoqi@0 428 _upper_high_boundary = high_boundary();
aoqi@0 429
aoqi@0 430 // High address of each region
aoqi@0 431 _lower_high = low_boundary();
aoqi@0 432 _middle_high = lower_high_boundary();
aoqi@0 433 _upper_high = middle_high_boundary();
aoqi@0 434
aoqi@0 435 // commit to initial size
aoqi@0 436 if (committed_size > 0) {
aoqi@0 437 if (!expand_by(committed_size)) {
aoqi@0 438 return false;
aoqi@0 439 }
aoqi@0 440 }
aoqi@0 441 return true;
aoqi@0 442 }
aoqi@0 443
aoqi@0 444
aoqi@0 445 VirtualSpace::~VirtualSpace() {
aoqi@0 446 release();
aoqi@0 447 }
aoqi@0 448
aoqi@0 449
aoqi@0 450 void VirtualSpace::release() {
aoqi@0 451 // This does not release memory it never reserved.
aoqi@0 452 // Caller must release via rs.release();
aoqi@0 453 _low_boundary = NULL;
aoqi@0 454 _high_boundary = NULL;
aoqi@0 455 _low = NULL;
aoqi@0 456 _high = NULL;
aoqi@0 457 _lower_high = NULL;
aoqi@0 458 _middle_high = NULL;
aoqi@0 459 _upper_high = NULL;
aoqi@0 460 _lower_high_boundary = NULL;
aoqi@0 461 _middle_high_boundary = NULL;
aoqi@0 462 _upper_high_boundary = NULL;
aoqi@0 463 _lower_alignment = 0;
aoqi@0 464 _middle_alignment = 0;
aoqi@0 465 _upper_alignment = 0;
aoqi@0 466 _special = false;
aoqi@0 467 _executable = false;
aoqi@0 468 }
aoqi@0 469
aoqi@0 470
aoqi@0 471 size_t VirtualSpace::committed_size() const {
aoqi@0 472 return pointer_delta(high(), low(), sizeof(char));
aoqi@0 473 }
aoqi@0 474
aoqi@0 475
aoqi@0 476 size_t VirtualSpace::reserved_size() const {
aoqi@0 477 return pointer_delta(high_boundary(), low_boundary(), sizeof(char));
aoqi@0 478 }
aoqi@0 479
aoqi@0 480
aoqi@0 481 size_t VirtualSpace::uncommitted_size() const {
aoqi@0 482 return reserved_size() - committed_size();
aoqi@0 483 }
aoqi@0 484
aoqi@0 485 size_t VirtualSpace::actual_committed_size() const {
aoqi@0 486 // Special VirtualSpaces commit all reserved space up front.
aoqi@0 487 if (special()) {
aoqi@0 488 return reserved_size();
aoqi@0 489 }
aoqi@0 490
aoqi@0 491 size_t committed_low = pointer_delta(_lower_high, _low_boundary, sizeof(char));
aoqi@0 492 size_t committed_middle = pointer_delta(_middle_high, _lower_high_boundary, sizeof(char));
aoqi@0 493 size_t committed_high = pointer_delta(_upper_high, _middle_high_boundary, sizeof(char));
aoqi@0 494
aoqi@0 495 #ifdef ASSERT
aoqi@0 496 size_t lower = pointer_delta(_lower_high_boundary, _low_boundary, sizeof(char));
aoqi@0 497 size_t middle = pointer_delta(_middle_high_boundary, _lower_high_boundary, sizeof(char));
aoqi@0 498 size_t upper = pointer_delta(_upper_high_boundary, _middle_high_boundary, sizeof(char));
aoqi@0 499
aoqi@0 500 if (committed_high > 0) {
aoqi@0 501 assert(committed_low == lower, "Must be");
aoqi@0 502 assert(committed_middle == middle, "Must be");
aoqi@0 503 }
aoqi@0 504
aoqi@0 505 if (committed_middle > 0) {
aoqi@0 506 assert(committed_low == lower, "Must be");
aoqi@0 507 }
aoqi@0 508 if (committed_middle < middle) {
aoqi@0 509 assert(committed_high == 0, "Must be");
aoqi@0 510 }
aoqi@0 511
aoqi@0 512 if (committed_low < lower) {
aoqi@0 513 assert(committed_high == 0, "Must be");
aoqi@0 514 assert(committed_middle == 0, "Must be");
aoqi@0 515 }
aoqi@0 516 #endif
aoqi@0 517
aoqi@0 518 return committed_low + committed_middle + committed_high;
aoqi@0 519 }
aoqi@0 520
aoqi@0 521
aoqi@0 522 bool VirtualSpace::contains(const void* p) const {
aoqi@0 523 return low() <= (const char*) p && (const char*) p < high();
aoqi@0 524 }
aoqi@0 525
aoqi@0 526 /*
aoqi@0 527 First we need to determine if a particular virtual space is using large
aoqi@0 528 pages. This is done at the initialize function and only virtual spaces
aoqi@0 529 that are larger than LargePageSizeInBytes use large pages. Once we
aoqi@0 530 have determined this, all expand_by and shrink_by calls must grow and
aoqi@0 531 shrink by large page size chunks. If a particular request
aoqi@0 532 is within the current large page, the call to commit and uncommit memory
aoqi@0 533 can be ignored. In the case that the low and high boundaries of this
aoqi@0 534 space is not large page aligned, the pages leading to the first large
aoqi@0 535 page address and the pages after the last large page address must be
aoqi@0 536 allocated with default pages.
aoqi@0 537 */
aoqi@0 538 bool VirtualSpace::expand_by(size_t bytes, bool pre_touch) {
aoqi@0 539 if (uncommitted_size() < bytes) return false;
aoqi@0 540
aoqi@0 541 if (special()) {
aoqi@0 542 // don't commit memory if the entire space is pinned in memory
aoqi@0 543 _high += bytes;
aoqi@0 544 return true;
aoqi@0 545 }
aoqi@0 546
aoqi@0 547 char* previous_high = high();
aoqi@0 548 char* unaligned_new_high = high() + bytes;
aoqi@0 549 assert(unaligned_new_high <= high_boundary(),
aoqi@0 550 "cannot expand by more than upper boundary");
aoqi@0 551
aoqi@0 552 // Calculate where the new high for each of the regions should be. If
aoqi@0 553 // the low_boundary() and high_boundary() are LargePageSizeInBytes aligned
aoqi@0 554 // then the unaligned lower and upper new highs would be the
aoqi@0 555 // lower_high() and upper_high() respectively.
aoqi@0 556 char* unaligned_lower_new_high =
aoqi@0 557 MIN2(unaligned_new_high, lower_high_boundary());
aoqi@0 558 char* unaligned_middle_new_high =
aoqi@0 559 MIN2(unaligned_new_high, middle_high_boundary());
aoqi@0 560 char* unaligned_upper_new_high =
aoqi@0 561 MIN2(unaligned_new_high, upper_high_boundary());
aoqi@0 562
aoqi@0 563 // Align the new highs based on the regions alignment. lower and upper
aoqi@0 564 // alignment will always be default page size. middle alignment will be
aoqi@0 565 // LargePageSizeInBytes if the actual size of the virtual space is in
aoqi@0 566 // fact larger than LargePageSizeInBytes.
aoqi@0 567 char* aligned_lower_new_high =
aoqi@0 568 (char*) round_to((intptr_t) unaligned_lower_new_high, lower_alignment());
aoqi@0 569 char* aligned_middle_new_high =
aoqi@0 570 (char*) round_to((intptr_t) unaligned_middle_new_high, middle_alignment());
aoqi@0 571 char* aligned_upper_new_high =
aoqi@0 572 (char*) round_to((intptr_t) unaligned_upper_new_high, upper_alignment());
aoqi@0 573
aoqi@0 574 // Determine which regions need to grow in this expand_by call.
aoqi@0 575 // If you are growing in the lower region, high() must be in that
aoqi@0 576 // region so calcuate the size based on high(). For the middle and
aoqi@0 577 // upper regions, determine the starting point of growth based on the
aoqi@0 578 // location of high(). By getting the MAX of the region's low address
aoqi@0 579 // (or the prevoius region's high address) and high(), we can tell if it
aoqi@0 580 // is an intra or inter region growth.
aoqi@0 581 size_t lower_needs = 0;
aoqi@0 582 if (aligned_lower_new_high > lower_high()) {
aoqi@0 583 lower_needs =
aoqi@0 584 pointer_delta(aligned_lower_new_high, lower_high(), sizeof(char));
aoqi@0 585 }
aoqi@0 586 size_t middle_needs = 0;
aoqi@0 587 if (aligned_middle_new_high > middle_high()) {
aoqi@0 588 middle_needs =
aoqi@0 589 pointer_delta(aligned_middle_new_high, middle_high(), sizeof(char));
aoqi@0 590 }
aoqi@0 591 size_t upper_needs = 0;
aoqi@0 592 if (aligned_upper_new_high > upper_high()) {
aoqi@0 593 upper_needs =
aoqi@0 594 pointer_delta(aligned_upper_new_high, upper_high(), sizeof(char));
aoqi@0 595 }
aoqi@0 596
aoqi@0 597 // Check contiguity.
aoqi@0 598 assert(low_boundary() <= lower_high() &&
aoqi@0 599 lower_high() <= lower_high_boundary(),
aoqi@0 600 "high address must be contained within the region");
aoqi@0 601 assert(lower_high_boundary() <= middle_high() &&
aoqi@0 602 middle_high() <= middle_high_boundary(),
aoqi@0 603 "high address must be contained within the region");
aoqi@0 604 assert(middle_high_boundary() <= upper_high() &&
aoqi@0 605 upper_high() <= upper_high_boundary(),
aoqi@0 606 "high address must be contained within the region");
aoqi@0 607
aoqi@0 608 // Commit regions
aoqi@0 609 if (lower_needs > 0) {
aoqi@0 610 assert(low_boundary() <= lower_high() &&
aoqi@0 611 lower_high() + lower_needs <= lower_high_boundary(),
aoqi@0 612 "must not expand beyond region");
aoqi@0 613 if (!os::commit_memory(lower_high(), lower_needs, _executable)) {
aoqi@0 614 debug_only(warning("INFO: os::commit_memory(" PTR_FORMAT
aoqi@0 615 ", lower_needs=" SIZE_FORMAT ", %d) failed",
aoqi@0 616 lower_high(), lower_needs, _executable);)
aoqi@0 617 return false;
aoqi@0 618 } else {
aoqi@0 619 _lower_high += lower_needs;
aoqi@0 620 }
aoqi@0 621 }
aoqi@0 622 if (middle_needs > 0) {
aoqi@0 623 assert(lower_high_boundary() <= middle_high() &&
aoqi@0 624 middle_high() + middle_needs <= middle_high_boundary(),
aoqi@0 625 "must not expand beyond region");
aoqi@0 626 if (!os::commit_memory(middle_high(), middle_needs, middle_alignment(),
aoqi@0 627 _executable)) {
aoqi@0 628 debug_only(warning("INFO: os::commit_memory(" PTR_FORMAT
aoqi@0 629 ", middle_needs=" SIZE_FORMAT ", " SIZE_FORMAT
aoqi@0 630 ", %d) failed", middle_high(), middle_needs,
aoqi@0 631 middle_alignment(), _executable);)
aoqi@0 632 return false;
aoqi@0 633 }
aoqi@0 634 _middle_high += middle_needs;
aoqi@0 635 }
aoqi@0 636 if (upper_needs > 0) {
aoqi@0 637 assert(middle_high_boundary() <= upper_high() &&
aoqi@0 638 upper_high() + upper_needs <= upper_high_boundary(),
aoqi@0 639 "must not expand beyond region");
aoqi@0 640 if (!os::commit_memory(upper_high(), upper_needs, _executable)) {
aoqi@0 641 debug_only(warning("INFO: os::commit_memory(" PTR_FORMAT
aoqi@0 642 ", upper_needs=" SIZE_FORMAT ", %d) failed",
aoqi@0 643 upper_high(), upper_needs, _executable);)
aoqi@0 644 return false;
aoqi@0 645 } else {
aoqi@0 646 _upper_high += upper_needs;
aoqi@0 647 }
aoqi@0 648 }
aoqi@0 649
aoqi@0 650 if (pre_touch || AlwaysPreTouch) {
tschatzl@7777 651 os::pretouch_memory(previous_high, unaligned_new_high);
aoqi@0 652 }
aoqi@0 653
aoqi@0 654 _high += bytes;
aoqi@0 655 return true;
aoqi@0 656 }
aoqi@0 657
aoqi@0 658 // A page is uncommitted if the contents of the entire page is deemed unusable.
aoqi@0 659 // Continue to decrement the high() pointer until it reaches a page boundary
aoqi@0 660 // in which case that particular page can now be uncommitted.
aoqi@0 661 void VirtualSpace::shrink_by(size_t size) {
aoqi@0 662 if (committed_size() < size)
aoqi@0 663 fatal("Cannot shrink virtual space to negative size");
aoqi@0 664
aoqi@0 665 if (special()) {
aoqi@0 666 // don't uncommit if the entire space is pinned in memory
aoqi@0 667 _high -= size;
aoqi@0 668 return;
aoqi@0 669 }
aoqi@0 670
aoqi@0 671 char* unaligned_new_high = high() - size;
aoqi@0 672 assert(unaligned_new_high >= low_boundary(), "cannot shrink past lower boundary");
aoqi@0 673
aoqi@0 674 // Calculate new unaligned address
aoqi@0 675 char* unaligned_upper_new_high =
aoqi@0 676 MAX2(unaligned_new_high, middle_high_boundary());
aoqi@0 677 char* unaligned_middle_new_high =
aoqi@0 678 MAX2(unaligned_new_high, lower_high_boundary());
aoqi@0 679 char* unaligned_lower_new_high =
aoqi@0 680 MAX2(unaligned_new_high, low_boundary());
aoqi@0 681
aoqi@0 682 // Align address to region's alignment
aoqi@0 683 char* aligned_upper_new_high =
aoqi@0 684 (char*) round_to((intptr_t) unaligned_upper_new_high, upper_alignment());
aoqi@0 685 char* aligned_middle_new_high =
aoqi@0 686 (char*) round_to((intptr_t) unaligned_middle_new_high, middle_alignment());
aoqi@0 687 char* aligned_lower_new_high =
aoqi@0 688 (char*) round_to((intptr_t) unaligned_lower_new_high, lower_alignment());
aoqi@0 689
aoqi@0 690 // Determine which regions need to shrink
aoqi@0 691 size_t upper_needs = 0;
aoqi@0 692 if (aligned_upper_new_high < upper_high()) {
aoqi@0 693 upper_needs =
aoqi@0 694 pointer_delta(upper_high(), aligned_upper_new_high, sizeof(char));
aoqi@0 695 }
aoqi@0 696 size_t middle_needs = 0;
aoqi@0 697 if (aligned_middle_new_high < middle_high()) {
aoqi@0 698 middle_needs =
aoqi@0 699 pointer_delta(middle_high(), aligned_middle_new_high, sizeof(char));
aoqi@0 700 }
aoqi@0 701 size_t lower_needs = 0;
aoqi@0 702 if (aligned_lower_new_high < lower_high()) {
aoqi@0 703 lower_needs =
aoqi@0 704 pointer_delta(lower_high(), aligned_lower_new_high, sizeof(char));
aoqi@0 705 }
aoqi@0 706
aoqi@0 707 // Check contiguity.
aoqi@0 708 assert(middle_high_boundary() <= upper_high() &&
aoqi@0 709 upper_high() <= upper_high_boundary(),
aoqi@0 710 "high address must be contained within the region");
aoqi@0 711 assert(lower_high_boundary() <= middle_high() &&
aoqi@0 712 middle_high() <= middle_high_boundary(),
aoqi@0 713 "high address must be contained within the region");
aoqi@0 714 assert(low_boundary() <= lower_high() &&
aoqi@0 715 lower_high() <= lower_high_boundary(),
aoqi@0 716 "high address must be contained within the region");
aoqi@0 717
aoqi@0 718 // Uncommit
aoqi@0 719 if (upper_needs > 0) {
aoqi@0 720 assert(middle_high_boundary() <= aligned_upper_new_high &&
aoqi@0 721 aligned_upper_new_high + upper_needs <= upper_high_boundary(),
aoqi@0 722 "must not shrink beyond region");
aoqi@0 723 if (!os::uncommit_memory(aligned_upper_new_high, upper_needs)) {
aoqi@0 724 debug_only(warning("os::uncommit_memory failed"));
aoqi@0 725 return;
aoqi@0 726 } else {
aoqi@0 727 _upper_high -= upper_needs;
aoqi@0 728 }
aoqi@0 729 }
aoqi@0 730 if (middle_needs > 0) {
aoqi@0 731 assert(lower_high_boundary() <= aligned_middle_new_high &&
aoqi@0 732 aligned_middle_new_high + middle_needs <= middle_high_boundary(),
aoqi@0 733 "must not shrink beyond region");
aoqi@0 734 if (!os::uncommit_memory(aligned_middle_new_high, middle_needs)) {
aoqi@0 735 debug_only(warning("os::uncommit_memory failed"));
aoqi@0 736 return;
aoqi@0 737 } else {
aoqi@0 738 _middle_high -= middle_needs;
aoqi@0 739 }
aoqi@0 740 }
aoqi@0 741 if (lower_needs > 0) {
aoqi@0 742 assert(low_boundary() <= aligned_lower_new_high &&
aoqi@0 743 aligned_lower_new_high + lower_needs <= lower_high_boundary(),
aoqi@0 744 "must not shrink beyond region");
aoqi@0 745 if (!os::uncommit_memory(aligned_lower_new_high, lower_needs)) {
aoqi@0 746 debug_only(warning("os::uncommit_memory failed"));
aoqi@0 747 return;
aoqi@0 748 } else {
aoqi@0 749 _lower_high -= lower_needs;
aoqi@0 750 }
aoqi@0 751 }
aoqi@0 752
aoqi@0 753 _high -= size;
aoqi@0 754 }
aoqi@0 755
aoqi@0 756 #ifndef PRODUCT
aoqi@0 757 void VirtualSpace::check_for_contiguity() {
aoqi@0 758 // Check contiguity.
aoqi@0 759 assert(low_boundary() <= lower_high() &&
aoqi@0 760 lower_high() <= lower_high_boundary(),
aoqi@0 761 "high address must be contained within the region");
aoqi@0 762 assert(lower_high_boundary() <= middle_high() &&
aoqi@0 763 middle_high() <= middle_high_boundary(),
aoqi@0 764 "high address must be contained within the region");
aoqi@0 765 assert(middle_high_boundary() <= upper_high() &&
aoqi@0 766 upper_high() <= upper_high_boundary(),
aoqi@0 767 "high address must be contained within the region");
aoqi@0 768 assert(low() >= low_boundary(), "low");
aoqi@0 769 assert(low_boundary() <= lower_high_boundary(), "lower high boundary");
aoqi@0 770 assert(upper_high_boundary() <= high_boundary(), "upper high boundary");
aoqi@0 771 assert(high() <= upper_high(), "upper high");
aoqi@0 772 }
aoqi@0 773
aoqi@0 774 void VirtualSpace::print_on(outputStream* out) {
aoqi@0 775 out->print ("Virtual space:");
aoqi@0 776 if (special()) out->print(" (pinned in memory)");
aoqi@0 777 out->cr();
aoqi@0 778 out->print_cr(" - committed: " SIZE_FORMAT, committed_size());
aoqi@0 779 out->print_cr(" - reserved: " SIZE_FORMAT, reserved_size());
aoqi@0 780 out->print_cr(" - [low, high]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low(), high());
aoqi@0 781 out->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low_boundary(), high_boundary());
aoqi@0 782 }
aoqi@0 783
aoqi@0 784 void VirtualSpace::print() {
aoqi@0 785 print_on(tty);
aoqi@0 786 }
aoqi@0 787
aoqi@0 788 /////////////// Unit tests ///////////////
aoqi@0 789
aoqi@0 790 #ifndef PRODUCT
aoqi@0 791
aoqi@0 792 #define test_log(...) \
aoqi@0 793 do {\
aoqi@0 794 if (VerboseInternalVMTests) { \
aoqi@0 795 tty->print_cr(__VA_ARGS__); \
aoqi@0 796 tty->flush(); \
aoqi@0 797 }\
aoqi@0 798 } while (false)
aoqi@0 799
aoqi@0 800 class TestReservedSpace : AllStatic {
aoqi@0 801 public:
aoqi@0 802 static void small_page_write(void* addr, size_t size) {
aoqi@0 803 size_t page_size = os::vm_page_size();
aoqi@0 804
aoqi@0 805 char* end = (char*)addr + size;
aoqi@0 806 for (char* p = (char*)addr; p < end; p += page_size) {
aoqi@0 807 *p = 1;
aoqi@0 808 }
aoqi@0 809 }
aoqi@0 810
aoqi@0 811 static void release_memory_for_test(ReservedSpace rs) {
aoqi@0 812 if (rs.special()) {
aoqi@0 813 guarantee(os::release_memory_special(rs.base(), rs.size()), "Shouldn't fail");
aoqi@0 814 } else {
aoqi@0 815 guarantee(os::release_memory(rs.base(), rs.size()), "Shouldn't fail");
aoqi@0 816 }
aoqi@0 817 }
aoqi@0 818
aoqi@0 819 static void test_reserved_space1(size_t size, size_t alignment) {
aoqi@0 820 test_log("test_reserved_space1(%p)", (void*) (uintptr_t) size);
aoqi@0 821
aoqi@0 822 assert(is_size_aligned(size, alignment), "Incorrect input parameters");
aoqi@0 823
aoqi@0 824 ReservedSpace rs(size, // size
aoqi@0 825 alignment, // alignment
aoqi@0 826 UseLargePages, // large
aoqi@0 827 NULL, // requested_address
aoqi@0 828 0); // noacces_prefix
aoqi@0 829
aoqi@0 830 test_log(" rs.special() == %d", rs.special());
aoqi@0 831
aoqi@0 832 assert(rs.base() != NULL, "Must be");
aoqi@0 833 assert(rs.size() == size, "Must be");
aoqi@0 834
aoqi@0 835 assert(is_ptr_aligned(rs.base(), alignment), "aligned sizes should always give aligned addresses");
aoqi@0 836 assert(is_size_aligned(rs.size(), alignment), "aligned sizes should always give aligned addresses");
aoqi@0 837
aoqi@0 838 if (rs.special()) {
aoqi@0 839 small_page_write(rs.base(), size);
aoqi@0 840 }
aoqi@0 841
aoqi@0 842 release_memory_for_test(rs);
aoqi@0 843 }
aoqi@0 844
aoqi@0 845 static void test_reserved_space2(size_t size) {
aoqi@0 846 test_log("test_reserved_space2(%p)", (void*)(uintptr_t)size);
aoqi@0 847
aoqi@0 848 assert(is_size_aligned(size, os::vm_allocation_granularity()), "Must be at least AG aligned");
aoqi@0 849
aoqi@0 850 ReservedSpace rs(size);
aoqi@0 851
aoqi@0 852 test_log(" rs.special() == %d", rs.special());
aoqi@0 853
aoqi@0 854 assert(rs.base() != NULL, "Must be");
aoqi@0 855 assert(rs.size() == size, "Must be");
aoqi@0 856
aoqi@0 857 if (rs.special()) {
aoqi@0 858 small_page_write(rs.base(), size);
aoqi@0 859 }
aoqi@0 860
aoqi@0 861 release_memory_for_test(rs);
aoqi@0 862 }
aoqi@0 863
aoqi@0 864 static void test_reserved_space3(size_t size, size_t alignment, bool maybe_large) {
aoqi@0 865 test_log("test_reserved_space3(%p, %p, %d)",
aoqi@0 866 (void*)(uintptr_t)size, (void*)(uintptr_t)alignment, maybe_large);
aoqi@0 867
aoqi@0 868 assert(is_size_aligned(size, os::vm_allocation_granularity()), "Must be at least AG aligned");
aoqi@0 869 assert(is_size_aligned(size, alignment), "Must be at least aligned against alignment");
aoqi@0 870
aoqi@0 871 bool large = maybe_large && UseLargePages && size >= os::large_page_size();
aoqi@0 872
aoqi@0 873 ReservedSpace rs(size, alignment, large, false);
aoqi@0 874
aoqi@0 875 test_log(" rs.special() == %d", rs.special());
aoqi@0 876
aoqi@0 877 assert(rs.base() != NULL, "Must be");
aoqi@0 878 assert(rs.size() == size, "Must be");
aoqi@0 879
aoqi@0 880 if (rs.special()) {
aoqi@0 881 small_page_write(rs.base(), size);
aoqi@0 882 }
aoqi@0 883
aoqi@0 884 release_memory_for_test(rs);
aoqi@0 885 }
aoqi@0 886
aoqi@0 887
aoqi@0 888 static void test_reserved_space1() {
aoqi@0 889 size_t size = 2 * 1024 * 1024;
aoqi@0 890 size_t ag = os::vm_allocation_granularity();
aoqi@0 891
aoqi@0 892 test_reserved_space1(size, ag);
aoqi@0 893 test_reserved_space1(size * 2, ag);
aoqi@0 894 test_reserved_space1(size * 10, ag);
aoqi@0 895 }
aoqi@0 896
aoqi@0 897 static void test_reserved_space2() {
aoqi@0 898 size_t size = 2 * 1024 * 1024;
aoqi@0 899 size_t ag = os::vm_allocation_granularity();
aoqi@0 900
aoqi@0 901 test_reserved_space2(size * 1);
aoqi@0 902 test_reserved_space2(size * 2);
aoqi@0 903 test_reserved_space2(size * 10);
aoqi@0 904 test_reserved_space2(ag);
aoqi@0 905 test_reserved_space2(size - ag);
aoqi@0 906 test_reserved_space2(size);
aoqi@0 907 test_reserved_space2(size + ag);
aoqi@0 908 test_reserved_space2(size * 2);
aoqi@0 909 test_reserved_space2(size * 2 - ag);
aoqi@0 910 test_reserved_space2(size * 2 + ag);
aoqi@0 911 test_reserved_space2(size * 3);
aoqi@0 912 test_reserved_space2(size * 3 - ag);
aoqi@0 913 test_reserved_space2(size * 3 + ag);
aoqi@0 914 test_reserved_space2(size * 10);
aoqi@0 915 test_reserved_space2(size * 10 + size / 2);
aoqi@0 916 }
aoqi@0 917
aoqi@0 918 static void test_reserved_space3() {
aoqi@0 919 size_t ag = os::vm_allocation_granularity();
aoqi@0 920
aoqi@0 921 test_reserved_space3(ag, ag , false);
aoqi@0 922 test_reserved_space3(ag * 2, ag , false);
aoqi@0 923 test_reserved_space3(ag * 3, ag , false);
aoqi@0 924 test_reserved_space3(ag * 2, ag * 2, false);
aoqi@0 925 test_reserved_space3(ag * 4, ag * 2, false);
aoqi@0 926 test_reserved_space3(ag * 8, ag * 2, false);
aoqi@0 927 test_reserved_space3(ag * 4, ag * 4, false);
aoqi@0 928 test_reserved_space3(ag * 8, ag * 4, false);
aoqi@0 929 test_reserved_space3(ag * 16, ag * 4, false);
aoqi@0 930
aoqi@0 931 if (UseLargePages) {
aoqi@0 932 size_t lp = os::large_page_size();
aoqi@0 933
aoqi@0 934 // Without large pages
aoqi@0 935 test_reserved_space3(lp, ag * 4, false);
aoqi@0 936 test_reserved_space3(lp * 2, ag * 4, false);
aoqi@0 937 test_reserved_space3(lp * 4, ag * 4, false);
aoqi@0 938 test_reserved_space3(lp, lp , false);
aoqi@0 939 test_reserved_space3(lp * 2, lp , false);
aoqi@0 940 test_reserved_space3(lp * 3, lp , false);
aoqi@0 941 test_reserved_space3(lp * 2, lp * 2, false);
aoqi@0 942 test_reserved_space3(lp * 4, lp * 2, false);
aoqi@0 943 test_reserved_space3(lp * 8, lp * 2, false);
aoqi@0 944
aoqi@0 945 // With large pages
aoqi@0 946 test_reserved_space3(lp, ag * 4 , true);
aoqi@0 947 test_reserved_space3(lp * 2, ag * 4, true);
aoqi@0 948 test_reserved_space3(lp * 4, ag * 4, true);
aoqi@0 949 test_reserved_space3(lp, lp , true);
aoqi@0 950 test_reserved_space3(lp * 2, lp , true);
aoqi@0 951 test_reserved_space3(lp * 3, lp , true);
aoqi@0 952 test_reserved_space3(lp * 2, lp * 2, true);
aoqi@0 953 test_reserved_space3(lp * 4, lp * 2, true);
aoqi@0 954 test_reserved_space3(lp * 8, lp * 2, true);
aoqi@0 955 }
aoqi@0 956 }
aoqi@0 957
aoqi@0 958 static void test_reserved_space() {
aoqi@0 959 test_reserved_space1();
aoqi@0 960 test_reserved_space2();
aoqi@0 961 test_reserved_space3();
aoqi@0 962 }
aoqi@0 963 };
aoqi@0 964
aoqi@0 965 void TestReservedSpace_test() {
aoqi@0 966 TestReservedSpace::test_reserved_space();
aoqi@0 967 }
aoqi@0 968
aoqi@0 969 #define assert_equals(actual, expected) \
aoqi@0 970 assert(actual == expected, \
aoqi@0 971 err_msg("Got " SIZE_FORMAT " expected " \
aoqi@0 972 SIZE_FORMAT, actual, expected));
aoqi@0 973
aoqi@0 974 #define assert_ge(value1, value2) \
aoqi@0 975 assert(value1 >= value2, \
aoqi@0 976 err_msg("'" #value1 "': " SIZE_FORMAT " '" \
aoqi@0 977 #value2 "': " SIZE_FORMAT, value1, value2));
aoqi@0 978
aoqi@0 979 #define assert_lt(value1, value2) \
aoqi@0 980 assert(value1 < value2, \
aoqi@0 981 err_msg("'" #value1 "': " SIZE_FORMAT " '" \
aoqi@0 982 #value2 "': " SIZE_FORMAT, value1, value2));
aoqi@0 983
aoqi@0 984
aoqi@0 985 class TestVirtualSpace : AllStatic {
aoqi@0 986 enum TestLargePages {
aoqi@0 987 Default,
aoqi@0 988 Disable,
aoqi@0 989 Reserve,
aoqi@0 990 Commit
aoqi@0 991 };
aoqi@0 992
aoqi@0 993 static ReservedSpace reserve_memory(size_t reserve_size_aligned, TestLargePages mode) {
aoqi@0 994 switch(mode) {
aoqi@0 995 default:
aoqi@0 996 case Default:
aoqi@0 997 case Reserve:
aoqi@0 998 return ReservedSpace(reserve_size_aligned);
aoqi@0 999 case Disable:
aoqi@0 1000 case Commit:
aoqi@0 1001 return ReservedSpace(reserve_size_aligned,
aoqi@0 1002 os::vm_allocation_granularity(),
aoqi@0 1003 /* large */ false, /* exec */ false);
aoqi@0 1004 }
aoqi@0 1005 }
aoqi@0 1006
aoqi@0 1007 static bool initialize_virtual_space(VirtualSpace& vs, ReservedSpace rs, TestLargePages mode) {
aoqi@0 1008 switch(mode) {
aoqi@0 1009 default:
aoqi@0 1010 case Default:
aoqi@0 1011 case Reserve:
aoqi@0 1012 return vs.initialize(rs, 0);
aoqi@0 1013 case Disable:
aoqi@0 1014 return vs.initialize_with_granularity(rs, 0, os::vm_page_size());
aoqi@0 1015 case Commit:
ehelin@7780 1016 return vs.initialize_with_granularity(rs, 0, os::page_size_for_region_unaligned(rs.size(), 1));
aoqi@0 1017 }
aoqi@0 1018 }
aoqi@0 1019
aoqi@0 1020 public:
aoqi@0 1021 static void test_virtual_space_actual_committed_space(size_t reserve_size, size_t commit_size,
aoqi@0 1022 TestLargePages mode = Default) {
aoqi@0 1023 size_t granularity = os::vm_allocation_granularity();
aoqi@0 1024 size_t reserve_size_aligned = align_size_up(reserve_size, granularity);
aoqi@0 1025
aoqi@0 1026 ReservedSpace reserved = reserve_memory(reserve_size_aligned, mode);
aoqi@0 1027
aoqi@0 1028 assert(reserved.is_reserved(), "Must be");
aoqi@0 1029
aoqi@0 1030 VirtualSpace vs;
aoqi@0 1031 bool initialized = initialize_virtual_space(vs, reserved, mode);
aoqi@0 1032 assert(initialized, "Failed to initialize VirtualSpace");
aoqi@0 1033
aoqi@0 1034 vs.expand_by(commit_size, false);
aoqi@0 1035
aoqi@0 1036 if (vs.special()) {
aoqi@0 1037 assert_equals(vs.actual_committed_size(), reserve_size_aligned);
aoqi@0 1038 } else {
aoqi@0 1039 assert_ge(vs.actual_committed_size(), commit_size);
aoqi@0 1040 // Approximate the commit granularity.
aoqi@0 1041 // Make sure that we don't commit using large pages
aoqi@0 1042 // if large pages has been disabled for this VirtualSpace.
aoqi@0 1043 size_t commit_granularity = (mode == Disable || !UseLargePages) ?
aoqi@0 1044 os::vm_page_size() : os::large_page_size();
aoqi@0 1045 assert_lt(vs.actual_committed_size(), commit_size + commit_granularity);
aoqi@0 1046 }
aoqi@0 1047
aoqi@0 1048 reserved.release();
aoqi@0 1049 }
aoqi@0 1050
aoqi@0 1051 static void test_virtual_space_actual_committed_space_one_large_page() {
aoqi@0 1052 if (!UseLargePages) {
aoqi@0 1053 return;
aoqi@0 1054 }
aoqi@0 1055
aoqi@0 1056 size_t large_page_size = os::large_page_size();
aoqi@0 1057
aoqi@0 1058 ReservedSpace reserved(large_page_size, large_page_size, true, false);
aoqi@0 1059
aoqi@0 1060 assert(reserved.is_reserved(), "Must be");
aoqi@0 1061
aoqi@0 1062 VirtualSpace vs;
aoqi@0 1063 bool initialized = vs.initialize(reserved, 0);
aoqi@0 1064 assert(initialized, "Failed to initialize VirtualSpace");
aoqi@0 1065
aoqi@0 1066 vs.expand_by(large_page_size, false);
aoqi@0 1067
aoqi@0 1068 assert_equals(vs.actual_committed_size(), large_page_size);
aoqi@0 1069
aoqi@0 1070 reserved.release();
aoqi@0 1071 }
aoqi@0 1072
aoqi@0 1073 static void test_virtual_space_actual_committed_space() {
aoqi@0 1074 test_virtual_space_actual_committed_space(4 * K, 0);
aoqi@0 1075 test_virtual_space_actual_committed_space(4 * K, 4 * K);
aoqi@0 1076 test_virtual_space_actual_committed_space(8 * K, 0);
aoqi@0 1077 test_virtual_space_actual_committed_space(8 * K, 4 * K);
aoqi@0 1078 test_virtual_space_actual_committed_space(8 * K, 8 * K);
aoqi@0 1079 test_virtual_space_actual_committed_space(12 * K, 0);
aoqi@0 1080 test_virtual_space_actual_committed_space(12 * K, 4 * K);
aoqi@0 1081 test_virtual_space_actual_committed_space(12 * K, 8 * K);
aoqi@0 1082 test_virtual_space_actual_committed_space(12 * K, 12 * K);
aoqi@0 1083 test_virtual_space_actual_committed_space(64 * K, 0);
aoqi@0 1084 test_virtual_space_actual_committed_space(64 * K, 32 * K);
aoqi@0 1085 test_virtual_space_actual_committed_space(64 * K, 64 * K);
aoqi@0 1086 test_virtual_space_actual_committed_space(2 * M, 0);
aoqi@0 1087 test_virtual_space_actual_committed_space(2 * M, 4 * K);
aoqi@0 1088 test_virtual_space_actual_committed_space(2 * M, 64 * K);
aoqi@0 1089 test_virtual_space_actual_committed_space(2 * M, 1 * M);
aoqi@0 1090 test_virtual_space_actual_committed_space(2 * M, 2 * M);
aoqi@0 1091 test_virtual_space_actual_committed_space(10 * M, 0);
aoqi@0 1092 test_virtual_space_actual_committed_space(10 * M, 4 * K);
aoqi@0 1093 test_virtual_space_actual_committed_space(10 * M, 8 * K);
aoqi@0 1094 test_virtual_space_actual_committed_space(10 * M, 1 * M);
aoqi@0 1095 test_virtual_space_actual_committed_space(10 * M, 2 * M);
aoqi@0 1096 test_virtual_space_actual_committed_space(10 * M, 5 * M);
aoqi@0 1097 test_virtual_space_actual_committed_space(10 * M, 10 * M);
aoqi@0 1098 }
aoqi@0 1099
aoqi@0 1100 static void test_virtual_space_disable_large_pages() {
aoqi@0 1101 if (!UseLargePages) {
aoqi@0 1102 return;
aoqi@0 1103 }
aoqi@0 1104 // These test cases verify that if we force VirtualSpace to disable large pages
aoqi@0 1105 test_virtual_space_actual_committed_space(10 * M, 0, Disable);
aoqi@0 1106 test_virtual_space_actual_committed_space(10 * M, 4 * K, Disable);
aoqi@0 1107 test_virtual_space_actual_committed_space(10 * M, 8 * K, Disable);
aoqi@0 1108 test_virtual_space_actual_committed_space(10 * M, 1 * M, Disable);
aoqi@0 1109 test_virtual_space_actual_committed_space(10 * M, 2 * M, Disable);
aoqi@0 1110 test_virtual_space_actual_committed_space(10 * M, 5 * M, Disable);
aoqi@0 1111 test_virtual_space_actual_committed_space(10 * M, 10 * M, Disable);
aoqi@0 1112
aoqi@0 1113 test_virtual_space_actual_committed_space(10 * M, 0, Reserve);
aoqi@0 1114 test_virtual_space_actual_committed_space(10 * M, 4 * K, Reserve);
aoqi@0 1115 test_virtual_space_actual_committed_space(10 * M, 8 * K, Reserve);
aoqi@0 1116 test_virtual_space_actual_committed_space(10 * M, 1 * M, Reserve);
aoqi@0 1117 test_virtual_space_actual_committed_space(10 * M, 2 * M, Reserve);
aoqi@0 1118 test_virtual_space_actual_committed_space(10 * M, 5 * M, Reserve);
aoqi@0 1119 test_virtual_space_actual_committed_space(10 * M, 10 * M, Reserve);
aoqi@0 1120
aoqi@0 1121 test_virtual_space_actual_committed_space(10 * M, 0, Commit);
aoqi@0 1122 test_virtual_space_actual_committed_space(10 * M, 4 * K, Commit);
aoqi@0 1123 test_virtual_space_actual_committed_space(10 * M, 8 * K, Commit);
aoqi@0 1124 test_virtual_space_actual_committed_space(10 * M, 1 * M, Commit);
aoqi@0 1125 test_virtual_space_actual_committed_space(10 * M, 2 * M, Commit);
aoqi@0 1126 test_virtual_space_actual_committed_space(10 * M, 5 * M, Commit);
aoqi@0 1127 test_virtual_space_actual_committed_space(10 * M, 10 * M, Commit);
aoqi@0 1128 }
aoqi@0 1129
aoqi@0 1130 static void test_virtual_space() {
aoqi@0 1131 test_virtual_space_actual_committed_space();
aoqi@0 1132 test_virtual_space_actual_committed_space_one_large_page();
aoqi@0 1133 test_virtual_space_disable_large_pages();
aoqi@0 1134 }
aoqi@0 1135 };
aoqi@0 1136
aoqi@0 1137 void TestVirtualSpace_test() {
aoqi@0 1138 TestVirtualSpace::test_virtual_space();
aoqi@0 1139 }
aoqi@0 1140
aoqi@0 1141 #endif // PRODUCT
aoqi@0 1142
aoqi@0 1143 #endif

mercurial