src/share/vm/runtime/virtualspace.cpp

Wed, 27 Apr 2016 01:25:04 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:25:04 +0800
changeset 0
f90c822e73f8
child 371
ce9746da18a3
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/
changeset: 6782:28b50d07f6f8
tag: jdk8u25-b17

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

mercurial