src/hotspot/share/gc/g1/g1RemSet.cpp
changeset 54111 e8de5d46ecd4
parent 54110 f4f0dce5d0bb
child 54255 c81fbf340ceb
equal deleted inserted replaced
54110:f4f0dce5d0bb 54111:e8de5d46ecd4
   112 
   112 
   113   // Temporary buffer holding the regions we used to store remembered set scan duplicate
   113   // Temporary buffer holding the regions we used to store remembered set scan duplicate
   114   // information. These are also called "dirty". Valid entries are from [0.._cur_dirty_region)
   114   // information. These are also called "dirty". Valid entries are from [0.._cur_dirty_region)
   115   uint* _dirty_region_buffer;
   115   uint* _dirty_region_buffer;
   116 
   116 
   117   typedef jbyte IsDirtyRegionState;
   117   // Flag for every region whether it is in the _dirty_region_buffer already
   118   static const IsDirtyRegionState Clean = 0;
   118   // to avoid duplicates.
   119   static const IsDirtyRegionState Dirty = 1;
   119   bool volatile* _in_dirty_region_buffer;
   120   // Holds a flag for every region whether it is in the _dirty_region_buffer already
       
   121   // to avoid duplicates. Uses jbyte since there are no atomic instructions for bools.
       
   122   IsDirtyRegionState* _in_dirty_region_buffer;
       
   123   size_t _cur_dirty_region;
   120   size_t _cur_dirty_region;
   124 
   121 
   125   // Creates a snapshot of the current _top values at the start of collection to
   122   // Creates a snapshot of the current _top values at the start of collection to
   126   // filter out card marks that we do not want to scan.
   123   // filter out card marks that we do not want to scan.
   127   class G1ResetScanTopClosure : public HeapRegionClosure {
   124   class G1ResetScanTopClosure : public HeapRegionClosure {
   167     }
   164     }
   168     if (_dirty_region_buffer != NULL) {
   165     if (_dirty_region_buffer != NULL) {
   169       FREE_C_HEAP_ARRAY(uint, _dirty_region_buffer);
   166       FREE_C_HEAP_ARRAY(uint, _dirty_region_buffer);
   170     }
   167     }
   171     if (_in_dirty_region_buffer != NULL) {
   168     if (_in_dirty_region_buffer != NULL) {
   172       FREE_C_HEAP_ARRAY(IsDirtyRegionState, _in_dirty_region_buffer);
   169       FREE_C_HEAP_ARRAY(bool, _in_dirty_region_buffer);
   173     }
   170     }
   174     if (_scan_top != NULL) {
   171     if (_scan_top != NULL) {
   175       FREE_C_HEAP_ARRAY(HeapWord*, _scan_top);
   172       FREE_C_HEAP_ARRAY(HeapWord*, _scan_top);
   176     }
   173     }
   177   }
   174   }
   181     assert(_iter_claims == NULL, "Must not be initialized twice");
   178     assert(_iter_claims == NULL, "Must not be initialized twice");
   182     _max_regions = max_regions;
   179     _max_regions = max_regions;
   183     _iter_states = NEW_C_HEAP_ARRAY(G1RemsetIterState, max_regions, mtGC);
   180     _iter_states = NEW_C_HEAP_ARRAY(G1RemsetIterState, max_regions, mtGC);
   184     _iter_claims = NEW_C_HEAP_ARRAY(size_t, max_regions, mtGC);
   181     _iter_claims = NEW_C_HEAP_ARRAY(size_t, max_regions, mtGC);
   185     _dirty_region_buffer = NEW_C_HEAP_ARRAY(uint, max_regions, mtGC);
   182     _dirty_region_buffer = NEW_C_HEAP_ARRAY(uint, max_regions, mtGC);
   186     _in_dirty_region_buffer = NEW_C_HEAP_ARRAY(IsDirtyRegionState, max_regions, mtGC);
   183     _in_dirty_region_buffer = NEW_C_HEAP_ARRAY(bool, max_regions, mtGC);
   187     _scan_top = NEW_C_HEAP_ARRAY(HeapWord*, max_regions, mtGC);
   184     _scan_top = NEW_C_HEAP_ARRAY(HeapWord*, max_regions, mtGC);
   188   }
   185   }
   189 
   186 
   190   void reset() {
   187   void reset() {
   191     for (uint i = 0; i < _max_regions; i++) {
   188     for (uint i = 0; i < _max_regions; i++) {
   195 
   192 
   196     G1ResetScanTopClosure cl(_scan_top);
   193     G1ResetScanTopClosure cl(_scan_top);
   197     G1CollectedHeap::heap()->heap_region_iterate(&cl);
   194     G1CollectedHeap::heap()->heap_region_iterate(&cl);
   198 
   195 
   199     memset((void*)_iter_claims, 0, _max_regions * sizeof(size_t));
   196     memset((void*)_iter_claims, 0, _max_regions * sizeof(size_t));
   200     memset(_in_dirty_region_buffer, Clean, _max_regions * sizeof(IsDirtyRegionState));
   197     memset((void*)_in_dirty_region_buffer, false, _max_regions * sizeof(bool));
   201     _cur_dirty_region = 0;
   198     _cur_dirty_region = 0;
   202   }
   199   }
   203 
   200 
   204   // Attempt to claim the remembered set of the region for iteration. Returns true
   201   // Attempt to claim the remembered set of the region for iteration. Returns true
   205   // if this call caused the transition from Unclaimed to Claimed.
   202   // if this call caused the transition from Unclaimed to Claimed.
   239   inline size_t iter_claimed_next(uint region, size_t step) {
   236   inline size_t iter_claimed_next(uint region, size_t step) {
   240     return Atomic::add(step, &_iter_claims[region]) - step;
   237     return Atomic::add(step, &_iter_claims[region]) - step;
   241   }
   238   }
   242 
   239 
   243   void add_dirty_region(uint region) {
   240   void add_dirty_region(uint region) {
   244     if (_in_dirty_region_buffer[region] == Dirty) {
   241     if (_in_dirty_region_buffer[region]) {
   245       return;
   242       return;
   246     }
   243     }
   247 
   244 
   248     bool marked_as_dirty = Atomic::cmpxchg(Dirty, &_in_dirty_region_buffer[region], Clean) == Clean;
   245     if (!Atomic::cmpxchg(true, &_in_dirty_region_buffer[region], false)) {
   249     if (marked_as_dirty) {
       
   250       size_t allocated = Atomic::add(1u, &_cur_dirty_region) - 1;
   246       size_t allocated = Atomic::add(1u, &_cur_dirty_region) - 1;
   251       _dirty_region_buffer[allocated] = region;
   247       _dirty_region_buffer[allocated] = region;
   252     }
   248     }
   253   }
   249   }
   254 
   250