43 #include "memory/universe.hpp" |
43 #include "memory/universe.hpp" |
44 #include "runtime/mutex.hpp" |
44 #include "runtime/mutex.hpp" |
45 #include "services/management.hpp" |
45 #include "services/management.hpp" |
46 #include "utilities/macros.hpp" |
46 #include "utilities/macros.hpp" |
47 |
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) : |
48 G1RootProcessor::G1RootProcessor(G1CollectedHeap* g1h, uint n_workers) : |
71 _g1h(g1h), |
49 _g1h(g1h), |
72 _process_strong_tasks(G1RP_PS_NumElements), |
50 _process_strong_tasks(G1RP_PS_NumElements), |
73 _srs(n_workers), |
51 _srs(n_workers) {} |
74 _lock(Mutex::leaf, "G1 Root Scan barrier lock", false, Mutex::_safepoint_check_never), |
|
75 _n_workers_discovered_strong_classes(0) {} |
|
76 |
52 |
77 void G1RootProcessor::evacuate_roots(G1ParScanThreadState* pss, uint worker_id) { |
53 void G1RootProcessor::evacuate_roots(G1ParScanThreadState* pss, uint worker_id) { |
78 G1GCPhaseTimes* phase_times = _g1h->phase_times(); |
54 G1GCPhaseTimes* phase_times = _g1h->phase_times(); |
79 |
55 |
80 G1EvacPhaseTimesTracker timer(phase_times, pss, G1GCPhaseTimes::ExtRootScan, worker_id); |
56 G1EvacPhaseTimesTracker timer(phase_times, pss, G1GCPhaseTimes::ExtRootScan, worker_id); |
81 |
57 |
82 G1EvacuationRootClosures* closures = pss->closures(); |
58 G1EvacuationRootClosures* closures = pss->closures(); |
83 process_java_roots(closures, phase_times, worker_id, closures->trace_metadata() /* notify_claimed_nmethods_done */); |
59 process_java_roots(closures, phase_times, worker_id); |
84 |
60 |
85 process_vm_roots(closures, phase_times, worker_id); |
61 process_vm_roots(closures, phase_times, worker_id); |
86 |
62 |
87 { |
63 { |
88 // Now the CM ref_processor roots. |
64 // Now the CM ref_processor roots. |
94 // until they can be processed at the end of marking. |
70 // until they can be processed at the end of marking. |
95 _g1h->ref_processor_cm()->weak_oops_do(closures->strong_oops()); |
71 _g1h->ref_processor_cm()->weak_oops_do(closures->strong_oops()); |
96 } |
72 } |
97 } |
73 } |
98 |
74 |
99 if (closures->trace_metadata()) { |
|
100 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::WaitForStrongRoots, worker_id); |
|
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()); |
75 _process_strong_tasks.all_tasks_completed(n_workers()); |
106 } |
76 } |
107 |
77 |
108 // Adaptor to pass the closures to the strong roots in the VM. |
78 // Adaptor to pass the closures to the strong roots in the VM. |
109 class StrongRootsClosures : public G1RootClosures { |
79 class StrongRootsClosures : public G1RootClosures { |
169 _process_strong_tasks.all_tasks_completed(n_workers()); |
139 _process_strong_tasks.all_tasks_completed(n_workers()); |
170 } |
140 } |
171 |
141 |
172 void G1RootProcessor::process_java_roots(G1RootClosures* closures, |
142 void G1RootProcessor::process_java_roots(G1RootClosures* closures, |
173 G1GCPhaseTimes* phase_times, |
143 G1GCPhaseTimes* phase_times, |
174 uint worker_id, |
144 uint worker_id) { |
175 bool notify_claimed_nmethods_done) { |
|
176 // We need to make make sure that the "strong" nmethods are processed first |
145 // 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 |
146 // using the strong closure. Only after that we process the weakly reachable |
178 // nmethods. |
147 // nmethods. |
179 // We need to strictly separate the strong and weak nmethod processing because |
148 // 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. |
149 // any processing claims that nmethod, i.e. will not be iterated again. |
195 Threads::possibly_parallel_oops_do(is_par, |
164 Threads::possibly_parallel_oops_do(is_par, |
196 closures->strong_oops(), |
165 closures->strong_oops(), |
197 closures->strong_codeblobs()); |
166 closures->strong_codeblobs()); |
198 } |
167 } |
199 |
168 |
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 { |
169 { |
207 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CLDGRoots, worker_id); |
170 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CLDGRoots, worker_id); |
208 if (_process_strong_tasks.try_claim_task(G1RP_PS_ClassLoaderDataGraph_oops_do)) { |
171 if (_process_strong_tasks.try_claim_task(G1RP_PS_ClassLoaderDataGraph_oops_do)) { |
209 ClassLoaderDataGraph::roots_cld_do(closures->strong_clds(), closures->weak_clds()); |
172 ClassLoaderDataGraph::roots_cld_do(closures->strong_clds(), closures->weak_clds()); |
210 } |
173 } |