231 }; 232 233 void G1RemSet::scanRS(G1ParPushHeapRSClosure* oc, 234 CodeBlobClosure* code_root_cl, 235 uint worker_i) { 236 double rs_time_start = os::elapsedTime(); 237 HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i); 238 239 ScanRSClosure scanRScl(oc, code_root_cl, worker_i); 240 241 _g1->collection_set_iterate_from(startRegion, &scanRScl); 242 scanRScl.set_try_claimed(); 243 _g1->collection_set_iterate_from(startRegion, &scanRScl); 244 245 double scan_rs_time_sec = (os::elapsedTime() - rs_time_start) 246 - scanRScl.strong_code_root_scan_time_sec(); 247 248 assert(_cards_scanned != NULL, "invariant"); 249 _cards_scanned[worker_i] = scanRScl.cards_done(); 250 251 _g1p->phase_times()->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0); 252 _g1p->phase_times()->record_strong_code_root_scan_time(worker_i, 253 scanRScl.strong_code_root_scan_time_sec() * 1000.0); 254 } 255 256 // Closure used for updating RSets and recording references that 257 // point into the collection set. Only called during an 258 // evacuation pause. 259 260 class RefineRecordRefsIntoCSCardTableEntryClosure: public CardTableEntryClosure { 261 G1RemSet* _g1rs; 262 DirtyCardQueue* _into_cset_dcq; 263 public: 264 RefineRecordRefsIntoCSCardTableEntryClosure(G1CollectedHeap* g1h, 265 DirtyCardQueue* into_cset_dcq) : 266 _g1rs(g1h->g1_rem_set()), _into_cset_dcq(into_cset_dcq) 267 {} 268 bool do_card_ptr(jbyte* card_ptr, uint worker_i) { 269 // The only time we care about recording cards that 270 // contain references that point into the collection set 271 // is during RSet updating within an evacuation pause. 272 // In this case worker_i should be the id of a GC worker thread. 273 assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause"); 274 assert(worker_i < ParallelGCThreads, "should be a GC worker"); 275 276 if (_g1rs->refine_card(card_ptr, worker_i, true)) { 277 // 'card_ptr' contains references that point into the collection 278 // set. We need to record the card in the DCQS 279 // (G1CollectedHeap::into_cset_dirty_card_queue_set()) 280 // that's used for that purpose. 281 // 282 // Enqueue the card 283 _into_cset_dcq->enqueue(card_ptr); 284 } 285 return true; 286 } 287 }; 288 289 void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i) { 290 double start = os::elapsedTime(); 291 // Apply the given closure to all remaining log entries. 292 RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq); 293 294 _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i); 295 296 _g1p->phase_times()->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0); 297 } 298 299 void G1RemSet::cleanupHRRS() { 300 HeapRegionRemSet::cleanup(); 301 } 302 303 void G1RemSet::oops_into_collection_set_do(G1ParPushHeapRSClosure* oc, 304 CodeBlobClosure* code_root_cl, 305 uint worker_i) { 306 #if CARD_REPEAT_HISTO 307 ct_freq_update_histo_and_reset(); 308 #endif 309 310 // We cache the value of 'oc' closure into the appropriate slot in the 311 // _cset_rs_update_cl for this worker 312 assert(worker_i < n_workers(), "sanity"); 313 _cset_rs_update_cl[worker_i] = oc; 314 315 // A DirtyCardQueue that is used to hold cards containing references 316 // that point into the collection set. This DCQ is associated with a | 231 }; 232 233 void G1RemSet::scanRS(G1ParPushHeapRSClosure* oc, 234 CodeBlobClosure* code_root_cl, 235 uint worker_i) { 236 double rs_time_start = os::elapsedTime(); 237 HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i); 238 239 ScanRSClosure scanRScl(oc, code_root_cl, worker_i); 240 241 _g1->collection_set_iterate_from(startRegion, &scanRScl); 242 scanRScl.set_try_claimed(); 243 _g1->collection_set_iterate_from(startRegion, &scanRScl); 244 245 double scan_rs_time_sec = (os::elapsedTime() - rs_time_start) 246 - scanRScl.strong_code_root_scan_time_sec(); 247 248 assert(_cards_scanned != NULL, "invariant"); 249 _cards_scanned[worker_i] = scanRScl.cards_done(); 250 251 _g1p->phase_times()->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, scan_rs_time_sec); 252 _g1p->phase_times()->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, scanRScl.strong_code_root_scan_time_sec()); 253 } 254 255 // Closure used for updating RSets and recording references that 256 // point into the collection set. Only called during an 257 // evacuation pause. 258 259 class RefineRecordRefsIntoCSCardTableEntryClosure: public CardTableEntryClosure { 260 G1RemSet* _g1rs; 261 DirtyCardQueue* _into_cset_dcq; 262 public: 263 RefineRecordRefsIntoCSCardTableEntryClosure(G1CollectedHeap* g1h, 264 DirtyCardQueue* into_cset_dcq) : 265 _g1rs(g1h->g1_rem_set()), _into_cset_dcq(into_cset_dcq) 266 {} 267 bool do_card_ptr(jbyte* card_ptr, uint worker_i) { 268 // The only time we care about recording cards that 269 // contain references that point into the collection set 270 // is during RSet updating within an evacuation pause. 271 // In this case worker_i should be the id of a GC worker thread. 272 assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause"); 273 assert(worker_i < ParallelGCThreads, "should be a GC worker"); 274 275 if (_g1rs->refine_card(card_ptr, worker_i, true)) { 276 // 'card_ptr' contains references that point into the collection 277 // set. We need to record the card in the DCQS 278 // (G1CollectedHeap::into_cset_dirty_card_queue_set()) 279 // that's used for that purpose. 280 // 281 // Enqueue the card 282 _into_cset_dcq->enqueue(card_ptr); 283 } 284 return true; 285 } 286 }; 287 288 void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i) { 289 G1GCParPhaseTimesTracker x(_g1p->phase_times(), G1GCPhaseTimes::UpdateRS, worker_i); 290 // Apply the given closure to all remaining log entries. 291 RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq); 292 293 _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i); 294 } 295 296 void G1RemSet::cleanupHRRS() { 297 HeapRegionRemSet::cleanup(); 298 } 299 300 void G1RemSet::oops_into_collection_set_do(G1ParPushHeapRSClosure* oc, 301 CodeBlobClosure* code_root_cl, 302 uint worker_i) { 303 #if CARD_REPEAT_HISTO 304 ct_freq_update_histo_and_reset(); 305 #endif 306 307 // We cache the value of 'oc' closure into the appropriate slot in the 308 // _cset_rs_update_cl for this worker 309 assert(worker_i < n_workers(), "sanity"); 310 _cset_rs_update_cl[worker_i] = oc; 311 312 // A DirtyCardQueue that is used to hold cards containing references 313 // that point into the collection set. This DCQ is associated with a |