1 /* 2 * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_MEMORY_ALLOCATION_INLINE_HPP 26 #define SHARE_MEMORY_ALLOCATION_INLINE_HPP 27 28 #include "runtime/atomic.hpp" 29 #include "runtime/globals.hpp" 30 #include "runtime/os.hpp" 31 #include "services/memTracker.hpp" 32 #include "utilities/align.hpp" 33 #include "utilities/globalDefinitions.hpp" 34 35 // Explicit C-heap memory management 36 37 #ifndef PRODUCT 38 // Increments unsigned long value for statistics (not atomic on MP, but avoids word-tearing on 32 bit). 39 inline void inc_stat_counter(volatile julong* dest, julong add_value) { 40 #ifdef _LP64 41 *dest += add_value; 42 #else 43 julong value = Atomic::load(dest); 44 Atomic::store(value + add_value, dest); 45 #endif 46 } 47 #endif 48 49 template <class E> 50 size_t MmapArrayAllocator<E>::size_for(size_t length) { 51 size_t size = length * sizeof(E); 52 int alignment = os::vm_allocation_granularity(); 53 return align_up(size, alignment); 54 } 55 56 template <class E> 57 E* MmapArrayAllocator<E>::allocate_or_null(size_t length, MEMFLAGS flags) { 58 size_t size = size_for(length); 59 int alignment = os::vm_allocation_granularity(); 60 61 char* addr = os::reserve_memory(size, NULL, alignment, flags); 62 if (addr == NULL) { 63 return NULL; 64 } 65 66 if (os::commit_memory(addr, size, !ExecMem)) { 67 return (E*)addr; 68 } else { 69 os::release_memory(addr, size); 70 return NULL; 71 } 72 } 73 74 template <class E> 75 E* MmapArrayAllocator<E>::allocate(size_t length, MEMFLAGS flags) { 76 size_t size = size_for(length); 77 int alignment = os::vm_allocation_granularity(); 78 79 char* addr = os::reserve_memory(size, NULL, alignment, flags); 80 if (addr == NULL) { 81 vm_exit_out_of_memory(size, OOM_MMAP_ERROR, "Allocator (reserve)"); 82 } 83 84 os::commit_memory_or_exit(addr, size, !ExecMem, "Allocator (commit)"); 85 86 return (E*)addr; 87 } 88 89 template <class E> 90 void MmapArrayAllocator<E>::free(E* addr, size_t length) { 91 bool result = os::release_memory((char*)addr, size_for(length)); 92 assert(result, "Failed to release memory"); 93 } 94 95 template <class E> 96 size_t MallocArrayAllocator<E>::size_for(size_t length) { 97 return length * sizeof(E); 98 } 99 100 template <class E> 101 E* MallocArrayAllocator<E>::allocate(size_t length, MEMFLAGS flags) { 102 return (E*)AllocateHeap(size_for(length), flags); 103 } 104 105 template<class E> 106 void MallocArrayAllocator<E>::free(E* addr) { 107 FreeHeap(addr); 108 } 109 110 template <class E> 111 bool ArrayAllocator<E>::should_use_malloc(size_t length) { 112 return MallocArrayAllocator<E>::size_for(length) < ArrayAllocatorMallocLimit; 113 } 114 115 template <class E> 116 E* ArrayAllocator<E>::allocate_malloc(size_t length, MEMFLAGS flags) { 117 return MallocArrayAllocator<E>::allocate(length, flags); 118 } 119 120 template <class E> 121 E* ArrayAllocator<E>::allocate_mmap(size_t length, MEMFLAGS flags) { 122 return MmapArrayAllocator<E>::allocate(length, flags); 123 } 124 125 template <class E> 126 E* ArrayAllocator<E>::allocate(size_t length, MEMFLAGS flags) { 127 if (should_use_malloc(length)) { 128 return allocate_malloc(length, flags); 129 } 130 131 return allocate_mmap(length, flags); 132 } 133 134 template <class E> 135 E* ArrayAllocator<E>::reallocate(E* old_addr, size_t old_length, size_t new_length, MEMFLAGS flags) { 136 E* new_addr = (new_length > 0) 137 ? allocate(new_length, flags) 138 : NULL; 139 140 if (new_addr != NULL && old_addr != NULL) { 141 memcpy(new_addr, old_addr, MIN2(old_length, new_length) * sizeof(E)); 142 } 143 144 if (old_addr != NULL) { 145 free(old_addr, old_length); 146 } 147 148 return new_addr; 149 } 150 151 template<class E> 152 void ArrayAllocator<E>::free_malloc(E* addr, size_t length) { 153 MallocArrayAllocator<E>::free(addr); 154 } 155 156 template<class E> 157 void ArrayAllocator<E>::free_mmap(E* addr, size_t length) { 158 MmapArrayAllocator<E>::free(addr, length); 159 } 160 161 template<class E> 162 void ArrayAllocator<E>::free(E* addr, size_t length) { 163 if (addr != NULL) { 164 if (should_use_malloc(length)) { 165 free_malloc(addr, length); 166 } else { 167 free_mmap(addr, length); 168 } 169 } 170 } 171 172 #endif // SHARE_MEMORY_ALLOCATION_INLINE_HPP