--- a/src/hotspot/share/gc/g1/heapRegionRemSet.hpp Thu Oct 17 20:27:44 2019 +0100
+++ b/src/hotspot/share/gc/g1/heapRegionRemSet.hpp Thu Oct 17 20:53:35 2019 +0100
@@ -28,6 +28,7 @@
#include "gc/g1/g1CodeCacheRemSet.hpp"
#include "gc/g1/g1FromCardCache.hpp"
#include "gc/g1/sparsePRT.hpp"
+#include "utilities/bitMap.hpp"
// Remembered set for a heap region. Represent a set of "cards" that
// contain pointers into the owner heap region. Cards are defined somewhat
@@ -37,7 +38,6 @@
class G1BlockOffsetTable;
class G1CardLiveData;
class HeapRegion;
-class HeapRegionRemSetIterator;
class PerRegionTable;
class SparsePRT;
class nmethod;
@@ -67,8 +67,6 @@
// thinking the PRT is for a different region, does no harm.
class OtherRegionsTable {
- friend class HeapRegionRemSetIterator;
-
G1CollectedHeap* _g1h;
Mutex* _m;
@@ -125,6 +123,9 @@
// Create a new remembered set. The given mutex is used to ensure consistency.
OtherRegionsTable(Mutex* m);
+ template <class Closure>
+ void iterate(Closure& v);
+
// Returns the card index of the given within_region pointer relative to the bottom
// of the given heap region.
static CardIdx_t card_within_region(OopOrNarrowOopStar within_region, HeapRegion* hr);
@@ -157,9 +158,132 @@
void clear();
};
+class PerRegionTable: public CHeapObj<mtGC> {
+ friend class OtherRegionsTable;
+
+ HeapRegion* _hr;
+ CHeapBitMap _bm;
+ jint _occupied;
+
+ // next pointer for free/allocated 'all' list
+ PerRegionTable* _next;
+
+ // prev pointer for the allocated 'all' list
+ PerRegionTable* _prev;
+
+ // next pointer in collision list
+ PerRegionTable * _collision_list_next;
+
+ // Global free list of PRTs
+ static PerRegionTable* volatile _free_list;
+
+protected:
+ PerRegionTable(HeapRegion* hr) :
+ _hr(hr),
+ _bm(HeapRegion::CardsPerRegion, mtGC),
+ _occupied(0),
+ _next(NULL), _prev(NULL),
+ _collision_list_next(NULL)
+ {}
+
+public:
+ // We need access in order to union things into the base table.
+ BitMap* bm() { return &_bm; }
+
+ HeapRegion* hr() const { return OrderAccess::load_acquire(&_hr); }
+
+ jint occupied() const {
+ // Overkill, but if we ever need it...
+ // guarantee(_occupied == _bm.count_one_bits(), "Check");
+ return _occupied;
+ }
+
+ void init(HeapRegion* hr, bool clear_links_to_all_list);
+
+ inline void add_reference(OopOrNarrowOopStar from);
+
+ inline void add_card(CardIdx_t from_card_index);
+
+ // (Destructively) union the bitmap of the current table into the given
+ // bitmap (which is assumed to be of the same size.)
+ void union_bitmap_into(BitMap* bm) {
+ bm->set_union(_bm);
+ }
+
+ // Mem size in bytes.
+ size_t mem_size() const {
+ return sizeof(PerRegionTable) + _bm.size_in_words() * HeapWordSize;
+ }
+
+ // Requires "from" to be in "hr()".
+ bool contains_reference(OopOrNarrowOopStar from) const {
+ assert(hr()->is_in_reserved(from), "Precondition.");
+ size_t card_ind = pointer_delta(from, hr()->bottom(),
+ G1CardTable::card_size);
+ return _bm.at(card_ind);
+ }
+
+ // Bulk-free the PRTs from prt to last, assumes that they are
+ // linked together using their _next field.
+ static void bulk_free(PerRegionTable* prt, PerRegionTable* last) {
+ while (true) {
+ PerRegionTable* fl = _free_list;
+ last->set_next(fl);
+ PerRegionTable* res = Atomic::cmpxchg(prt, &_free_list, fl);
+ if (res == fl) {
+ return;
+ }
+ }
+ ShouldNotReachHere();
+ }
+
+ static void free(PerRegionTable* prt) {
+ bulk_free(prt, prt);
+ }
+
+ // Returns an initialized PerRegionTable instance.
+ static PerRegionTable* alloc(HeapRegion* hr);
+
+ PerRegionTable* next() const { return _next; }
+ void set_next(PerRegionTable* next) { _next = next; }
+ PerRegionTable* prev() const { return _prev; }
+ void set_prev(PerRegionTable* prev) { _prev = prev; }
+
+ // Accessor and Modification routines for the pointer for the
+ // singly linked collision list that links the PRTs within the
+ // OtherRegionsTable::_fine_grain_regions hash table.
+ //
+ // It might be useful to also make the collision list doubly linked
+ // to avoid iteration over the collisions list during scrubbing/deletion.
+ // OTOH there might not be many collisions.
+
+ PerRegionTable* collision_list_next() const {
+ return _collision_list_next;
+ }
+
+ void set_collision_list_next(PerRegionTable* next) {
+ _collision_list_next = next;
+ }
+
+ PerRegionTable** collision_list_next_addr() {
+ return &_collision_list_next;
+ }
+
+ static size_t fl_mem_size() {
+ PerRegionTable* cur = _free_list;
+ size_t res = 0;
+ while (cur != NULL) {
+ res += cur->mem_size();
+ cur = cur->next();
+ }
+ return res;
+ }
+
+ static void test_fl_mem_size();
+};
+
class HeapRegionRemSet : public CHeapObj<mtGC> {
friend class VMStructs;
- friend class HeapRegionRemSetIterator;
private:
G1BlockOffsetTable* _bot;
@@ -179,20 +303,26 @@
public:
HeapRegionRemSet(G1BlockOffsetTable* bot, HeapRegion* hr);
+ // Setup sparse and fine-grain tables sizes.
static void setup_remset_size();
- bool cardset_is_empty() const {
- return _other_regions.is_empty();
- }
-
bool is_empty() const {
- return (strong_code_roots_list_length() == 0) && cardset_is_empty();
+ return (strong_code_roots_list_length() == 0) && _other_regions.is_empty();
}
bool occupancy_less_or_equal_than(size_t occ) const {
return (strong_code_roots_list_length() == 0) && _other_regions.occupancy_less_or_equal_than(occ);
}
+ // For each PRT in the card (remembered) set call one of the following methods
+ // of the given closure:
+ //
+ // set_full_region_dirty(uint region_idx) - pass the region index for coarse PRTs
+ // set_bitmap_dirty(uint region_idx, BitMap* bitmap) - pass the region index and bitmap for fine PRTs
+ // set_cards_dirty(uint region_idx, elem_t* cards, uint num_cards) - pass region index and cards for sparse PRTs
+ template <class Closure>
+ inline void iterate_prts(Closure& cl);
+
size_t occupied() {
MutexLocker x(&_m, Mutex::_no_safepoint_check_flag);
return occupied_locked();
@@ -243,12 +373,6 @@
_state = Complete;
}
- // Used in the sequential case.
- void add_reference(OopOrNarrowOopStar from) {
- add_reference(from, 0);
- }
-
- // Used in the parallel case.
void add_reference(OopOrNarrowOopStar from, uint tid) {
RemSetState state = _state;
if (state == Untracked) {
@@ -338,70 +462,4 @@
#endif
};
-class HeapRegionRemSetIterator : public StackObj {
-private:
- // The region RSet over which we are iterating.
- HeapRegionRemSet* _hrrs;
-
- // Local caching of HRRS fields.
- const BitMap* _coarse_map;
-
- G1BlockOffsetTable* _bot;
- G1CollectedHeap* _g1h;
-
- // The number of cards yielded since initialization.
- size_t _n_yielded_fine;
- size_t _n_yielded_coarse;
- size_t _n_yielded_sparse;
-
- // Indicates what granularity of table that we are currently iterating over.
- // We start iterating over the sparse table, progress to the fine grain
- // table, and then finish with the coarse table.
- enum IterState {
- Sparse,
- Fine,
- Coarse
- };
- IterState _is;
-
- // For both Coarse and Fine remembered set iteration this contains the
- // first card number of the heap region we currently iterate over.
- size_t _cur_region_card_offset;
-
- // Current region index for the Coarse remembered set iteration.
- int _coarse_cur_region_index;
- size_t _coarse_cur_region_cur_card;
-
- bool coarse_has_next(size_t& card_index);
-
- // The PRT we are currently iterating over.
- PerRegionTable* _fine_cur_prt;
- // Card offset within the current PRT.
- size_t _cur_card_in_prt;
-
- // Update internal variables when switching to the given PRT.
- void switch_to_prt(PerRegionTable* prt);
- bool fine_has_next();
- bool fine_has_next(size_t& card_index);
-
- // The Sparse remembered set iterator.
- SparsePRTIter _sparse_iter;
-
-public:
- HeapRegionRemSetIterator(HeapRegionRemSet* hrrs);
-
- // If there remains one or more cards to be yielded, returns true and
- // sets "card_index" to one of those cards (which is then considered
- // yielded.) Otherwise, returns false (and leaves "card_index"
- // undefined.)
- bool has_next(size_t& card_index);
-
- size_t n_yielded_fine() { return _n_yielded_fine; }
- size_t n_yielded_coarse() { return _n_yielded_coarse; }
- size_t n_yielded_sparse() { return _n_yielded_sparse; }
- size_t n_yielded() {
- return n_yielded_fine() + n_yielded_coarse() + n_yielded_sparse();
- }
-};
-
#endif // SHARE_GC_G1_HEAPREGIONREMSET_HPP