45
45
#include " services/management.hpp"
46
46
#include " utilities/macros.hpp"
47
47
48
- void G1RootProcessor::worker_has_discovered_all_strong_classes () {
48
+ void G1RootProcessor::worker_has_discovered_all_strong_nmethods () {
49
49
assert (ClassUnloadingWithConcurrentMark, " Currently only needed when doing G1 Class Unloading" );
50
50
51
51
uint new_value = (uint)Atomic::add (1 , &_n_workers_discovered_strong_classes);
@@ -56,7 +56,7 @@ void G1RootProcessor::worker_has_discovered_all_strong_classes() {
56
56
}
57
57
}
58
58
59
- void G1RootProcessor::wait_until_all_strong_classes_discovered () {
59
+ void G1RootProcessor::wait_until_all_strong_nmethods_discovered () {
60
60
assert (ClassUnloadingWithConcurrentMark, " Currently only needed when doing G1 Class Unloading" );
61
61
62
62
if ((uint)_n_workers_discovered_strong_classes != n_workers ()) {
@@ -71,7 +71,7 @@ G1RootProcessor::G1RootProcessor(G1CollectedHeap* g1h, uint n_workers) :
71
71
_g1h(g1h),
72
72
_process_strong_tasks(G1RP_PS_NumElements),
73
73
_srs(n_workers),
74
- _lock(Mutex::leaf, " G1 Root Scanning barrier lock" , false , Monitor::_safepoint_check_never),
74
+ _lock(Mutex::leaf, " G1 Root Scan barrier lock" , false , Monitor::_safepoint_check_never),
75
75
_n_workers_discovered_strong_classes(0 ) {}
76
76
77
77
void G1RootProcessor::evacuate_roots (G1ParScanThreadState* pss, uint worker_i) {
@@ -80,13 +80,7 @@ void G1RootProcessor::evacuate_roots(G1ParScanThreadState* pss, uint worker_i) {
80
80
G1EvacPhaseTimesTracker timer (phase_times, pss, G1GCPhaseTimes::ExtRootScan, worker_i);
81
81
82
82
G1EvacuationRootClosures* closures = pss->closures ();
83
- process_java_roots (closures, phase_times, worker_i);
84
-
85
- // This is the point where this worker thread will not find more strong CLDs/nmethods.
86
- // Report this so G1 can synchronize the strong and weak CLDs/nmethods processing.
87
- if (closures->trace_metadata ()) {
88
- worker_has_discovered_all_strong_classes ();
89
- }
83
+ process_java_roots (closures, phase_times, worker_i, closures->trace_metadata () /* notify_claimed_nmethods_done */ );
90
84
91
85
process_vm_roots (closures, phase_times, worker_i);
92
86
@@ -103,21 +97,9 @@ void G1RootProcessor::evacuate_roots(G1ParScanThreadState* pss, uint worker_i) {
103
97
}
104
98
105
99
if (closures->trace_metadata ()) {
106
- {
107
- G1GCParPhaseTimesTracker x (phase_times, G1GCPhaseTimes::WaitForStrongCLD, worker_i);
108
- // Barrier to make sure all workers passed
109
- // the strong CLD and strong nmethods phases.
110
- wait_until_all_strong_classes_discovered ();
111
- }
112
-
113
- // Now take the complement of the strong CLDs.
114
- G1GCParPhaseTimesTracker x (phase_times, G1GCPhaseTimes::WeakCLDRoots, worker_i);
115
- assert (closures->second_pass_weak_clds () != NULL , " Should be non-null if we are tracing metadata." );
116
- ClassLoaderDataGraph::roots_cld_do (NULL , closures->second_pass_weak_clds ());
117
- } else {
118
- phase_times->record_time_secs (G1GCPhaseTimes::WaitForStrongCLD, worker_i, 0.0 );
119
- phase_times->record_time_secs (G1GCPhaseTimes::WeakCLDRoots, worker_i, 0.0 );
120
- assert (closures->second_pass_weak_clds () == NULL , " Should be null if not tracing metadata." );
100
+ G1GCParPhaseTimesTracker x (phase_times, G1GCPhaseTimes::WaitForStrongRoots, worker_i);
101
+ // Wait to make sure all workers passed the strong nmethods phase.
102
+ wait_until_all_strong_nmethods_discovered ();
121
103
}
122
104
123
105
_process_strong_tasks.all_tasks_completed (n_workers ());
@@ -189,24 +171,44 @@ void G1RootProcessor::process_all_roots(OopClosure* oops,
189
171
190
172
void G1RootProcessor::process_java_roots (G1RootClosures* closures,
191
173
G1GCPhaseTimes* phase_times,
192
- uint worker_i) {
193
- // Iterating over the CLDG and the Threads are done early to allow us to
194
- // first process the strong CLDs and nmethods and then, after a barrier,
195
- // let the thread process the weak CLDs and nmethods.
196
- {
197
- G1GCParPhaseTimesTracker x (phase_times, G1GCPhaseTimes::CLDGRoots, worker_i);
198
- if (_process_strong_tasks.try_claim_task (G1RP_PS_ClassLoaderDataGraph_oops_do)) {
199
- ClassLoaderDataGraph::roots_cld_do (closures->strong_clds (), closures->weak_clds ());
200
- }
201
- }
202
-
174
+ uint worker_i,
175
+ bool notify_claimed_nmethods_done) {
176
+ // We need to make make sure that the "strong" nmethods are processed first
177
+ // using the strong closure. Only after that we process the weakly reachable
178
+ // nmethods.
179
+ // We need to strictly separate the strong and weak nmethod processing because
180
+ // any processing claims that nmethod, i.e. will not be iterated again.
181
+ // Which means if an nmethod is processed first and claimed, the strong processing
182
+ // will not happen, and the oops reachable by that nmethod will not be marked
183
+ // properly.
184
+ //
185
+ // That is why we process strong nmethods first, synchronize all threads via a
186
+ // barrier, and only then allow weak processing. To minimize the wait time at
187
+ // that barrier we do the strong nmethod processing first, and immediately after-
188
+ // wards indicate that that thread is done. Hopefully other root processing after
189
+ // nmethod processing is enough so there is no need to wait.
190
+ //
191
+ // This is only required in the concurrent start pause with class unloading enabled.
203
192
{
204
193
G1GCParPhaseTimesTracker x (phase_times, G1GCPhaseTimes::ThreadRoots, worker_i);
205
194
bool is_par = n_workers () > 1 ;
206
195
Threads::possibly_parallel_oops_do (is_par,
207
196
closures->strong_oops (),
208
197
closures->strong_codeblobs ());
209
198
}
199
+
200
+ // This is the point where this worker thread will not find more strong nmethods.
201
+ // Report this so G1 can synchronize the strong and weak CLDs/nmethods processing.
202
+ if (notify_claimed_nmethods_done) {
203
+ worker_has_discovered_all_strong_nmethods ();
204
+ }
205
+
206
+ {
207
+ G1GCParPhaseTimesTracker x (phase_times, G1GCPhaseTimes::CLDGRoots, worker_i);
208
+ if (_process_strong_tasks.try_claim_task (G1RP_PS_ClassLoaderDataGraph_oops_do)) {
209
+ ClassLoaderDataGraph::roots_cld_do (closures->strong_clds (), closures->weak_clds ());
210
+ }
211
+ }
210
212
}
211
213
212
214
void G1RootProcessor::process_vm_roots (G1RootClosures* closures,
0 commit comments