1 /* 2 * Copyright (c) 2017, 2019, Red Hat, Inc. All rights reserved. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 * 22 */ 23 24 #ifndef SHARE_VM_GC_SHENANDOAHUTILS_HPP 25 #define SHARE_VM_GC_SHENANDOAHUTILS_HPP 26 27 #include "gc/shared/gcCause.hpp" 28 #include "gc/shared/gcTraceTime.inline.hpp" 29 #include "gc/shared/vmGCOperations.hpp" 30 #include "gc/shared/isGCActiveMark.hpp" 31 #include "gc/shared/suspendibleThreadSet.hpp" 32 #include "gc/shenandoah/shenandoahPhaseTimings.hpp" 33 #include "gc/shenandoah/shenandoahThreadLocalData.hpp" 34 #include "jfr/jfrEvents.hpp" 35 #include "memory/allocation.hpp" 36 #include "runtime/safepoint.hpp" 37 #include "runtime/vmThread.hpp" 38 #include "runtime/vmOperations.hpp" 39 #include "services/memoryService.hpp" 40 41 class GCTimer; 42 43 class ShenandoahGCSession : public StackObj { 44 private: 45 ShenandoahHeap* const _heap; 46 GCTimer* const _timer; 47 GCTracer* const _tracer; 48 49 TraceMemoryManagerStats _trace_cycle; 50 public: 51 ShenandoahGCSession(GCCause::Cause cause); 52 ~ShenandoahGCSession(); 53 }; 54 55 class ShenandoahPausePhase : public StackObj { 56 private: 57 GCTraceTimeImplWrapper<LogLevel::Info, LOG_TAGS(gc)> _tracer; 58 ConcurrentGCTimer* const _timer; 59 60 public: 61 ShenandoahPausePhase(const char* title, bool log_heap_usage = false); 62 ~ShenandoahPausePhase(); 63 }; 64 65 class ShenandoahConcurrentPhase : public StackObj { 66 private: 67 GCTraceTimeImplWrapper<LogLevel::Info, LOG_TAGS(gc)> _tracer; 68 ConcurrentGCTimer* const _timer; 69 70 public: 71 ShenandoahConcurrentPhase(const char* title, bool log_heap_usage = false); 72 ~ShenandoahConcurrentPhase(); 73 }; 74 75 class ShenandoahGCPhase : public StackObj { 76 private: 77 static ShenandoahPhaseTimings::Phase _current_phase; 78 79 ShenandoahPhaseTimings* const _timings; 80 const ShenandoahPhaseTimings::Phase _phase; 81 ShenandoahPhaseTimings::Phase _parent_phase; 82 double _start; 83 84 public: 85 ShenandoahGCPhase(ShenandoahPhaseTimings::Phase phase); 86 ~ShenandoahGCPhase(); 87 88 static ShenandoahPhaseTimings::Phase current_phase() { return _current_phase; } 89 90 static bool is_current_phase_valid(); 91 }; 92 93 class ShenandoahGCSubPhase: public ShenandoahGCPhase { 94 private: 95 ConcurrentGCTimer* const _timer; 96 97 public: 98 ShenandoahGCSubPhase(ShenandoahPhaseTimings::Phase phase); 99 ~ShenandoahGCSubPhase(); 100 }; 101 102 class ShenandoahGCWorkerPhase : public StackObj { 103 private: 104 ShenandoahPhaseTimings* const _timings; 105 const ShenandoahPhaseTimings::Phase _phase; 106 public: 107 ShenandoahGCWorkerPhase(ShenandoahPhaseTimings::Phase phase); 108 ~ShenandoahGCWorkerPhase(); 109 }; 110 111 // Aggregates all the things that should happen before/after the pause. 112 class ShenandoahGCPauseMark : public StackObj { 113 private: 114 ShenandoahHeap* const _heap; 115 const GCIdMark _gc_id_mark; 116 const SvcGCMarker _svc_gc_mark; 117 const IsGCActiveMark _is_gc_active_mark; 118 TraceMemoryManagerStats _trace_pause; 119 120 public: 121 ShenandoahGCPauseMark(uint gc_id, SvcGCMarker::reason_type type); 122 }; 123 124 class ShenandoahSafepoint : public AllStatic { 125 public: 126 // check if Shenandoah GC safepoint is in progress 127 static inline bool is_at_shenandoah_safepoint() { 128 if (!SafepointSynchronize::is_at_safepoint()) return false; 129 130 VM_Operation* vm_op = VMThread::vm_operation(); 131 if (vm_op == NULL) return false; 132 133 VM_Operation::VMOp_Type type = vm_op->type(); 134 return type == VM_Operation::VMOp_ShenandoahInitMark || 135 type == VM_Operation::VMOp_ShenandoahFinalMarkStartEvac || 136 type == VM_Operation::VMOp_ShenandoahInitUpdateRefs || 137 type == VM_Operation::VMOp_ShenandoahFinalUpdateRefs || 138 type == VM_Operation::VMOp_ShenandoahFullGC || 139 type == VM_Operation::VMOp_ShenandoahDegeneratedGC; 140 } 141 }; 142 143 class ShenandoahWorkerSession : public StackObj { 144 protected: 145 uint _worker_id; 146 147 ShenandoahWorkerSession(uint worker_id); 148 ~ShenandoahWorkerSession(); 149 public: 150 static inline uint worker_id() { 151 Thread* thr = Thread::current(); 152 uint id = ShenandoahThreadLocalData::worker_id(thr); 153 assert(id != ShenandoahThreadLocalData::INVALID_WORKER_ID, "Worker session has not been created"); 154 return id; 155 } 156 }; 157 158 class ShenandoahConcurrentWorkerSession : public ShenandoahWorkerSession { 159 public: 160 ShenandoahConcurrentWorkerSession(uint worker_id) : ShenandoahWorkerSession(worker_id) { } 161 ~ShenandoahConcurrentWorkerSession(); 162 }; 163 164 class ShenandoahParallelWorkerSession : public ShenandoahWorkerSession { 165 public: 166 ShenandoahParallelWorkerSession(uint worker_id) : ShenandoahWorkerSession(worker_id) { } 167 ~ShenandoahParallelWorkerSession(); 168 }; 169 170 class ShenandoahSuspendibleThreadSetJoiner { 171 private: 172 SuspendibleThreadSetJoiner _joiner; 173 public: 174 ShenandoahSuspendibleThreadSetJoiner(bool active = true) : _joiner(active) { 175 assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "STS should be joined before evac scope"); 176 } 177 ~ShenandoahSuspendibleThreadSetJoiner() { 178 assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "STS should be left after evac scope"); 179 } 180 }; 181 182 class ShenandoahSuspendibleThreadSetLeaver { 183 private: 184 SuspendibleThreadSetLeaver _leaver; 185 public: 186 ShenandoahSuspendibleThreadSetLeaver(bool active = true) : _leaver(active) { 187 assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "STS should be left after evac scope"); 188 } 189 ~ShenandoahSuspendibleThreadSetLeaver() { 190 assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "STS should be joined before evac scope"); 191 } 192 }; 193 194 class ShenandoahUtils { 195 public: 196 static size_t round_up_power_of_2(size_t value); 197 }; 198 199 #endif // SHARE_VM_GC_SHENANDOAHUTILS_HPP