@@ -149,22 +149,35 @@ void G1RootProcessor::process_all_roots(OopClosure* oops,
149
149
void G1RootProcessor::process_java_roots (G1RootClosures* closures,
150
150
G1GCPhaseTimes* phase_times,
151
151
uint worker_id) {
152
- // We need to make make sure that the "strong" nmethods are processed first
153
- // using the strong closure. Only after that we process the weakly reachable
154
- // nmethods.
155
- // We need to strictly separate the strong and weak nmethod processing because
156
- // any processing claims that nmethod, i.e. will not be iterated again.
157
- // Which means if an nmethod is processed first and claimed, the strong processing
158
- // will not happen, and the oops reachable by that nmethod will not be marked
159
- // properly.
152
+ // In the concurrent start pause, when class unloading is enabled, G1
153
+ // processes nmethods in two ways, as "strong" and "weak" nmethods.
160
154
//
161
- // That is why we process strong nmethods first, synchronize all threads via a
162
- // barrier, and only then allow weak processing. To minimize the wait time at
163
- // that barrier we do the strong nmethod processing first, and immediately after-
164
- // wards indicate that that thread is done. Hopefully other root processing after
165
- // nmethod processing is enough so there is no need to wait.
155
+ // 1) Strong nmethods are reachable from the thread stack frames. G1 applies
156
+ // the G1RootClosures::strong_codeblobs() closure on them. The closure
157
+ // iterates over all oops embedded inside each nmethod, and performs 3
158
+ // operations:
159
+ // a) evacuates; relocate objects outside of collection set
160
+ // b) fixes up; remap oops to reflect new addresses
161
+ // c) mark; mark object alive
162
+ // This keeps these oops alive wrt. to the upcoming marking phase, and their
163
+ // classes will not be unloaded.
166
164
//
167
- // This is only required in the concurrent start pause with class unloading enabled.
165
+ // 2) Weak nmethods are reachable only from the code root remembered set (see
166
+ // G1CodeRootSet). G1 applies the G1RootClosures::weak_codeblobs() closure on
167
+ // them. The closure iterates over all oops embedded inside each nmethod, and
168
+ // performs 2 operations: a) and b).
169
+ // Since these oops are *not* marked, their classes can potentially be
170
+ // unloaded.
171
+ //
172
+ // G1 doesn't segregate strong/weak nmethods processing (finish processing
173
+ // all strong nmethods before starting with any weak nmethods, or vice
174
+ // versa), as that could lead to poor CPU utilization (a single slow thread
175
+ // prevents all other thread from crossing the synchronization barrier).
176
+ // Instead, G1 interleaves strong and weak nmethods processing via
177
+ // per-nmethod synchronization. A nmethod is either *strongly* or *weakly*
178
+ // claimed before processing. A weakly claimed nmethod could be strongly
179
+ // claimed again for performing marking (the c) operation above); see
180
+ // oops_do_process_weak and oops_do_process_strong in nmethod.hpp
168
181
{
169
182
G1GCParPhaseTimesTracker x (phase_times, G1GCPhaseTimes::ThreadRoots, worker_id);
170
183
bool is_par = n_workers () > 1 ;
0 commit comments