1 /* 2 * Copyright (c) 2017, 2019, Red Hat, Inc. 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 25 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHUTILS_HPP 26 #define SHARE_GC_SHENANDOAH_SHENANDOAHUTILS_HPP 27 28 #include "gc/shared/gcCause.hpp" 29 #include "gc/shared/gcTraceTime.inline.hpp" 30 #include "gc/shared/gcVMOperations.hpp" 31 #include "gc/shared/isGCActiveMark.hpp" 32 #include "gc/shared/suspendibleThreadSet.hpp" 33 #include "gc/shared/weakProcessorPhaseTimes.hpp" 34 #include "gc/shenandoah/shenandoahPhaseTimings.hpp" 35 #include "gc/shenandoah/shenandoahThreadLocalData.hpp" 36 #include "jfr/jfrEvents.hpp" 37 #include "memory/allocation.hpp" 38 #include "runtime/safepoint.hpp" 39 #include "runtime/vmThread.hpp" 40 #include "runtime/vmOperations.hpp" 41 #include "services/memoryService.hpp" 42 43 class GCTimer; 44 45 class ShenandoahGCSession : public StackObj { 46 private: 47 ShenandoahHeap* const _heap; 48 GCTimer* const _timer; 49 GCTracer* const _tracer; 50 51 TraceMemoryManagerStats _trace_cycle; 52 public: 53 ShenandoahGCSession(GCCause::Cause cause); 54 ~ShenandoahGCSession(); 55 }; 56 57 class ShenandoahPausePhase : public StackObj { 58 private: 59 GCTraceTimeWrapper<LogLevel::Info, LOG_TAGS(gc)> _tracer; 60 ConcurrentGCTimer* const _timer; 61 62 public: 63 ShenandoahPausePhase(const char* title, bool log_heap_usage = false); 64 ~ShenandoahPausePhase(); 65 }; 66 67 class ShenandoahConcurrentPhase : public StackObj { 68 private: 69 GCTraceTimeWrapper<LogLevel::Info, LOG_TAGS(gc)> _tracer; 70 ConcurrentGCTimer* const _timer; 71 72 public: 73 ShenandoahConcurrentPhase(const char* title, bool log_heap_usage = false); 74 ~ShenandoahConcurrentPhase(); 75 }; 76 77 class ShenandoahGCPhase : public StackObj { 78 private: 79 static ShenandoahPhaseTimings::Phase _current_phase; 80 81 ShenandoahPhaseTimings* const _timings; 82 const ShenandoahPhaseTimings::Phase _phase; 83 ShenandoahPhaseTimings::Phase _parent_phase; 84 double _start; 85 86 public: 87 ShenandoahGCPhase(ShenandoahPhaseTimings::Phase phase); 88 ~ShenandoahGCPhase(); 89 90 static ShenandoahPhaseTimings::Phase current_phase() { return _current_phase; } 91 92 static bool is_current_phase_valid(); 93 }; 94 95 class ShenandoahGCSubPhase: public ShenandoahGCPhase { 96 private: 97 ConcurrentGCTimer* const _timer; 98 99 public: 100 ShenandoahGCSubPhase(ShenandoahPhaseTimings::Phase phase); 101 ~ShenandoahGCSubPhase(); 102 }; 103 104 class ShenandoahGCWorkerPhase : public StackObj { 105 private: 106 ShenandoahPhaseTimings* const _timings; 107 const ShenandoahPhaseTimings::Phase _phase; 108 public: 109 ShenandoahGCWorkerPhase(ShenandoahPhaseTimings::Phase phase); 110 ~ShenandoahGCWorkerPhase(); 111 }; 112 113 // Aggregates all the things that should happen before/after the pause. 114 class ShenandoahGCPauseMark : public StackObj { 115 private: 116 ShenandoahHeap* const _heap; 117 const GCIdMark _gc_id_mark; 118 const SvcGCMarker _svc_gc_mark; 119 const IsGCActiveMark _is_gc_active_mark; 120 TraceMemoryManagerStats _trace_pause; 121 122 public: 123 ShenandoahGCPauseMark(uint gc_id, SvcGCMarker::reason_type type); 124 }; 125 126 class ShenandoahSafepoint : public AllStatic { 127 public: 128 // check if Shenandoah GC safepoint is in progress 129 static inline bool is_at_shenandoah_safepoint() { 130 if (!SafepointSynchronize::is_at_safepoint()) return false; 131 132 VM_Operation* vm_op = VMThread::vm_operation(); 133 if (vm_op == NULL) return false; 134 135 VM_Operation::VMOp_Type type = vm_op->type(); 136 return type == VM_Operation::VMOp_ShenandoahInitMark || 137 type == VM_Operation::VMOp_ShenandoahFinalMarkStartEvac || 138 type == VM_Operation::VMOp_ShenandoahInitUpdateRefs || 139 type == VM_Operation::VMOp_ShenandoahFinalUpdateRefs || 140 type == VM_Operation::VMOp_ShenandoahFullGC || 141 type == VM_Operation::VMOp_ShenandoahDegeneratedGC; 142 } 143 }; 144 145 class ShenandoahWorkerSession : public StackObj { 146 protected: 147 uint _worker_id; 148 149 ShenandoahWorkerSession(uint worker_id); 150 ~ShenandoahWorkerSession(); 151 public: 152 static inline uint worker_id() { 153 Thread* thr = Thread::current(); 154 uint id = ShenandoahThreadLocalData::worker_id(thr); 155 assert(id != ShenandoahThreadLocalData::INVALID_WORKER_ID, "Worker session has not been created"); 156 return id; 157 } 158 }; 159 160 class ShenandoahConcurrentWorkerSession : public ShenandoahWorkerSession { 161 private: 162 EventGCPhaseConcurrent _event; 163 164 public: 165 ShenandoahConcurrentWorkerSession(uint worker_id) : ShenandoahWorkerSession(worker_id) { } 166 ~ShenandoahConcurrentWorkerSession(); 167 }; 168 169 class ShenandoahParallelWorkerSession : public ShenandoahWorkerSession { 170 private: 171 EventGCPhaseParallel _event; 172 173 public: 174 ShenandoahParallelWorkerSession(uint worker_id) : ShenandoahWorkerSession(worker_id) { } 175 ~ShenandoahParallelWorkerSession(); 176 }; 177 178 class ShenandoahSuspendibleThreadSetJoiner { 179 private: 180 SuspendibleThreadSetJoiner _joiner; 181 public: 182 ShenandoahSuspendibleThreadSetJoiner(bool active = true) : _joiner(active) { 183 assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "STS should be joined before evac scope"); 184 } 185 ~ShenandoahSuspendibleThreadSetJoiner() { 186 assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "STS should be left after evac scope"); 187 } 188 }; 189 190 class ShenandoahSuspendibleThreadSetLeaver { 191 private: 192 SuspendibleThreadSetLeaver _leaver; 193 public: 194 ShenandoahSuspendibleThreadSetLeaver(bool active = true) : _leaver(active) { 195 assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "STS should be left after evac scope"); 196 } 197 ~ShenandoahSuspendibleThreadSetLeaver() { 198 assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "STS should be joined before evac scope"); 199 } 200 }; 201 202 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHUTILS_HPP