1 /*
2 * Copyright (c) 1997, 2025, 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 "logging/log.hpp"
26 #include "memory/memoryReserver.hpp"
27 #include "oops/compressedOops.hpp"
28 #include "oops/markWord.hpp"
29 #include "runtime/globals_extension.hpp"
30 #include "runtime/java.hpp"
31 #include "runtime/os.inline.hpp"
32 #include "utilities/formatBuffer.hpp"
33 #include "utilities/globalDefinitions.hpp"
34 #include "utilities/powerOfTwo.hpp"
35
36 static void sanity_check_size_and_alignment(size_t size, size_t alignment) {
37 assert(size > 0, "Precondition");
38
39 DEBUG_ONLY(const size_t granularity = os::vm_allocation_granularity());
40 assert(is_aligned(size, granularity), "size not aligned to os::vm_allocation_granularity()");
41
42 assert(alignment >= granularity, "Must be set");
43 assert(is_power_of_2(alignment), "not a power of 2");
44 assert(is_aligned(alignment, granularity), "alignment not aligned to os::vm_allocation_granularity()");
45 }
46
47 static void sanity_check_page_size(size_t page_size) {
48 assert(page_size >= os::vm_page_size(), "Invalid page size");
49 assert(is_power_of_2(page_size), "Invalid page size");
50 }
51
52 static void sanity_check_arguments(size_t size, size_t alignment, size_t page_size) {
53 sanity_check_size_and_alignment(size, alignment);
54 sanity_check_page_size(page_size);
55 }
56
57 static bool large_pages_requested() {
58 return UseLargePages &&
59 (!FLAG_IS_DEFAULT(UseLargePages) || !FLAG_IS_DEFAULT(LargePageSizeInBytes));
60 }
61
62 static void log_on_large_pages_failure(char* req_addr, size_t bytes) {
63 if (large_pages_requested()) {
64 // Compressed oops logging.
65 log_debug(gc, heap, coops)("Reserve regular memory without large pages");
66 // JVM style warning that we did not succeed in using large pages.
67 warning("Failed to reserve and commit memory using large pages. "
68 "req_addr: " PTR_FORMAT " bytes: %zu",
69 p2i(req_addr), bytes);
70 }
71 }
72
73 static bool use_explicit_large_pages(size_t page_size) {
74 return !os::can_commit_large_page_memory() &&
75 page_size != os::vm_page_size();
76 }
77
78 static char* reserve_memory_inner(char* requested_address,
79 size_t size,
80 size_t alignment,
81 bool exec,
82 MemTag mem_tag) {
83 // If the memory was requested at a particular address, use
84 // os::attempt_reserve_memory_at() to avoid mapping over something
85 // important. If the reservation fails, return null.
86 if (requested_address != nullptr) {
87 assert(is_aligned(requested_address, alignment),
88 "Requested address " PTR_FORMAT " must be aligned to %zu",
89 p2i(requested_address), alignment);
90 return os::attempt_reserve_memory_at(requested_address, size, mem_tag, exec);
91 }
92
93 // Optimistically assume that the OS returns an aligned base pointer.
94 // When reserving a large address range, most OSes seem to align to at
95 // least 64K.
96 char* base = os::reserve_memory(size, mem_tag, exec);
97 if (is_aligned(base, alignment)) {
98 return base;
99 }
100
101 // Base not aligned, retry.
102 if (!os::release_memory(base, size)) {
103 fatal("os::release_memory failed");
104 }
105
106 // Map using the requested alignment.
107 return os::reserve_memory_aligned(size, alignment, mem_tag, exec);
108 }
109
110 ReservedSpace MemoryReserver::reserve_memory(char* requested_address,
111 size_t size,
112 size_t alignment,
113 size_t page_size,
114 bool exec,
115 MemTag mem_tag) {
116 char* base = reserve_memory_inner(requested_address, size, alignment, exec, mem_tag);
117
118 if (base != nullptr) {
119 return ReservedSpace(base, size, alignment, page_size, exec, false /* special */);
120 }
121
122 // Failed
123 return {};
124 }
125
126 ReservedSpace MemoryReserver::reserve_memory_special(char* requested_address,
127 size_t size,
128 size_t alignment,
129 size_t page_size,
130 bool exec) {
131 log_trace(pagesize)("Attempt special mapping: size: " EXACTFMT ", alignment: " EXACTFMT,
132 EXACTFMTARGS(size),
133 EXACTFMTARGS(alignment));
134
135 char* base = os::reserve_memory_special(size, alignment, page_size, requested_address, exec);
136
137 if (base != nullptr) {
138 assert(is_aligned(base, alignment),
139 "reserve_memory_special() returned an unaligned address, "
140 "base: " PTR_FORMAT " alignment: 0x%zx",
141 p2i(base), alignment);
142
143 return ReservedSpace(base, size, alignment, page_size, exec, true /* special */);
144 }
145
146 // Failed
147 return {};
148 }
149
150 ReservedSpace MemoryReserver::reserve(char* requested_address,
151 size_t size,
152 size_t alignment,
153 size_t page_size,
154 bool executable,
155 MemTag mem_tag) {
156 sanity_check_arguments(size, alignment, page_size);
157
158 // Reserve the memory.
159
160 // There are basically three different cases that we need to handle:
161 // 1. Mapping backed by a file
162 // 2. Mapping backed by explicit large pages
163 // 3. Mapping backed by normal pages or transparent huge pages
164 // The first two have restrictions that requires the whole mapping to be
165 // committed up front. To record this the ReservedSpace is marked 'special'.
166
167 // == Case 1 ==
168 // This case is contained within the HeapReserver
169
170 // == Case 2 ==
171 if (use_explicit_large_pages(page_size)) {
172 // System can't commit large pages i.e. use transparent huge pages and
173 // the caller requested large pages. To satisfy this request we use
174 // explicit large pages and these have to be committed up front to ensure
175 // no reservations are lost.
176 do {
177 ReservedSpace reserved = reserve_memory_special(requested_address, size, alignment, page_size, executable);
178 if (reserved.is_reserved()) {
179 // Successful reservation using large pages.
180 return reserved;
181 }
182 page_size = os::page_sizes().next_smaller(page_size);
183 } while (page_size > os::vm_page_size());
184
185 // Failed to reserve explicit large pages, do proper logging.
186 log_on_large_pages_failure(requested_address, size);
187 // Now fall back to normal reservation.
188 assert(page_size == os::vm_page_size(), "inv");
189 }
190
191 // == Case 3 ==
192 return reserve_memory(requested_address, size, alignment, page_size, executable, mem_tag);
193 }
194
195 ReservedSpace MemoryReserver::reserve(char* requested_address,
196 size_t size,
197 size_t alignment,
198 size_t page_size,
199 MemTag mem_tag) {
200 return reserve(requested_address,
201 size,
202 alignment,
203 page_size,
204 !ExecMem,
205 mem_tag);
206 }
207
208
209 ReservedSpace MemoryReserver::reserve(size_t size,
210 size_t alignment,
211 size_t page_size,
212 MemTag mem_tag) {
213 return reserve(nullptr /* requested_address */,
214 size,
215 alignment,
216 page_size,
217 mem_tag);
218 }
219
220 ReservedSpace MemoryReserver::reserve(size_t size,
221 MemTag mem_tag) {
222 // Want to use large pages where possible. If the size is
223 // not large page aligned the mapping will be a mix of
224 // large and normal pages.
225 size_t page_size = os::page_size_for_region_unaligned(size, 1);
226 size_t alignment = os::vm_allocation_granularity();
227
228 return reserve(size,
229 alignment,
230 page_size,
231 mem_tag);
232 }
233
234 bool MemoryReserver::release(const ReservedSpace& reserved) {
235 assert(reserved.is_reserved(), "Precondition");
236
237 if (reserved.special()) {
238 return os::release_memory_special(reserved.base(), reserved.size());
239 } else {
240 return os::release_memory(reserved.base(), reserved.size());
241 }
242 }
243
244 static char* map_memory_to_file(char* requested_address,
245 size_t size,
246 size_t alignment,
247 int fd,
248 MemTag mem_tag) {
249 // If the memory was requested at a particular address, use
250 // os::attempt_reserve_memory_at() to avoid mapping over something
251 // important. If the reservation fails, return null.
252 if (requested_address != nullptr) {
253 assert(is_aligned(requested_address, alignment),
254 "Requested address " PTR_FORMAT " must be aligned to %zu",
255 p2i(requested_address), alignment);
256 return os::attempt_map_memory_to_file_at(requested_address, size, fd, mem_tag);
257 }
258
259 // Optimistically assume that the OS returns an aligned base pointer.
260 // When reserving a large address range, most OSes seem to align to at
261 // least 64K.
262 char* base = os::map_memory_to_file(size, fd, mem_tag);
263 if (is_aligned(base, alignment)) {
264 return base;
265 }
266
267
268 // Base not aligned, retry.
269 if (!os::unmap_memory(base, size)) {
270 fatal("os::unmap_memory failed");
271 }
272
273 // Map using the requested alignment.
274 return os::map_memory_to_file_aligned(size, alignment, fd, mem_tag);
275 }
276
277 ReservedSpace FileMappedMemoryReserver::reserve(char* requested_address,
278 size_t size,
279 size_t alignment,
280 int fd,
281 MemTag mem_tag) {
282 sanity_check_size_and_alignment(size, alignment);
283
284 char* base = map_memory_to_file(requested_address, size, alignment, fd, mem_tag);
285
286 if (base != nullptr) {
287 return ReservedSpace(base, size, alignment, os::vm_page_size(), !ExecMem, true /* special */);
288 }
289
290 // Failed
291 return {};
292 }
293
294 ReservedSpace CodeMemoryReserver::reserve(size_t size,
295 size_t alignment,
296 size_t page_size) {
297 return MemoryReserver::reserve(nullptr /* requested_address */,
298 size,
299 alignment,
300 page_size,
301 ExecMem,
302 mtCode);
303 }
304
305 ReservedHeapSpace HeapReserver::Instance::reserve_uncompressed_oops_heap(size_t size,
306 size_t alignment,
307 size_t page_size) {
308 ReservedSpace reserved = reserve_memory(size, alignment, page_size);
309
310 if (reserved.is_reserved()) {
311 return ReservedHeapSpace(reserved, 0 /* noaccess_prefix */);
312 }
313
314 // Failed
315 return {};
316 }
317
318
319 static int maybe_create_file(const char* heap_allocation_directory) {
320 if (heap_allocation_directory == nullptr) {
321 return -1;
322 }
323
324 int fd = os::create_file_for_heap(heap_allocation_directory);
325 if (fd == -1) {
326 vm_exit_during_initialization(
327 err_msg("Could not create file for Heap at location %s", heap_allocation_directory));
328 }
329
330 return fd;
331 }
332
333 HeapReserver::Instance::Instance(const char* heap_allocation_directory)
334 : _fd(maybe_create_file(heap_allocation_directory)) {}
335
336 HeapReserver::Instance::~Instance() {
337 if (_fd != -1) {
338 ::close(_fd);
339 }
340 }
341
342 ReservedSpace HeapReserver::Instance::reserve_memory(size_t size,
343 size_t alignment,
344 size_t page_size,
345 char* requested_address) {
346
347 // There are basically three different cases that we need to handle below:
348 // 1. Mapping backed by a file
349 // 2. Mapping backed by explicit large pages
350 // 3. Mapping backed by normal pages or transparent huge pages
351 // The first two have restrictions that requires the whole mapping to be
352 // committed up front. To record this the ReservedSpace is marked 'special'.
353
354 // == Case 1 ==
355 if (_fd != -1) {
356 // When there is a backing file directory for this space then whether
357 // large pages are allocated is up to the filesystem of the backing file.
358 // So UseLargePages is not taken into account for this reservation.
359 //
360 // If requested, let the user know that explicit large pages can't be used.
361 if (use_explicit_large_pages(page_size) && large_pages_requested()) {
362 log_debug(gc, heap)("Cannot allocate explicit large pages for Java Heap when AllocateHeapAt option is set.");
363 }
364
365 // Always return, not possible to fall back to reservation not using a file.
366 return FileMappedMemoryReserver::reserve(requested_address, size, alignment, _fd, mtJavaHeap);
367 }
368
369 // == Case 2 & 3 ==
370 return MemoryReserver::reserve(requested_address, size, alignment, page_size, mtJavaHeap);
371 }
372
373 // Compressed oop support is not relevant in 32bit builds.
374 #ifdef _LP64
375
376 void HeapReserver::Instance::release(const ReservedSpace& reserved) {
377 if (reserved.is_reserved()) {
378 if (_fd == -1) {
379 if (reserved.special()) {
380 os::release_memory_special(reserved.base(), reserved.size());
381 } else{
382 os::release_memory(reserved.base(), reserved.size());
383 }
384 } else {
385 os::unmap_memory(reserved.base(), reserved.size());
386 }
387 }
388 }
389
390 // Tries to allocate memory of size 'size' at address requested_address with alignment 'alignment'.
391 // Does not check whether the reserved memory actually is at requested_address, as the memory returned
392 // might still fulfill the wishes of the caller.
393 // Assures the memory is aligned to 'alignment'.
394 ReservedSpace HeapReserver::Instance::try_reserve_memory(size_t size,
395 size_t alignment,
396 size_t page_size,
397 char* requested_address) {
398 // Try to reserve the memory for the heap.
399 log_trace(gc, heap, coops)("Trying to allocate at address " PTR_FORMAT
400 " heap of size 0x%zx",
401 p2i(requested_address),
402 size);
403
404 ReservedSpace reserved = reserve_memory(size, alignment, page_size, requested_address);
405
406 if (reserved.is_reserved()) {
407 // Check alignment constraints.
408 assert(reserved.alignment() == alignment, "Unexpected");
409 assert(is_aligned(reserved.base(), alignment), "Unexpected");
410 return reserved;
411 }
412
413 // Failed
414 return {};
415 }
416
417 ReservedSpace HeapReserver::Instance::try_reserve_range(char *highest_start,
418 char *lowest_start,
419 size_t attach_point_alignment,
420 char *aligned_heap_base_min_address,
421 char *upper_bound,
422 size_t size,
423 size_t alignment,
424 size_t page_size) {
425 assert(is_aligned(highest_start, attach_point_alignment), "precondition");
426 assert(is_aligned(lowest_start, attach_point_alignment), "precondition");
427
428 const size_t attach_range = pointer_delta(highest_start, lowest_start, sizeof(char));
429 const size_t num_attempts_possible = (attach_range / attach_point_alignment) + 1;
430 const size_t num_attempts_to_try = MIN2((size_t)HeapSearchSteps, num_attempts_possible);
431 const size_t num_intervals = num_attempts_to_try - 1;
432 const size_t stepsize = num_intervals == 0 ? 0 : align_down(attach_range / num_intervals, attach_point_alignment);
433
434 for (size_t i = 0; i < num_attempts_to_try; ++i) {
435 char* const attach_point = highest_start - stepsize * i;
436 ReservedSpace reserved = try_reserve_memory(size, alignment, page_size, attach_point);
437
438 if (reserved.is_reserved()) {
439 if (reserved.base() >= aligned_heap_base_min_address &&
440 size <= (uintptr_t)(upper_bound - reserved.base())) {
441 // Got a successful reservation.
442 return reserved;
443 }
444
445 release(reserved);
446 }
447 }
448
449 // Failed
450 return {};
451 }
452
453 #define SIZE_64K ((uint64_t) UCONST64( 0x10000))
454 #define SIZE_256M ((uint64_t) UCONST64( 0x10000000))
455 #define SIZE_32G ((uint64_t) UCONST64( 0x800000000))
456
457 // Helper for heap allocation. Returns an array with addresses
458 // (OS-specific) which are suited for disjoint base mode. Array is
459 // null terminated.
460 static char** get_attach_addresses_for_disjoint_mode() {
461 static uint64_t addresses[] = {
462 2 * SIZE_32G,
463 3 * SIZE_32G,
464 4 * SIZE_32G,
465 8 * SIZE_32G,
466 10 * SIZE_32G,
467 1 * SIZE_64K * SIZE_32G,
468 2 * SIZE_64K * SIZE_32G,
469 3 * SIZE_64K * SIZE_32G,
470 4 * SIZE_64K * SIZE_32G,
471 16 * SIZE_64K * SIZE_32G,
472 32 * SIZE_64K * SIZE_32G,
473 34 * SIZE_64K * SIZE_32G,
474 0
475 };
476
477 // Sort out addresses smaller than HeapBaseMinAddress. This assumes
478 // the array is sorted.
479 uint i = 0;
480 while (addresses[i] != 0 &&
481 (addresses[i] < OopEncodingHeapMax || addresses[i] < HeapBaseMinAddress)) {
482 i++;
483 }
484 uint start = i;
485
486 // Avoid more steps than requested.
487 i = 0;
488 while (addresses[start+i] != 0) {
489 if (i == HeapSearchSteps) {
490 addresses[start+i] = 0;
491 break;
492 }
493 i++;
494 }
495
496 return (char**) &addresses[start];
497 }
498
499 // Create protection page at the beginning of the space.
500 static ReservedSpace establish_noaccess_prefix(const ReservedSpace& reserved, size_t noaccess_prefix) {
501 assert(reserved.alignment() >= os::vm_page_size(), "must be at least page size big");
502 assert(reserved.is_reserved(), "should only be called on a reserved memory area");
503
504 if (reserved.end() > (char *)OopEncodingHeapMax) {
505 if (true
506 WIN64_ONLY(&& !UseLargePages)
507 AIX_ONLY(&& (os::Aix::supports_64K_mmap_pages() || os::vm_page_size() == 4*K))) {
508 // Protect memory at the base of the allocated region.
509 if (!os::protect_memory(reserved.base(), noaccess_prefix, os::MEM_PROT_NONE, reserved.special())) {
510 fatal("cannot protect protection page");
511 }
512 log_debug(gc, heap, coops)("Protected page at the reserved heap base: "
513 PTR_FORMAT " / %zd bytes",
514 p2i(reserved.base()),
515 noaccess_prefix);
516 assert(CompressedOops::use_implicit_null_checks() == true, "not initialized?");
517 } else {
518 CompressedOops::set_use_implicit_null_checks(false);
519 }
520 }
521
522 return reserved.last_part(noaccess_prefix);
523 }
524
525 ReservedHeapSpace HeapReserver::Instance::reserve_compressed_oops_heap(const size_t size, size_t alignment, size_t page_size) {
526 const size_t noaccess_prefix_size = lcm(os::vm_page_size(), alignment);
527 const size_t granularity = os::vm_allocation_granularity();
528
529 assert(size + noaccess_prefix_size <= OopEncodingHeapMax, "can not allocate compressed oop heap for this size");
530 assert(is_aligned(size, granularity), "size not aligned to os::vm_allocation_granularity()");
531
532 assert(alignment >= os::vm_page_size(), "alignment too small");
533 assert(is_aligned(alignment, granularity), "alignment not aligned to os::vm_allocation_granularity()");
534 assert(is_power_of_2(alignment), "not a power of 2");
535
536 // The necessary attach point alignment for generated wish addresses.
537 // This is needed to increase the chance of attaching for mmap and shmat.
538 // AIX is the only platform that uses System V shm for reserving virtual memory.
539 // In this case, the required alignment of the allocated size (64K) and the alignment
540 // of possible start points of the memory region (256M) differ.
541 // This is not reflected by os_allocation_granularity().
542 // The logic here is dual to the one in pd_reserve_memory in os_aix.cpp
543 const size_t os_attach_point_alignment =
544 AIX_ONLY(os::vm_page_size() == 4*K ? 4*K : 256*M)
545 NOT_AIX(os::vm_allocation_granularity());
546
547 const size_t attach_point_alignment = lcm(alignment, os_attach_point_alignment);
548
549 char* aligned_heap_base_min_address = align_up((char*)HeapBaseMinAddress, alignment);
550 size_t noaccess_prefix = ((aligned_heap_base_min_address + size) > (char*)OopEncodingHeapMax) ?
551 noaccess_prefix_size : 0;
552
553 ReservedSpace reserved{};
554
555 // Attempt to alloc at user-given address.
556 if (!FLAG_IS_DEFAULT(HeapBaseMinAddress)) {
557 reserved = try_reserve_memory(size + noaccess_prefix, alignment, page_size, aligned_heap_base_min_address);
558 if (reserved.base() != aligned_heap_base_min_address) { // Enforce this exact address.
559 release(reserved);
560 reserved = {};
561 }
562 }
563
564 // Keep heap at HeapBaseMinAddress.
565 if (!reserved.is_reserved()) {
566
567 // Try to allocate the heap at addresses that allow efficient oop compression.
568 // Different schemes are tried, in order of decreasing optimization potential.
569 //
570 // For this, try_reserve_heap() is called with the desired heap base addresses.
571 // A call into the os layer to allocate at a given address can return memory
572 // at a different address than requested. Still, this might be memory at a useful
573 // address. try_reserve_heap() always returns this allocated memory, as only here
574 // the criteria for a good heap are checked.
575
576 // Attempt to allocate so that we can run without base and scale (32-Bit unscaled compressed oops).
577 // Give it several tries from top of range to bottom.
578 if (aligned_heap_base_min_address + size <= (char *)UnscaledOopHeapMax) {
579
580 // Calc address range within we try to attach (range of possible start addresses).
581 char* const highest_start = align_down((char *)UnscaledOopHeapMax - size, attach_point_alignment);
582 char* const lowest_start = align_up(aligned_heap_base_min_address, attach_point_alignment);
583 reserved = try_reserve_range(highest_start, lowest_start, attach_point_alignment,
584 aligned_heap_base_min_address, (char *)UnscaledOopHeapMax, size, alignment, page_size);
585 }
586
587 // zerobased: Attempt to allocate in the lower 32G.
588 char *zerobased_max = (char *)OopEncodingHeapMax;
589
590 // Give it several tries from top of range to bottom.
591 if (aligned_heap_base_min_address + size <= zerobased_max && // Zerobased theoretical possible.
592 ((!reserved.is_reserved()) || // No previous try succeeded.
593 (reserved.end() > zerobased_max))) { // Unscaled delivered an arbitrary address.
594
595 // Release previous reservation
596 release(reserved);
597
598 // Calc address range within we try to attach (range of possible start addresses).
599 char *const highest_start = align_down(zerobased_max - size, attach_point_alignment);
600 // Need to be careful about size being guaranteed to be less
601 // than UnscaledOopHeapMax due to type constraints.
602 char *lowest_start = aligned_heap_base_min_address;
603 uint64_t unscaled_end = UnscaledOopHeapMax - size;
604 if (unscaled_end < UnscaledOopHeapMax) { // unscaled_end wrapped if size is large
605 lowest_start = MAX2(lowest_start, (char*)unscaled_end);
606 }
607 lowest_start = align_up(lowest_start, attach_point_alignment);
608 reserved = try_reserve_range(highest_start, lowest_start, attach_point_alignment,
609 aligned_heap_base_min_address, zerobased_max, size, alignment, page_size);
610 }
611
612 // Now we go for heaps with base != 0. We need a noaccess prefix to efficiently
613 // implement null checks.
614 noaccess_prefix = noaccess_prefix_size;
615
616 // Try to attach at addresses that are aligned to OopEncodingHeapMax. Disjointbase mode.
617 char** addresses = get_attach_addresses_for_disjoint_mode();
618 int i = 0;
619 while ((addresses[i] != nullptr) && // End of array not yet reached.
620 ((!reserved.is_reserved()) || // No previous try succeeded.
621 (reserved.end() > zerobased_max && // Not zerobased or unscaled address.
622 // Not disjoint address.
623 !CompressedOops::is_disjoint_heap_base_address((address)reserved.base())))) {
624
625 // Release previous reservation
626 release(reserved);
627
628 char* const attach_point = addresses[i];
629 assert(attach_point >= aligned_heap_base_min_address, "Flag support broken");
630 reserved = try_reserve_memory(size + noaccess_prefix, alignment, page_size, attach_point);
631 i++;
632 }
633
634 // Last, desperate try without any placement.
635 if (!reserved.is_reserved()) {
636 log_trace(gc, heap, coops)("Trying to allocate at address null heap of size 0x%zx", size + noaccess_prefix);
637 assert(alignment >= os::vm_page_size(), "Unexpected");
638 reserved = reserve_memory(size + noaccess_prefix, alignment, page_size);
639 }
640 }
641
642 // No more reserve attempts
643
644 if (reserved.is_reserved()) {
645 // Successfully found and reserved memory for the heap.
646
647 if (reserved.size() > size) {
648 // We reserved heap memory with a noaccess prefix.
649
650 assert(reserved.size() == size + noaccess_prefix, "Prefix should be included");
651 // It can happen we get a zerobased/unscaled heap with noaccess prefix,
652 // if we had to try at arbitrary address.
653 reserved = establish_noaccess_prefix(reserved, noaccess_prefix);
654 assert(reserved.size() == size, "Prefix should be gone");
655 return ReservedHeapSpace(reserved, noaccess_prefix);
656 }
657
658 // We reserved heap memory without a noaccess prefix.
659 return ReservedHeapSpace(reserved, 0 /* noaccess_prefix */);
660 }
661
662 // Failed
663 return {};
664 }
665
666 #endif // _LP64
667
668 ReservedHeapSpace HeapReserver::Instance::reserve_heap(size_t size, size_t alignment, size_t page_size) {
669 if (UseCompressedOops) {
670 #ifdef _LP64
671 return reserve_compressed_oops_heap(size, alignment, page_size);
672 #endif
673 } else {
674 return reserve_uncompressed_oops_heap(size, alignment, page_size);
675 }
676 }
677
678 ReservedHeapSpace HeapReserver::reserve(size_t size, size_t alignment, size_t page_size, const char* heap_allocation_directory) {
679 sanity_check_arguments(size, alignment, page_size);
680
681 assert(alignment != 0, "Precondition");
682 assert(is_aligned(size, alignment), "Precondition");
683
684 Instance instance(heap_allocation_directory);
685
686 return instance.reserve_heap(size, alignment, page_size);
687 }