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 }