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:
VM_ZOperation()61   VM_ZOperation() :
62       _gc_id(GCId::current()),
63       _gc_locked(false),
64       _success(false) {}
65 
needs_inactive_gc_locker() const66   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 
doit_prologue()75   virtual bool doit_prologue() {
76     Heap_lock->lock();
77     return true;
78   }
79 
doit()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 
doit_epilogue()101   virtual void doit_epilogue() {
102     Heap_lock->unlock();
103   }
104 
gc_locked() const105   bool gc_locked() const {
106     return _gc_locked;
107   }
108 
success() const109   bool success() const {
110     return _success;
111   }
112 };
113 
should_clear_soft_references()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 
should_boost_worker_threads()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:
type() const157   virtual VMOp_Type type() const {
158     return VMOp_ZMarkStart;
159   }
160 
needs_inactive_gc_locker() const161   virtual bool needs_inactive_gc_locker() const {
162     return true;
163   }
164 
do_operation()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:
type() const186   virtual VMOp_Type type() const {
187     return VMOp_ZMarkEnd;
188   }
189 
do_operation()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:
type() const199   virtual VMOp_Type type() const {
200     return VMOp_ZRelocateStart;
201   }
202 
needs_inactive_gc_locker() const203   virtual bool needs_inactive_gc_locker() const {
204     return true;
205   }
206 
do_operation()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:
type() const217   virtual VMOp_Type type() const {
218     return VMOp_ZVerify;
219   }
220 
doit()221   virtual void doit() {
222     ZVerify::after_weak_processing();
223   }
224 };
225 
ZDriver()226 ZDriver::ZDriver() :
227     _gc_cycle_port(),
228     _gc_locker_port() {
229   set_name("ZDriver");
230   create_and_start();
231 }
232 
collect(GCCause::Cause cause)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>
pause()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 
pause_mark_start()295 void ZDriver::pause_mark_start() {
296   pause<VM_ZMarkStart>();
297 }
298 
concurrent_mark()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 
pause_mark_end()306 bool ZDriver::pause_mark_end() {
307   return pause<VM_ZMarkEnd>();
308 }
309 
concurrent_mark_continue()310 void ZDriver::concurrent_mark_continue() {
311   ZStatTimer timer(ZPhaseConcurrentMarkContinue);
312   ZHeap::heap()->mark(false /* initial */);
313 }
314 
concurrent_process_non_strong_references()315 void ZDriver::concurrent_process_non_strong_references() {
316   ZStatTimer timer(ZPhaseConcurrentProcessNonStrongReferences);
317   ZHeap::heap()->process_non_strong_references();
318 }
319 
concurrent_reset_relocation_set()320 void ZDriver::concurrent_reset_relocation_set() {
321   ZStatTimer timer(ZPhaseConcurrentResetRelocationSet);
322   ZHeap::heap()->reset_relocation_set();
323 }
324 
pause_verify()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 
concurrent_select_relocation_set()337 void ZDriver::concurrent_select_relocation_set() {
338   ZStatTimer timer(ZPhaseConcurrentSelectRelocationSet);
339   ZHeap::heap()->select_relocation_set();
340 }
341 
pause_relocate_start()342 void ZDriver::pause_relocate_start() {
343   pause<VM_ZRelocateStart>();
344 }
345 
concurrent_relocate()346 void ZDriver::concurrent_relocate() {
347   ZStatTimer timer(ZPhaseConcurrentRelocated);
348   ZHeap::heap()->relocate();
349 }
350 
check_out_of_memory()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:
ZDriverGCScope(GCCause::Cause cause)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 
~ZDriverGCScope()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 
gc(GCCause::Cause cause)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 
run_service()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 
stop_service()445 void ZDriver::stop_service() {
446   _gc_cycle_port.send_async(GCCause::_no_gc);
447 }
448