src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp

Print this page
rev 5920 : 8035406: Improve data structure for Code Cache remembered sets
Summary: Change the code cache remembered sets data structure from a GrowableArray to a chunked list of nmethods. This makes the data structure more amenable to parallelization, and decreases freeing time.
Reviewed-by:
rev 5921 : 8027295: Free CSet takes ~50% of young pause time
Summary: Improve fast card cache iteration and avoid taking locks when freeing the collection set.
Reviewed-by:

@@ -360,21 +360,32 @@
 int**  OtherRegionsTable::_from_card_cache = NULL;
 size_t OtherRegionsTable::_from_card_cache_max_regions = 0;
 size_t OtherRegionsTable::_from_card_cache_mem_size = 0;
 
 void OtherRegionsTable::init_from_card_cache(size_t max_regions) {
-  _from_card_cache_max_regions = max_regions;
+  guarantee(_from_card_cache == NULL, "Should not call this multiple times");
 
+  // Pad rows to cache line sizes.
+  static const int ints_per_cache_line = DEFAULT_CACHE_LINE_SIZE / sizeof(int);
   int n_par_rs = HeapRegionRemSet::num_par_rem_sets();
+  _from_card_cache_max_regions = align_size_up(max_regions, ints_per_cache_line);
+
+  // Need to make sure that the arrays are aligned too. Allocate a suitably
+  // large array to be able to align its base address later. We do not store
+  // the old pointer as we never free that memory.
+  size_t num_ints_to_alloc = n_par_rs * _from_card_cache_max_regions + ints_per_cache_line - 1;
+  int* data = NEW_C_HEAP_ARRAY(int, num_ints_to_alloc, mtGC);
+  data = (int*) (align_size_up_((uintptr_t)data, DEFAULT_CACHE_LINE_SIZE));
+
   _from_card_cache = NEW_C_HEAP_ARRAY(int*, n_par_rs, mtGC);
   for (int i = 0; i < n_par_rs; i++) {
-    _from_card_cache[i] = NEW_C_HEAP_ARRAY(int, max_regions, mtGC);
-    for (size_t j = 0; j < max_regions; j++) {
+    _from_card_cache[i] = data + i * _from_card_cache_max_regions;
+    for (size_t j = 0; j < _from_card_cache_max_regions; j++) {
       _from_card_cache[i][j] = -1;  // An invalid value.
     }
   }
-  _from_card_cache_mem_size = n_par_rs * max_regions * sizeof(int);
+  _from_card_cache_mem_size = num_ints_to_alloc * sizeof(int);
 }
 
 void OtherRegionsTable::shrink_from_card_cache(size_t new_n_regs) {
   for (int i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) {
     assert(new_n_regs <= _from_card_cache_max_regions, "Must be within max.");

@@ -726,11 +737,12 @@
   return PerRegionTable::fl_mem_size();
 }
 
 void OtherRegionsTable::clear_fcc() {
   size_t hrs_idx = hr()->hrs_index();
-  for (int i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) {
+  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;
   }
 }
 
 void OtherRegionsTable::clear() {