changeset 4523: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>