void do_oop_work(T* p) { _work->do_oop(p); T oop_or_narrowoop = oopDesc::load_heap_oop(p); if (!oopDesc::is_null(oop_or_narrowoop)) { oop o = oopDesc::decode_heap_oop_not_null(oop_or_narrowoop); HeapRegion* hr = _g1h->heap_region_containing_raw(o); assert(!_g1h->obj_in_cs(o) || hr->rem_set()->strong_code_roots_list_contains(_nm), "if o still in CS then evacuation failed and nm must already be in the remset"); hr->add_strong_code_root(_nm); } }
ScanRSClosure(OopsInHeapRegionClosure* oc, int worker_i) : _oc(oc), _cards(0), _cards_done(0), _worker_i(worker_i), _try_claimed(false) { _g1h = G1CollectedHeap::heap(); _bot_shared = _g1h->bot_shared(); _ct_bs = (CardTableModRefBS*) (_g1h->barrier_set()); _block_size = MAX2<int>(G1RSetScanBlockSize, 1); }
bool doHeapRegion(HeapRegion* r) { assert(r->in_collection_set(), "should only be called on elements of CS."); HeapRegionRemSet* hrrs = r->rem_set(); if (hrrs->iter_is_complete()) return false; // All done. if (!_try_claimed && !hrrs->claim_iter()) return false; // If we ever free the collection set concurrently, we should also // clear the card table concurrently therefore we won't need to // add regions of the collection set to the dirty cards region. _g1h->push_dirty_cards_region(r); // If we didn't return above, then // _try_claimed || r->claim_iter() // is true: either we're supposed to work on claimed-but-not-complete // regions, or we successfully claimed the region. HeapRegionRemSetIterator iter(hrrs); size_t card_index; // We claim cards in block so as to reduce the contention. The block size is determined by // the G1RSetScanBlockSize parameter. size_t jump_to_card = hrrs->iter_claimed_next(_block_size); for (size_t current_card = 0; iter.has_next(card_index); current_card++) { if (current_card >= jump_to_card + _block_size) { jump_to_card = hrrs->iter_claimed_next(_block_size); } if (current_card < jump_to_card) continue; HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index); #if 0 gclog_or_tty->print("Rem set iteration yielded card [" PTR_FORMAT ", " PTR_FORMAT ").\n", card_start, card_start + CardTableModRefBS::card_size_in_words); #endif HeapRegion* card_region = _g1h->heap_region_containing(card_start); _cards++; if (!card_region->is_on_dirty_cards_region_list()) { _g1h->push_dirty_cards_region(card_region); } // If the card is dirty, then we will scan it during updateRS. if (!card_region->in_collection_set() && !_ct_bs->is_card_dirty(card_index)) { scanCard(card_index, card_region); } } if (!_try_claimed) { // Scan the strong code root list attached to the current region scan_strong_code_roots(r); hrrs->set_iter_complete(); } return false; }
bool doHeapRegion(HeapRegion* r) { assert(r->in_collection_set(), "should only be called on elements of CS."); HeapRegionRemSet* hrrs = r->rem_set(); if (hrrs->iter_is_complete()) return false; // All done. if (!_try_claimed && !hrrs->claim_iter()) return false; _g1h->push_dirty_cards_region(r); // If we didn't return above, then // _try_claimed || r->claim_iter() // is true: either we're supposed to work on claimed-but-not-complete // regions, or we successfully claimed the region. HeapRegionRemSetIterator* iter = _g1h->rem_set_iterator(_worker_i); hrrs->init_iterator(iter); size_t card_index; // We claim cards in block so as to recude the contention. The block size is determined by // the G1RSetScanBlockSize parameter. size_t jump_to_card = hrrs->iter_claimed_next(_block_size); for (size_t current_card = 0; iter->has_next(card_index); current_card++) { if (current_card >= jump_to_card + _block_size) { jump_to_card = hrrs->iter_claimed_next(_block_size); } if (current_card < jump_to_card) continue; HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index); #if 0 gclog_or_tty->print("Rem set iteration yielded card [" PTR_FORMAT ", " PTR_FORMAT ").\n", card_start, card_start + CardTableModRefBS::card_size_in_words); #endif HeapRegion* card_region = _g1h->heap_region_containing(card_start); assert(card_region != NULL, "Yielding cards not in the heap?"); _cards++; if (!card_region->is_on_dirty_cards_region_list()) { _g1h->push_dirty_cards_region(card_region); } // If the card is dirty, then we will scan it during updateRS. if (!card_region->in_collection_set() && !_ct_bs->is_card_dirty(card_index)) { // We make the card as "claimed" lazily (so races are possible but they're benign), // which reduces the number of duplicate scans (the rsets of the regions in the cset // can intersect). if (!_ct_bs->is_card_claimed(card_index)) { _ct_bs->set_card_claimed(card_index); scanCard(card_index, card_region); } } } if (!_try_claimed) { hrrs->set_iter_complete(); } return false; }
ScanRSClosure(G1ParPushHeapRSClosure* oc, CodeBlobClosure* code_root_cl, uint worker_i) : _oc(oc), _code_root_cl(code_root_cl), _strong_code_root_scan_time_sec(0.0), _cards(0), _cards_done(0), _worker_i(worker_i), _try_claimed(false) { _g1h = G1CollectedHeap::heap(); _bot_shared = _g1h->bot_shared(); _ct_bs = _g1h->g1_barrier_set(); _block_size = MAX2<int>(G1RSetScanBlockSize, 1); }
// use_prev_marking == true -> use "prev" marking information, // use_prev_marking == false -> use "next" marking information VerifyLiveClosure(G1CollectedHeap* g1h, bool use_prev_marking) : _g1h(g1h), _bs(NULL), _containing_obj(NULL), _failures(false), _n_failures(0), _use_prev_marking(use_prev_marking) { BarrierSet* bs = _g1h->barrier_set(); if (bs->is_a(BarrierSet::CardTableModRef)) _bs = (CardTableModRefBS*)bs; }
// _vo == UsePrevMarking -> use "prev" marking information, // _vo == UseNextMarking -> use "next" marking information, // _vo == UseMarkWord -> use mark word from object header. VerifyLiveClosure(G1CollectedHeap* g1h, VerifyOption vo) : _g1h(g1h), _bs(NULL), _containing_obj(NULL), _failures(false), _n_failures(0), _vo(vo) { BarrierSet* bs = _g1h->barrier_set(); if (bs->is_a(BarrierSet::CardTableModRef)) _bs = (CardTableModRefBS*)bs; }
ScrubRSClosure(BitMap* region_bm, BitMap* card_bm) : _g1h(G1CollectedHeap::heap()), _region_bm(region_bm), _card_bm(card_bm), _ctbs(NULL) { ModRefBarrierSet* bs = _g1h->mr_bs(); guarantee(bs->is_a(BarrierSet::CardTableModRef), "Precondition"); _ctbs = (CardTableModRefBS*)bs; }
template <class T> void do_oop_work(T* p) { oop obj = oopDesc::load_decode_heap_oop(p); if (_g1->obj_in_cs(obj)) { size_t card_index = _ct_bs->index_for(p); if (_ct_bs->mark_card_deferred(card_index)) { _dcq->enqueue((jbyte*)_ct_bs->byte_for_index(card_index)); } } }
void update_sets() { // We'll recalculate total used bytes and recreate the free list // at the end of the GC, so no point in updating those values here. _g1h->update_sets_after_freeing_regions(0, /* pre_used */ NULL, /* free_list */ NULL, /* old_proxy_set */ &_humongous_proxy_set, false /* par */); }
bool doHeapRegion(HeapRegion *hr) { bool during_initial_mark = _g1h->g1_policy()->during_initial_mark_pause(); bool during_conc_mark = _g1h->mark_in_progress(); assert(!hr->isHumongous(), "sanity"); assert(hr->in_collection_set(), "bad CS"); if (hr->claimHeapRegion(HeapRegion::ParEvacFailureClaimValue)) { if (hr->evacuation_failed()) { RemoveSelfForwardPtrObjClosure rspc(_g1h, _cm, hr, &_update_rset_cl, during_initial_mark, during_conc_mark, _worker_id); hr->note_self_forwarding_removal_start(during_initial_mark, during_conc_mark); _g1h->check_bitmaps("Self-Forwarding Ptr Removal", hr); // In the common case (i.e. when there is no evacuation // failure) we make sure that the following is done when // the region is freed so that it is "ready-to-go" when it's // re-allocated. However, when evacuation failure happens, a // region will remain in the heap and might ultimately be added // to a CSet in the future. So we have to be careful here and // make sure the region's RSet is ready for parallel iteration // whenever this might be required in the future. hr->rem_set()->reset_for_par_iteration(); hr->reset_bot(); _update_rset_cl.set_region(hr); hr->object_iterate(&rspc); hr->rem_set()->clean_strong_code_roots(hr); hr->note_self_forwarding_removal_end(during_initial_mark, during_conc_mark, rspc.marked_bytes()); } } return false; }
bool do_card_ptr(jbyte* card_ptr, int worker_i) { // Construct the region representing the card. HeapWord* start = _ct_bs->addr_for(card_ptr); // And find the region containing it. HeapRegion* r = _g1->heap_region_containing(start); assert(r != NULL, "unexpected null"); // Scan oops in the card looking for references into the collection set HeapWord* end = _ct_bs->addr_for(card_ptr + 1); MemRegion scanRegion(start, end); UpdateRSetImmediate update_rs_cl(_g1->g1_rem_set()); FilterIntoCSClosure update_rs_cset_oop_cl(NULL, _g1, &update_rs_cl); FilterOutOfRegionClosure filter_then_update_rs_cset_oop_cl(r, &update_rs_cset_oop_cl); // We can pass false as the "filter_young" parameter here as: // * we should be in a STW pause, // * the DCQS to which this closure is applied is used to hold // references that point into the collection set from the prior // RSet updating, // * the post-write barrier shouldn't be logging updates to young // regions (but there is a situation where this can happen - see // the comment in G1RemSet::concurrentRefineOneCard below - // that should not be applicable here), and // * during actual RSet updating, the filtering of cards in young // regions in HeapRegion::oops_on_card_seq_iterate_careful is // employed. // As a result, when this closure is applied to "refs into cset" // DCQS, we shouldn't see any cards in young regions. update_rs_cl.set_region(r); HeapWord* stop_point = r->oops_on_card_seq_iterate_careful(scanRegion, &filter_then_update_rs_cset_oop_cl, false /* filter_young */); // Since this is performed in the event of an evacuation failure, we // we shouldn't see a non-null stop point assert(stop_point == NULL, "saw an unallocated region"); return true; }
void free_humongous_region(HeapRegion* hr) { HeapWord* end = hr->end(); size_t dummy_pre_used; FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep"); assert(hr->startsHumongous(), "Only the start of a humongous region should be freed."); _g1h->free_humongous_region(hr, &dummy_pre_used, &dummy_free_list, &_humongous_proxy_set, false /* par */); hr->prepare_for_compaction(&_cp); // Also clear the part of the card table that will be unused after // compaction. _mrbs->clear(MemRegion(hr->compaction_top(), end)); dummy_free_list.remove_all(); }
ScrubRSClosure(BitMap* region_bm, BitMap* card_bm) : _g1h(G1CollectedHeap::heap()), _region_bm(region_bm), _card_bm(card_bm), _ctbs(_g1h->g1_barrier_set()) {}
UpdateRSetDeferred(G1CollectedHeap* g1, DirtyCardQueue* dcq) : _g1(g1), _ct_bs(_g1->g1_barrier_set()), _dcq(dcq) {}
void work(uint worker_id) { RemoveSelfForwardPtrHRClosure rsfp_cl(_g1h, worker_id); HeapRegion* hr = _g1h->start_cset_region_for_worker(worker_id); _g1h->collection_set_iterate_from(hr, &rsfp_cl); }
RemoveSelfForwardPtrHRClosure(G1CollectedHeap* g1h, uint worker_id) : _g1h(g1h), _dcq(&g1h->dirty_card_queue_set()), _update_rset_cl(g1h, &_dcq), _worker_id(worker_id), _cm(_g1h->concurrent_mark()) { }
G1PrepareCompactClosure() : _g1h(G1CollectedHeap::heap()), _mrbs(_g1h->g1_barrier_set()), _humongous_regions_removed() { }
template <class T> void do_oop_work(T* p) { HeapRegion* to = _g1->heap_region_containing(oopDesc::load_decode_heap_oop(p)); if (to->in_collection_set()) { to->rem_set()->add_reference(p, 0); } }
G1PrepareCompactClosure(CompactibleSpace* cs) : _g1h(G1CollectedHeap::heap()), _mrbs(_g1h->g1_barrier_set()), _cp(NULL, cs, cs->initialize_threshold()), _humongous_proxy_set("G1MarkSweep Humongous Proxy Set") { }
template <class T> void do_oop_work(T* p) { oop obj = oopDesc::load_decode_heap_oop(p); HeapRegion* to = _g1->heap_region_containing(obj); guarantee(to == NULL || !to->in_collection_set(), "Missed a rem set member."); }
UpdateRSetOopsIntoCSDeferred(G1CollectedHeap* g1, DirtyCardQueue* dcq) : _g1(g1), _ct_bs((CardTableModRefBS*)_g1->barrier_set()), _dcq(dcq) { }
bool is_young_list_full() { uint young_list_length = _g1->young_list()->length(); uint young_list_target_length = _young_list_target_length; return young_list_length >= young_list_target_length; }
bool can_expand_young_list() { uint young_list_length = _g1->young_list()->length(); uint young_list_max_length = _young_list_max_length; return young_list_length < young_list_max_length; }
// Set all cards back to clean. void cleanup() {_g1h->cleanUpCardTable();}
template <class T> void do_oop_work(T* p) { assert(_containing_obj != NULL, "Precondition"); assert(!_g1h->is_obj_dead_cond(_containing_obj, _use_prev_marking), "Precondition"); T heap_oop = oopDesc::load_heap_oop(p); if (!oopDesc::is_null(heap_oop)) { oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); bool failed = false; if (!_g1h->is_in_closed_subset(obj) || _g1h->is_obj_dead_cond(obj, _use_prev_marking)) { if (!_failures) { gclog_or_tty->print_cr(""); gclog_or_tty->print_cr("----------"); } if (!_g1h->is_in_closed_subset(obj)) { HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p); gclog_or_tty->print_cr("Field "PTR_FORMAT " of live obj "PTR_FORMAT" in region " "["PTR_FORMAT", "PTR_FORMAT")", p, (void*) _containing_obj, from->bottom(), from->end()); print_object(gclog_or_tty, _containing_obj); gclog_or_tty->print_cr("points to obj "PTR_FORMAT" not in the heap", (void*) obj); } else { HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p); HeapRegion* to = _g1h->heap_region_containing((HeapWord*)obj); gclog_or_tty->print_cr("Field "PTR_FORMAT " of live obj "PTR_FORMAT" in region " "["PTR_FORMAT", "PTR_FORMAT")", p, (void*) _containing_obj, from->bottom(), from->end()); print_object(gclog_or_tty, _containing_obj); gclog_or_tty->print_cr("points to dead obj "PTR_FORMAT" in region " "["PTR_FORMAT", "PTR_FORMAT")", (void*) obj, to->bottom(), to->end()); print_object(gclog_or_tty, obj); } gclog_or_tty->print_cr("----------"); _failures = true; failed = true; _n_failures++; } if (!_g1h->full_collection()) { HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p); HeapRegion* to = _g1h->heap_region_containing(obj); if (from != NULL && to != NULL && from != to && !to->isHumongous()) { jbyte cv_obj = *_bs->byte_for_const(_containing_obj); jbyte cv_field = *_bs->byte_for_const(p); const jbyte dirty = CardTableModRefBS::dirty_card_val(); bool is_bad = !(from->is_young() || to->rem_set()->contains_reference(p) || !G1HRRSFlushLogBuffersOnVerify && // buffers were not flushed (_containing_obj->is_objArray() ? cv_field == dirty : cv_obj == dirty || cv_field == dirty)); if (is_bad) { if (!_failures) { gclog_or_tty->print_cr(""); gclog_or_tty->print_cr("----------"); } gclog_or_tty->print_cr("Missing rem set entry:"); gclog_or_tty->print_cr("Field "PTR_FORMAT " of obj "PTR_FORMAT ", in region %d ["PTR_FORMAT ", "PTR_FORMAT"),", p, (void*) _containing_obj, from->hrs_index(), from->bottom(), from->end()); _containing_obj->print_on(gclog_or_tty); gclog_or_tty->print_cr("points to obj "PTR_FORMAT " in region %d ["PTR_FORMAT ", "PTR_FORMAT").", (void*) obj, to->hrs_index(), to->bottom(), to->end()); obj->print_on(gclog_or_tty); gclog_or_tty->print_cr("Obj head CTE = %d, field CTE = %d.", cv_obj, cv_field); gclog_or_tty->print_cr("----------"); _failures = true; if (!failed) _n_failures++; } } } } }
template <class T> void do_oop_work(T* p) { oop obj = oopDesc::load_decode_heap_oop(p); if (_g1->obj_in_cs(obj)) _blk->do_oop(p); }