28 #include "classfile/stringTable.hpp"
29 #include "classfile/systemDictionary.hpp"
30 #include "code/codeCache.hpp"
31 #include "gc/g1/g1BarrierSet.hpp"
32 #include "gc/g1/g1CodeBlobClosure.hpp"
33 #include "gc/g1/g1CollectedHeap.inline.hpp"
34 #include "gc/g1/g1CollectorState.hpp"
35 #include "gc/g1/g1GCPhaseTimes.hpp"
36 #include "gc/g1/g1ParScanThreadState.inline.hpp"
37 #include "gc/g1/g1Policy.hpp"
38 #include "gc/g1/g1RootClosures.hpp"
39 #include "gc/g1/g1RootProcessor.hpp"
40 #include "gc/g1/heapRegion.inline.hpp"
41 #include "gc/shared/referenceProcessor.hpp"
42 #include "memory/allocation.inline.hpp"
43 #include "memory/universe.hpp"
44 #include "runtime/mutex.hpp"
45 #include "services/management.hpp"
46 #include "utilities/macros.hpp"
47
48 void G1RootProcessor::worker_has_discovered_all_strong_classes() {
49 assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading");
50
51 uint new_value = (uint)Atomic::add(1, &_n_workers_discovered_strong_classes);
52 if (new_value == n_workers()) {
53 // This thread is last. Notify the others.
54 MonitorLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
55 _lock.notify_all();
56 }
57 }
58
59 void G1RootProcessor::wait_until_all_strong_classes_discovered() {
60 assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading");
61
62 if ((uint)_n_workers_discovered_strong_classes != n_workers()) {
63 MonitorLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
64 while ((uint)_n_workers_discovered_strong_classes != n_workers()) {
65 ml.wait(0);
66 }
67 }
68 }
69
70 G1RootProcessor::G1RootProcessor(G1CollectedHeap* g1h, uint n_workers) :
71 _g1h(g1h),
72 _process_strong_tasks(G1RP_PS_NumElements),
73 _srs(n_workers),
74 _lock(Mutex::leaf, "G1 Root Scanning barrier lock", false, Monitor::_safepoint_check_never),
75 _n_workers_discovered_strong_classes(0) {}
76
77 void G1RootProcessor::evacuate_roots(G1ParScanThreadState* pss, uint worker_i) {
78 G1GCPhaseTimes* phase_times = _g1h->phase_times();
79
80 G1EvacPhaseTimesTracker timer(phase_times, pss, G1GCPhaseTimes::ExtRootScan, worker_i);
81
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 }
90
91 process_vm_roots(closures, phase_times, worker_i);
92
93 {
94 // Now the CM ref_processor roots.
95 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CMRefRoots, worker_i);
96 if (_process_strong_tasks.try_claim_task(G1RP_PS_refProcessor_oops_do)) {
97 // We need to treat the discovered reference lists of the
98 // concurrent mark ref processor as roots and keep entries
99 // (which are added by the marking threads) on them live
100 // until they can be processed at the end of marking.
101 _g1h->ref_processor_cm()->weak_oops_do(closures->strong_oops());
102 }
103 }
104
105 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.");
121 }
122
123 _process_strong_tasks.all_tasks_completed(n_workers());
124 }
125
126 // Adaptor to pass the closures to the strong roots in the VM.
127 class StrongRootsClosures : public G1RootClosures {
128 OopClosure* _roots;
129 CLDClosure* _clds;
130 CodeBlobClosure* _blobs;
131 public:
132 StrongRootsClosures(OopClosure* roots, CLDClosure* clds, CodeBlobClosure* blobs) :
133 _roots(roots), _clds(clds), _blobs(blobs) {}
134
135 OopClosure* weak_oops() { return NULL; }
136 OopClosure* strong_oops() { return _roots; }
137
138 CLDClosure* weak_clds() { return NULL; }
139 CLDClosure* strong_clds() { return _clds; }
140
172 // We don't want to visit code blobs more than once, so we return NULL for the
173 // strong case and walk the entire code cache as a separate step.
174 CodeBlobClosure* strong_codeblobs() { return NULL; }
175 };
176
177 void G1RootProcessor::process_all_roots(OopClosure* oops,
178 CLDClosure* clds,
179 CodeBlobClosure* blobs) {
180 AllRootsClosures closures(oops, clds);
181
182 process_java_roots(&closures, NULL, 0);
183 process_vm_roots(&closures, NULL, 0);
184
185 process_code_cache_roots(blobs, NULL, 0);
186
187 _process_strong_tasks.all_tasks_completed(n_workers());
188 }
189
190 void G1RootProcessor::process_java_roots(G1RootClosures* closures,
191 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
203 {
204 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ThreadRoots, worker_i);
205 bool is_par = n_workers() > 1;
206 Threads::possibly_parallel_oops_do(is_par,
207 closures->strong_oops(),
208 closures->strong_codeblobs());
209 }
210 }
211
212 void G1RootProcessor::process_vm_roots(G1RootClosures* closures,
213 G1GCPhaseTimes* phase_times,
214 uint worker_i) {
215 OopClosure* strong_roots = closures->strong_oops();
216
217 {
218 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::UniverseRoots, worker_i);
219 if (_process_strong_tasks.try_claim_task(G1RP_PS_Universe_oops_do)) {
220 Universe::oops_do(strong_roots);
221 }
222 }
223
224 {
225 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::JNIRoots, worker_i);
226 if (_process_strong_tasks.try_claim_task(G1RP_PS_JNIHandles_oops_do)) {
227 JNIHandles::oops_do(strong_roots);
228 }
|
28 #include "classfile/stringTable.hpp"
29 #include "classfile/systemDictionary.hpp"
30 #include "code/codeCache.hpp"
31 #include "gc/g1/g1BarrierSet.hpp"
32 #include "gc/g1/g1CodeBlobClosure.hpp"
33 #include "gc/g1/g1CollectedHeap.inline.hpp"
34 #include "gc/g1/g1CollectorState.hpp"
35 #include "gc/g1/g1GCPhaseTimes.hpp"
36 #include "gc/g1/g1ParScanThreadState.inline.hpp"
37 #include "gc/g1/g1Policy.hpp"
38 #include "gc/g1/g1RootClosures.hpp"
39 #include "gc/g1/g1RootProcessor.hpp"
40 #include "gc/g1/heapRegion.inline.hpp"
41 #include "gc/shared/referenceProcessor.hpp"
42 #include "memory/allocation.inline.hpp"
43 #include "memory/universe.hpp"
44 #include "runtime/mutex.hpp"
45 #include "services/management.hpp"
46 #include "utilities/macros.hpp"
47
48 void G1RootProcessor::worker_has_discovered_all_strong_nmethods() {
49 assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading");
50
51 uint new_value = (uint)Atomic::add(1, &_n_workers_discovered_strong_classes);
52 if (new_value == n_workers()) {
53 // This thread is last. Notify the others.
54 MonitorLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
55 _lock.notify_all();
56 }
57 }
58
59 void G1RootProcessor::wait_until_all_strong_nmethods_discovered() {
60 assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading");
61
62 if ((uint)_n_workers_discovered_strong_classes != n_workers()) {
63 MonitorLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
64 while ((uint)_n_workers_discovered_strong_classes != n_workers()) {
65 ml.wait(0);
66 }
67 }
68 }
69
70 G1RootProcessor::G1RootProcessor(G1CollectedHeap* g1h, uint n_workers) :
71 _g1h(g1h),
72 _process_strong_tasks(G1RP_PS_NumElements),
73 _srs(n_workers),
74 _lock(Mutex::leaf, "G1 Root Scan barrier lock", false, Monitor::_safepoint_check_never),
75 _n_workers_discovered_strong_classes(0) {}
76
77 void G1RootProcessor::evacuate_roots(G1ParScanThreadState* pss, uint worker_i) {
78 G1GCPhaseTimes* phase_times = _g1h->phase_times();
79
80 G1EvacPhaseTimesTracker timer(phase_times, pss, G1GCPhaseTimes::ExtRootScan, worker_i);
81
82 G1EvacuationRootClosures* closures = pss->closures();
83 process_java_roots(closures, phase_times, worker_i, closures->trace_metadata() /* notify_claimed_roots_done */);
84
85 process_vm_roots(closures, phase_times, worker_i);
86
87 {
88 // Now the CM ref_processor roots.
89 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CMRefRoots, worker_i);
90 if (_process_strong_tasks.try_claim_task(G1RP_PS_refProcessor_oops_do)) {
91 // We need to treat the discovered reference lists of the
92 // concurrent mark ref processor as roots and keep entries
93 // (which are added by the marking threads) on them live
94 // until they can be processed at the end of marking.
95 _g1h->ref_processor_cm()->weak_oops_do(closures->strong_oops());
96 }
97 }
98
99 if (closures->trace_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();
103 }
104
105 _process_strong_tasks.all_tasks_completed(n_workers());
106 }
107
108 // Adaptor to pass the closures to the strong roots in the VM.
109 class StrongRootsClosures : public G1RootClosures {
110 OopClosure* _roots;
111 CLDClosure* _clds;
112 CodeBlobClosure* _blobs;
113 public:
114 StrongRootsClosures(OopClosure* roots, CLDClosure* clds, CodeBlobClosure* blobs) :
115 _roots(roots), _clds(clds), _blobs(blobs) {}
116
117 OopClosure* weak_oops() { return NULL; }
118 OopClosure* strong_oops() { return _roots; }
119
120 CLDClosure* weak_clds() { return NULL; }
121 CLDClosure* strong_clds() { return _clds; }
122
154 // We don't want to visit code blobs more than once, so we return NULL for the
155 // strong case and walk the entire code cache as a separate step.
156 CodeBlobClosure* strong_codeblobs() { return NULL; }
157 };
158
159 void G1RootProcessor::process_all_roots(OopClosure* oops,
160 CLDClosure* clds,
161 CodeBlobClosure* blobs) {
162 AllRootsClosures closures(oops, clds);
163
164 process_java_roots(&closures, NULL, 0);
165 process_vm_roots(&closures, NULL, 0);
166
167 process_code_cache_roots(blobs, NULL, 0);
168
169 _process_strong_tasks.all_tasks_completed(n_workers());
170 }
171
172 void G1RootProcessor::process_java_roots(G1RootClosures* closures,
173 G1GCPhaseTimes* phase_times,
174 uint worker_i,
175 bool notify_claimed_roots_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.
192 {
193 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ThreadRoots, worker_i);
194 bool is_par = n_workers() > 1;
195 Threads::possibly_parallel_oops_do(is_par,
196 closures->strong_oops(),
197 closures->strong_codeblobs());
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_roots_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 }
212 }
213
214 void G1RootProcessor::process_vm_roots(G1RootClosures* closures,
215 G1GCPhaseTimes* phase_times,
216 uint worker_i) {
217 OopClosure* strong_roots = closures->strong_oops();
218
219 {
220 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::UniverseRoots, worker_i);
221 if (_process_strong_tasks.try_claim_task(G1RP_PS_Universe_oops_do)) {
222 Universe::oops_do(strong_roots);
223 }
224 }
225
226 {
227 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::JNIRoots, worker_i);
228 if (_process_strong_tasks.try_claim_task(G1RP_PS_JNIHandles_oops_do)) {
229 JNIHandles::oops_do(strong_roots);
230 }
|