rev 60421 : [mq]: 8248401-stefank-review

   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 };
 386 
 387 void ZDriver::gc(GCCause::Cause cause) {
 388   ZDriverGCScope scope(cause);
 389 
 390   // Phase 1: Pause Mark Start
 391   pause_mark_start();
 392 
 393   // Phase 2: Concurrent Mark
 394   concurrent_mark();
 395 
 396   // Phase 3: Pause Mark End
 397   while (!pause_mark_end()) {
 398     // Phase 3.5: Concurrent Mark Continue
 399     concurrent_mark_continue();
 400   }
 401 
 402   // Phase 4: Concurrent Process Non-Strong References
 403   concurrent_process_non_strong_references();
 404 
 405   // Phase 5: Concurrent Reset Relocation Set
 406   concurrent_reset_relocation_set();
 407 
 408   // Phase 6: Pause Verify
 409   pause_verify();
 410 
 411   // Phase 7: Concurrent Select Relocation Set
 412   concurrent_select_relocation_set();
 413 
 414   // Phase 8: Pause Relocate Start
 415   pause_relocate_start();
 416 
 417   // Phase 9: Concurrent Relocate
 418   concurrent_relocate();
 419 }
 420 
 421 void ZDriver::run_service() {
 422   // Main loop
 423   while (!should_terminate()) {
 424     // Wait for GC request
 425     const GCCause::Cause cause = _gc_cycle_port.receive();
 426     if (cause == GCCause::_no_gc) {
 427       continue;
 428     }
 429 
 430     ZBreakpoint::at_before_gc();
 431 
 432     // Run GC
 433     gc(cause);
 434 
 435     // Notify GC completed
 436     _gc_cycle_port.ack();
 437 
 438     // Check for out of memory condition
 439     check_out_of_memory();
 440 
 441     ZBreakpoint::at_after_gc();
 442   }
 443 }
 444 
 445 void ZDriver::stop_service() {
 446   _gc_cycle_port.send_async(GCCause::_no_gc);
 447 }
--- EOF ---