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_GC_SHENANDOAH_SHENANDOAHUTILS_HPP
25#define SHARE_GC_SHENANDOAH_SHENANDOAHUTILS_HPP
26
27#include "gc/shared/gcCause.hpp"
28#include "gc/shared/gcVMOperations.hpp"
29#include "gc/shared/isGCActiveMark.hpp"
30#include "gc/shared/suspendibleThreadSet.hpp"
31#include "gc/shared/weakProcessorPhaseTimes.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
41class GCTimer;
42class GCTracer;
43
44class ShenandoahGCSession : public StackObj {
45private:
46 ShenandoahHeap* const _heap;
47 GCTimer* const _timer;
48 GCTracer* const _tracer;
49
50 TraceMemoryManagerStats _trace_cycle;
51public:
52 ShenandoahGCSession(GCCause::Cause cause);
53 ~ShenandoahGCSession();
54};
55
56class ShenandoahGCPhase : public StackObj {
57private:
58 static const ShenandoahPhaseTimings::Phase _invalid_phase = ShenandoahPhaseTimings::_num_phases;
59 static ShenandoahPhaseTimings::Phase _current_phase;
60
61 ShenandoahHeap* const _heap;
62 const ShenandoahPhaseTimings::Phase _phase;
63 ShenandoahPhaseTimings::Phase _parent_phase;
64public:
65 ShenandoahGCPhase(ShenandoahPhaseTimings::Phase phase);
66 ~ShenandoahGCPhase();
67
68 static ShenandoahPhaseTimings::Phase current_phase() { return _current_phase; }
69
70 static bool is_valid_phase(ShenandoahPhaseTimings::Phase phase);
71 static bool is_current_phase_valid() { return is_valid_phase(current_phase()); }
72 static bool is_root_work_phase();
73};
74
75// Aggregates all the things that should happen before/after the pause.
76class ShenandoahGCPauseMark : public StackObj {
77private:
78 ShenandoahHeap* const _heap;
79 const GCIdMark _gc_id_mark;
80 const SvcGCMarker _svc_gc_mark;
81 const IsGCActiveMark _is_gc_active_mark;
82 TraceMemoryManagerStats _trace_pause;
83
84public:
85 ShenandoahGCPauseMark(uint gc_id, SvcGCMarker::reason_type type);
86 ~ShenandoahGCPauseMark();
87};
88
89class ShenandoahAllocTrace : public StackObj {
90private:
91 double _start;
92 size_t _size;
93 ShenandoahAllocRequest::Type _alloc_type;
94public:
95 ShenandoahAllocTrace(size_t words_size, ShenandoahAllocRequest::Type alloc_type);
96 ~ShenandoahAllocTrace();
97};
98
99class ShenandoahSafepoint : public AllStatic {
100public:
101 // check if Shenandoah GC safepoint is in progress
102 static inline bool is_at_shenandoah_safepoint() {
103 if (!SafepointSynchronize::is_at_safepoint()) return false;
104
105 VM_Operation* vm_op = VMThread::vm_operation();
106 if (vm_op == NULL) return false;
107
108 VM_Operation::VMOp_Type type = vm_op->type();
109 return type == VM_Operation::VMOp_ShenandoahInitMark ||
110 type == VM_Operation::VMOp_ShenandoahFinalMarkStartEvac ||
111 type == VM_Operation::VMOp_ShenandoahFinalEvac ||
112 type == VM_Operation::VMOp_ShenandoahInitTraversalGC ||
113 type == VM_Operation::VMOp_ShenandoahFinalTraversalGC ||
114 type == VM_Operation::VMOp_ShenandoahInitUpdateRefs ||
115 type == VM_Operation::VMOp_ShenandoahFinalUpdateRefs ||
116 type == VM_Operation::VMOp_ShenandoahFullGC ||
117 type == VM_Operation::VMOp_ShenandoahDegeneratedGC;
118 }
119};
120
121class ShenandoahWorkerSession : public StackObj {
122protected:
123 uint _worker_id;
124
125 ShenandoahWorkerSession(uint worker_id);
126 ~ShenandoahWorkerSession();
127public:
128 static inline uint worker_id() {
129 Thread* thr = Thread::current();
130 uint id = ShenandoahThreadLocalData::worker_id(thr);
131 assert(id != ShenandoahThreadLocalData::INVALID_WORKER_ID, "Worker session has not been created");
132 return id;
133 }
134};
135
136class ShenandoahConcurrentWorkerSession : public ShenandoahWorkerSession {
137private:
138 EventGCPhaseConcurrent _event;
139
140public:
141 ShenandoahConcurrentWorkerSession(uint worker_id) : ShenandoahWorkerSession(worker_id) { }
142 ~ShenandoahConcurrentWorkerSession();
143};
144
145class ShenandoahParallelWorkerSession : public ShenandoahWorkerSession {
146private:
147 EventGCPhaseParallel _event;
148
149public:
150 ShenandoahParallelWorkerSession(uint worker_id) : ShenandoahWorkerSession(worker_id) { }
151 ~ShenandoahParallelWorkerSession();
152};
153
154class ShenandoahSuspendibleThreadSetJoiner {
155private:
156 SuspendibleThreadSetJoiner _joiner;
157public:
158 ShenandoahSuspendibleThreadSetJoiner(bool active = true) : _joiner(active) {
159 assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "STS should be joined before evac scope");
160 }
161 ~ShenandoahSuspendibleThreadSetJoiner() {
162 assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "STS should be left after evac scope");
163 }
164};
165
166class ShenandoahSuspendibleThreadSetLeaver {
167private:
168 SuspendibleThreadSetLeaver _leaver;
169public:
170 ShenandoahSuspendibleThreadSetLeaver(bool active = true) : _leaver(active) {
171 assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "STS should be left after evac scope");
172 }
173 ~ShenandoahSuspendibleThreadSetLeaver() {
174 assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "STS should be joined before evac scope");
175 }
176};
177
178class ShenandoahTimingConverter : public AllStatic {
179public:
180 static void weak_processing_timing_to_shenandoah_timing(WeakProcessorPhaseTimes* weak_processing_timings,
181 ShenandoahWorkerTimings* sh_worker_times);
182private:
183 static void weak_processing_phase_to_shenandoah_phase(WeakProcessorPhases::Phase wpp,
184 WeakProcessorPhaseTimes* weak_processing_timings,
185 ShenandoahPhaseTimings::GCParPhases spp,
186 ShenandoahWorkerTimings* sh_worker_times);
187};
188
189#endif // SHARE_GC_SHENANDOAH_SHENANDOAHUTILS_HPP
190