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