src/share/vm/runtime/virtualspace.cpp

Wed, 14 Oct 2020 17:44:48 +0800

author
aoqi
date
Wed, 14 Oct 2020 17:44:48 +0800
changeset 9931
fd44df5e3bc3
parent 9572
624a0741915c
permissions
-rw-r--r--

Merge

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

mercurial