1 /*
  2  * Copyright (c) 2015, 2021, 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/gcVMOperations.hpp"
 28 #include "gc/shared/isGCActiveMark.hpp"
 29 #include "gc/z/zAbort.inline.hpp"
 30 #include "gc/z/zBreakpoint.hpp"
 31 #include "gc/z/zCollectedHeap.hpp"
 32 #include "gc/z/zDriver.hpp"
 33 #include "gc/z/zHeap.inline.hpp"
 34 #include "gc/z/zMessagePort.inline.hpp"
 35 #include "gc/z/zServiceability.hpp"
 36 #include "gc/z/zStat.hpp"
 37 #include "gc/z/zVerify.hpp"
 38 #include "logging/log.hpp"
 39 #include "memory/universe.hpp"
 40 #include "runtime/vmOperations.hpp"
 41 #include "runtime/vmThread.hpp"
 42 
 43 static const ZStatPhaseCycle      ZPhaseCycle("Garbage Collection Cycle");
 44 static const ZStatPhasePause      ZPhasePauseMarkStart("Pause Mark Start");
 45 static const ZStatPhaseConcurrent ZPhaseConcurrentMark("Concurrent Mark");
 46 static const ZStatPhaseConcurrent ZPhaseConcurrentMarkContinue("Concurrent Mark Continue");
 47 static const ZStatPhaseConcurrent ZPhaseConcurrentMarkFree("Concurrent Mark Free");
 48 static const ZStatPhasePause      ZPhasePauseMarkEnd("Pause Mark End");
 49 static const ZStatPhaseConcurrent ZPhaseConcurrentProcessNonStrongReferences("Concurrent Process Non-Strong References");
 50 static const ZStatPhaseConcurrent ZPhaseConcurrentResetRelocationSet("Concurrent Reset Relocation Set");
 51 static const ZStatPhaseConcurrent ZPhaseConcurrentSelectRelocationSet("Concurrent Select Relocation Set");
 52 static const ZStatPhasePause      ZPhasePauseRelocateStart("Pause Relocate Start");
 53 static const ZStatPhaseConcurrent ZPhaseConcurrentRelocated("Concurrent Relocate");
 54 static const ZStatCriticalPhase   ZCriticalPhaseGCLockerStall("GC Locker Stall", false /* verbose */);
 55 static const ZStatSampler         ZSamplerJavaThreads("System", "Java Threads", ZStatUnitThreads);
 56 
 57 ZDriverRequest::ZDriverRequest() :
 58     ZDriverRequest(GCCause::_no_gc) {}
 59 
 60 ZDriverRequest::ZDriverRequest(GCCause::Cause cause) :
 61     ZDriverRequest(cause, ConcGCThreads) {}
 62 
 63 ZDriverRequest::ZDriverRequest(GCCause::Cause cause, uint nworkers) :
 64     _cause(cause),
 65     _nworkers(nworkers) {}
 66 
 67 bool ZDriverRequest::operator==(const ZDriverRequest& other) const {
 68   return _cause == other._cause;
 69 }
 70 
 71 GCCause::Cause ZDriverRequest::cause() const {
 72   return _cause;
 73 }
 74 
 75 uint ZDriverRequest::nworkers() const {
 76   return _nworkers;
 77 }
 78 
 79 class VM_ZOperation : public VM_Operation {
 80 private:
 81   const uint _gc_id;
 82   bool       _gc_locked;
 83   bool       _success;
 84 
 85 public:
 86   VM_ZOperation() :
 87       _gc_id(GCId::current()),
 88       _gc_locked(false),
 89       _success(false) {}
 90 
 91   virtual bool needs_inactive_gc_locker() const {
 92     // An inactive GC locker is needed in operations where we change the bad
 93     // mask or move objects. Changing the bad mask will invalidate all oops,
 94     // which makes it conceptually the same thing as moving all objects.
 95     return false;
 96   }
 97 
 98   virtual bool skip_thread_oop_barriers() const {
 99     return true;
100   }
101 
102   virtual bool do_operation() = 0;
103 
104   virtual bool doit_prologue() {
105     Heap_lock->lock();
106     return true;
107   }
108 
109   virtual void doit() {
110     // Abort if GC locker state is incompatible
111     if (needs_inactive_gc_locker() && GCLocker::check_active_before_gc()) {
112       _gc_locked = true;
113       return;
114     }
115 
116     // Setup GC id and active marker
117     GCIdMark gc_id_mark(_gc_id);
118     IsGCActiveMark gc_active_mark;
119 
120     // Verify before operation
121     ZVerify::before_zoperation();
122 
123     // Execute operation
124     _success = do_operation();
125 
126     // Update statistics
127     ZStatSample(ZSamplerJavaThreads, Threads::number_of_threads());
128   }
129 
130   virtual void doit_epilogue() {
131     Heap_lock->unlock();
132   }
133 
134   bool gc_locked() const {
135     return _gc_locked;
136   }
137 
138   bool success() const {
139     return _success;
140   }
141 };
142 
143 class VM_ZMarkStart : public VM_ZOperation {
144 public:
145   virtual VMOp_Type type() const {
146     return VMOp_ZMarkStart;
147   }
148 
149   virtual bool needs_inactive_gc_locker() const {
150     return true;
151   }
152 
153   virtual bool do_operation() {
154     ZStatTimer timer(ZPhasePauseMarkStart);
155     ZServiceabilityPauseTracer tracer;
156 
157     ZCollectedHeap::heap()->increment_total_collections(true /* full */);
158 
159     ZHeap::heap()->mark_start();
160     return true;
161   }
162 };
163 
164 class VM_ZMarkEnd : public VM_ZOperation {
165 public:
166   virtual VMOp_Type type() const {
167     return VMOp_ZMarkEnd;
168   }
169 
170   virtual bool do_operation() {
171     ZStatTimer timer(ZPhasePauseMarkEnd);
172     ZServiceabilityPauseTracer tracer;
173     return ZHeap::heap()->mark_end();
174   }
175 };
176 
177 class VM_ZRelocateStart : public VM_ZOperation {
178 public:
179   virtual VMOp_Type type() const {
180     return VMOp_ZRelocateStart;
181   }
182 
183   virtual bool needs_inactive_gc_locker() const {
184     return true;
185   }
186 
187   virtual bool do_operation() {
188     ZStatTimer timer(ZPhasePauseRelocateStart);
189     ZServiceabilityPauseTracer tracer;
190     ZHeap::heap()->relocate_start();
191     return true;
192   }
193 };
194 
195 class VM_ZVerify : public VM_Operation {
196 public:
197   virtual VMOp_Type type() const {
198     return VMOp_ZVerify;
199   }
200 
201   virtual bool skip_thread_oop_barriers() const {
202     return true;
203   }
204 
205   virtual void doit() {
206     ZVerify::after_weak_processing();
207   }
208 };
209 
210 ZDriver::ZDriver() :
211     _gc_cycle_port(),
212     _gc_locker_port() {
213   set_name("ZDriver");
214   create_and_start();
215 }
216 
217 bool ZDriver::is_busy() const {
218   return _gc_cycle_port.is_busy();
219 }
220 
221 void ZDriver::collect(const ZDriverRequest& request) {
222   switch (request.cause()) {
223   case GCCause::_wb_young_gc:
224   case GCCause::_wb_conc_mark:
225   case GCCause::_wb_full_gc:
226   case GCCause::_dcmd_gc_run:
227   case GCCause::_java_lang_system_gc:
228   case GCCause::_full_gc_alot:
229   case GCCause::_scavenge_alot:
230   case GCCause::_jvmti_force_gc:
231   case GCCause::_metadata_GC_clear_soft_refs:

232     // Start synchronous GC
233     _gc_cycle_port.send_sync(request);
234     break;
235 
236   case GCCause::_z_timer:
237   case GCCause::_z_warmup:
238   case GCCause::_z_allocation_rate:
239   case GCCause::_z_allocation_stall:
240   case GCCause::_z_proactive:
241   case GCCause::_z_high_usage:
242   case GCCause::_metadata_GC_threshold:
243     // Start asynchronous GC
244     _gc_cycle_port.send_async(request);
245     break;
246 
247   case GCCause::_gc_locker:
248     // Restart VM operation previously blocked by the GC locker
249     _gc_locker_port.signal();
250     break;
251 
252   case GCCause::_wb_breakpoint:
253     ZBreakpoint::start_gc();
254     _gc_cycle_port.send_async(request);
255     break;
256 
257   default:
258     // Other causes not supported
259     fatal("Unsupported GC cause (%s)", GCCause::to_string(request.cause()));
260     break;
261   }
262 }
263 
264 template <typename T>
265 bool ZDriver::pause() {
266   for (;;) {
267     T op;
268     VMThread::execute(&op);
269     if (op.gc_locked()) {
270       // Wait for GC to become unlocked and restart the VM operation
271       ZStatTimer timer(ZCriticalPhaseGCLockerStall);
272       _gc_locker_port.wait();
273       continue;
274     }
275 
276     // Notify VM operation completed
277     _gc_locker_port.ack();
278 
279     return op.success();
280   }
281 }
282 
283 void ZDriver::pause_mark_start() {
284   pause<VM_ZMarkStart>();
285 }
286 
287 void ZDriver::concurrent_mark() {
288   ZStatTimer timer(ZPhaseConcurrentMark);
289   ZBreakpoint::at_after_marking_started();
290   ZHeap::heap()->mark(true /* initial */);
291   ZBreakpoint::at_before_marking_completed();
292 }
293 
294 bool ZDriver::pause_mark_end() {
295   return pause<VM_ZMarkEnd>();
296 }
297 
298 void ZDriver::concurrent_mark_continue() {
299   ZStatTimer timer(ZPhaseConcurrentMarkContinue);
300   ZHeap::heap()->mark(false /* initial */);
301 }
302 
303 void ZDriver::concurrent_mark_free() {
304   ZStatTimer timer(ZPhaseConcurrentMarkFree);
305   ZHeap::heap()->mark_free();
306 }
307 
308 void ZDriver::concurrent_process_non_strong_references() {
309   ZStatTimer timer(ZPhaseConcurrentProcessNonStrongReferences);
310   ZBreakpoint::at_after_reference_processing_started();
311   ZHeap::heap()->process_non_strong_references();
312 }
313 
314 void ZDriver::concurrent_reset_relocation_set() {
315   ZStatTimer timer(ZPhaseConcurrentResetRelocationSet);
316   ZHeap::heap()->reset_relocation_set();
317 }
318 
319 void ZDriver::pause_verify() {
320   if (VerifyBeforeGC || VerifyDuringGC || VerifyAfterGC) {
321     // Full verification
322     VM_Verify op;
323     VMThread::execute(&op);
324   } else if (ZVerifyRoots || ZVerifyObjects) {
325     // Limited verification
326     VM_ZVerify op;
327     VMThread::execute(&op);
328   }
329 }
330 
331 void ZDriver::concurrent_select_relocation_set() {
332   ZStatTimer timer(ZPhaseConcurrentSelectRelocationSet);
333   ZHeap::heap()->select_relocation_set();
334 }
335 
336 void ZDriver::pause_relocate_start() {
337   pause<VM_ZRelocateStart>();
338 }
339 
340 void ZDriver::concurrent_relocate() {
341   ZStatTimer timer(ZPhaseConcurrentRelocated);
342   ZHeap::heap()->relocate();
343 }
344 
345 void ZDriver::check_out_of_memory() {
346   ZHeap::heap()->check_out_of_memory();
347 }
348 
349 static bool should_clear_soft_references(const ZDriverRequest& request) {
350   // Clear soft references if implied by the GC cause
351   if (request.cause() == GCCause::_wb_full_gc ||
352       request.cause() == GCCause::_metadata_GC_clear_soft_refs ||
353       request.cause() == GCCause::_z_allocation_stall) {
354     // Clear
355     return true;
356   }
357 
358   // Don't clear
359   return false;
360 }
361 
362 static uint select_active_worker_threads_dynamic(const ZDriverRequest& request) {
363   // Use requested number of worker threads
364   return request.nworkers();
365 }
366 
367 static uint select_active_worker_threads_static(const ZDriverRequest& request) {
368   const GCCause::Cause cause = request.cause();
369   const uint nworkers = request.nworkers();
370 
371   // Boost number of worker threads if implied by the GC cause
372   if (cause == GCCause::_wb_full_gc ||
373       cause == GCCause::_java_lang_system_gc ||
374       cause == GCCause::_metadata_GC_clear_soft_refs ||
375       cause == GCCause::_z_allocation_stall) {
376     // Boost
377     const uint boosted_nworkers = MAX2(nworkers, ParallelGCThreads);
378     return boosted_nworkers;
379   }
380 
381   // Use requested number of worker threads
382   return nworkers;
383 }
384 
385 static uint select_active_worker_threads(const ZDriverRequest& request) {
386   if (UseDynamicNumberOfGCThreads) {
387     return select_active_worker_threads_dynamic(request);
388   } else {
389     return select_active_worker_threads_static(request);
390   }
391 }
392 
393 class ZDriverGCScope : public StackObj {
394 private:
395   GCIdMark                   _gc_id;
396   GCCause::Cause             _gc_cause;
397   GCCauseSetter              _gc_cause_setter;
398   ZStatTimer                 _timer;
399   ZServiceabilityCycleTracer _tracer;
400 
401 public:
402   ZDriverGCScope(const ZDriverRequest& request) :
403       _gc_id(),
404       _gc_cause(request.cause()),
405       _gc_cause_setter(ZCollectedHeap::heap(), _gc_cause),
406       _timer(ZPhaseCycle),
407       _tracer() {
408     // Update statistics
409     ZStatCycle::at_start();
410 
411     // Set up soft reference policy
412     const bool clear = should_clear_soft_references(request);
413     ZHeap::heap()->set_soft_reference_policy(clear);
414 
415     // Select number of worker threads to use
416     const uint nworkers = select_active_worker_threads(request);
417     ZHeap::heap()->set_active_workers(nworkers);
418   }
419 
420   ~ZDriverGCScope() {
421     // Update statistics
422     ZStatCycle::at_end(_gc_cause, ZHeap::heap()->active_workers());
423 
424     // Update data used by soft reference policy
425     Universe::heap()->update_capacity_and_used_at_gc();
426 
427     // Signal that we have completed a visit to all live objects
428     Universe::heap()->record_whole_heap_examined_timestamp();
429   }
430 };
431 
432 // Macro to execute a termination check after a concurrent phase. Note
433 // that it's important that the termination check comes after the call
434 // to the function f, since we can't abort between pause_relocate_start()
435 // and concurrent_relocate(). We need to let concurrent_relocate() call
436 // abort_page() on the remaining entries in the relocation set.
437 #define concurrent(f)                 \
438   do {                                \
439     concurrent_##f();                 \
440     if (should_terminate()) {         \
441       return;                         \
442     }                                 \
443   } while (false)
444 
445 void ZDriver::gc(const ZDriverRequest& request) {
446   ZDriverGCScope scope(request);
447 
448   // Phase 1: Pause Mark Start
449   pause_mark_start();
450 
451   // Phase 2: Concurrent Mark
452   concurrent(mark);
453 
454   // Phase 3: Pause Mark End
455   while (!pause_mark_end()) {
456     // Phase 3.5: Concurrent Mark Continue
457     concurrent(mark_continue);
458   }
459 
460   // Phase 4: Concurrent Mark Free
461   concurrent(mark_free);
462 
463   // Phase 5: Concurrent Process Non-Strong References
464   concurrent(process_non_strong_references);
465 
466   // Phase 6: Concurrent Reset Relocation Set
467   concurrent(reset_relocation_set);
468 
469   // Phase 7: Pause Verify
470   pause_verify();
471 
472   // Phase 8: Concurrent Select Relocation Set
473   concurrent(select_relocation_set);
474 
475   // Phase 9: Pause Relocate Start
476   pause_relocate_start();
477 
478   // Phase 10: Concurrent Relocate
479   concurrent(relocate);
480 }
481 
482 void ZDriver::run_service() {
483   // Main loop
484   while (!should_terminate()) {
485     // Wait for GC request
486     const ZDriverRequest request = _gc_cycle_port.receive();
487     if (request.cause() == GCCause::_no_gc) {
488       continue;
489     }
490 
491     ZBreakpoint::at_before_gc();
492 
493     // Run GC
494     gc(request);
495 
496     if (should_terminate()) {
497       // Abort
498       break;
499     }
500 
501     // Notify GC completed
502     _gc_cycle_port.ack();
503 
504     // Check for out of memory condition
505     check_out_of_memory();
506 
507     ZBreakpoint::at_after_gc();
508   }
509 }
510 
511 void ZDriver::stop_service() {
512   ZAbort::abort();
513   _gc_cycle_port.send_async(GCCause::_no_gc);
514 }
--- EOF ---