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