1 /* 2 * Copyright (c) 2015, 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 #ifndef SHARE_GC_Z_ZVALUE_INLINE_HPP 25 #define SHARE_GC_Z_ZVALUE_INLINE_HPP 26 27 #include "gc/z/zCPU.inline.hpp" 28 #include "gc/z/zGlobals.hpp" 29 #include "gc/z/zNUMA.hpp" 30 #include "gc/z/zThread.inline.hpp" 31 #include "gc/z/zUtils.hpp" 32 #include "gc/z/zValue.hpp" 33 #include "runtime/globals.hpp" 34 #include "utilities/align.hpp" 35 36 // 37 // Storage 38 // 39 40 template <typename T> uintptr_t ZValueStorage<T>::_end = 0; 41 template <typename T> uintptr_t ZValueStorage<T>::_top = 0; 42 43 template <typename S> 44 uintptr_t ZValueStorage<S>::alloc(size_t size) { 45 assert(size <= offset, "Allocation too large"); 46 47 // Allocate entry in existing memory block 48 const uintptr_t addr = align_up(_top, S::alignment()); 49 _top = addr + size; 50 51 if (_top < _end) { 52 // Success 53 return addr; 54 } 55 56 // Allocate new block of memory 57 const size_t block_alignment = offset; 58 const size_t block_size = offset * S::count(); 59 _top = ZUtils::alloc_aligned(block_alignment, block_size); 60 _end = _top + offset; 61 62 // Retry allocation 63 return alloc(size); 64 } 65 66 inline size_t ZContendedStorage::alignment() { 67 return ZCacheLineSize; 68 } 69 70 inline uint32_t ZContendedStorage::count() { 71 return 1; 72 } 73 74 inline uint32_t ZContendedStorage::id() { 75 return 0; 76 } 77 78 inline size_t ZPerCPUStorage::alignment() { 79 return sizeof(uintptr_t); 80 } 81 82 inline uint32_t ZPerCPUStorage::count() { 83 return ZCPU::count(); 84 } 85 86 inline uint32_t ZPerCPUStorage::id() { 87 return ZCPU::id(); 88 } 89 90 inline size_t ZPerNUMAStorage::alignment() { 91 return sizeof(uintptr_t); 92 } 93 94 inline uint32_t ZPerNUMAStorage::count() { 95 return ZNUMA::count(); 96 } 97 98 inline uint32_t ZPerNUMAStorage::id() { 99 return ZNUMA::id(); 100 } 101 102 inline size_t ZPerWorkerStorage::alignment() { 103 return sizeof(uintptr_t); 104 } 105 106 inline uint32_t ZPerWorkerStorage::count() { 107 return MAX2(ParallelGCThreads, ConcGCThreads); 108 } 109 110 inline uint32_t ZPerWorkerStorage::id() { 111 return ZThread::worker_id(); 112 } 113 114 // 115 // Value 116 // 117 118 template <typename S, typename T> 119 inline uintptr_t ZValue<S, T>::value_addr(uint32_t value_id) const { 120 return _addr + (value_id * S::offset); 121 } 122 123 template <typename S, typename T> 124 inline ZValue<S, T>::ZValue() : 125 _addr(S::alloc(sizeof(T))) { 126 // Initialize all instances 127 ZValueIterator<S, T> iter(this); 128 for (T* addr; iter.next(&addr);) { 129 ::new (addr) T; 130 } 131 } 132 133 template <typename S, typename T> 134 inline ZValue<S, T>::ZValue(const T& value) : 135 _addr(S::alloc(sizeof(T))) { 136 // Initialize all instances 137 ZValueIterator<S, T> iter(this); 138 for (T* addr; iter.next(&addr);) { 139 ::new (addr) T(value); 140 } 141 } 142 143 template <typename S, typename T> 144 inline const T* ZValue<S, T>::addr(uint32_t value_id) const { 145 return reinterpret_cast<const T*>(value_addr(value_id)); 146 } 147 148 template <typename S, typename T> 149 inline T* ZValue<S, T>::addr(uint32_t value_id) { 150 return reinterpret_cast<T*>(value_addr(value_id)); 151 } 152 153 template <typename S, typename T> 154 inline const T& ZValue<S, T>::get(uint32_t value_id) const { 155 return *addr(value_id); 156 } 157 158 template <typename S, typename T> 159 inline T& ZValue<S, T>::get(uint32_t value_id) { 160 return *addr(value_id); 161 } 162 163 template <typename S, typename T> 164 inline void ZValue<S, T>::set(const T& value, uint32_t value_id) { 165 get(value_id) = value; 166 } 167 168 template <typename S, typename T> 169 inline void ZValue<S, T>::set_all(const T& value) { 170 ZValueIterator<S, T> iter(this); 171 for (T* addr; iter.next(&addr);) { 172 *addr = value; 173 } 174 } 175 176 // 177 // Iterator 178 // 179 180 template <typename S, typename T> 181 inline ZValueIterator<S, T>::ZValueIterator(ZValue<S, T>* value) : 182 _value(value), 183 _value_id(0) {} 184 185 template <typename S, typename T> 186 inline bool ZValueIterator<S, T>::next(T** value) { 187 if (_value_id < S::count()) { 188 *value = _value->addr(_value_id++); 189 return true; 190 } 191 return false; 192 } 193 194 template <typename S, typename T> 195 inline ZValueConstIterator<S, T>::ZValueConstIterator(const ZValue<S, T>* value) : 196 _value(value), 197 _value_id(0) {} 198 199 template <typename S, typename T> 200 inline bool ZValueConstIterator<S, T>::next(const T** value) { 201 if (_value_id < S::count()) { 202 *value = _value->addr(_value_id++); 203 return true; 204 } 205 return false; 206 } 207 208 209 #endif // SHARE_GC_Z_ZVALUE_INLINE_HPP