--- old/src/share/vm/gc/g1/g1HotCardCache.cpp 2016-03-09 15:15:52.219223397 +0100 +++ new/src/share/vm/gc/g1/g1HotCardCache.cpp 2016-03-09 15:15:52.075218527 +0100 @@ -36,7 +36,7 @@ _use_cache = true; _hot_cache_size = (size_t)1 << G1ConcRSLogCacheSize; - _hot_cache = _hot_cache_memory.allocate(_hot_cache_size); + _hot_cache = ArrayAllocator::allocate(_hot_cache_size); reset_hot_cache_internal(); @@ -51,7 +51,7 @@ G1HotCardCache::~G1HotCardCache() { if (default_use_cache()) { assert(_hot_cache != NULL, "Logic"); - _hot_cache_memory.free(); + ArrayAllocator::free(_hot_cache, _hot_cache_size); _hot_cache = NULL; } } --- old/src/share/vm/gc/g1/g1HotCardCache.hpp 2016-03-09 15:15:52.983249235 +0100 +++ new/src/share/vm/gc/g1/g1HotCardCache.hpp 2016-03-09 15:15:52.835244230 +0100 @@ -61,7 +61,6 @@ G1CardCounts _card_counts; - ArrayAllocator _hot_cache_memory; // The card cache table jbyte** _hot_cache; --- old/src/share/vm/gc/shared/taskqueue.hpp 2016-03-09 15:15:53.743274939 +0100 +++ new/src/share/vm/gc/shared/taskqueue.hpp 2016-03-09 15:15:53.631271151 +0100 @@ -248,7 +248,6 @@ template class GenericTaskQueue: public TaskQueueSuper { - ArrayAllocator _array_allocator; protected: typedef typename TaskQueueSuper::Age Age; typedef typename TaskQueueSuper::idx_t idx_t; --- old/src/share/vm/gc/shared/taskqueue.inline.hpp 2016-03-09 15:15:54.511300912 +0100 +++ new/src/share/vm/gc/shared/taskqueue.inline.hpp 2016-03-09 15:15:54.363295907 +0100 @@ -44,12 +44,13 @@ template inline void GenericTaskQueue::initialize() { - _elems = _array_allocator.allocate(N); + _elems = ArrayAllocator::allocate(N); } template inline GenericTaskQueue::~GenericTaskQueue() { - FREE_C_HEAP_ARRAY(E, _elems); + assert(false, "This code is currently never called"); + ArrayAllocator::free(const_cast(_elems), N); } template --- old/src/share/vm/memory/allocation.hpp 2016-03-09 15:15:55.247325804 +0100 +++ new/src/share/vm/memory/allocation.hpp 2016-03-09 15:15:55.135322016 +0100 @@ -724,30 +724,23 @@ // is set so that we always use malloc except for Solaris where we set the // limit to get mapped memory. template -class ArrayAllocator VALUE_OBJ_CLASS_SPEC { - char* _addr; - bool _use_malloc; - size_t _size; - bool _free_in_destructor; +class ArrayAllocator : public AllStatic { + private: + static bool should_use_malloc(size_t length); - static bool should_use_malloc(size_t size) { - return size < ArrayAllocatorMallocLimit; - } + static size_t size_for_malloc(size_t length); + static size_t size_for_mmap(size_t length); - static char* allocate_inner(size_t& size, bool& use_malloc); - public: - ArrayAllocator(bool free_in_destructor = true) : - _addr(NULL), _use_malloc(false), _size(0), _free_in_destructor(free_in_destructor) { } + static E* allocate_malloc(size_t length); + static E* allocate_mmap(size_t length); - ~ArrayAllocator() { - if (_free_in_destructor) { - free(); - } - } + static void free_malloc(E* addr, size_t length); + static void free_mmap(E* addr, size_t length); - E* allocate(size_t length); - E* reallocate(size_t new_length); - void free(); + public: + static E* allocate(size_t length); + static E* reallocate(E* old_addr, size_t old_length, size_t new_length); + static void free(E* addr, size_t length); }; #endif // SHARE_VM_MEMORY_ALLOCATION_HPP --- old/src/share/vm/memory/allocation.inline.hpp 2016-03-09 15:15:56.023352047 +0100 +++ new/src/share/vm/memory/allocation.inline.hpp 2016-03-09 15:15:55.911348260 +0100 @@ -151,66 +151,87 @@ } template -char* ArrayAllocator::allocate_inner(size_t &size, bool &use_malloc) { - char* addr = NULL; +size_t ArrayAllocator::size_for_malloc(size_t length) { + return length * sizeof(E); +} - 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 addr; - } - } +template +size_t ArrayAllocator::size_for_mmap(size_t length) { + size_t size = length * sizeof(E); + int alignment = os::vm_allocation_granularity(); + return align_size_up(size, alignment); +} + +template +bool ArrayAllocator::should_use_malloc(size_t length) { + return size_for_malloc(length) < ArrayAllocatorMallocLimit; +} + +template +E* ArrayAllocator::allocate_malloc(size_t length) { + return (E*)AllocateHeap(size_for_malloc(length), F); +} +template +E* ArrayAllocator::allocate_mmap(size_t length) { + size_t size = size_for_mmap(length); int alignment = os::vm_allocation_granularity(); - size = align_size_up(size, alignment); - addr = os::reserve_memory(size, NULL, alignment, F); + char* addr = os::reserve_memory(size, NULL, alignment, F); if (addr == NULL) { vm_exit_out_of_memory(size, OOM_MMAP_ERROR, "Allocator (reserve)"); } os::commit_memory_or_exit(addr, size, !ExecMem, "Allocator (commit)"); - return addr; + + return (E*)addr; } template E* ArrayAllocator::allocate(size_t length) { - assert(_addr == NULL, "Already in use"); - - _size = sizeof(E) * length; - _use_malloc = should_use_malloc(_size); - _addr = allocate_inner(_size, _use_malloc); + if (should_use_malloc(length)) { + return allocate_malloc(length); + } - return (E*)_addr; + return allocate_mmap(length); } template -E* ArrayAllocator::reallocate(size_t new_length) { - size_t new_size = sizeof(E) * new_length; - bool use_malloc = should_use_malloc(new_size); - char* new_addr = allocate_inner(new_size, use_malloc); +E* ArrayAllocator::reallocate(E* old_addr, size_t old_length, size_t new_length) { + E* new_addr = (new_length > 0) + ? allocate(new_length) + : NULL; - memcpy(new_addr, _addr, MIN2(new_size, _size)); + if (new_addr != NULL && old_addr != NULL) { + memcpy(new_addr, old_addr, MIN2(old_length, new_length) * sizeof(E)); + } + + if (old_addr != NULL) { + free(old_addr, old_length); + } - free(); - _size = new_size; - _use_malloc = use_malloc; - _addr = new_addr; - return (E*)new_addr; + return new_addr; +} + +template +void ArrayAllocator::free_malloc(E* addr, size_t /*length*/) { + FreeHeap(addr); +} + +template +void ArrayAllocator::free_mmap(E* addr, size_t length) { + bool result = os::release_memory((char*)addr, size_for_mmap(length)); + assert(result, "Failed to release memory"); } template -void ArrayAllocator::free() { - if (_addr != NULL) { - if (_use_malloc) { - FreeHeap(_addr); +void ArrayAllocator::free(E* addr, size_t length) { + if (addr != NULL) { + if (should_use_malloc(length)) { + free_malloc(addr, length); } else { - os::release_memory(_addr, _size); + free_mmap(addr, length); } - _addr = NULL; } } --- old/src/share/vm/utilities/bitMap.cpp 2016-03-09 15:15:56.863380456 +0100 +++ new/src/share/vm/utilities/bitMap.cpp 2016-03-09 15:15:56.715375452 +0100 @@ -30,14 +30,14 @@ #include "utilities/copy.hpp" BitMap::BitMap(bm_word_t* map, idx_t size_in_bits) : - _map(map), _size(size_in_bits), _map_allocator(false) + _map(map), _size(size_in_bits) { assert(sizeof(bm_word_t) == BytesPerWord, "Implementation assumption."); } BitMap::BitMap(idx_t size_in_bits, bool in_resource_area) : - _map(NULL), _size(0), _map_allocator(false) + _map(NULL), _size(0) { assert(sizeof(bm_word_t) == BytesPerWord, "Implementation assumption."); resize(size_in_bits, in_resource_area); @@ -54,7 +54,7 @@ Copy::disjoint_words((HeapWord*)old_map, (HeapWord*) _map, MIN2(old_size_in_words, new_size_in_words)); } else { - _map = _map_allocator.reallocate(new_size_in_words); + _map = ArrayAllocator::reallocate(old_map, old_size_in_words, new_size_in_words); } if (new_size_in_words > old_size_in_words) { --- old/src/share/vm/utilities/bitMap.hpp 2016-03-09 15:15:57.615405889 +0100 +++ new/src/share/vm/utilities/bitMap.hpp 2016-03-09 15:15:57.503402102 +0100 @@ -48,7 +48,6 @@ } RangeSizeHint; private: - ArrayAllocator _map_allocator; bm_word_t* _map; // First word in bitmap idx_t _size; // Size of bitmap (in bits) @@ -114,7 +113,7 @@ public: // Constructs a bitmap with no map, and size 0. - BitMap() : _map(NULL), _size(0), _map_allocator(false) {} + BitMap() : _map(NULL), _size(0) {} // Constructs a bitmap with the given map and size. BitMap(bm_word_t* map, idx_t size_in_bits);