1 /* 2 * Copyright (c) 2015, 2020, 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/z/zBreakpoint.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 "gc/z/zVerify.hpp" 36 #include "logging/log.hpp" 37 #include "memory/universe.hpp" 38 #include "runtime/vmOperations.hpp" 39 #include "runtime/vmThread.hpp" 40 41 static const ZStatPhaseCycle ZPhaseCycle("Garbage Collection Cycle"); 42 static const ZStatPhasePause ZPhasePauseMarkStart("Pause Mark Start"); 43 static const ZStatPhaseConcurrent ZPhaseConcurrentMark("Concurrent Mark"); 44 static const ZStatPhaseConcurrent ZPhaseConcurrentMarkContinue("Concurrent Mark Continue"); 45 static const ZStatPhasePause ZPhasePauseMarkEnd("Pause Mark End"); 46 static const ZStatPhaseConcurrent ZPhaseConcurrentProcessNonStrongReferences("Concurrent Process Non-Strong References"); 47 static const ZStatPhaseConcurrent ZPhaseConcurrentResetRelocationSet("Concurrent Reset Relocation Set"); 48 static const ZStatPhaseConcurrent ZPhaseConcurrentSelectRelocationSet("Concurrent Select 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 VM_ZOperation : public VM_Operation { 55 private: 56 const uint _gc_id; 57 bool _gc_locked; 58 bool _success; 59 60 public: 61 VM_ZOperation() : 62 _gc_id(GCId::current()), 63 _gc_locked(false), 64 _success(false) {} 65 66 virtual bool needs_inactive_gc_locker() const { 67 // An inactive GC locker is needed in operations where we change the bad 68 // mask or move objects. Changing the bad mask will invalidate all oops, 69 // which makes it conceptually the same thing as moving all objects. 70 return false; 71 } 72 73 virtual bool do_operation() = 0; 74 75 virtual bool doit_prologue() { 76 Heap_lock->lock(); 77 return true; 78 } 79 80 virtual void doit() { 81 // Abort if GC locker state is incompatible 82 if (needs_inactive_gc_locker() && GCLocker::check_active_before_gc()) { 83 _gc_locked = true; 84 return; 85 } 86 87 // Setup GC id and active marker 88 GCIdMark gc_id_mark(_gc_id); 89 IsGCActiveMark gc_active_mark; 90 91 // Verify before operation 92 ZVerify::before_zoperation(); 93 94 // Execute operation 95 _success = do_operation(); 96 97 // Update statistics 98 ZStatSample(ZSamplerJavaThreads, Threads::number_of_threads()); 99 } 100 101 virtual void doit_epilogue() { 102 Heap_lock->unlock(); 103 } 104 105 bool gc_locked() const { 106 return _gc_locked; 107 } 108 109 bool success() const { 110 return _success; 111 } 112 }; 113 114 static bool should_clear_soft_references() { 115 // Clear if one or more allocations have stalled 116 const bool stalled = ZHeap::heap()->is_alloc_stalled(); 117 if (stalled) { 118 // Clear 119 return true; 120 } 121 122 // Clear if implied by the GC cause 123 const GCCause::Cause cause = ZCollectedHeap::heap()->gc_cause(); 124 if (cause == GCCause::_wb_full_gc || 125 cause == GCCause::_metadata_GC_clear_soft_refs) { 126 // Clear 127 return true; 128 } 129 130 // Don't clear 131 return false; 132 } 133 134 static bool should_boost_worker_threads() { 135 // Boost worker threads if one or more allocations have stalled 136 const bool stalled = ZHeap::heap()->is_alloc_stalled(); 137 if (stalled) { 138 // Boost 139 return true; 140 } 141 142 // Boost worker threads if implied by the GC cause 143 const GCCause::Cause cause = ZCollectedHeap::heap()->gc_cause(); 144 if (cause == GCCause::_wb_full_gc || 145 cause == GCCause::_java_lang_system_gc || 146 cause == GCCause::_metadata_GC_clear_soft_refs) { 147 // Boost 148 return true; 149 } 150 151 // Don't boost 152 return false; 153 } 154 155 class VM_ZMarkStart : public VM_ZOperation { 156 public: 157 virtual VMOp_Type type() const { 158 return VMOp_ZMarkStart; 159 } 160 161 virtual bool needs_inactive_gc_locker() const { 162 return true; 163 } 164 165 virtual bool do_operation() { 166 ZStatTimer timer(ZPhasePauseMarkStart); 167 ZServiceabilityPauseTracer tracer; 168 169 // Set up soft reference policy 170 const bool clear = should_clear_soft_references(); 171 ZHeap::heap()->set_soft_reference_policy(clear); 172 173 // Set up boost mode 174 const bool boost = should_boost_worker_threads(); 175 ZHeap::heap()->set_boost_worker_threads(boost); 176 177 ZCollectedHeap::heap()->increment_total_collections(true /* full */); 178 179 ZHeap::heap()->mark_start(); 180 return true; 181 } 182 }; 183 184 class VM_ZMarkEnd : public VM_ZOperation { 185 public: 186 virtual VMOp_Type type() const { 187 return VMOp_ZMarkEnd; 188 } 189 190 virtual bool do_operation() { 191 ZStatTimer timer(ZPhasePauseMarkEnd); 192 ZServiceabilityPauseTracer tracer; 193 return ZHeap::heap()->mark_end(); 194 } 195 }; 196 197 class VM_ZRelocateStart : public VM_ZOperation { 198 public: 199 virtual VMOp_Type type() const { 200 return VMOp_ZRelocateStart; 201 } 202 203 virtual bool needs_inactive_gc_locker() const { 204 return true; 205 } 206 207 virtual bool do_operation() { 208 ZStatTimer timer(ZPhasePauseRelocateStart); 209 ZServiceabilityPauseTracer tracer; 210 ZHeap::heap()->relocate_start(); 211 return true; 212 } 213 }; 214 215 class VM_ZVerify : public VM_Operation { 216 public: 217 virtual VMOp_Type type() const { 218 return VMOp_ZVerify; 219 } 220 221 virtual void doit() { 222 ZVerify::after_weak_processing(); 223 } 224 }; 225 226 ZDriver::ZDriver() : 227 _gc_cycle_port(), 228 _gc_locker_port() { 229 set_name("ZDriver"); 230 create_and_start(); 231 } 232 233 void ZDriver::collect(GCCause::Cause cause) { 234 switch (cause) { 235 case GCCause::_wb_young_gc: 236 case GCCause::_wb_conc_mark: 237 case GCCause::_wb_full_gc: 238 case GCCause::_dcmd_gc_run: 239 case GCCause::_java_lang_system_gc: 240 case GCCause::_full_gc_alot: 241 case GCCause::_scavenge_alot: 242 case GCCause::_jvmti_force_gc: 243 case GCCause::_metadata_GC_clear_soft_refs: 244 // Start synchronous GC 245 _gc_cycle_port.send_sync(cause); 246 break; 247 248 case GCCause::_z_timer: 249 case GCCause::_z_warmup: 250 case GCCause::_z_allocation_rate: 251 case GCCause::_z_allocation_stall: 252 case GCCause::_z_proactive: 253 case GCCause::_z_high_usage: 254 case GCCause::_metadata_GC_threshold: 255 // Start asynchronous GC 256 _gc_cycle_port.send_async(cause); 257 break; 258 259 case GCCause::_gc_locker: 260 // Restart VM operation previously blocked by the GC locker 261 _gc_locker_port.signal(); 262 break; 263 264 case GCCause::_wb_breakpoint: 265 ZBreakpoint::start_gc(); 266 _gc_cycle_port.send_async(cause); 267 break; 268 269 default: 270 // Other causes not supported 271 fatal("Unsupported GC cause (%s)", GCCause::to_string(cause)); 272 break; 273 } 274 } 275 276 template <typename T> 277 bool ZDriver::pause() { 278 for (;;) { 279 T op; 280 VMThread::execute(&op); 281 if (op.gc_locked()) { 282 // Wait for GC to become unlocked and restart the VM operation 283 ZStatTimer timer(ZCriticalPhaseGCLockerStall); 284 _gc_locker_port.wait(); 285 continue; 286 } 287 288 // Notify VM operation completed 289 _gc_locker_port.ack(); 290 291 return op.success(); 292 } 293 } 294 295 void ZDriver::pause_mark_start() { 296 pause<VM_ZMarkStart>(); 297 } 298 299 void ZDriver::concurrent_mark() { 300 ZStatTimer timer(ZPhaseConcurrentMark); 301 ZBreakpoint::at_after_marking_started(); 302 ZHeap::heap()->mark(true /* initial */); 303 ZBreakpoint::at_before_marking_completed(); 304 } 305 306 bool ZDriver::pause_mark_end() { 307 return pause<VM_ZMarkEnd>(); 308 } 309 310 void ZDriver::concurrent_mark_continue() { 311 ZStatTimer timer(ZPhaseConcurrentMarkContinue); 312 ZHeap::heap()->mark(false /* initial */); 313 } 314 315 void ZDriver::concurrent_process_non_strong_references() { 316 ZStatTimer timer(ZPhaseConcurrentProcessNonStrongReferences); 317 ZHeap::heap()->process_non_strong_references(); 318 } 319 320 void ZDriver::concurrent_reset_relocation_set() { 321 ZStatTimer timer(ZPhaseConcurrentResetRelocationSet); 322 ZHeap::heap()->reset_relocation_set(); 323 } 324 325 void ZDriver::pause_verify() { 326 if (VerifyBeforeGC || VerifyDuringGC || VerifyAfterGC) { 327 // Full verification 328 VM_Verify op; 329 VMThread::execute(&op); 330 } else if (ZVerifyRoots || ZVerifyObjects) { 331 // Limited verification 332 VM_ZVerify op; 333 VMThread::execute(&op); 334 } 335 } 336 337 void ZDriver::concurrent_select_relocation_set() { 338 ZStatTimer timer(ZPhaseConcurrentSelectRelocationSet); 339 ZHeap::heap()->select_relocation_set(); 340 } 341 342 void ZDriver::pause_relocate_start() { 343 pause<VM_ZRelocateStart>(); 344 } 345 346 void ZDriver::concurrent_relocate() { 347 ZStatTimer timer(ZPhaseConcurrentRelocated); 348 ZHeap::heap()->relocate(); 349 } 350 351 void ZDriver::check_out_of_memory() { 352 ZHeap::heap()->check_out_of_memory(); 353 } 354 355 class ZDriverGCScope : public StackObj { 356 private: 357 GCIdMark _gc_id; 358 GCCause::Cause _gc_cause; 359 GCCauseSetter _gc_cause_setter; 360 ZStatTimer _timer; 361 ZServiceabilityCycleTracer _tracer; 362 363 public: 364 ZDriverGCScope(GCCause::Cause cause) : 365 _gc_id(), 366 _gc_cause(cause), 367 _gc_cause_setter(ZCollectedHeap::heap(), cause), 368 _timer(ZPhaseCycle), 369 _tracer() { 370 // Update statistics 371 ZStatCycle::at_start(); 372 } 373 374 ~ZDriverGCScope() { 375 // Calculate boost factor 376 const double boost_factor = (double)ZHeap::heap()->nconcurrent_worker_threads() / 377 (double)ZHeap::heap()->nconcurrent_no_boost_worker_threads(); 378 379 // Update statistics 380 ZStatCycle::at_end(_gc_cause, boost_factor); 381 382 // Update data used by soft reference policy 383 Universe::update_heap_info_at_gc(); 384 385 // Signal that we have completed a visit to all live objects 386 Universe::heap()->next_whole_heap_examined(); 387 } 388 }; 389 390 void ZDriver::gc(GCCause::Cause cause) { 391 ZDriverGCScope scope(cause); 392 393 // Phase 1: Pause Mark Start 394 pause_mark_start(); 395 396 // Phase 2: Concurrent Mark 397 concurrent_mark(); 398 399 // Phase 3: Pause Mark End 400 while (!pause_mark_end()) { 401 // Phase 3.5: Concurrent Mark Continue 402 concurrent_mark_continue(); 403 } 404 405 // Phase 4: Concurrent Process Non-Strong References 406 concurrent_process_non_strong_references(); 407 408 // Phase 5: Concurrent Reset Relocation Set 409 concurrent_reset_relocation_set(); 410 411 // Phase 6: Pause Verify 412 pause_verify(); 413 414 // Phase 7: Concurrent Select Relocation Set 415 concurrent_select_relocation_set(); 416 417 // Phase 8: Pause Relocate Start 418 pause_relocate_start(); 419 420 // Phase 9: Concurrent Relocate 421 concurrent_relocate(); 422 } 423 424 void ZDriver::run_service() { 425 // Main loop 426 while (!should_terminate()) { 427 // Wait for GC request 428 const GCCause::Cause cause = _gc_cycle_port.receive(); 429 if (cause == GCCause::_no_gc) { 430 continue; 431 } 432 433 ZBreakpoint::at_before_gc(); 434 435 // Run GC 436 gc(cause); 437 438 // Notify GC completed 439 _gc_cycle_port.ack(); 440 441 // Check for out of memory condition 442 check_out_of_memory(); 443 444 ZBreakpoint::at_after_gc(); 445 } 446 } 447 448 void ZDriver::stop_service() { 449 _gc_cycle_port.send_async(GCCause::_no_gc); 450 }