Skip to content

Commit 2273f95

Browse files
AntonKozlovtstuefe
authored andcommitted
8234930: Use MAP_JIT when allocating pages for code cache on macOS
Reviewed-by: stuefe, iklam, burban
1 parent da2415f commit 2273f95

File tree

11 files changed

+85
-59
lines changed

11 files changed

+85
-59
lines changed

src/hotspot/os/aix/os_aix.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1958,7 +1958,7 @@ void os::pd_commit_memory_or_exit(char* addr, size_t size,
19581958
pd_commit_memory_or_exit(addr, size, exec, mesg);
19591959
}
19601960

1961-
bool os::pd_uncommit_memory(char* addr, size_t size) {
1961+
bool os::pd_uncommit_memory(char* addr, size_t size, bool exec) {
19621962
assert(is_aligned_to(addr, os::vm_page_size()),
19631963
"addr " PTR_FORMAT " not aligned to vm_page_size (" PTR_FORMAT ")",
19641964
p2i(addr), os::vm_page_size());
@@ -2035,7 +2035,7 @@ char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info
20352035
}
20362036

20372037
// Reserves and attaches a shared memory segment.
2038-
char* os::pd_reserve_memory(size_t bytes) {
2038+
char* os::pd_reserve_memory(size_t bytes, bool exec) {
20392039
// Always round to os::vm_page_size(), which may be larger than 4K.
20402040
bytes = align_up(bytes, os::vm_page_size());
20412041

@@ -2236,7 +2236,7 @@ char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, i
22362236

22372237
// Reserve memory at an arbitrary address, only if that area is
22382238
// available (and not reserved for something else).
2239-
char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes) {
2239+
char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec) {
22402240
char* addr = NULL;
22412241

22422242
// Always round to os::vm_page_size(), which may be larger than 4K.

src/hotspot/os/bsd/os_bsd.cpp

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,12 +1678,25 @@ static void warn_fail_commit_memory(char* addr, size_t size, bool exec,
16781678
// problem.
16791679
bool os::pd_commit_memory(char* addr, size_t size, bool exec) {
16801680
int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
1681-
#ifdef __OpenBSD__
1681+
#if defined(__OpenBSD__)
16821682
// XXX: Work-around mmap/MAP_FIXED bug temporarily on OpenBSD
16831683
Events::log(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(addr), p2i(addr+size), prot);
16841684
if (::mprotect(addr, size, prot) == 0) {
16851685
return true;
16861686
}
1687+
#elif defined(__APPLE__)
1688+
if (exec) {
1689+
// Do not replace MAP_JIT mappings, see JDK-8234930
1690+
if (::mprotect(addr, size, prot) == 0) {
1691+
return true;
1692+
}
1693+
} else {
1694+
uintptr_t res = (uintptr_t) ::mmap(addr, size, prot,
1695+
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
1696+
if (res != (uintptr_t) MAP_FAILED) {
1697+
return true;
1698+
}
1699+
}
16871700
#else
16881701
uintptr_t res = (uintptr_t) ::mmap(addr, size, prot,
16891702
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
@@ -1766,11 +1779,22 @@ char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info
17661779
}
17671780

17681781

1769-
bool os::pd_uncommit_memory(char* addr, size_t size) {
1770-
#ifdef __OpenBSD__
1782+
bool os::pd_uncommit_memory(char* addr, size_t size, bool exec) {
1783+
#if defined(__OpenBSD__)
17711784
// XXX: Work-around mmap/MAP_FIXED bug temporarily on OpenBSD
17721785
Events::log(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with PROT_NONE", p2i(addr), p2i(addr+size));
17731786
return ::mprotect(addr, size, PROT_NONE) == 0;
1787+
#elif defined(__APPLE__)
1788+
if (exec) {
1789+
if (::madvise(addr, size, MADV_FREE) != 0) {
1790+
return false;
1791+
}
1792+
return ::mprotect(addr, size, PROT_NONE) == 0;
1793+
} else {
1794+
uintptr_t res = (uintptr_t) ::mmap(addr, size, PROT_NONE,
1795+
MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0);
1796+
return res != (uintptr_t) MAP_FAILED;
1797+
}
17741798
#else
17751799
uintptr_t res = (uintptr_t) ::mmap(addr, size, PROT_NONE,
17761800
MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0);
@@ -1791,9 +1815,10 @@ bool os::remove_stack_guard_pages(char* addr, size_t size) {
17911815
// 'requested_addr' is only treated as a hint, the return value may or
17921816
// may not start from the requested address. Unlike Bsd mmap(), this
17931817
// function returns NULL to indicate failure.
1794-
static char* anon_mmap(char* requested_addr, size_t bytes) {
1818+
static char* anon_mmap(char* requested_addr, size_t bytes, bool exec) {
17951819
// MAP_FIXED is intentionally left out, to leave existing mappings intact.
1796-
const int flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS;
1820+
const int flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS
1821+
MACOS_ONLY(| (exec ? MAP_JIT : 0));
17971822

17981823
// Map reserved/uncommitted pages PROT_NONE so we fail early if we
17991824
// touch an uncommitted page. Otherwise, the read/write might
@@ -1807,8 +1832,8 @@ static int anon_munmap(char * addr, size_t size) {
18071832
return ::munmap(addr, size) == 0;
18081833
}
18091834

1810-
char* os::pd_reserve_memory(size_t bytes) {
1811-
return anon_mmap(NULL /* addr */, bytes);
1835+
char* os::pd_reserve_memory(size_t bytes, bool exec) {
1836+
return anon_mmap(NULL /* addr */, bytes, exec);
18121837
}
18131838

18141839
bool os::pd_release_memory(char* addr, size_t size) {
@@ -1893,7 +1918,7 @@ bool os::can_execute_large_page_memory() {
18931918

18941919
char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) {
18951920
assert(file_desc >= 0, "file_desc is not valid");
1896-
char* result = pd_attempt_reserve_memory_at(requested_addr, bytes);
1921+
char* result = pd_attempt_reserve_memory_at(requested_addr, bytes, !ExecMem);
18971922
if (result != NULL) {
18981923
if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == NULL) {
18991924
vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory"));
@@ -1905,7 +1930,7 @@ char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, i
19051930
// Reserve memory at an arbitrary address, only if that area is
19061931
// available (and not reserved for something else).
19071932

1908-
char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes) {
1933+
char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec) {
19091934
// Assert only that the size is a multiple of the page size, since
19101935
// that's all that mmap requires, and since that's all we really know
19111936
// about at this low abstraction level. If we need higher alignment,
@@ -1918,7 +1943,7 @@ char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes) {
19181943

19191944
// Bsd mmap allows caller to pass an address as hint; give it a try first,
19201945
// if kernel honors the hint then we can return immediately.
1921-
char * addr = anon_mmap(requested_addr, bytes);
1946+
char * addr = anon_mmap(requested_addr, bytes, exec);
19221947
if (addr == requested_addr) {
19231948
return requested_addr;
19241949
}

src/hotspot/os/linux/os_linux.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3272,7 +3272,7 @@ struct bitmask* os::Linux::_numa_nodes_ptr;
32723272
struct bitmask* os::Linux::_numa_interleave_bitmask;
32733273
struct bitmask* os::Linux::_numa_membind_bitmask;
32743274

3275-
bool os::pd_uncommit_memory(char* addr, size_t size) {
3275+
bool os::pd_uncommit_memory(char* addr, size_t size, bool exec) {
32763276
uintptr_t res = (uintptr_t) ::mmap(addr, size, PROT_NONE,
32773277
MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0);
32783278
return res != (uintptr_t) MAP_FAILED;
@@ -3516,7 +3516,7 @@ static int anon_munmap(char * addr, size_t size) {
35163516
return ::munmap(addr, size) == 0;
35173517
}
35183518

3519-
char* os::pd_reserve_memory(size_t bytes) {
3519+
char* os::pd_reserve_memory(size_t bytes, bool exec) {
35203520
return anon_mmap(NULL, bytes);
35213521
}
35223522

@@ -4197,7 +4197,7 @@ bool os::can_execute_large_page_memory() {
41974197

41984198
char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) {
41994199
assert(file_desc >= 0, "file_desc is not valid");
4200-
char* result = pd_attempt_reserve_memory_at(requested_addr, bytes);
4200+
char* result = pd_attempt_reserve_memory_at(requested_addr, bytes, !ExecMem);
42014201
if (result != NULL) {
42024202
if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == NULL) {
42034203
vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory"));
@@ -4209,7 +4209,7 @@ char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, i
42094209
// Reserve memory at an arbitrary address, only if that area is
42104210
// available (and not reserved for something else).
42114211

4212-
char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes) {
4212+
char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec) {
42134213
// Assert only that the size is a multiple of the page size, since
42144214
// that's all that mmap requires, and since that's all we really know
42154215
// about at this low abstraction level. If we need higher alignment,

src/hotspot/os/posix/os_posix.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,9 +336,9 @@ static char* chop_extra_memory(size_t size, size_t alignment, char* extra_base,
336336
// Multiple threads can race in this code, and can remap over each other with MAP_FIXED,
337337
// so on posix, unmap the section at the start and at the end of the chunk that we mapped
338338
// rather than unmapping and remapping the whole chunk to get requested alignment.
339-
char* os::reserve_memory_aligned(size_t size, size_t alignment) {
339+
char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec) {
340340
size_t extra_size = calculate_aligned_extra_size(size, alignment);
341-
char* extra_base = os::reserve_memory(extra_size);
341+
char* extra_base = os::reserve_memory(extra_size, exec);
342342
if (extra_base == NULL) {
343343
return NULL;
344344
}

src/hotspot/os/windows/os_windows.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3262,21 +3262,22 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi
32623262
return aligned_base;
32633263
}
32643264

3265-
char* os::reserve_memory_aligned(size_t size, size_t alignment) {
3265+
char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec) {
3266+
// exec can be ignored
32663267
return map_or_reserve_memory_aligned(size, alignment, -1 /* file_desc */);
32673268
}
32683269

32693270
char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int fd) {
32703271
return map_or_reserve_memory_aligned(size, alignment, fd);
32713272
}
32723273

3273-
char* os::pd_reserve_memory(size_t bytes) {
3274-
return pd_attempt_reserve_memory_at(NULL /* addr */, bytes);
3274+
char* os::pd_reserve_memory(size_t bytes, bool exec) {
3275+
return pd_attempt_reserve_memory_at(NULL /* addr */, bytes, exec);
32753276
}
32763277

32773278
// Reserve memory at an arbitrary address, only if that area is
32783279
// available (and not reserved for something else).
3279-
char* os::pd_attempt_reserve_memory_at(char* addr, size_t bytes) {
3280+
char* os::pd_attempt_reserve_memory_at(char* addr, size_t bytes, bool exec) {
32803281
assert((size_t)addr % os::vm_allocation_granularity() == 0,
32813282
"reserve alignment");
32823283
assert(bytes % os::vm_page_size() == 0, "reserve page size");
@@ -3471,7 +3472,7 @@ void os::pd_commit_memory_or_exit(char* addr, size_t size,
34713472
pd_commit_memory_or_exit(addr, size, exec, mesg);
34723473
}
34733474

3474-
bool os::pd_uncommit_memory(char* addr, size_t bytes) {
3475+
bool os::pd_uncommit_memory(char* addr, size_t bytes, bool exec) {
34753476
if (bytes == 0) {
34763477
// Don't bother the OS with noops.
34773478
return true;

src/hotspot/share/gc/z/zMarkStackAllocator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ ZMarkStackSpace::ZMarkStackSpace() :
4242

4343
// Reserve address space
4444
const size_t size = ZMarkStackSpaceLimit;
45-
const uintptr_t addr = (uintptr_t)os::reserve_memory(size, mtGC);
45+
const uintptr_t addr = (uintptr_t)os::reserve_memory(size, !ExecMem, mtGC);
4646
if (addr == 0) {
4747
log_error_pd(gc, marking)("Failed to reserve address space for mark stacks");
4848
return;

src/hotspot/share/memory/allocation.inline.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ template <class E>
5656
E* MmapArrayAllocator<E>::allocate_or_null(size_t length, MEMFLAGS flags) {
5757
size_t size = size_for(length);
5858

59-
char* addr = os::reserve_memory(size, flags);
59+
char* addr = os::reserve_memory(size, !ExecMem, flags);
6060
if (addr == NULL) {
6161
return NULL;
6262
}
@@ -73,7 +73,7 @@ template <class E>
7373
E* MmapArrayAllocator<E>::allocate(size_t length, MEMFLAGS flags) {
7474
size_t size = size_for(length);
7575

76-
char* addr = os::reserve_memory(size, flags);
76+
char* addr = os::reserve_memory(size, !ExecMem, flags);
7777
if (addr == NULL) {
7878
vm_exit_out_of_memory(size, OOM_MMAP_ERROR, "Allocator (reserve)");
7979
}

src/hotspot/share/memory/virtualspace.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -81,27 +81,27 @@ ReservedSpace::ReservedSpace(char* base, size_t size, size_t alignment,
8181
}
8282

8383
// Helper method
84-
static char* attempt_map_or_reserve_memory_at(char* base, size_t size, int fd) {
84+
static char* attempt_map_or_reserve_memory_at(char* base, size_t size, int fd, bool executable) {
8585
if (fd != -1) {
8686
return os::attempt_map_memory_to_file_at(base, size, fd);
8787
}
88-
return os::attempt_reserve_memory_at(base, size);
88+
return os::attempt_reserve_memory_at(base, size, executable);
8989
}
9090

9191
// Helper method
92-
static char* map_or_reserve_memory(size_t size, int fd) {
92+
static char* map_or_reserve_memory(size_t size, int fd, bool executable) {
9393
if (fd != -1) {
9494
return os::map_memory_to_file(size, fd);
9595
}
96-
return os::reserve_memory(size);
96+
return os::reserve_memory(size, executable);
9797
}
9898

9999
// Helper method
100-
static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fd) {
100+
static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fd, bool executable) {
101101
if (fd != -1) {
102102
return os::map_memory_to_file_aligned(size, alignment, fd);
103103
}
104-
return os::reserve_memory_aligned(size, alignment);
104+
return os::reserve_memory_aligned(size, alignment, executable);
105105
}
106106

107107
// Helper method
@@ -212,13 +212,13 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large,
212212
// important. If available space is not detected, return NULL.
213213

214214
if (requested_address != 0) {
215-
base = attempt_map_or_reserve_memory_at(requested_address, size, _fd_for_heap);
215+
base = attempt_map_or_reserve_memory_at(requested_address, size, _fd_for_heap, _executable);
216216
if (failed_to_reserve_as_requested(base, requested_address, size, false, _fd_for_heap != -1)) {
217217
// OS ignored requested address. Try different address.
218218
base = NULL;
219219
}
220220
} else {
221-
base = map_or_reserve_memory(size, _fd_for_heap);
221+
base = map_or_reserve_memory(size, _fd_for_heap, _executable);
222222
}
223223

224224
if (base == NULL) return;
@@ -230,7 +230,7 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large,
230230

231231
// Make sure that size is aligned
232232
size = align_up(size, alignment);
233-
base = map_or_reserve_memory_aligned(size, alignment, _fd_for_heap);
233+
base = map_or_reserve_memory_aligned(size, alignment, _fd_for_heap, _executable);
234234

235235
if (requested_address != 0 &&
236236
failed_to_reserve_as_requested(base, requested_address, size, false, _fd_for_heap != -1)) {
@@ -414,13 +414,13 @@ void ReservedHeapSpace::try_reserve_heap(size_t size,
414414
}
415415

416416
if (requested_address != 0) {
417-
base = attempt_map_or_reserve_memory_at(requested_address, size, _fd_for_heap);
417+
base = attempt_map_or_reserve_memory_at(requested_address, size, _fd_for_heap, executable());
418418
} else {
419419
// Optimistically assume that the OSes returns an aligned base pointer.
420420
// When reserving a large address range, most OSes seem to align to at
421421
// least 64K.
422422
// If the returned memory is not aligned we will release and retry.
423-
base = map_or_reserve_memory(size, _fd_for_heap);
423+
base = map_or_reserve_memory(size, _fd_for_heap, executable());
424424
}
425425
}
426426
if (base == NULL) { return; }
@@ -1024,7 +1024,7 @@ void VirtualSpace::shrink_by(size_t size) {
10241024
assert(middle_high_boundary() <= aligned_upper_new_high &&
10251025
aligned_upper_new_high + upper_needs <= upper_high_boundary(),
10261026
"must not shrink beyond region");
1027-
if (!os::uncommit_memory(aligned_upper_new_high, upper_needs)) {
1027+
if (!os::uncommit_memory(aligned_upper_new_high, upper_needs, _executable)) {
10281028
debug_only(warning("os::uncommit_memory failed"));
10291029
return;
10301030
} else {
@@ -1035,7 +1035,7 @@ void VirtualSpace::shrink_by(size_t size) {
10351035
assert(lower_high_boundary() <= aligned_middle_new_high &&
10361036
aligned_middle_new_high + middle_needs <= middle_high_boundary(),
10371037
"must not shrink beyond region");
1038-
if (!os::uncommit_memory(aligned_middle_new_high, middle_needs)) {
1038+
if (!os::uncommit_memory(aligned_middle_new_high, middle_needs, _executable)) {
10391039
debug_only(warning("os::uncommit_memory failed"));
10401040
return;
10411041
} else {
@@ -1046,7 +1046,7 @@ void VirtualSpace::shrink_by(size_t size) {
10461046
assert(low_boundary() <= aligned_lower_new_high &&
10471047
aligned_lower_new_high + lower_needs <= lower_high_boundary(),
10481048
"must not shrink beyond region");
1049-
if (!os::uncommit_memory(aligned_lower_new_high, lower_needs)) {
1049+
if (!os::uncommit_memory(aligned_lower_new_high, lower_needs, _executable)) {
10501050
debug_only(warning("os::uncommit_memory failed"));
10511051
return;
10521052
} else {

src/hotspot/share/runtime/os.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1645,8 +1645,8 @@ bool os::create_stack_guard_pages(char* addr, size_t bytes) {
16451645
return os::pd_create_stack_guard_pages(addr, bytes);
16461646
}
16471647

1648-
char* os::reserve_memory(size_t bytes, MEMFLAGS flags) {
1649-
char* result = pd_reserve_memory(bytes);
1648+
char* os::reserve_memory(size_t bytes, bool executable, MEMFLAGS flags) {
1649+
char* result = pd_reserve_memory(bytes, executable);
16501650
if (result != NULL) {
16511651
MemTracker::record_virtual_memory_reserve(result, bytes, CALLER_PC);
16521652
if (flags != mtOther) {
@@ -1657,8 +1657,8 @@ char* os::reserve_memory(size_t bytes, MEMFLAGS flags) {
16571657
return result;
16581658
}
16591659

1660-
char* os::attempt_reserve_memory_at(char* addr, size_t bytes) {
1661-
char* result = pd_attempt_reserve_memory_at(addr, bytes);
1660+
char* os::attempt_reserve_memory_at(char* addr, size_t bytes, bool executable) {
1661+
char* result = pd_attempt_reserve_memory_at(addr, bytes, executable);
16621662
if (result != NULL) {
16631663
MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
16641664
} else {
@@ -1697,16 +1697,16 @@ void os::commit_memory_or_exit(char* addr, size_t size, size_t alignment_hint,
16971697
MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC);
16981698
}
16991699

1700-
bool os::uncommit_memory(char* addr, size_t bytes) {
1700+
bool os::uncommit_memory(char* addr, size_t bytes, bool executable) {
17011701
bool res;
17021702
if (MemTracker::tracking_level() > NMT_minimal) {
17031703
Tracker tkr(Tracker::uncommit);
1704-
res = pd_uncommit_memory(addr, bytes);
1704+
res = pd_uncommit_memory(addr, bytes, executable);
17051705
if (res) {
17061706
tkr.record((address)addr, bytes);
17071707
}
17081708
} else {
1709-
res = pd_uncommit_memory(addr, bytes);
1709+
res = pd_uncommit_memory(addr, bytes, executable);
17101710
}
17111711
return res;
17121712
}

0 commit comments

Comments
 (0)