From 4a685f181b71f534118a40a3314cb09e285c84e8 Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Mon, 8 Apr 2013 07:49:28 +0200 Subject: [PATCH] 7197666: java -d64 -version core dumps in a box with lots of memory Allow task queues to be mmapped instead of malloced on Solaris Reviewed-by: coleenp, jmasa, johnc, tschatzl --- hotspot/src/share/vm/memory/allocation.hpp | 19 ++++++++ .../src/share/vm/memory/allocation.inline.hpp | 44 +++++++++++++++++++ hotspot/src/share/vm/runtime/globals.hpp | 9 +++- hotspot/src/share/vm/utilities/taskqueue.hpp | 3 +- 4 files changed, 72 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/memory/allocation.hpp b/hotspot/src/share/vm/memory/allocation.hpp index e1e266ec5cf..bc01b0135b0 100644 --- a/hotspot/src/share/vm/memory/allocation.hpp +++ b/hotspot/src/share/vm/memory/allocation.hpp @@ -611,4 +611,23 @@ public: 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 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 diff --git a/hotspot/src/share/vm/memory/allocation.inline.hpp b/hotspot/src/share/vm/memory/allocation.inline.hpp index 6c236e17b7a..79bd774e358 100644 --- a/hotspot/src/share/vm/memory/allocation.inline.hpp +++ b/hotspot/src/share/vm/memory/allocation.inline.hpp @@ -108,5 +108,49 @@ template void CHeapObj::operator delete(void* p){ FreeHeap(p, F); } +template +E* ArrayAllocator::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); + 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 +void ArrayAllocator::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 diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 49f734ab97c..011112ce9a5 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -3668,8 +3668,13 @@ class CommandLineFlags { product(bool, PrintGCCause, true, \ "Include GC cause in GC logging") \ \ - product(bool, AllowNonVirtualCalls, false, \ - "Obey the ACC_SUPER flag and allow invokenonvirtual calls") + product(bool , AllowNonVirtualCalls, false, \ + "Obey the ACC_SUPER flag and allow invokenonvirtual calls") \ + \ + 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.") /* * Macros for factoring of globals diff --git a/hotspot/src/share/vm/utilities/taskqueue.hpp b/hotspot/src/share/vm/utilities/taskqueue.hpp index dd98186bb36..980b7e973e0 100644 --- a/hotspot/src/share/vm/utilities/taskqueue.hpp +++ b/hotspot/src/share/vm/utilities/taskqueue.hpp @@ -253,6 +253,7 @@ public: template class GenericTaskQueue: public TaskQueueSuper { + ArrayAllocator _array_allocator; protected: typedef typename TaskQueueSuper::Age Age; typedef typename TaskQueueSuper::idx_t idx_t; @@ -314,7 +315,7 @@ GenericTaskQueue::GenericTaskQueue() { template void GenericTaskQueue::initialize() { - _elems = NEW_C_HEAP_ARRAY(E, N, F); + _elems = _array_allocator.allocate(N); } template