diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index 64face5268a..9d161bc9dab 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -2269,7 +2269,7 @@ void os::pd_commit_memory_or_exit(char* addr, size_t size, pd_commit_memory_or_exit(addr, size, exec, mesg); } -bool os::pd_uncommit_memory(char* addr, size_t size) { +bool os::pd_uncommit_memory(char* addr, size_t size, bool exec) { assert(is_aligned_to(addr, os::vm_page_size()), "addr " PTR_FORMAT " not aligned to vm_page_size (" PTR_FORMAT ")", p2i(addr), os::vm_page_size()); @@ -2347,7 +2347,7 @@ char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info // Reserves and attaches a shared memory segment. // Will assert if a wish address is given and could not be obtained. -char* os::pd_reserve_memory(size_t bytes, char* requested_addr, size_t alignment_hint) { +char* os::pd_reserve_memory(size_t bytes, char* requested_addr, size_t alignment_hint, bool executable) { // All other Unices do a mmap(MAP_FIXED) if the addr is given, // thereby clobbering old mappings at that place. That is probably diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index 943133e27e5..5b049c15d04 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -1907,12 +1907,16 @@ static void warn_fail_commit_memory(char* addr, size_t size, bool exec, // problem. bool os::pd_commit_memory(char* addr, size_t size, bool exec) { int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; -#ifdef __OpenBSD__ +#if defined(__OpenBSD__) // XXX: Work-around mmap/MAP_FIXED bug temporarily on OpenBSD Events::log(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(addr), p2i(addr+size), prot); if (::mprotect(addr, size, prot) == 0) { return true; } +#elif defined(__APPLE__) + if (::mprotect(addr, size, prot) == 0) { + return true; + } #else uintptr_t res = (uintptr_t) ::mmap(addr, size, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); @@ -1995,11 +1999,22 @@ char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info } -bool os::pd_uncommit_memory(char* addr, size_t size) { -#ifdef __OpenBSD__ +bool os::pd_uncommit_memory(char* addr, size_t size, bool exec) { +#if defined(__OpenBSD__) // XXX: Work-around mmap/MAP_FIXED bug temporarily on OpenBSD Events::log(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with PROT_NONE", p2i(addr), p2i(addr+size)); return ::mprotect(addr, size, PROT_NONE) == 0; +#elif defined(__APPLE__) + if (exec) { + if (::madvise(addr, size, MADV_FREE) != 0) { + return false; + } + return ::mprotect(addr, size, PROT_NONE) == 0; + } else { + uintptr_t res = (uintptr_t) ::mmap(addr, size, PROT_NONE, + MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0); + return res != (uintptr_t) MAP_FAILED; + } #else uintptr_t res = (uintptr_t) ::mmap(addr, size, PROT_NONE, MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0); @@ -2014,7 +2029,7 @@ bool os::pd_create_stack_guard_pages(char* addr, size_t size) { // If this is a growable mapping, remove the guard pages entirely by // munmap()ping them. If not, just call uncommit_memory(). bool os::remove_stack_guard_pages(char* addr, size_t size) { - return os::uncommit_memory(addr, size); + return os::uncommit_memory(addr, size, !ExecMem); } // If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory @@ -2023,11 +2038,17 @@ bool os::remove_stack_guard_pages(char* addr, size_t size) { // 'requested_addr' is only treated as a hint, the return value may or // may not start from the requested address. Unlike Bsd mmap(), this // function returns NULL to indicate failure. -static char* anon_mmap(char* requested_addr, size_t bytes, bool fixed) { +static char* anon_mmap(char* requested_addr, size_t bytes, bool fixed, bool executable) { char * addr; int flags; flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS; +#ifdef __APPLE__ + if (executable) { + guarantee(!fixed, "MAP_JIT (for execute) is incompatible with MAP_FIXED"); + flags |= MAP_JIT; + } +#endif if (fixed) { assert((uintptr_t)requested_addr % os::Bsd::page_size() == 0, "unaligned address"); flags |= MAP_FIXED; @@ -2047,8 +2068,9 @@ static int anon_munmap(char * addr, size_t size) { } char* os::pd_reserve_memory(size_t bytes, char* requested_addr, - size_t alignment_hint) { - return anon_mmap(requested_addr, bytes, (requested_addr != NULL)); + size_t alignment_hint, + bool executable) { + return anon_mmap(requested_addr, bytes, (requested_addr != NULL), executable); } bool os::pd_release_memory(char* addr, size_t size) { @@ -2158,7 +2180,7 @@ char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) { // Bsd mmap allows caller to pass an address as hint; give it a try first, // if kernel honors the hint then we can return immediately. - char * addr = anon_mmap(requested_addr, bytes, false); + char * addr = anon_mmap(requested_addr, bytes, false/*fixed*/, false/*executable*/); if (addr == requested_addr) { return requested_addr; } diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index be6dfef313a..216e39384dc 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -3456,7 +3456,7 @@ struct bitmask* os::Linux::_numa_nodes_ptr; struct bitmask* os::Linux::_numa_interleave_bitmask; struct bitmask* os::Linux::_numa_membind_bitmask; -bool os::pd_uncommit_memory(char* addr, size_t size) { +bool os::pd_uncommit_memory(char* addr, size_t size, bool exec) { uintptr_t res = (uintptr_t) ::mmap(addr, size, PROT_NONE, MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0); return res != (uintptr_t) MAP_FAILED; @@ -3641,7 +3641,7 @@ bool os::remove_stack_guard_pages(char* addr, size_t size) { return ::munmap(addr, size) == 0; } - return os::uncommit_memory(addr, size); + return os::uncommit_memory(addr, size, !ExecMem); } // If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory @@ -3716,7 +3716,8 @@ static int anon_munmap(char * addr, size_t size) { } char* os::pd_reserve_memory(size_t bytes, char* requested_addr, - size_t alignment_hint) { + size_t alignment_hint, + bool executable) { return anon_mmap(requested_addr, bytes, (requested_addr != NULL)); } diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index e687521022e..332e99ca014 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -3105,7 +3105,7 @@ char* os::reserve_memory_aligned(size_t size, size_t alignment, int file_desc) { return aligned_base; } -char* os::pd_reserve_memory(size_t bytes, char* addr, size_t alignment_hint) { +char* os::pd_reserve_memory(size_t bytes, char* addr, size_t alignment_hint, bool executable) { assert((size_t)addr % os::vm_allocation_granularity() == 0, "reserve alignment"); assert(bytes % os::vm_page_size() == 0, "reserve page size"); @@ -3308,7 +3308,7 @@ void os::pd_commit_memory_or_exit(char* addr, size_t size, pd_commit_memory_or_exit(addr, size, exec, mesg); } -bool os::pd_uncommit_memory(char* addr, size_t bytes) { +bool os::pd_uncommit_memory(char* addr, size_t bytes, bool exec) { if (bytes == 0) { // Don't bother the OS with noops. return true; @@ -3327,7 +3327,7 @@ bool os::pd_create_stack_guard_pages(char* addr, size_t size) { } bool os::remove_stack_guard_pages(char* addr, size_t size) { - return os::uncommit_memory(addr, size); + return os::uncommit_memory(addr, size, !ExecMem); } static bool protect_pages_individually(char* addr, size_t bytes, unsigned int p, DWORD *old_status) { diff --git a/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp b/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp index be7fa937ed2..ca86478a5e2 100644 --- a/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp +++ b/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp @@ -216,7 +216,7 @@ void G1PageBasedVirtualSpace::uncommit_internal(size_t start_page, size_t end_pa "Given start page " SIZE_FORMAT " is larger or equal to end page " SIZE_FORMAT, start_page, end_page); char* start_addr = page_start(start_page); - os::uncommit_memory(start_addr, pointer_delta(bounded_end_addr(end_page), start_addr, sizeof(char))); + os::uncommit_memory(start_addr, pointer_delta(bounded_end_addr(end_page), start_addr, sizeof(char)), !ExecMem); } void G1PageBasedVirtualSpace::uncommit(size_t start_page, size_t size_in_pages) { diff --git a/src/hotspot/share/gc/parallel/psCardTable.cpp b/src/hotspot/share/gc/parallel/psCardTable.cpp index 9ad29779ed7..322802a92c8 100644 --- a/src/hotspot/share/gc/parallel/psCardTable.cpp +++ b/src/hotspot/share/gc/parallel/psCardTable.cpp @@ -587,7 +587,8 @@ bool PSCardTable::resize_commit_uncommit(int changed_region, MemRegion(cur_committed.start(), new_start_aligned)); if (!uncommit_region.is_empty()) { if (!os::uncommit_memory((char*)uncommit_region.start(), - uncommit_region.byte_size())) { + uncommit_region.byte_size(), + !ExecMem)) { // If the uncommit fails, ignore it. Let the // committed table resizing go even though the committed // table will over state the committed space. diff --git a/src/hotspot/share/gc/parallel/psVirtualspace.cpp b/src/hotspot/share/gc/parallel/psVirtualspace.cpp index 473a1f26854..f25d295093a 100644 --- a/src/hotspot/share/gc/parallel/psVirtualspace.cpp +++ b/src/hotspot/share/gc/parallel/psVirtualspace.cpp @@ -113,7 +113,7 @@ bool PSVirtualSpace::shrink_by(size_t bytes) { } char* const base_addr = committed_high_addr() - bytes; - bool result = special() || os::uncommit_memory(base_addr, bytes); + bool result = special() || os::uncommit_memory(base_addr, bytes, !ExecMem); if (result) { _committed_high_addr -= bytes; } diff --git a/src/hotspot/share/gc/shared/cardTable.cpp b/src/hotspot/share/gc/shared/cardTable.cpp index b2a7118e8aa..a74070c8d47 100644 --- a/src/hotspot/share/gc/shared/cardTable.cpp +++ b/src/hotspot/share/gc/shared/cardTable.cpp @@ -254,7 +254,8 @@ void CardTable::resize_covered_region(MemRegion new_region) { cur_committed.end())); if (!uncommit_region.is_empty()) { if (!os::uncommit_memory((char*)uncommit_region.start(), - uncommit_region.byte_size())) { + uncommit_region.byte_size(), + !ExecMem)) { assert(false, "Card table contraction failed"); // The call failed so don't change the end of the // committed region. This is better than taking the diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 7df181fa2ca..d016ee33310 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -1338,7 +1338,7 @@ void ShenandoahHeap::object_iterate(ObjectClosure* cl) { assert(oop_stack.is_empty(), "should be empty"); - if (!_aux_bitmap_region_special && !os::uncommit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size())) { + if (!_aux_bitmap_region_special && !os::uncommit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size(), !ExecMem)) { log_warning(gc)("Could not uncommit native memory for auxiliary marking bitmap for heap iteration"); } } @@ -2690,7 +2690,7 @@ bool ShenandoahHeap::uncommit_bitmap_slice(ShenandoahHeapRegion *r) { size_t slice = r->index() / _bitmap_regions_per_slice; size_t off = _bitmap_bytes_per_slice * slice; size_t len = _bitmap_bytes_per_slice; - if (!os::uncommit_memory((char*)_bitmap_region.start() + off, len)) { + if (!os::uncommit_memory((char*)_bitmap_region.start() + off, len, !ExecMem)) { return false; } return true; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp index d50353eb455..dd8fbd87d31 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp @@ -627,7 +627,7 @@ void ShenandoahHeapRegion::do_commit() { void ShenandoahHeapRegion::do_uncommit() { ShenandoahHeap* heap = ShenandoahHeap::heap(); - if (!heap->is_heap_region_special() && !os::uncommit_memory((char *) bottom(), RegionSizeBytes)) { + if (!heap->is_heap_region_special() && !os::uncommit_memory((char *) bottom(), RegionSizeBytes, !ExecMem)) { report_java_out_of_memory("Unable to uncommit region"); } if (!heap->uncommit_bitmap_slice(this)) { diff --git a/src/hotspot/share/memory/virtualspace.cpp b/src/hotspot/share/memory/virtualspace.cpp index 7f88f0dcf50..e148e7575fb 100644 --- a/src/hotspot/share/memory/virtualspace.cpp +++ b/src/hotspot/share/memory/virtualspace.cpp @@ -193,7 +193,7 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, base = NULL; } } else { - base = os::reserve_memory(size, NULL, alignment, _fd_for_heap); + base = os::reserve_memory(size, NULL, alignment, _fd_for_heap, _executable); } if (base == NULL) return; @@ -985,7 +985,7 @@ void VirtualSpace::shrink_by(size_t size) { assert(middle_high_boundary() <= aligned_upper_new_high && aligned_upper_new_high + upper_needs <= upper_high_boundary(), "must not shrink beyond region"); - if (!os::uncommit_memory(aligned_upper_new_high, upper_needs)) { + if (!os::uncommit_memory(aligned_upper_new_high, upper_needs, _executable)) { debug_only(warning("os::uncommit_memory failed")); return; } else { @@ -996,7 +996,7 @@ void VirtualSpace::shrink_by(size_t size) { assert(lower_high_boundary() <= aligned_middle_new_high && aligned_middle_new_high + middle_needs <= middle_high_boundary(), "must not shrink beyond region"); - if (!os::uncommit_memory(aligned_middle_new_high, middle_needs)) { + if (!os::uncommit_memory(aligned_middle_new_high, middle_needs, _executable)) { debug_only(warning("os::uncommit_memory failed")); return; } else { @@ -1007,7 +1007,7 @@ void VirtualSpace::shrink_by(size_t size) { assert(low_boundary() <= aligned_lower_new_high && aligned_lower_new_high + lower_needs <= lower_high_boundary(), "must not shrink beyond region"); - if (!os::uncommit_memory(aligned_lower_new_high, lower_needs)) { + if (!os::uncommit_memory(aligned_lower_new_high, lower_needs, _executable)) { debug_only(warning("os::uncommit_memory failed")); return; } else { diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 586c2b7d9cc..6a606cc6400 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -773,7 +773,7 @@ WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size WB_END WB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) - os::uncommit_memory((char *)(uintptr_t)addr, size); + os::uncommit_memory((char *)(uintptr_t)addr, size, !ExecMem); WB_END WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 2a3621f3712..df7be196d96 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1652,7 +1652,7 @@ bool os::create_stack_guard_pages(char* addr, size_t bytes) { return os::pd_create_stack_guard_pages(addr, bytes); } -char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint, int file_desc) { +char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint, int file_desc, bool executable) { char* result = NULL; if (file_desc != -1) { @@ -1663,7 +1663,7 @@ char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint, int fi MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC); } } else { - result = pd_reserve_memory(bytes, addr, alignment_hint); + result = pd_reserve_memory(bytes, addr, alignment_hint, executable); if (result != NULL) { MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC); } @@ -1728,16 +1728,16 @@ void os::commit_memory_or_exit(char* addr, size_t size, size_t alignment_hint, MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC); } -bool os::uncommit_memory(char* addr, size_t bytes) { +bool os::uncommit_memory(char* addr, size_t bytes, bool exec) { bool res; if (MemTracker::tracking_level() > NMT_minimal) { Tracker tkr(Tracker::uncommit); - res = pd_uncommit_memory(addr, bytes); + res = pd_uncommit_memory(addr, bytes, exec); if (res) { tkr.record((address)addr, bytes); } } else { - res = pd_uncommit_memory(addr, bytes); + res = pd_uncommit_memory(addr, bytes, exec); } return res; } diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 21031656aa5..7d9a91f5ffa 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -114,7 +114,8 @@ class os: AllStatic { } static char* pd_reserve_memory(size_t bytes, char* addr = 0, - size_t alignment_hint = 0); + size_t alignment_hint = 0, + bool executable = false); static char* pd_attempt_reserve_memory_at(size_t bytes, char* addr); static char* pd_attempt_reserve_memory_at(size_t bytes, char* addr, int file_desc); static bool pd_commit_memory(char* addr, size_t bytes, bool executable); @@ -127,7 +128,7 @@ class os: AllStatic { static void pd_commit_memory_or_exit(char* addr, size_t size, size_t alignment_hint, bool executable, const char* mesg); - static bool pd_uncommit_memory(char* addr, size_t bytes); + static bool pd_uncommit_memory(char* addr, size_t bytes, bool exec); static bool pd_release_memory(char* addr, size_t bytes); static char* pd_map_memory(int fd, const char* file_name, size_t file_offset, @@ -311,7 +312,8 @@ class os: AllStatic { static int vm_allocation_granularity(); static char* reserve_memory(size_t bytes, char* addr = 0, - size_t alignment_hint = 0, int file_desc = -1); + size_t alignment_hint = 0, int file_desc = -1, + bool executable = false); static char* reserve_memory(size_t bytes, char* addr, size_t alignment_hint, MEMFLAGS flags); static char* reserve_memory_aligned(size_t size, size_t alignment, int file_desc = -1); @@ -338,7 +340,7 @@ class os: AllStatic { static void commit_memory_or_exit(char* addr, size_t size, size_t alignment_hint, bool executable, const char* mesg); - static bool uncommit_memory(char* addr, size_t bytes); + static bool uncommit_memory(char* addr, size_t bytes, bool exec); static bool release_memory(char* addr, size_t bytes); // Touch memory pages that cover the memory range from start to end (exclusive) diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index 204cd033589..5f8c9100927 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -2754,7 +2754,7 @@ void JavaThread::create_stack_guard_pages() { } else { log_warning(os, thread)("Attempt to protect stack guard pages failed (" PTR_FORMAT "-" PTR_FORMAT ").", p2i(low_addr), p2i(low_addr + len)); - if (os::uncommit_memory((char *) low_addr, len)) { + if (os::uncommit_memory((char *) low_addr, len, !ExecMem)) { log_warning(os, thread)("Attempt to deallocate stack guard pages failed."); } return;