< prev index next >

src/share/vm/gc/g1/g1RemSet.cpp

Print this page
rev 13047 : imported patch 8071280-specialize-heapregion-oops-on-card-seq-iterate
rev 13048 : imported patch 8071280-kim-review
rev 13050 : imported patch 8071280-erikh-review
rev 13051 : imported patch 8162928-micro-optimizations-in-remembered-set-scan
rev 13052 : imported patch 8162928-reviews
rev 13053 : imported patch 8177707-specialize-refine-card
rev 13054 : imported patch 8177707-review-kim-sangheon
rev 13056 : imported patch 8177044-remove-scan-top
rev 13057 : imported patch 8177044-kim-review
rev 13058 : imported patch 8177044-ehelin-review

*** 114,132 **** static const IsDirtyRegionState Dirty = 1; // Holds a flag for every region whether it is in the _dirty_region_buffer already // to avoid duplicates. Uses jbyte since there are no atomic instructions for bools. IsDirtyRegionState* _in_dirty_region_buffer; size_t _cur_dirty_region; public: G1RemSetScanState() : _max_regions(0), _iter_states(NULL), _iter_claims(NULL), _dirty_region_buffer(NULL), _in_dirty_region_buffer(NULL), ! _cur_dirty_region(0) { ! } ~G1RemSetScanState() { if (_iter_states != NULL) { FREE_C_HEAP_ARRAY(G1RemsetIterState, _iter_states); --- 114,158 ---- static const IsDirtyRegionState Dirty = 1; // Holds a flag for every region whether it is in the _dirty_region_buffer already // to avoid duplicates. Uses jbyte since there are no atomic instructions for bools. IsDirtyRegionState* _in_dirty_region_buffer; size_t _cur_dirty_region; + + // Creates a snapshot of the current _top values at the start of collection to + // filter out card marks that we do not want to scan. + class G1ResetScanTopClosure : public HeapRegionClosure { + private: + HeapWord** _scan_top; + public: + G1ResetScanTopClosure(HeapWord** scan_top) : _scan_top(scan_top) { } + + virtual bool doHeapRegion(HeapRegion* r) { + uint hrm_index = r->hrm_index(); + if (!r->in_collection_set() && r->is_old_or_humongous()) { + _scan_top[hrm_index] = r->top(); + } else { + _scan_top[hrm_index] = r->bottom(); + } + return false; + } + }; + + // For each region, contains the maximum top() value to be used during this garbage + // collection. Subsumes common checks like filtering out everything but old and + // humongous regions outside the collection set. + // This is valid because we are not interested in scanning stray remembered set + // entries from free or archive regions. + HeapWord** _scan_top; public: G1RemSetScanState() : _max_regions(0), _iter_states(NULL), _iter_claims(NULL), _dirty_region_buffer(NULL), _in_dirty_region_buffer(NULL), ! _cur_dirty_region(0), ! _scan_top(NULL) { } ~G1RemSetScanState() { if (_iter_states != NULL) { FREE_C_HEAP_ARRAY(G1RemsetIterState, _iter_states);
*** 138,163 **** --- 164,197 ---- FREE_C_HEAP_ARRAY(uint, _dirty_region_buffer); } if (_in_dirty_region_buffer != NULL) { FREE_C_HEAP_ARRAY(IsDirtyRegionState, _in_dirty_region_buffer); } + if (_scan_top != NULL) { + FREE_C_HEAP_ARRAY(HeapWord*, _scan_top); + } } void initialize(uint max_regions) { assert(_iter_states == NULL, "Must not be initialized twice"); assert(_iter_claims == NULL, "Must not be initialized twice"); _max_regions = max_regions; _iter_states = NEW_C_HEAP_ARRAY(G1RemsetIterState, max_regions, mtGC); _iter_claims = NEW_C_HEAP_ARRAY(size_t, max_regions, mtGC); _dirty_region_buffer = NEW_C_HEAP_ARRAY(uint, max_regions, mtGC); _in_dirty_region_buffer = NEW_C_HEAP_ARRAY(IsDirtyRegionState, max_regions, mtGC); + _scan_top = NEW_C_HEAP_ARRAY(HeapWord*, max_regions, mtGC); } void reset() { for (uint i = 0; i < _max_regions; i++) { _iter_states[i] = Unclaimed; } + + G1ResetScanTopClosure cl(_scan_top); + G1CollectedHeap::heap()->heap_region_iterate(&cl); + memset((void*)_iter_claims, 0, _max_regions * sizeof(size_t)); memset(_in_dirty_region_buffer, Clean, _max_regions * sizeof(IsDirtyRegionState)); _cur_dirty_region = 0; }
*** 210,219 **** --- 244,257 ---- size_t allocated = Atomic::add(1, &_cur_dirty_region) - 1; _dirty_region_buffer[allocated] = region; } } + HeapWord* scan_top(uint region_idx) const { + return _scan_top[region_idx]; + } + // Clear the card table of "dirty" regions. void clear_card_table(WorkGang* workers) { if (_cur_dirty_region == 0) { return; }
*** 305,315 **** _block_size = MAX2<size_t>(G1RSetScanBlockSize, 1); } void G1ScanRSClosure::scan_card(size_t index, HeapWord* card_start, HeapRegion *r) { MemRegion card_region(card_start, BOTConstants::N_words); ! MemRegion pre_gc_allocated(r->bottom(), r->scan_top()); MemRegion mr = pre_gc_allocated.intersection(card_region); if (!mr.is_empty() && !_ct_bs->is_card_claimed(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). --- 343,353 ---- _block_size = MAX2<size_t>(G1RSetScanBlockSize, 1); } void G1ScanRSClosure::scan_card(size_t index, HeapWord* card_start, HeapRegion *r) { MemRegion card_region(card_start, BOTConstants::N_words); ! MemRegion pre_gc_allocated(r->bottom(), _scan_state->scan_top(r->hrm_index())); MemRegion mr = pre_gc_allocated.intersection(card_region); if (!mr.is_empty() && !_ct_bs->is_card_claimed(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).
*** 713,771 **** // 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); ! // This check is needed for some uncommon cases where we should ! // ignore the card. ! // ! // The region could be young. Cards for young regions are ! // distinctly marked (set to g1_young_gen), so the post-barrier will ! // filter them out. However, that marking is performed ! // concurrently. A write to a young object could occur before the ! // card has been marked young, slipping past the filter. ! // ! // The card could be stale, because the region has been freed since ! // the card was recorded. In this case the region type could be ! // anything. If (still) free or (reallocated) young, just ignore ! // it. If (reallocated) old or humongous, the later card trimming ! // and additional checks in iteration may detect staleness. At ! // worst, we end up processing a stale card unnecessarily. ! // ! // In the normal (non-stale) case, the synchronization between the ! // enqueueing of the card and processing it here will have ensured ! // we see the up-to-date region type here. ! if (!r->is_old_or_humongous()) { ! return false; ! } ! ! // While we are processing RSet buffers during the collection, we ! // actually don't want to scan any cards on the collection set, ! // since we don't want to update remembered sets with entries that ! // point into the collection set, given that live objects from the ! // collection set are about to move and such entries will be stale ! // very soon. This change also deals with a reliability issue which ! // involves scanning a card in the collection set and coming across ! // an array that was being chunked and looking malformed. Note, ! // however, that if evacuation fails, we have to scan any objects ! // that were not moved and create any missing entries. ! if (r->in_collection_set()) { ! return false; ! } ! ! // Trim the region designated by the card to what's been allocated ! // in the region. The card could be stale, or the card could cover ! // (part of) an object at the end of the allocated space and extend ! // beyond the end of allocation. ! ! // If we're in a STW GC, then a card might be in a GC alloc region ! // and extend onto a GC LAB, which may not be parsable. Stop such ! // at the "scan_top" of the region. ! HeapWord* scan_limit = r->scan_top(); ! if (scan_limit <= start) { ! // If the trimmed region is empty, the card must be stale. return false; } // Okay to clean and process the card now. There are still some // stale card cases that may be detected by iteration and dealt with --- 751,763 ---- // 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); ! HeapWord* scan_limit = _scan_state->scan_top(r->hrm_index()); if (scan_limit <= start) { ! // If the card starts above the area in the region containing objects to scan, skip it. return false; } // Okay to clean and process the card now. There are still some // stale card cases that may be detected by iteration and dealt with
< prev index next >