28
28
29
29
#include " gc/shared/gcCause.hpp"
30
30
#include " gc/shenandoah/shenandoahController.hpp"
31
- #include " gc/shenandoah/shenandoahGenerationType.hpp"
32
31
#include " gc/shenandoah/shenandoahGC.hpp"
33
- #include " gc/shenandoah/shenandoahPadding.hpp"
34
32
#include " gc/shenandoah/shenandoahSharedVariables.hpp"
33
+ #include " runtime/mutexLocker.hpp"
35
34
36
35
class ShenandoahOldGeneration ;
37
36
class ShenandoahGeneration ;
@@ -52,21 +51,43 @@ class ShenandoahGenerationalControlThread: public ShenandoahController {
52
51
stopped
53
52
} GCMode;
54
53
54
+ class ShenandoahGCRequest {
55
+ public:
56
+ ShenandoahGCRequest () : generation(nullptr ), cause(GCCause::_no_gc) {}
57
+ ShenandoahGeneration* generation;
58
+ GCCause::Cause cause;
59
+ };
60
+
55
61
private:
62
+ // This lock is used to coordinate setting the _requested_gc_cause, _requested generation
63
+ // and _gc_mode. It is important that these be changed together and have a consistent view.
56
64
Monitor _control_lock;
57
- Monitor _regulator_lock;
58
-
59
- ShenandoahSharedFlag _allow_old_preemption;
60
- ShenandoahSharedFlag _preemption_requested;
61
65
66
+ // Represents a normal (non cancellation) gc request. This can be set by mutators (System.gc,
67
+ // whitebox gc, etc.) or by the regulator thread when the heuristics want to start a cycle.
62
68
GCCause::Cause _requested_gc_cause;
63
- volatile ShenandoahGenerationType _requested_generation;
69
+
70
+ // This is the generation the request should operate on.
71
+ ShenandoahGeneration* _requested_generation;
72
+
73
+ // The mode is read frequently by requesting threads and only ever written by the control thread.
74
+ // This may be read without taking the _control_lock, but should be read again under the lock
75
+ // before making any state changes (double-checked locking idiom).
76
+ volatile GCMode _gc_mode;
77
+
78
+ // Only the control thread knows the correct degeneration point. This is used to have the
79
+ // control thread resume a STW cycle from the point where the concurrent cycle was cancelled.
64
80
ShenandoahGC::ShenandoahDegenPoint _degen_point;
65
- ShenandoahGeneration* _degen_generation;
66
81
67
- shenandoah_padding (0 );
68
- volatile GCMode _mode;
69
- shenandoah_padding (1 );
82
+ // A reference to the heap
83
+ ShenandoahGenerationalHeap* _heap;
84
+
85
+ // This is used to keep track of whether to age objects during the current cycle.
86
+ uint _age_period;
87
+
88
+ // This is true when the old generation cycle is in an interruptible phase (i.e., marking or
89
+ // preparing for mark).
90
+ ShenandoahSharedFlag _allow_old_preemption;
70
91
71
92
public:
72
93
ShenandoahGenerationalControlThread ();
@@ -77,54 +98,68 @@ class ShenandoahGenerationalControlThread: public ShenandoahController {
77
98
void request_gc (GCCause::Cause cause) override ;
78
99
79
100
// Return true if the request to start a concurrent GC for the given generation succeeded.
80
- bool request_concurrent_gc (ShenandoahGenerationType generation);
101
+ bool request_concurrent_gc (ShenandoahGeneration* generation);
81
102
82
- GCMode gc_mode () {
83
- return _mode;
103
+ // Returns the current state of the control thread
104
+ GCMode gc_mode () const {
105
+ return _gc_mode;
84
106
}
85
107
private:
86
-
87
108
// Returns true if the cycle has been cancelled or degenerated.
88
109
bool check_cancellation_or_degen (ShenandoahGC::ShenandoahDegenPoint point);
89
110
111
+ // Executes one GC cycle
112
+ void run_gc_cycle (const ShenandoahGCRequest& request);
113
+
90
114
// Returns true if the old generation marking completed (i.e., final mark executed for old generation).
91
115
bool resume_concurrent_old_cycle (ShenandoahOldGeneration* generation, GCCause::Cause cause);
116
+
117
+ // Various service methods handle different gc cycle types
92
118
void service_concurrent_cycle (ShenandoahGeneration* generation, GCCause::Cause cause, bool reset_old_bitmap_specially);
93
119
void service_stw_full_cycle (GCCause::Cause cause);
94
- void service_stw_degenerated_cycle (GCCause::Cause cause, ShenandoahGC::ShenandoahDegenPoint point);
120
+ void service_stw_degenerated_cycle (const ShenandoahGCRequest& request);
121
+ void service_concurrent_normal_cycle (const ShenandoahGCRequest& request);
122
+ void service_concurrent_old_cycle (const ShenandoahGCRequest& request);
95
123
96
124
void notify_gc_waiters ();
97
125
98
- // Handle GC request.
99
- // Blocks until GC is over.
126
+ // Blocks until at least one global GC cycle is complete.
100
127
void handle_requested_gc (GCCause::Cause cause);
101
128
102
- bool is_explicit_gc (GCCause::Cause cause) const ;
103
- bool is_implicit_gc (GCCause::Cause cause) const ;
104
-
105
129
// Returns true if the old generation marking was interrupted to allow a young cycle.
106
- bool preempt_old_marking (ShenandoahGenerationType generation);
130
+ bool preempt_old_marking (ShenandoahGeneration* generation);
107
131
108
- void process_phase_timings (const ShenandoahGenerationalHeap* heap);
109
-
110
- void service_concurrent_normal_cycle (ShenandoahGenerationalHeap* heap,
111
- ShenandoahGenerationType generation,
112
- GCCause::Cause cause);
113
-
114
- void service_concurrent_old_cycle (ShenandoahGenerationalHeap* heap,
115
- GCCause::Cause &cause);
132
+ // Flushes cycle timings to global timings and prints the phase timings for the last completed cycle.
133
+ void process_phase_timings () const ;
116
134
135
+ // Set the gc mode and post a notification if it has changed. The overloaded variant should be used
136
+ // when the _control_lock is already held.
117
137
void set_gc_mode (GCMode new_mode);
138
+ void set_gc_mode (MonitorLocker& ml, GCMode new_mode);
118
139
140
+ // Return printable name for the given gc mode.
119
141
static const char * gc_mode_name (GCMode mode);
120
142
121
- void notify_control_thread ();
143
+ // Takes the request lock and updates the requested cause and generation, then notifies the control thread.
144
+ // The overloaded variant should be used when the _control_lock is already held.
145
+ void notify_control_thread (GCCause::Cause cause, ShenandoahGeneration* generation);
146
+ void notify_control_thread (MonitorLocker& ml, GCCause::Cause cause, ShenandoahGeneration* generation);
147
+
148
+ // Notifies the control thread, but does not update the requested cause or generation.
149
+ // The overloaded variant should be used when the _control_lock is already held.
150
+ void notify_cancellation (GCCause::Cause cause);
151
+ void notify_cancellation (MonitorLocker& ml, GCCause::Cause cause);
152
+
153
+ // Configure the heap to age objects and regions if the aging period has elapsed.
154
+ void maybe_set_aging_cycle ();
122
155
123
- void service_concurrent_cycle (ShenandoahHeap* heap,
124
- ShenandoahGeneration* generation,
125
- GCCause::Cause &cause,
126
- bool do_old_gc_bootstrap);
156
+ // Take the _control_lock and check for a request to run a gc cycle. If a request is found,
157
+ // the `prepare` methods are used to configure the heap and update heuristics accordingly.
158
+ void check_for_request (ShenandoahGCRequest& request);
127
159
160
+ GCMode prepare_for_allocation_failure_gc (ShenandoahGCRequest &request);
161
+ GCMode prepare_for_explicit_gc (ShenandoahGCRequest &request) const ;
162
+ GCMode prepare_for_concurrent_gc (const ShenandoahGCRequest &request) const ;
128
163
};
129
164
130
165
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHGENERATIONALCONTROLTHREAD_HPP
0 commit comments