1 /* 2 * Copyright (c) 2015, 2018, 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_HPP 25 #define SHARE_GC_Z_ZVALUE_HPP 26 27 #include "memory/allocation.hpp" 28 #include "gc/z/zCPU.hpp" 29 #include "gc/z/zGlobals.hpp" 30 #include "gc/z/zNUMA.hpp" 31 #include "gc/z/zThread.hpp" 32 #include "gc/z/zUtils.hpp" 33 #include "utilities/align.hpp" 34 35 template <typename S> 36 class ZValueStorage : public AllStatic { 37 private: 38 static uintptr_t _top; 39 static uintptr_t _end; 40 41 public: 42 static const size_t offset = 4 * K; 43 44 static uintptr_t alloc(size_t size) { 45 guarantee(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 67 template <typename T> uintptr_t ZValueStorage<T>::_end = 0; 68 template <typename T> uintptr_t ZValueStorage<T>::_top = 0; 69 70 class ZContendedStorage : public ZValueStorage<ZContendedStorage> { 71 public: 72 static size_t alignment() { 73 return ZCacheLineSize; 74 } 75 76 static uint32_t count() { 77 return 1; 78 } 79 80 static uint32_t id() { 81 return 0; 82 } 83 }; 84 85 class ZPerCPUStorage : public ZValueStorage<ZPerCPUStorage> { 86 public: 87 static size_t alignment() { 88 return sizeof(uintptr_t); 89 } 90 91 static uint32_t count() { 92 return ZCPU::count(); 93 } 94 95 static uint32_t id() { 96 return ZCPU::id(); 97 } 98 }; 99 100 class ZPerNUMAStorage : public ZValueStorage<ZPerNUMAStorage> { 101 public: 102 static size_t alignment() { 103 return sizeof(uintptr_t); 104 } 105 106 static uint32_t count() { 107 return ZNUMA::count(); 108 } 109 110 static uint32_t id() { 111 return ZNUMA::id(); 112 } 113 }; 114 115 class ZPerWorkerStorage : public ZValueStorage<ZPerWorkerStorage> { 116 public: 117 static size_t alignment() { 118 return sizeof(uintptr_t); 119 } 120 121 static uint32_t count() { 122 return MAX2(ParallelGCThreads, ConcGCThreads); 123 } 124 125 static uint32_t id() { 126 return ZThread::worker_id(); 127 } 128 }; 129 130 template <typename S, typename T> 131 class ZValueIterator; 132 133 template <typename S, typename T> 134 class ZValue : public CHeapObj<mtGC> { 135 private: 136 const uintptr_t _addr; 137 138 uintptr_t value_addr(uint32_t value_id) const { 139 return _addr + (value_id * S::offset); 140 } 141 142 public: 143 ZValue() : 144 _addr(S::alloc(sizeof(T))) { 145 // Initialize all instances 146 ZValueIterator<S, T> iter(this); 147 for (T* addr; iter.next(&addr);) { 148 ::new (addr) T; 149 } 150 } 151 152 ZValue(const T& value) : 153 _addr(S::alloc(sizeof(T))) { 154 // Initialize all instances 155 ZValueIterator<S, T> iter(this); 156 for (T* addr; iter.next(&addr);) { 157 ::new (addr) T(value); 158 } 159 } 160 161 // Not implemented 162 ZValue(const ZValue<S, T>& value); 163 ZValue<S, T>& operator=(const ZValue<S, T>& value); 164 165 const T* addr(uint32_t value_id = S::id()) const { 166 return reinterpret_cast<const T*>(value_addr(value_id)); 167 } 168 169 T* addr(uint32_t value_id = S::id()) { 170 return reinterpret_cast<T*>(value_addr(value_id)); 171 } 172 173 const T& get(uint32_t value_id = S::id()) const { 174 return *addr(value_id); 175 } 176 177 T& get(uint32_t value_id = S::id()) { 178 return *addr(value_id); 179 } 180 181 void set(const T& value, uint32_t value_id = S::id()) { 182 get(value_id) = value; 183 } 184 185 void set_all(const T& value) { 186 ZValueIterator<S, T> iter(this); 187 for (T* addr; iter.next(&addr);) { 188 *addr = value; 189 } 190 } 191 }; 192 193 template <typename T> 194 class ZContended : public ZValue<ZContendedStorage, T> { 195 public: 196 ZContended() : 197 ZValue<ZContendedStorage, T>() {} 198 199 ZContended(const T& value) : 200 ZValue<ZContendedStorage, T>(value) {} 201 202 using ZValue<ZContendedStorage, T>::operator=; 203 }; 204 205 template <typename T> 206 class ZPerCPU : public ZValue<ZPerCPUStorage, T> { 207 public: 208 ZPerCPU() : 209 ZValue<ZPerCPUStorage, T>() {} 210 211 ZPerCPU(const T& value) : 212 ZValue<ZPerCPUStorage, T>(value) {} 213 214 using ZValue<ZPerCPUStorage, T>::operator=; 215 }; 216 217 template <typename T> 218 class ZPerNUMA : public ZValue<ZPerNUMAStorage, T> { 219 public: 220 ZPerNUMA() : 221 ZValue<ZPerNUMAStorage, T>() {} 222 223 ZPerNUMA(const T& value) : 224 ZValue<ZPerNUMAStorage, T>(value) {} 225 226 using ZValue<ZPerNUMAStorage, T>::operator=; 227 }; 228 229 template <typename T> 230 class ZPerWorker : public ZValue<ZPerWorkerStorage, T> { 231 public: 232 ZPerWorker() : 233 ZValue<ZPerWorkerStorage, T>() {} 234 235 ZPerWorker(const T& value) : 236 ZValue<ZPerWorkerStorage, T>(value) {} 237 238 using ZValue<ZPerWorkerStorage, T>::operator=; 239 }; 240 241 template <typename S, typename T> 242 class ZValueIterator { 243 private: 244 ZValue<S, T>* const _value; 245 uint32_t _value_id; 246 247 public: 248 ZValueIterator(ZValue<S, T>* value) : 249 _value(value), 250 _value_id(0) {} 251 252 bool next(T** value) { 253 if (_value_id < S::count()) { 254 *value = _value->addr(_value_id++); 255 return true; 256 } 257 return false; 258 } 259 }; 260 261 template <typename T> 262 class ZPerCPUIterator : public ZValueIterator<ZPerCPUStorage, T> { 263 public: 264 ZPerCPUIterator(ZPerCPU<T>* value) : 265 ZValueIterator<ZPerCPUStorage, T>(value) {} 266 }; 267 268 template <typename T> 269 class ZPerNUMAIterator : public ZValueIterator<ZPerNUMAStorage, T> { 270 public: 271 ZPerNUMAIterator(ZPerNUMA<T>* value) : 272 ZValueIterator<ZPerNUMAStorage, T>(value) {} 273 }; 274 275 template <typename T> 276 class ZPerWorkerIterator : public ZValueIterator<ZPerWorkerStorage, T> { 277 public: 278 ZPerWorkerIterator(ZPerWorker<T>* value) : 279 ZValueIterator<ZPerWorkerStorage, T>(value) {} 280 }; 281 282 template <typename S, typename T> 283 class ZValueConstIterator { 284 private: 285 const ZValue<S, T>* const _value; 286 uint32_t _value_id; 287 288 public: 289 ZValueConstIterator(const ZValue<S, T>* value) : 290 _value(value), 291 _value_id(0) {} 292 293 bool next(const T** value) { 294 if (_value_id < S::count()) { 295 *value = _value->addr(_value_id++); 296 return true; 297 } 298 return false; 299 } 300 }; 301 302 template <typename T> 303 class ZPerCPUConstIterator : public ZValueConstIterator<ZPerCPUStorage, T> { 304 public: 305 ZPerCPUConstIterator(const ZPerCPU<T>* value) : 306 ZValueConstIterator<ZPerCPUStorage, T>(value) {} 307 }; 308 309 template <typename T> 310 class ZPerNUMAConstIterator : public ZValueConstIterator<ZPerNUMAStorage, T> { 311 public: 312 ZPerNUMAConstIterator(const ZPerNUMA<T>* value) : 313 ZValueConstIterator<ZPerNUMAStorage, T>(value) {} 314 }; 315 316 template <typename T> 317 class ZPerWorkerConstIterator : public ZValueConstIterator<ZPerWorkerStorage, T> { 318 public: 319 ZPerWorkerConstIterator(const ZPerWorker<T>* value) : 320 ZValueConstIterator<ZPerWorkerStorage, T>(value) {} 321 }; 322 323 #endif // SHARE_GC_Z_ZVALUE_HPP