# HG changeset patch # User tschatzl # Date 1395671450 -3600 # Node ID ae7336d6337eb00bd07a4e1f4d14945e776b6021 # Parent eff02b5bd56ca919c1038aec2f3753a53ed86a91 8034868: Extract G1 From Card Cache into separate class Summary: Refactor the From Card Cache into a separate class. Reviewed-by: jmasa diff -r eff02b5bd56c -r ae7336d6337e src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Mon Mar 24 15:30:46 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Mon Mar 24 15:30:50 2014 +0100 @@ -1954,7 +1954,7 @@ int n_queues = MAX2((int)ParallelGCThreads, 1); _task_queues = new RefToScanQueueSet(n_queues); - int n_rem_sets = HeapRegionRemSet::num_par_rem_sets(); + uint n_rem_sets = HeapRegionRemSet::num_par_rem_sets(); assert(n_rem_sets > 0, "Invariant."); _worker_cset_start_region = NEW_C_HEAP_ARRAY(HeapRegion*, n_queues, mtGC); diff -r eff02b5bd56c -r ae7336d6337e src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp --- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Mon Mar 24 15:30:46 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Mon Mar 24 15:30:50 2014 +0100 @@ -358,48 +358,66 @@ "just checking"); } -int** OtherRegionsTable::_from_card_cache = NULL; -uint OtherRegionsTable::_from_card_cache_max_regions = 0; -size_t OtherRegionsTable::_from_card_cache_mem_size = 0; +int** FromCardCache::_cache = NULL; +uint FromCardCache::_max_regions = 0; +size_t FromCardCache::_static_mem_size = 0; -void OtherRegionsTable::init_from_card_cache(uint max_regions) { - guarantee(_from_card_cache == NULL, "Should not call this multiple times"); - uint n_par_rs = HeapRegionRemSet::num_par_rem_sets(); +void FromCardCache::initialize(uint n_par_rs, uint max_num_regions) { + guarantee(_cache == NULL, "Should not call this multiple times"); - _from_card_cache_max_regions = max_regions; - _from_card_cache = Padded2DArray::create_unfreeable(n_par_rs, - _from_card_cache_max_regions, - &_from_card_cache_mem_size); + _max_regions = max_num_regions; + _cache = Padded2DArray::create_unfreeable(n_par_rs, + _max_regions, + &_static_mem_size); for (uint i = 0; i < n_par_rs; i++) { - for (uint j = 0; j < _from_card_cache_max_regions; j++) { - _from_card_cache[i][j] = -1; // An invalid value. + for (uint j = 0; j < _max_regions; j++) { + set(i, j, InvalidCard); } } } -void OtherRegionsTable::shrink_from_card_cache(uint new_n_regs) { +void FromCardCache::shrink(uint new_num_regions) { for (uint i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) { - assert(new_n_regs <= _from_card_cache_max_regions, "Must be within max."); - for (uint j = new_n_regs; j < _from_card_cache_max_regions; j++) { - _from_card_cache[i][j] = -1; // An invalid value. + assert(new_num_regions <= _max_regions, "Must be within max."); + for (uint j = new_num_regions; j < _max_regions; j++) { + set(i, j, InvalidCard); } } } #ifndef PRODUCT -void OtherRegionsTable::print_from_card_cache() { +void FromCardCache::print(outputStream* out) { for (uint i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) { - for (uint j = 0; j < _from_card_cache_max_regions; j++) { - gclog_or_tty->print_cr("_from_card_cache[%d][%d] = %d.", - i, j, _from_card_cache[i][j]); + for (uint j = 0; j < _max_regions; j++) { + out->print_cr("_from_card_cache["UINT32_FORMAT"]["UINT32_FORMAT"] = "INT32_FORMAT".", + i, j, at(i, j)); } } } #endif +void FromCardCache::clear(uint region_idx) { + uint num_par_remsets = HeapRegionRemSet::num_par_rem_sets(); + for (uint i = 0; i < num_par_remsets; i++) { + set(i, region_idx, InvalidCard); + } +} + +void OtherRegionsTable::init_from_card_cache(uint max_regions) { + FromCardCache::initialize(HeapRegionRemSet::num_par_rem_sets(), max_regions); +} + +void OtherRegionsTable::shrink_from_card_cache(uint new_num_regions) { + FromCardCache::shrink(new_num_regions); +} + +void OtherRegionsTable::print_from_card_cache() { + FromCardCache::print(); +} + void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, int tid) { - size_t cur_hrs_ind = (size_t) hr()->hrs_index(); + uint cur_hrs_ind = hr()->hrs_index(); if (G1TraceHeapRegionRememberedSet) { gclog_or_tty->print_cr("ORT::add_reference_work(" PTR_FORMAT "->" PTR_FORMAT ").", @@ -412,19 +430,17 @@ int from_card = (int)(uintptr_t(from) >> CardTableModRefBS::card_shift); if (G1TraceHeapRegionRememberedSet) { - gclog_or_tty->print_cr("Table for [" PTR_FORMAT "...): card %d (cache = %d)", + gclog_or_tty->print_cr("Table for [" PTR_FORMAT "...): card %d (cache = "INT32_FORMAT")", hr()->bottom(), from_card, - _from_card_cache[tid][cur_hrs_ind]); + FromCardCache::at((uint)tid, cur_hrs_ind)); } - if (from_card == _from_card_cache[tid][cur_hrs_ind]) { + if (FromCardCache::contains_or_replace((uint)tid, cur_hrs_ind, from_card)) { if (G1TraceHeapRegionRememberedSet) { gclog_or_tty->print_cr(" from-card cache hit."); } assert(contains_reference(from), "We just added it!"); return; - } else { - _from_card_cache[tid][cur_hrs_ind] = from_card; } // Note that this may be a continued H region. @@ -722,7 +738,7 @@ } size_t OtherRegionsTable::static_mem_size() { - return _from_card_cache_mem_size; + return FromCardCache::static_mem_size(); } size_t OtherRegionsTable::fl_mem_size() { @@ -730,11 +746,7 @@ } void OtherRegionsTable::clear_fcc() { - uint hrs_idx = hr()->hrs_index(); - uint num_par_remsets = HeapRegionRemSet::num_par_rem_sets(); - for (uint i = 0; i < num_par_remsets; i++) { - _from_card_cache[i][hrs_idx] = -1; - } + FromCardCache::clear(hr()->hrs_index()); } void OtherRegionsTable::clear() { @@ -768,13 +780,13 @@ // Check to see if any of the fcc entries come from here. uint hr_ind = hr()->hrs_index(); for (uint tid = 0; tid < HeapRegionRemSet::num_par_rem_sets(); tid++) { - int fcc_ent = _from_card_cache[tid][hr_ind]; - if (fcc_ent != -1) { + int fcc_ent = FromCardCache::at(tid, hr_ind); + if (fcc_ent != FromCardCache::InvalidCard) { HeapWord* card_addr = (HeapWord*) (uintptr_t(fcc_ent) << CardTableModRefBS::card_shift); if (hr()->is_in_reserved(card_addr)) { // Clear the from card cache. - _from_card_cache[tid][hr_ind] = -1; + FromCardCache::set(tid, hr_ind, FromCardCache::InvalidCard); } } } @@ -830,8 +842,6 @@ "Must be in range."); return _sparse_table.contains_card(hr_ind, card_index); } - - } void @@ -932,7 +942,6 @@ _other_regions.scrub(ctbs, region_bm, card_bm); } - // Code roots support void HeapRegionRemSet::add_strong_code_root(nmethod* nm) { diff -r eff02b5bd56c -r ae7336d6337e src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp --- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Mon Mar 24 15:30:46 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Mon Mar 24 15:30:50 2014 +0100 @@ -45,6 +45,54 @@ class HRRSCleanupTask : public SparsePRTCleanupTask { }; +// The FromCardCache remembers the most recently processed card on the heap on +// a per-region and per-thread basis. +class FromCardCache : public AllStatic { + private: + // Array of card indices. Indexed by thread X and heap region to minimize + // thread contention. + static int** _cache; + static uint _max_regions; + static size_t _static_mem_size; + + public: + enum { + InvalidCard = -1 // Card value of an invalid card, i.e. a card index not otherwise used. + }; + + static void clear(uint region_idx); + + // Returns true if the given card is in the cache at the given location, or + // replaces the card at that location and returns false. + static bool contains_or_replace(uint worker_id, uint region_idx, int card) { + int card_in_cache = at(worker_id, region_idx); + if (card_in_cache == card) { + return true; + } else { + set(worker_id, region_idx, card); + return false; + } + } + + static int at(uint worker_id, uint region_idx) { + return _cache[worker_id][region_idx]; + } + + static void set(uint worker_id, uint region_idx, int val) { + _cache[worker_id][region_idx] = val; + } + + static void initialize(uint n_par_rs, uint max_num_regions); + + static void shrink(uint new_num_regions); + + static void print(outputStream* out = gclog_or_tty) PRODUCT_RETURN; + + static size_t static_mem_size() { + return _static_mem_size; + } +}; + // The "_coarse_map" is a bitmap with one bit for each region, where set // bits indicate that the corresponding region may contain some pointer // into the owning region. @@ -119,11 +167,6 @@ // false. bool del_single_region_table(size_t ind, HeapRegion* hr); - // Indexed by thread X heap region, to minimize thread contention. - static int** _from_card_cache; - static uint _from_card_cache_max_regions; - static size_t _from_card_cache_mem_size; - // link/add the given fine grain remembered set into the "all" list void link_to_all(PerRegionTable * prt); // unlink/remove the given fine grain remembered set into the "all" list @@ -174,7 +217,7 @@ // Declares that only regions i s.t. 0 <= i < new_n_regs are in use. // Make sure any entries for higher regions are invalid. - static void shrink_from_card_cache(uint new_n_regs); + static void shrink_from_card_cache(uint new_num_regions); static void print_from_card_cache(); };