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