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 #include "precompiled.hpp" 25 #include "gc/shared/threadLocalAllocBuffer.inline.hpp" 26 #include "gc/z/zCollectedHeap.hpp" 27 #include "gc/z/zGlobals.hpp" 28 #include "gc/z/zHeap.inline.hpp" 29 #include "gc/z/zObjectAllocator.hpp" 30 #include "gc/z/zPage.inline.hpp" 31 #include "gc/z/zStat.hpp" 32 #include "gc/z/zThread.hpp" 33 #include "gc/z/zUtils.inline.hpp" 34 #include "logging/log.hpp" 35 #include "runtime/atomic.hpp" 36 #include "runtime/safepoint.hpp" 37 #include "runtime/thread.hpp" 38 #include "runtime/threadSMR.hpp" 39 #include "utilities/align.hpp" 40 #include "utilities/debug.hpp" 41 42 static const ZStatCounter ZCounterUndoObjectAllocationSucceeded("Memory", "Undo Object Allocation Succeeded", ZStatUnitOpsPerSecond); 43 static const ZStatCounter ZCounterUndoObjectAllocationFailed("Memory", "Undo Object Allocation Failed", ZStatUnitOpsPerSecond); 44 static const ZStatSubPhase ZSubPhasePauseRetireTLABS("Pause Retire TLABS"); 45 static const ZStatSubPhase ZSubPhasePauseRemapTLABS("Pause Remap TLABS"); 46 47 ZObjectAllocator::ZObjectAllocator(uint nworkers) : 48 _nworkers(nworkers), 49 _used(0), 50 _shared_medium_page(NULL), 51 _shared_small_page(NULL), 52 _worker_small_page(NULL) {} 53 54 ZPage* ZObjectAllocator::alloc_page(uint8_t type, size_t size, ZAllocationFlags flags) { 55 ZPage* const page = ZHeap::heap()->alloc_page(type, size, flags); 56 if (page != NULL) { 57 // Increment used bytes 58 Atomic::add(size, _used.addr()); 59 } 60 61 return page; 62 } 63 64 uintptr_t ZObjectAllocator::alloc_object_in_shared_page(ZPage** shared_page, 65 uint8_t page_type, 66 size_t page_size, 67 size_t size, 68 ZAllocationFlags flags) { 69 uintptr_t addr = 0; 70 ZPage* page = *shared_page; 71 72 if (page != NULL) { 73 addr = page->alloc_object_atomic(size); 74 } 75 76 if (addr == 0) { 77 // Allocate new page 78 ZPage* const new_page = alloc_page(page_type, page_size, flags); 79 if (new_page != NULL) { 80 // Allocate object before installing the new page 81 addr = new_page->alloc_object(size); 82 83 retry: 84 // Install new page 85 ZPage* const prev_page = Atomic::cmpxchg(new_page, shared_page, page); 86 if (prev_page != page) { 87 if (prev_page == NULL) { 88 // Previous page was retired, retry installing the new page 89 page = prev_page; 90 goto retry; 91 } 92 93 // Another page already installed, try allocation there first 94 const uintptr_t prev_addr = prev_page->alloc_object_atomic(size); 95 if (prev_addr == 0) { 96 // Allocation failed, retry installing the new page 97 page = prev_page; 98 goto retry; 99 } 100 101 // Allocation succeeded in already installed page 102 addr = prev_addr; 103 104 // Undo new page allocation 105 ZHeap::heap()->undo_alloc_page(new_page); 106 } 107 } 108 } 109 110 return addr; 111 } 112 113 uintptr_t ZObjectAllocator::alloc_large_object(size_t size, ZAllocationFlags flags) { 114 assert(ZThread::is_java(), "Should be a Java thread"); 115 116 uintptr_t addr = 0; 117 118 // Allocate new large page 119 const size_t page_size = align_up(size, ZPageSizeMin); 120 ZPage* const page = alloc_page(ZPageTypeLarge, page_size, flags); 121 if (page != NULL) { 122 // Allocate the object 123 addr = page->alloc_object(size); 124 } 125 126 return addr; 127 } 128 129 uintptr_t ZObjectAllocator::alloc_medium_object(size_t size, ZAllocationFlags flags) { 130 return alloc_object_in_shared_page(_shared_medium_page.addr(), ZPageTypeMedium, ZPageSizeMedium, size, flags); 131 } 132 133 uintptr_t ZObjectAllocator::alloc_small_object_from_nonworker(size_t size, ZAllocationFlags flags) { 134 assert(ZThread::is_java() || ZThread::is_vm(), "Should be a Java or VM thread"); 135 136 if (flags.relocation() && flags.java_thread()) { 137 // For relocations from Java threads, try TLAB allocation first 138 const uintptr_t addr = (uintptr_t)Thread::current()->tlab().allocate(ZUtils::bytes_to_words(size)); 139 if (addr != 0) { 140 return addr; 141 } 142 } 143 144 // Non-worker small page allocation can never use the reserve 145 flags.set_no_reserve(); 146 147 return alloc_object_in_shared_page(_shared_small_page.addr(), ZPageTypeSmall, ZPageSizeSmall, size, flags); 148 } 149 150 uintptr_t ZObjectAllocator::alloc_small_object_from_worker(size_t size, ZAllocationFlags flags) { 151 assert(ZThread::is_worker(), "Should be a worker thread"); 152 153 ZPage* page = _worker_small_page.get(); 154 uintptr_t addr = 0; 155 156 if (page != NULL) { 157 addr = page->alloc_object(size); 158 } 159 160 if (addr == 0) { 161 // Allocate new page 162 page = alloc_page(ZPageTypeSmall, ZPageSizeSmall, flags); 163 if (page != NULL) { 164 addr = page->alloc_object(size); 165 } 166 _worker_small_page.set(page); 167 } 168 169 return addr; 170 } 171 172 uintptr_t ZObjectAllocator::alloc_small_object(size_t size, ZAllocationFlags flags) { 173 if (flags.worker_thread()) { 174 return alloc_small_object_from_worker(size, flags); 175 } else { 176 return alloc_small_object_from_nonworker(size, flags); 177 } 178 } 179 180 uintptr_t ZObjectAllocator::alloc_object(size_t size, ZAllocationFlags flags) { 181 if (size <= ZObjectSizeLimitSmall) { 182 // Small 183 return alloc_small_object(size, flags); 184 } else if (size <= ZObjectSizeLimitMedium) { 185 // Medium 186 return alloc_medium_object(size, flags); 187 } else { 188 // Large 189 return alloc_large_object(size, flags); 190 } 191 } 192 193 uintptr_t ZObjectAllocator::alloc_object(size_t size) { 194 assert(ZThread::is_java(), "Must be a Java thread"); 195 196 ZAllocationFlags flags; 197 flags.set_java_thread(); 198 flags.set_no_reserve(); 199 200 if (!ZStallOnOutOfMemory) { 201 flags.set_non_blocking(); 202 } 203 204 return alloc_object(size, flags); 205 } 206 207 uintptr_t ZObjectAllocator::alloc_object_for_relocation(size_t size) { 208 assert(ZThread::is_java() || ZThread::is_worker() || ZThread::is_vm(), "Unknown thread"); 209 210 ZAllocationFlags flags; 211 flags.set_relocation(); 212 flags.set_non_blocking(); 213 214 if (ZThread::is_worker()) { 215 flags.set_worker_thread(); 216 } else if (ZThread::is_java()) { 217 flags.set_java_thread(); 218 } 219 220 return alloc_object(size, flags); 221 } 222 223 bool ZObjectAllocator::undo_alloc_large_object(ZPage* page) { 224 assert(page->type() == ZPageTypeLarge, "Invalid page type"); 225 226 // Undo page allocation 227 ZHeap::heap()->undo_alloc_page(page); 228 return true; 229 } 230 231 bool ZObjectAllocator::undo_alloc_medium_object(ZPage* page, uintptr_t addr, size_t size) { 232 assert(page->type() == ZPageTypeMedium, "Invalid page type"); 233 234 // Try atomic undo on shared page 235 return page->undo_alloc_object_atomic(addr, size); 236 } 237 238 bool ZObjectAllocator::undo_alloc_small_object_from_nonworker(ZPage* page, uintptr_t addr, size_t size) { 239 assert(page->type() == ZPageTypeSmall, "Invalid page type"); 240 241 if (ZThread::is_java()) { 242 // Try undo allocation in TLAB 243 if (Thread::current()->tlab().undo_allocate((HeapWord*)addr, ZUtils::bytes_to_words(size))) { 244 return true; 245 } 246 } 247 248 // Try atomic undo on shared page 249 return page->undo_alloc_object_atomic(addr, size); 250 } 251 252 bool ZObjectAllocator::undo_alloc_small_object_from_worker(ZPage* page, uintptr_t addr, size_t size) { 253 assert(page->type() == ZPageTypeSmall, "Invalid page type"); 254 assert(page == _worker_small_page.get(), "Invalid page"); 255 256 // Non-atomic undo on worker-local page 257 const bool success = page->undo_alloc_object(addr, size); 258 assert(success, "Should always succeed"); 259 return success; 260 } 261 262 bool ZObjectAllocator::undo_alloc_small_object(ZPage* page, uintptr_t addr, size_t size) { 263 if (ZThread::is_worker()) { 264 return undo_alloc_small_object_from_worker(page, addr, size); 265 } else { 266 return undo_alloc_small_object_from_nonworker(page, addr, size); 267 } 268 } 269 270 bool ZObjectAllocator::undo_alloc_object(ZPage* page, uintptr_t addr, size_t size) { 271 const uint8_t type = page->type(); 272 273 if (type == ZPageTypeSmall) { 274 return undo_alloc_small_object(page, addr, size); 275 } else if (type == ZPageTypeMedium) { 276 return undo_alloc_medium_object(page, addr, size); 277 } else { 278 return undo_alloc_large_object(page); 279 } 280 } 281 282 void ZObjectAllocator::undo_alloc_object_for_relocation(ZPage* page, uintptr_t addr, size_t size) { 283 if (undo_alloc_object(page, addr, size)) { 284 ZStatInc(ZCounterUndoObjectAllocationSucceeded); 285 } else { 286 ZStatInc(ZCounterUndoObjectAllocationFailed); 287 log_trace(gc)("Failed to undo object allocation: " PTR_FORMAT ", Size: " SIZE_FORMAT ", Thread: " PTR_FORMAT " (%s)", 288 addr, size, ZThread::id(), ZThread::name()); 289 } 290 } 291 292 size_t ZObjectAllocator::used() const { 293 size_t total_used = 0; 294 295 ZPerCPUConstIterator<size_t> iter(&_used); 296 for (const size_t* cpu_used; iter.next(&cpu_used);) { 297 total_used += *cpu_used; 298 } 299 300 return total_used; 301 } 302 303 size_t ZObjectAllocator::remaining() const { 304 assert(ZThread::is_java(), "Should be a Java thread"); 305 306 ZPage* page = _shared_small_page.get(); 307 if (page != NULL) { 308 return page->remaining(); 309 } 310 311 return 0; 312 } 313 314 void ZObjectAllocator::retire_tlabs() { 315 ZStatTimer timer(ZSubPhasePauseRetireTLABS); 316 assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint"); 317 318 // Retire TLABs 319 if (UseTLAB) { 320 ZCollectedHeap* heap = ZCollectedHeap::heap(); 321 heap->accumulate_statistics_all_tlabs(); 322 heap->ensure_parsability(true /* retire_tlabs */); 323 heap->resize_all_tlabs(); 324 } 325 326 // Reset used 327 _used.set_all(0); 328 329 // Reset allocation pages 330 _shared_medium_page.set(NULL); 331 _shared_small_page.set_all(NULL); 332 _worker_small_page.set_all(NULL); 333 } 334 335 static void remap_tlab_address(HeapWord** p) { 336 *p = (HeapWord*)ZAddress::good_or_null((uintptr_t)*p); 337 } 338 339 void ZObjectAllocator::remap_tlabs() { 340 ZStatTimer timer(ZSubPhasePauseRemapTLABS); 341 assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint"); 342 343 if (UseTLAB) { 344 for (JavaThreadIteratorWithHandle iter; JavaThread* thread = iter.next(); ) { 345 thread->tlab().addresses_do(remap_tlab_address); 346 } 347 } 348 }