Mercurial > hg > graal-jvmci-8
comparison src/share/vm/gc_implementation/g1/g1RootProcessor.cpp @ 22910:3ca53859c3c7
8027962: Per-phase timing measurements for strong roots processing
Reviewed-by: tschatzl, ecaspole
author | brutisso |
---|---|
date | Thu, 19 Mar 2015 15:25:54 +0100 |
parents | 38d6febe66af |
children | 9b582718fbea |
comparison
equal
deleted
inserted
replaced
22909:38d6febe66af | 22910:3ca53859c3c7 |
---|---|
126 CLDClosure* scan_weak_clds, | 126 CLDClosure* scan_weak_clds, |
127 bool trace_metadata, | 127 bool trace_metadata, |
128 uint worker_i) { | 128 uint worker_i) { |
129 // First scan the shared roots. | 129 // First scan the shared roots. |
130 double ext_roots_start = os::elapsedTime(); | 130 double ext_roots_start = os::elapsedTime(); |
131 G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times(); | |
131 | 132 |
132 BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots); | 133 BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots); |
133 BufferingOopClosure buf_scan_non_heap_weak_roots(scan_non_heap_weak_roots); | 134 BufferingOopClosure buf_scan_non_heap_weak_roots(scan_non_heap_weak_roots); |
134 | 135 |
135 OopClosure* const weak_roots = &buf_scan_non_heap_weak_roots; | 136 OopClosure* const weak_roots = &buf_scan_non_heap_weak_roots; |
140 | 141 |
141 process_java_roots(strong_roots, | 142 process_java_roots(strong_roots, |
142 trace_metadata ? scan_strong_clds : NULL, | 143 trace_metadata ? scan_strong_clds : NULL, |
143 scan_strong_clds, | 144 scan_strong_clds, |
144 trace_metadata ? NULL : scan_weak_clds, | 145 trace_metadata ? NULL : scan_weak_clds, |
145 &root_code_blobs); | 146 &root_code_blobs, |
147 phase_times, | |
148 worker_i); | |
146 | 149 |
147 // This is the point where this worker thread will not find more strong CLDs/nmethods. | 150 // This is the point where this worker thread will not find more strong CLDs/nmethods. |
148 // Report this so G1 can synchronize the strong and weak CLDs/nmethods processing. | 151 // Report this so G1 can synchronize the strong and weak CLDs/nmethods processing. |
149 if (trace_metadata) { | 152 if (trace_metadata) { |
150 worker_has_discovered_all_strong_classes(); | 153 worker_has_discovered_all_strong_classes(); |
151 } | 154 } |
152 | 155 |
153 process_vm_roots(strong_roots, weak_roots); | 156 process_vm_roots(strong_roots, weak_roots, phase_times, worker_i); |
154 | 157 |
155 // Now the CM ref_processor roots. | 158 { |
156 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_refProcessor_oops_do)) { | 159 // Now the CM ref_processor roots. |
157 // We need to treat the discovered reference lists of the | 160 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CMRefRoots, worker_i); |
158 // concurrent mark ref processor as roots and keep entries | 161 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_refProcessor_oops_do)) { |
159 // (which are added by the marking threads) on them live | 162 // We need to treat the discovered reference lists of the |
160 // until they can be processed at the end of marking. | 163 // concurrent mark ref processor as roots and keep entries |
161 _g1h->ref_processor_cm()->weak_oops_do(&buf_scan_non_heap_roots); | 164 // (which are added by the marking threads) on them live |
165 // until they can be processed at the end of marking. | |
166 _g1h->ref_processor_cm()->weak_oops_do(&buf_scan_non_heap_roots); | |
167 } | |
162 } | 168 } |
163 | 169 |
164 if (trace_metadata) { | 170 if (trace_metadata) { |
165 // Barrier to make sure all workers passed | 171 { |
166 // the strong CLD and strong nmethods phases. | 172 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::WaitForStrongCLD, worker_i); |
167 wait_until_all_strong_classes_discovered(); | 173 // Barrier to make sure all workers passed |
174 // the strong CLD and strong nmethods phases. | |
175 wait_until_all_strong_classes_discovered(); | |
176 } | |
168 | 177 |
169 // Now take the complement of the strong CLDs. | 178 // Now take the complement of the strong CLDs. |
179 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::WeakCLDRoots, worker_i); | |
170 ClassLoaderDataGraph::roots_cld_do(NULL, scan_weak_clds); | 180 ClassLoaderDataGraph::roots_cld_do(NULL, scan_weak_clds); |
181 } else { | |
182 phase_times->record_time_secs(G1GCPhaseTimes::WaitForStrongCLD, worker_i, 0.0); | |
183 phase_times->record_time_secs(G1GCPhaseTimes::WeakCLDRoots, worker_i, 0.0); | |
171 } | 184 } |
172 | 185 |
173 // Finish up any enqueued closure apps (attributed as object copy time). | 186 // Finish up any enqueued closure apps (attributed as object copy time). |
174 buf_scan_non_heap_roots.done(); | 187 buf_scan_non_heap_roots.done(); |
175 buf_scan_non_heap_weak_roots.done(); | 188 buf_scan_non_heap_weak_roots.done(); |
176 | 189 |
177 double obj_copy_time_sec = buf_scan_non_heap_roots.closure_app_seconds() | 190 double obj_copy_time_sec = buf_scan_non_heap_roots.closure_app_seconds() |
178 + buf_scan_non_heap_weak_roots.closure_app_seconds(); | 191 + buf_scan_non_heap_weak_roots.closure_app_seconds(); |
179 | 192 |
180 G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times(); | |
181 phase_times->record_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, obj_copy_time_sec); | 193 phase_times->record_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, obj_copy_time_sec); |
182 | 194 |
183 double ext_root_time_sec = os::elapsedTime() - ext_roots_start - obj_copy_time_sec; | 195 double ext_root_time_sec = os::elapsedTime() - ext_roots_start - obj_copy_time_sec; |
184 | 196 |
185 phase_times->record_time_secs(G1GCPhaseTimes::ExtRootScan, worker_i, ext_root_time_sec); | 197 phase_times->record_time_secs(G1GCPhaseTimes::ExtRootScan, worker_i, ext_root_time_sec); |
199 | 211 |
200 void G1RootProcessor::process_strong_roots(OopClosure* oops, | 212 void G1RootProcessor::process_strong_roots(OopClosure* oops, |
201 CLDClosure* clds, | 213 CLDClosure* clds, |
202 CodeBlobClosure* blobs) { | 214 CodeBlobClosure* blobs) { |
203 | 215 |
204 process_java_roots(oops, clds, clds, NULL, blobs); | 216 process_java_roots(oops, clds, clds, NULL, blobs, NULL, 0); |
205 process_vm_roots(oops, NULL); | 217 process_vm_roots(oops, NULL, NULL, 0); |
206 | 218 |
207 _process_strong_tasks->all_tasks_completed(); | 219 _process_strong_tasks->all_tasks_completed(); |
208 } | 220 } |
209 | 221 |
210 void G1RootProcessor::process_all_roots(OopClosure* oops, | 222 void G1RootProcessor::process_all_roots(OopClosure* oops, |
211 CLDClosure* clds, | 223 CLDClosure* clds, |
212 CodeBlobClosure* blobs) { | 224 CodeBlobClosure* blobs) { |
213 | 225 |
214 process_java_roots(oops, NULL, clds, clds, NULL); | 226 process_java_roots(oops, NULL, clds, clds, NULL, NULL, 0); |
215 process_vm_roots(oops, oops); | 227 process_vm_roots(oops, oops, NULL, 0); |
216 | 228 |
217 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_CodeCache_oops_do)) { | 229 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_CodeCache_oops_do)) { |
218 CodeCache::blobs_do(blobs); | 230 CodeCache::blobs_do(blobs); |
219 } | 231 } |
220 | 232 |
223 | 235 |
224 void G1RootProcessor::process_java_roots(OopClosure* strong_roots, | 236 void G1RootProcessor::process_java_roots(OopClosure* strong_roots, |
225 CLDClosure* thread_stack_clds, | 237 CLDClosure* thread_stack_clds, |
226 CLDClosure* strong_clds, | 238 CLDClosure* strong_clds, |
227 CLDClosure* weak_clds, | 239 CLDClosure* weak_clds, |
228 CodeBlobClosure* strong_code) { | 240 CodeBlobClosure* strong_code, |
241 G1GCPhaseTimes* phase_times, | |
242 uint worker_i) { | |
229 assert(thread_stack_clds == NULL || weak_clds == NULL, "There is overlap between those, only one may be set"); | 243 assert(thread_stack_clds == NULL || weak_clds == NULL, "There is overlap between those, only one may be set"); |
230 // Iterating over the CLDG and the Threads are done early to allow us to | 244 // Iterating over the CLDG and the Threads are done early to allow us to |
231 // first process the strong CLDs and nmethods and then, after a barrier, | 245 // first process the strong CLDs and nmethods and then, after a barrier, |
232 // let the thread process the weak CLDs and nmethods. | 246 // let the thread process the weak CLDs and nmethods. |
233 | 247 { |
234 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_ClassLoaderDataGraph_oops_do)) { | 248 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CLDGRoots, worker_i); |
235 ClassLoaderDataGraph::roots_cld_do(strong_clds, weak_clds); | 249 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_ClassLoaderDataGraph_oops_do)) { |
236 } | 250 ClassLoaderDataGraph::roots_cld_do(strong_clds, weak_clds); |
237 | 251 } |
238 Threads::possibly_parallel_oops_do(strong_roots, thread_stack_clds, strong_code); | 252 } |
253 | |
254 { | |
255 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ThreadRoots, worker_i); | |
256 Threads::possibly_parallel_oops_do(strong_roots, thread_stack_clds, strong_code); | |
257 } | |
239 } | 258 } |
240 | 259 |
241 void G1RootProcessor::process_vm_roots(OopClosure* strong_roots, | 260 void G1RootProcessor::process_vm_roots(OopClosure* strong_roots, |
242 OopClosure* weak_roots) { | 261 OopClosure* weak_roots, |
243 | 262 G1GCPhaseTimes* phase_times, |
244 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_Universe_oops_do)) { | 263 uint worker_i) { |
245 Universe::oops_do(strong_roots); | 264 { |
246 } | 265 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::UniverseRoots, worker_i); |
247 | 266 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_Universe_oops_do)) { |
248 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_JNIHandles_oops_do)) { | 267 Universe::oops_do(strong_roots); |
249 JNIHandles::oops_do(strong_roots); | 268 } |
250 } | 269 } |
251 | 270 |
252 if (!_process_strong_tasks-> is_task_claimed(G1RP_PS_ObjectSynchronizer_oops_do)) { | 271 { |
253 ObjectSynchronizer::oops_do(strong_roots); | 272 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::JNIRoots, worker_i); |
254 } | 273 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_JNIHandles_oops_do)) { |
255 | 274 JNIHandles::oops_do(strong_roots); |
256 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_FlatProfiler_oops_do)) { | 275 } |
257 FlatProfiler::oops_do(strong_roots); | 276 } |
258 } | 277 |
259 | 278 { |
260 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_Management_oops_do)) { | 279 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ObjectSynchronizerRoots, worker_i); |
261 Management::oops_do(strong_roots); | 280 if (!_process_strong_tasks-> is_task_claimed(G1RP_PS_ObjectSynchronizer_oops_do)) { |
262 } | 281 ObjectSynchronizer::oops_do(strong_roots); |
263 | 282 } |
264 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_jvmti_oops_do)) { | 283 } |
265 JvmtiExport::oops_do(strong_roots); | 284 |
266 } | 285 { |
267 | 286 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::FlatProfilerRoots, worker_i); |
268 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_SystemDictionary_oops_do)) { | 287 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_FlatProfiler_oops_do)) { |
269 SystemDictionary::roots_oops_do(strong_roots, weak_roots); | 288 FlatProfiler::oops_do(strong_roots); |
270 } | 289 } |
271 | 290 } |
272 // All threads execute the following. A specific chunk of buckets | 291 |
273 // from the StringTable are the individual tasks. | 292 { |
274 if (weak_roots != NULL) { | 293 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ManagementRoots, worker_i); |
275 StringTable::possibly_parallel_oops_do(weak_roots); | 294 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_Management_oops_do)) { |
295 Management::oops_do(strong_roots); | |
296 } | |
297 } | |
298 | |
299 { | |
300 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::JVMTIRoots, worker_i); | |
301 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_jvmti_oops_do)) { | |
302 JvmtiExport::oops_do(strong_roots); | |
303 } | |
304 } | |
305 | |
306 { | |
307 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::SystemDictionaryRoots, worker_i); | |
308 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_SystemDictionary_oops_do)) { | |
309 SystemDictionary::roots_oops_do(strong_roots, weak_roots); | |
310 } | |
311 } | |
312 | |
313 { | |
314 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::StringTableRoots, worker_i); | |
315 // All threads execute the following. A specific chunk of buckets | |
316 // from the StringTable are the individual tasks. | |
317 if (weak_roots != NULL) { | |
318 StringTable::possibly_parallel_oops_do(weak_roots); | |
319 } | |
276 } | 320 } |
277 } | 321 } |
278 | 322 |
279 void G1RootProcessor::scan_remembered_sets(G1ParPushHeapRSClosure* scan_rs, | 323 void G1RootProcessor::scan_remembered_sets(G1ParPushHeapRSClosure* scan_rs, |
280 OopClosure* scan_non_heap_weak_roots, | 324 OopClosure* scan_non_heap_weak_roots, |
281 uint worker_i) { | 325 uint worker_i) { |
326 G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times(); | |
327 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CodeCacheRoots, worker_i); | |
328 | |
282 // Now scan the complement of the collection set. | 329 // Now scan the complement of the collection set. |
283 G1CodeBlobClosure scavenge_cs_nmethods(scan_non_heap_weak_roots); | 330 G1CodeBlobClosure scavenge_cs_nmethods(scan_non_heap_weak_roots); |
284 | 331 |
285 _g1h->g1_rem_set()->oops_into_collection_set_do(scan_rs, &scavenge_cs_nmethods, worker_i); | 332 _g1h->g1_rem_set()->oops_into_collection_set_do(scan_rs, &scavenge_cs_nmethods, worker_i); |
286 } | 333 } |