OpenJDK / jdk / hs
changeset 23545:2c14fb03a06d
8037959: BitMap::resize frees old map before copying memory if !in_resource_area
Summary: Add reallocate functionality to ArrayAllocator and use it from BitMap::resize
Reviewed-by: brutisso, tschatzl
author | mgerdin |
---|---|
date | Wed, 02 Apr 2014 14:17:34 +0200 |
parents | e6362a5ba011 |
children | 35f998f35ed7 60303358c862 |
files | hotspot/src/share/vm/memory/allocation.hpp hotspot/src/share/vm/memory/allocation.inline.hpp hotspot/src/share/vm/prims/jni.cpp hotspot/src/share/vm/utilities/bitMap.cpp |
diffstat | 4 files changed, 135 insertions(+), 28 deletions(-) [+] |
line wrap: on
line diff
--- a/hotspot/src/share/vm/memory/allocation.hpp Mon Mar 31 14:02:40 2014 +0200 +++ b/hotspot/src/share/vm/memory/allocation.hpp Wed Apr 02 14:17:34 2014 +0200 @@ -748,6 +748,12 @@ bool _use_malloc; size_t _size; bool _free_in_destructor; + + static bool should_use_malloc(size_t size) { + return size < ArrayAllocatorMallocLimit; + } + + 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) { } @@ -759,6 +765,7 @@ } E* allocate(size_t length); + E* reallocate(size_t new_length); void free(); };
--- a/hotspot/src/share/vm/memory/allocation.inline.hpp Mon Mar 31 14:02:40 2014 +0200 +++ b/hotspot/src/share/vm/memory/allocation.inline.hpp Wed Apr 02 14:17:34 2014 +0200 @@ -122,35 +122,57 @@ } template <class E, MEMFLAGS F> +char* ArrayAllocator<E, F>::allocate_inner(size_t &size, bool &use_malloc) { + char* addr = NULL; + + 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; + } + } + + 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, OOM_MMAP_ERROR, "Allocator (reserve)"); + } + + os::commit_memory_or_exit(addr, size, !ExecMem, "Allocator (commit)"); + return addr; +} + +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, OOM_MMAP_ERROR, "Allocator (reserve)"); - } - - os::commit_memory_or_exit(_addr, _size, !ExecMem, "Allocator (commit)"); + _use_malloc = should_use_malloc(_size); + _addr = allocate_inner(_size, _use_malloc); return (E*)_addr; } +template <class E, MEMFLAGS F> +E* ArrayAllocator<E, F>::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); + + memcpy(new_addr, _addr, MIN2(new_size, _size)); + + free(); + _size = new_size; + _use_malloc = use_malloc; + _addr = new_addr; + return (E*)new_addr; +} + template<class E, MEMFLAGS F> void ArrayAllocator<E, F>::free() { if (_addr != NULL) {
--- a/hotspot/src/share/vm/prims/jni.cpp Mon Mar 31 14:02:40 2014 +0200 +++ b/hotspot/src/share/vm/prims/jni.cpp Wed Apr 02 14:17:34 2014 +0200 @@ -3878,6 +3878,7 @@ void TestVirtualSpaceNode_test(); void TestNewSize_test(); void TestKlass_test(); +void TestBitMap_test(); #if INCLUDE_ALL_GCS void TestOldFreeSpaceCalculation_test(); void TestG1BiasedArray_test(); @@ -3903,6 +3904,7 @@ run_unit_test(test_loggc_filename()); run_unit_test(TestNewSize_test()); run_unit_test(TestKlass_test()); + run_unit_test(TestBitMap_test()); #if INCLUDE_VM_STRUCTS run_unit_test(VMStructs::test()); #endif
--- a/hotspot/src/share/vm/utilities/bitMap.cpp Mon Mar 31 14:02:40 2014 +0200 +++ b/hotspot/src/share/vm/utilities/bitMap.cpp Wed Apr 02 14:17:34 2014 +0200 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" #include "utilities/bitMap.inline.hpp" #include "utilities/copy.hpp" #ifdef TARGET_OS_FAMILY_linux @@ -67,16 +68,14 @@ idx_t new_size_in_words = size_in_words(); if (in_resource_area) { _map = NEW_RESOURCE_ARRAY(bm_word_t, new_size_in_words); + Copy::disjoint_words((HeapWord*)old_map, (HeapWord*) _map, + MIN2(old_size_in_words, new_size_in_words)); } else { - if (old_map != NULL) { - _map_allocator.free(); - } - _map = _map_allocator.allocate(new_size_in_words); + _map = _map_allocator.reallocate(new_size_in_words); } - Copy::disjoint_words((HeapWord*)old_map, (HeapWord*) _map, - MIN2(old_size_in_words, new_size_in_words)); + if (new_size_in_words > old_size_in_words) { - clear_range_of_words(old_size_in_words, size_in_words()); + clear_range_of_words(old_size_in_words, new_size_in_words); } } @@ -536,6 +535,83 @@ tty->cr(); } +class TestBitMap : public AllStatic { + const static BitMap::idx_t BITMAP_SIZE = 1024; + static void fillBitMap(BitMap& map) { + map.set_bit(1); + map.set_bit(3); + map.set_bit(17); + map.set_bit(512); + } + + static void testResize(bool in_resource_area) { + { + BitMap map(0, in_resource_area); + map.resize(BITMAP_SIZE, in_resource_area); + fillBitMap(map); + + BitMap map2(BITMAP_SIZE, in_resource_area); + fillBitMap(map2); + assert(map.is_same(map2), "could be"); + } + + { + BitMap map(128, in_resource_area); + map.resize(BITMAP_SIZE, in_resource_area); + fillBitMap(map); + + BitMap map2(BITMAP_SIZE, in_resource_area); + fillBitMap(map2); + assert(map.is_same(map2), "could be"); + } + + { + BitMap map(BITMAP_SIZE, in_resource_area); + map.resize(BITMAP_SIZE, in_resource_area); + fillBitMap(map); + + BitMap map2(BITMAP_SIZE, in_resource_area); + fillBitMap(map2); + assert(map.is_same(map2), "could be"); + } + } + + static void testResizeResource() { + ResourceMark rm; + testResize(true); + } + + static void testResizeNonResource() { + const uintx bitmap_bytes = BITMAP_SIZE / BitsPerByte; + + // Test the default behavior + testResize(false); + + { + // Make sure that AllocatorMallocLimit is larger than our allocation request + // forcing it to call standard malloc() + UIntFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes * 4); + testResize(false); + } + { + // Make sure that AllocatorMallocLimit is smaller than our allocation request + // forcing it to call mmap() (or equivalent) + UIntFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes / 4); + testResize(false); + } + } + + public: + static void test() { + testResizeResource(); + testResizeNonResource(); + } + +}; + +void TestBitMap_test() { + TestBitMap::test(); +} #endif