OpenJDK / bsd-port / bsd-port / hotspot
changeset 4715:dffc616548d2
7197666: java -d64 -version core dumps in a box with lots of memory
Summary: Allow task queues to be mmapped instead of malloced on Solaris
Reviewed-by: coleenp, jmasa, johnc, tschatzl
author | brutisso |
---|---|
date | Wed, 22 May 2013 07:30:15 +0200 |
parents | cea88a661227 |
children | 044681b8bab0 851f1e0cef3c |
files | src/share/vm/memory/allocation.hpp src/share/vm/memory/allocation.inline.hpp src/share/vm/runtime/globals.hpp src/share/vm/utilities/taskqueue.hpp |
diffstat | 4 files changed, 70 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/vm/memory/allocation.hpp Tue May 21 20:46:58 2013 +0200 +++ b/src/share/vm/memory/allocation.hpp Wed May 22 07:30:15 2013 +0200 @@ -555,4 +555,23 @@ void check() PRODUCT_RETURN; }; +// Helper class to allocate arrays that may become large. +// Uses the OS malloc for allocations smaller than ArrayAllocatorMallocLimit +// and uses mapped memory for larger allocations. +// Most OS mallocs do something similar but Solaris malloc does not revert +// to mapped memory for large allocations. By default ArrayAllocatorMallocLimit +// is set so that we always use malloc except for Solaris where we set the +// limit to get mapped memory. +template <class E, MEMFLAGS F> +class ArrayAllocator : StackObj { + char* _addr; + bool _use_malloc; + size_t _size; + public: + ArrayAllocator() : _addr(NULL), _use_malloc(false), _size(0) { } + ~ArrayAllocator() { free(); } + E* allocate(size_t length); + void free(); +}; + #endif // SHARE_VM_MEMORY_ALLOCATION_HPP
--- a/src/share/vm/memory/allocation.inline.hpp Tue May 21 20:46:58 2013 +0200 +++ b/src/share/vm/memory/allocation.inline.hpp Wed May 22 07:30:15 2013 +0200 @@ -103,5 +103,49 @@ FreeHeap(p, F); } +template <class E, MEMFLAGS F> +E* ArrayAllocator<E, F>::allocate(size_t length) { + assert(_addr == NULL, "Already in use"); + + _size = sizeof(E) * length; + _use_malloc = _size < ArrayAllocatorMallocLimit; + + if (_use_malloc) { + _addr = AllocateHeap(_size, F); + if (_addr == NULL && _size >= (size_t)os::vm_allocation_granularity()) { + // malloc failed let's try with mmap instead + _use_malloc = false; + } else { + return (E*)_addr; + } + } + + int alignment = os::vm_allocation_granularity(); + _size = align_size_up(_size, alignment); + + _addr = os::reserve_memory(_size, NULL, alignment, F); + if (_addr == NULL) { + vm_exit_out_of_memory(_size, "Allocator (reserve)"); + } + + bool success = os::commit_memory(_addr, _size, false /* executable */); + if (!success) { + vm_exit_out_of_memory(_size, "Allocator (commit)"); + } + + return (E*)_addr; +} + +template<class E, MEMFLAGS F> +void ArrayAllocator<E, F>::free() { + if (_addr != NULL) { + if (_use_malloc) { + FreeHeap(_addr, F); + } else { + os::release_memory(_addr, _size); + } + _addr = NULL; + } +} #endif // SHARE_VM_MEMORY_ALLOCATION_INLINE_HPP
--- a/src/share/vm/runtime/globals.hpp Tue May 21 20:46:58 2013 +0200 +++ b/src/share/vm/runtime/globals.hpp Wed May 22 07:30:15 2013 +0200 @@ -3633,6 +3633,11 @@ product(bool, PrintGCCause, true, \ "Include GC cause in GC logging") \ \ + experimental(uintx, ArrayAllocatorMallocLimit, \ + SOLARIS_ONLY(64*K) NOT_SOLARIS(max_uintx), \ + "Allocation less than this value will be allocated " \ + "using malloc. Larger allocations will use mmap.") \ + \ product(bool, EnableTracing, false, \ "Enable event-based tracing") \ product(bool, UseLockedTracing, false, \
--- a/src/share/vm/utilities/taskqueue.hpp Tue May 21 20:46:58 2013 +0200 +++ b/src/share/vm/utilities/taskqueue.hpp Wed May 22 07:30:15 2013 +0200 @@ -253,6 +253,7 @@ template <class E, MEMFLAGS F, unsigned int N = TASKQUEUE_SIZE> class GenericTaskQueue: public TaskQueueSuper<N, F> { + ArrayAllocator<E, F> _array_allocator; protected: typedef typename TaskQueueSuper<N, F>::Age Age; typedef typename TaskQueueSuper<N, F>::idx_t idx_t; @@ -314,7 +315,7 @@ template<class E, MEMFLAGS F, unsigned int N> void GenericTaskQueue<E, F, N>::initialize() { - _elems = NEW_C_HEAP_ARRAY(E, N, F); + _elems = _array_allocator.allocate(N); } template<class E, MEMFLAGS F, unsigned int N>