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 |