src/hotspot/share/gc/g1/heapRegionRemSet.hpp
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 54623 1126f0607c70
child 58679 9c3209ff7550
--- 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