< prev index next >

src/hotspot/share/gc/shared/cardTableRS.cpp

Print this page




 122 }
 123 
 124 inline bool ClearNoncleanCardWrapper::clear_card(CardValue* entry) {
 125   if (_is_par) {
 126     return clear_card_parallel(entry);
 127   } else {
 128     return clear_card_serial(entry);
 129   }
 130 }
 131 
 132 inline bool ClearNoncleanCardWrapper::clear_card_parallel(CardValue* entry) {
 133   while (true) {
 134     // In the parallel case, we may have to do this several times.
 135     CardValue entry_val = *entry;
 136     assert(entry_val != CardTableRS::clean_card_val(),
 137            "We shouldn't be looking at clean cards, and this should "
 138            "be the only place they get cleaned.");
 139     if (CardTableRS::card_is_dirty_wrt_gen_iter(entry_val)
 140         || _ct->is_prev_youngergen_card_val(entry_val)) {
 141       CardValue res =
 142         Atomic::cmpxchg(CardTableRS::clean_card_val(), entry, entry_val);
 143       if (res == entry_val) {
 144         break;
 145       } else {
 146         assert(res == CardTableRS::cur_youngergen_and_prev_nonclean_card,
 147                "The CAS above should only fail if another thread did "
 148                "a GC write barrier.");
 149       }
 150     } else if (entry_val ==
 151                CardTableRS::cur_youngergen_and_prev_nonclean_card) {
 152       // Parallelism shouldn't matter in this case.  Only the thread
 153       // assigned to scan the card should change this value.
 154       *entry = _ct->cur_youngergen_card_val();
 155       break;
 156     } else {
 157       assert(entry_val == _ct->cur_youngergen_card_val(),
 158              "Should be the only possibility.");
 159       // In this case, the card was clean before, and become
 160       // cur_youngergen only because of processing of a promoted object.
 161       // We don't have to look at the card.
 162       return false;


 247 // clean (by dirty->clean before) ==> cur_younger_gen
 248 // dirty                          ==> cur_youngergen_and_prev_nonclean_card
 249 // precleaned                     ==> cur_youngergen_and_prev_nonclean_card
 250 // prev-younger-gen               ==> cur_youngergen_and_prev_nonclean_card
 251 // cur-younger-gen                ==> cur_younger_gen
 252 // cur_youngergen_and_prev_nonclean_card ==> no change.
 253 void CardTableRS::write_ref_field_gc_par(void* field, oop new_val) {
 254   volatile CardValue* entry = byte_for(field);
 255   do {
 256     CardValue entry_val = *entry;
 257     // We put this first because it's probably the most common case.
 258     if (entry_val == clean_card_val()) {
 259       // No threat of contention with cleaning threads.
 260       *entry = cur_youngergen_card_val();
 261       return;
 262     } else if (card_is_dirty_wrt_gen_iter(entry_val)
 263                || is_prev_youngergen_card_val(entry_val)) {
 264       // Mark it as both cur and prev youngergen; card cleaning thread will
 265       // eventually remove the previous stuff.
 266       CardValue new_val = cur_youngergen_and_prev_nonclean_card;
 267       CardValue res = Atomic::cmpxchg(new_val, entry, entry_val);
 268       // Did the CAS succeed?
 269       if (res == entry_val) return;
 270       // Otherwise, retry, to see the new value.
 271       continue;
 272     } else {
 273       assert(entry_val == cur_youngergen_and_prev_nonclean_card
 274              || entry_val == cur_youngergen_card_val(),
 275              "should be only possibilities.");
 276       return;
 277     }
 278   } while (true);
 279 }
 280 
 281 void CardTableRS::younger_refs_in_space_iterate(Space* sp,
 282                                                 OopsInGenClosure* cl,
 283                                                 uint n_threads) {
 284   verify_used_region_at_save_marks(sp);
 285 
 286   const MemRegion urasm = sp->used_region_at_save_marks();
 287   non_clean_card_iterate_possibly_parallel(sp, urasm, cl, this, n_threads);




 122 }
 123 
 124 inline bool ClearNoncleanCardWrapper::clear_card(CardValue* entry) {
 125   if (_is_par) {
 126     return clear_card_parallel(entry);
 127   } else {
 128     return clear_card_serial(entry);
 129   }
 130 }
 131 
 132 inline bool ClearNoncleanCardWrapper::clear_card_parallel(CardValue* entry) {
 133   while (true) {
 134     // In the parallel case, we may have to do this several times.
 135     CardValue entry_val = *entry;
 136     assert(entry_val != CardTableRS::clean_card_val(),
 137            "We shouldn't be looking at clean cards, and this should "
 138            "be the only place they get cleaned.");
 139     if (CardTableRS::card_is_dirty_wrt_gen_iter(entry_val)
 140         || _ct->is_prev_youngergen_card_val(entry_val)) {
 141       CardValue res =
 142         Atomic::cmpxchg(entry, entry_val, CardTableRS::clean_card_val());
 143       if (res == entry_val) {
 144         break;
 145       } else {
 146         assert(res == CardTableRS::cur_youngergen_and_prev_nonclean_card,
 147                "The CAS above should only fail if another thread did "
 148                "a GC write barrier.");
 149       }
 150     } else if (entry_val ==
 151                CardTableRS::cur_youngergen_and_prev_nonclean_card) {
 152       // Parallelism shouldn't matter in this case.  Only the thread
 153       // assigned to scan the card should change this value.
 154       *entry = _ct->cur_youngergen_card_val();
 155       break;
 156     } else {
 157       assert(entry_val == _ct->cur_youngergen_card_val(),
 158              "Should be the only possibility.");
 159       // In this case, the card was clean before, and become
 160       // cur_youngergen only because of processing of a promoted object.
 161       // We don't have to look at the card.
 162       return false;


 247 // clean (by dirty->clean before) ==> cur_younger_gen
 248 // dirty                          ==> cur_youngergen_and_prev_nonclean_card
 249 // precleaned                     ==> cur_youngergen_and_prev_nonclean_card
 250 // prev-younger-gen               ==> cur_youngergen_and_prev_nonclean_card
 251 // cur-younger-gen                ==> cur_younger_gen
 252 // cur_youngergen_and_prev_nonclean_card ==> no change.
 253 void CardTableRS::write_ref_field_gc_par(void* field, oop new_val) {
 254   volatile CardValue* entry = byte_for(field);
 255   do {
 256     CardValue entry_val = *entry;
 257     // We put this first because it's probably the most common case.
 258     if (entry_val == clean_card_val()) {
 259       // No threat of contention with cleaning threads.
 260       *entry = cur_youngergen_card_val();
 261       return;
 262     } else if (card_is_dirty_wrt_gen_iter(entry_val)
 263                || is_prev_youngergen_card_val(entry_val)) {
 264       // Mark it as both cur and prev youngergen; card cleaning thread will
 265       // eventually remove the previous stuff.
 266       CardValue new_val = cur_youngergen_and_prev_nonclean_card;
 267       CardValue res = Atomic::cmpxchg(entry, entry_val, new_val);
 268       // Did the CAS succeed?
 269       if (res == entry_val) return;
 270       // Otherwise, retry, to see the new value.
 271       continue;
 272     } else {
 273       assert(entry_val == cur_youngergen_and_prev_nonclean_card
 274              || entry_val == cur_youngergen_card_val(),
 275              "should be only possibilities.");
 276       return;
 277     }
 278   } while (true);
 279 }
 280 
 281 void CardTableRS::younger_refs_in_space_iterate(Space* sp,
 282                                                 OopsInGenClosure* cl,
 283                                                 uint n_threads) {
 284   verify_used_region_at_save_marks(sp);
 285 
 286   const MemRegion urasm = sp->used_region_at_save_marks();
 287   non_clean_card_iterate_possibly_parallel(sp, urasm, cl, this, n_threads);


< prev index next >