// clean (by dirty->clean before) ==> cur_younger_gen // dirty ==> cur_youngergen_and_prev_nonclean_card // precleaned ==> cur_youngergen_and_prev_nonclean_card // prev-younger-gen ==> cur_youngergen_and_prev_nonclean_card // cur-younger-gen ==> cur_younger_gen // cur_youngergen_and_prev_nonclean_card ==> no change. void CardTableRS::write_ref_field_gc_par(void* field, oop new_val) { jbyte* entry = ct_bs()->byte_for(field); do { jbyte entry_val = *entry; // We put this first because it's probably the most common case. if (entry_val == clean_card_val()) { // No threat of contention with cleaning threads. *entry = cur_youngergen_card_val(); return; } else if (card_is_dirty_wrt_gen_iter(entry_val) || is_prev_youngergen_card_val(entry_val)) { // Mark it as both cur and prev youngergen; card cleaning thread will // eventually remove the previous stuff. jbyte new_val = cur_youngergen_and_prev_nonclean_card; jbyte res = Atomic::cmpxchg(new_val, entry, entry_val); // Did the CAS succeed? if (res == entry_val) return; // Otherwise, retry, to see the new value. continue; } else { assert(entry_val == cur_youngergen_and_prev_nonclean_card || entry_val == cur_youngergen_card_val(), "should be only possibilities."); return; } } while (true); }
// Returns "true" iff the value "cv" may have represented a dirty card at // some point. virtual bool card_may_have_been_dirty(jbyte cv) { return card_is_dirty_wrt_gen_iter(cv); }
bool CardTableModRefBSForCTRS::card_may_have_been_dirty(jbyte cv) { return cv != clean_card && (card_is_dirty_wrt_gen_iter(cv) || CardTableRS::youngergen_may_have_been_dirty(cv)); }
bool CardTableModRefBSForCTRS::card_will_be_scanned(jbyte cv) { return card_is_dirty_wrt_gen_iter(cv) || _rs->is_prev_nonclean_card_val(cv); }