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/gcId.hpp" 26 #include "gc/shared/gcLocker.hpp" 27 #include "gc/shared/isGCActiveMark.hpp" 28 #include "gc/shared/vmGCOperations.hpp" 29 #include "gc/z/zCollectedHeap.hpp" 30 #include "gc/z/zDriver.hpp" 31 #include "gc/z/zHeap.inline.hpp" 32 #include "gc/z/zMessagePort.inline.hpp" 33 #include "gc/z/zServiceability.hpp" 34 #include "gc/z/zStat.hpp" 35 #include "logging/log.hpp" 36 #include "runtime/vm_operations.hpp" 37 #include "runtime/vmThread.hpp" 38 39 static const ZStatPhaseCycle ZPhaseCycle("Garbage Collection Cycle"); 40 static const ZStatPhasePause ZPhasePauseMarkStart("Pause Mark Start"); 41 static const ZStatPhaseConcurrent ZPhaseConcurrentMark("Concurrent Mark"); 42 static const ZStatPhaseConcurrent ZPhaseConcurrentMarkContinue("Concurrent Mark Continue"); 43 static const ZStatPhasePause ZPhasePauseMarkEnd("Pause Mark End"); 44 static const ZStatPhaseConcurrent ZPhaseConcurrentProcessNonStrongReferences("Concurrent Process Non-Strong References"); 45 static const ZStatPhaseConcurrent ZPhaseConcurrentResetRelocationSet("Concurrent Reset Relocation Set"); 46 static const ZStatPhaseConcurrent ZPhaseConcurrentDestroyDetachedPages("Concurrent Destroy Detached Pages"); 47 static const ZStatPhaseConcurrent ZPhaseConcurrentSelectRelocationSet("Concurrent Select Relocation Set"); 48 static const ZStatPhaseConcurrent ZPhaseConcurrentPrepareRelocationSet("Concurrent Prepare Relocation Set"); 49 static const ZStatPhasePause ZPhasePauseRelocateStart("Pause Relocate Start"); 50 static const ZStatPhaseConcurrent ZPhaseConcurrentRelocated("Concurrent Relocate"); 51 static const ZStatCriticalPhase ZCriticalPhaseGCLockerStall("GC Locker Stall", false /* verbose */); 52 static const ZStatSampler ZSamplerJavaThreads("System", "Java Threads", ZStatUnitThreads); 53 54 class ZOperationClosure : public StackObj { 55 public: 56 virtual const char* name() const = 0; 57 58 virtual bool needs_inactive_gc_locker() const { 59 // An inactive GC locker is needed in operations where we change the good 60 // mask or move objects. Changing the good mask will invalidate all oops, 61 // which makes it conceptually the same thing as moving all objects. 62 return false; 63 } 64 65 virtual bool do_operation() = 0; 66 }; 67 68 class VM_ZOperation : public VM_Operation { 69 private: 70 ZOperationClosure* _cl; 71 uint _gc_id; 72 bool _gc_locked; 73 bool _success; 74 75 public: 76 VM_ZOperation(ZOperationClosure* cl) : 77 _cl(cl), 78 _gc_id(GCId::current()), 79 _gc_locked(false), 80 _success(false) {} 81 82 virtual VMOp_Type type() const { 83 return VMOp_ZOperation; 84 } 85 86 virtual const char* name() const { 87 return _cl->name(); 88 } 89 90 virtual bool doit_prologue() { 91 Heap_lock->lock(); 92 return true; 93 } 94 95 virtual void doit() { 96 assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint"); 97 98 ZStatSample(ZSamplerJavaThreads, Threads::number_of_threads()); 99 100 // JVMTI support 101 SvcGCMarker sgcm(SvcGCMarker::OTHER); 102 103 // Setup GC id 104 GCIdMark gcid(_gc_id); 105 106 if (_cl->needs_inactive_gc_locker() && GCLocker::check_active_before_gc()) { 107 // GC locker is active, bail out 108 _gc_locked = true; 109 } else { 110 // Execute operation 111 IsGCActiveMark mark; 112 _success = _cl->do_operation(); 113 } 114 } 115 116 virtual void doit_epilogue() { 117 Heap_lock->unlock(); 118 } 119 120 bool gc_locked() { 121 return _gc_locked; 122 } 123 124 bool success() const { 125 return _success; 126 } 127 }; 128 129 class ZMarkStartClosure : public ZOperationClosure { 130 public: 131 virtual const char* name() const { 132 return "ZMarkStart"; 133 } 134 135 virtual bool needs_inactive_gc_locker() const { 136 return true; 137 } 138 139 virtual bool do_operation() { 140 ZStatTimer timer(ZPhasePauseMarkStart); 141 ZServiceabilityMarkStartTracer tracer; 142 143 ZCollectedHeap::heap()->increment_total_collections(true /* full */); 144 145 ZHeap::heap()->mark_start(); 146 return true; 147 } 148 }; 149 150 class ZMarkEndClosure : public ZOperationClosure { 151 public: 152 virtual const char* name() const { 153 return "ZMarkEnd"; 154 } 155 156 virtual bool do_operation() { 157 ZStatTimer timer(ZPhasePauseMarkEnd); 158 ZServiceabilityMarkEndTracer tracer; 159 160 return ZHeap::heap()->mark_end(); 161 } 162 }; 163 164 class ZRelocateStartClosure : public ZOperationClosure { 165 public: 166 virtual const char* name() const { 167 return "ZRelocateStart"; 168 } 169 170 virtual bool needs_inactive_gc_locker() const { 171 return true; 172 } 173 174 virtual bool do_operation() { 175 ZStatTimer timer(ZPhasePauseRelocateStart); 176 ZServiceabilityRelocateStartTracer tracer; 177 178 ZHeap::heap()->relocate_start(); 179 return true; 180 } 181 }; 182 183 ZDriver::ZDriver() : 184 _gc_cycle_port(), 185 _gc_locker_port() { 186 set_name("ZDriver"); 187 create_and_start(); 188 } 189 190 bool ZDriver::vm_operation(ZOperationClosure* cl) { 191 for (;;) { 192 VM_ZOperation op(cl); 193 VMThread::execute(&op); 194 if (op.gc_locked()) { 195 // Wait for GC to become unlocked and restart the VM operation 196 ZStatTimer timer(ZCriticalPhaseGCLockerStall); 197 _gc_locker_port.wait(); 198 continue; 199 } 200 201 // Notify VM operation completed 202 _gc_locker_port.ack(); 203 204 return op.success(); 205 } 206 } 207 208 void ZDriver::collect(GCCause::Cause cause) { 209 switch (cause) { 210 case GCCause::_wb_young_gc: 211 case GCCause::_wb_conc_mark: 212 case GCCause::_wb_full_gc: 213 case GCCause::_dcmd_gc_run: 214 case GCCause::_java_lang_system_gc: 215 case GCCause::_full_gc_alot: 216 case GCCause::_scavenge_alot: 217 case GCCause::_jvmti_force_gc: 218 case GCCause::_metadata_GC_clear_soft_refs: 219 // Start synchronous GC 220 _gc_cycle_port.send_sync(cause); 221 break; 222 223 case GCCause::_z_timer: 224 case GCCause::_z_warmup: 225 case GCCause::_z_allocation_rate: 226 case GCCause::_z_allocation_stall: 227 case GCCause::_z_proactive: 228 case GCCause::_metadata_GC_threshold: 229 // Start asynchronous GC 230 _gc_cycle_port.send_async(cause); 231 break; 232 233 case GCCause::_gc_locker: 234 // Restart VM operation previously blocked by the GC locker 235 _gc_locker_port.signal(); 236 break; 237 238 default: 239 // Other causes not supported 240 fatal("Unsupported GC cause (%s)", GCCause::to_string(cause)); 241 break; 242 } 243 } 244 245 GCCause::Cause ZDriver::start_gc_cycle() { 246 // Wait for GC request 247 return _gc_cycle_port.receive(); 248 } 249 250 class ZSoftReferencePolicyScope : public StackObj { 251 private: 252 bool should_clear_soft_reference(GCCause::Cause cause) const { 253 const bool clear = ZCollectedHeap::heap()->soft_ref_policy()->should_clear_all_soft_refs(); 254 255 // Clear all soft reference if the policy says so, or if 256 // the GC cause indicates that we're running low on memory. 257 return clear || 258 cause == GCCause::_z_allocation_stall || 259 cause == GCCause::_metadata_GC_clear_soft_refs; 260 } 261 262 void clear_should_clear_soft_reference() const { 263 ZCollectedHeap::heap()->soft_ref_policy()->set_should_clear_all_soft_refs(false); 264 } 265 266 public: 267 ZSoftReferencePolicyScope(GCCause::Cause cause) { 268 const bool clear = should_clear_soft_reference(cause); 269 ZHeap::heap()->set_soft_reference_policy(clear); 270 clear_should_clear_soft_reference(); 271 } 272 273 ~ZSoftReferencePolicyScope() { 274 Universe::update_heap_info_at_gc(); 275 } 276 }; 277 278 class ZDriverCycleScope : public StackObj { 279 private: 280 GCIdMark _gc_id; 281 GCCauseSetter _gc_cause_setter; 282 ZSoftReferencePolicyScope _soft_ref_policy; 283 ZStatTimer _timer; 284 285 bool should_boost_worker_threads(GCCause::Cause cause) const { 286 return cause == GCCause::_java_lang_system_gc || 287 cause == GCCause::_z_allocation_stall; 288 } 289 290 public: 291 ZDriverCycleScope(GCCause::Cause cause) : 292 _gc_id(), 293 _gc_cause_setter(ZCollectedHeap::heap(), cause), 294 _soft_ref_policy(cause), 295 _timer(ZPhaseCycle) { 296 // Update statistics 297 ZStatCycle::at_start(); 298 299 // Set boost mode 300 const bool boost = should_boost_worker_threads(cause); 301 ZHeap::heap()->set_boost_worker_threads(boost); 302 } 303 304 ~ZDriverCycleScope() { 305 // Calculate boost factor 306 const double boost_factor = (double)ZHeap::heap()->nconcurrent_worker_threads() / 307 (double)ZHeap::heap()->nconcurrent_no_boost_worker_threads(); 308 309 // Update statistics 310 ZStatCycle::at_end(boost_factor); 311 } 312 }; 313 314 void ZDriver::run_gc_cycle(GCCause::Cause cause) { 315 ZDriverCycleScope scope(cause); 316 317 // Phase 1: Pause Mark Start 318 { 319 ZMarkStartClosure cl; 320 vm_operation(&cl); 321 } 322 323 // Phase 2: Concurrent Mark 324 { 325 ZStatTimer timer(ZPhaseConcurrentMark); 326 ZHeap::heap()->mark(); 327 } 328 329 // Phase 3: Pause Mark End 330 { 331 ZMarkEndClosure cl; 332 while (!vm_operation(&cl)) { 333 // Phase 3.5: Concurrent Mark Continue 334 ZStatTimer timer(ZPhaseConcurrentMarkContinue); 335 ZHeap::heap()->mark(); 336 } 337 } 338 339 // Phase 4: Concurrent Process Non-Strong References 340 { 341 ZStatTimer timer(ZPhaseConcurrentProcessNonStrongReferences); 342 ZHeap::heap()->process_non_strong_references(); 343 } 344 345 // Phase 5: Concurrent Reset Relocation Set 346 { 347 ZStatTimer timer(ZPhaseConcurrentResetRelocationSet); 348 ZHeap::heap()->reset_relocation_set(); 349 } 350 351 // Phase 6: Concurrent Destroy Detached Pages 352 { 353 ZStatTimer timer(ZPhaseConcurrentDestroyDetachedPages); 354 ZHeap::heap()->destroy_detached_pages(); 355 } 356 357 // Phase 7: Concurrent Select Relocation Set 358 { 359 ZStatTimer timer(ZPhaseConcurrentSelectRelocationSet); 360 ZHeap::heap()->select_relocation_set(); 361 } 362 363 // Phase 8: Prepare Relocation Set 364 { 365 ZStatTimer timer(ZPhaseConcurrentPrepareRelocationSet); 366 ZHeap::heap()->prepare_relocation_set(); 367 } 368 369 // Phase 9: Pause Relocate Start 370 { 371 ZRelocateStartClosure cl; 372 vm_operation(&cl); 373 } 374 375 // Phase 10: Concurrent Relocate 376 { 377 ZStatTimer timer(ZPhaseConcurrentRelocated); 378 ZHeap::heap()->relocate(); 379 } 380 } 381 382 void ZDriver::end_gc_cycle() { 383 // Notify GC cycle completed 384 _gc_cycle_port.ack(); 385 386 // Check for out of memory condition 387 ZHeap::heap()->check_out_of_memory(); 388 } 389 390 void ZDriver::run_service() { 391 // Main loop 392 while (!should_terminate()) { 393 const GCCause::Cause cause = start_gc_cycle(); 394 if (cause != GCCause::_no_gc) { 395 run_gc_cycle(cause); 396 end_gc_cycle(); 397 } 398 } 399 } 400 401 void ZDriver::stop_service() { 402 _gc_cycle_port.send_async(GCCause::_no_gc); 403 }