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