258 err_msg("The region at the current position %u must be available or at the end of the heap.", cur)); |
258 err_msg("The region at the current position %u must be available or at the end of the heap.", cur)); |
259 #endif |
259 #endif |
260 return num_regions; |
260 return num_regions; |
261 } |
261 } |
262 |
262 |
263 uint HeapRegionManager::start_region_for_worker(uint worker_i, uint num_workers, uint num_regions) const { |
263 void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, HeapRegionClaimer* hrclaimer) const { |
264 return num_regions * worker_i / num_workers; |
264 const uint start_index = hrclaimer->start_region_for_worker(worker_id); |
265 } |
|
266 |
|
267 void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, uint num_workers, jint claim_value) const { |
|
268 const uint start_index = start_region_for_worker(worker_id, num_workers, _allocated_heapregions_length); |
|
269 |
265 |
270 // Every worker will actually look at all regions, skipping over regions that |
266 // Every worker will actually look at all regions, skipping over regions that |
271 // are currently not committed. |
267 // are currently not committed. |
272 // This also (potentially) iterates over regions newly allocated during GC. This |
268 // This also (potentially) iterates over regions newly allocated during GC. This |
273 // is no problem except for some extra work. |
269 // is no problem except for some extra work. |
274 for (uint count = 0; count < _allocated_heapregions_length; count++) { |
270 const uint n_regions = hrclaimer->n_regions(); |
275 const uint index = (start_index + count) % _allocated_heapregions_length; |
271 for (uint count = 0; count < n_regions; count++) { |
276 assert(0 <= index && index < _allocated_heapregions_length, "sanity"); |
272 const uint index = (start_index + count) % n_regions; |
|
273 assert(0 <= index && index < n_regions, "sanity"); |
277 // Skip over unavailable regions |
274 // Skip over unavailable regions |
278 if (!is_available(index)) { |
275 if (!is_available(index)) { |
279 continue; |
276 continue; |
280 } |
277 } |
281 HeapRegion* r = _regions.get_by_index(index); |
278 HeapRegion* r = _regions.get_by_index(index); |
282 // We'll ignore "continues humongous" regions (we'll process them |
279 // We'll ignore "continues humongous" regions (we'll process them |
283 // when we come across their corresponding "start humongous" |
280 // when we come across their corresponding "start humongous" |
284 // region) and regions already claimed. |
281 // region) and regions already claimed. |
285 if (r->claim_value() == claim_value || r->is_continues_humongous()) { |
282 if (hrclaimer->is_region_claimed(index) || r->is_continues_humongous()) { |
286 continue; |
283 continue; |
287 } |
284 } |
288 // OK, try to claim it |
285 // OK, try to claim it |
289 if (!r->claimHeapRegion(claim_value)) { |
286 if (!hrclaimer->claim_region(index)) { |
290 continue; |
287 continue; |
291 } |
288 } |
292 // Success! |
289 // Success! |
293 if (r->is_starts_humongous()) { |
290 if (r->is_starts_humongous()) { |
294 // If the region is "starts humongous" we'll iterate over its |
291 // If the region is "starts humongous" we'll iterate over its |
304 |
301 |
305 assert(chr->is_continues_humongous(), "Must be humongous region"); |
302 assert(chr->is_continues_humongous(), "Must be humongous region"); |
306 assert(chr->humongous_start_region() == r, |
303 assert(chr->humongous_start_region() == r, |
307 err_msg("Must work on humongous continuation of the original start region " |
304 err_msg("Must work on humongous continuation of the original start region " |
308 PTR_FORMAT ", but is " PTR_FORMAT, p2i(r), p2i(chr))); |
305 PTR_FORMAT ", but is " PTR_FORMAT, p2i(r), p2i(chr))); |
309 assert(chr->claim_value() != claim_value, |
306 assert(!hrclaimer->is_region_claimed(ch_index), |
310 "Must not have been claimed yet because claiming of humongous continuation first claims the start region"); |
307 "Must not have been claimed yet because claiming of humongous continuation first claims the start region"); |
311 |
308 |
312 bool claim_result = chr->claimHeapRegion(claim_value); |
309 // There's no need to actually claim the continues humongous region, but we can do it in an assert as an extra precaution. |
313 // We should always be able to claim it; no one else should |
310 assert(hrclaimer->claim_region(ch_index), "We should always be able to claim the continuesHumongous part of the humongous object"); |
314 // be trying to claim this region. |
|
315 guarantee(claim_result, "We should always be able to claim the is_continues_humongous part of the humongous object"); |
|
316 |
311 |
317 bool res2 = blk->doHeapRegion(chr); |
312 bool res2 = blk->doHeapRegion(chr); |
318 if (res2) { |
313 if (res2) { |
319 return; |
314 return; |
320 } |
315 } |
443 void HeapRegionManager::verify_optional() { |
438 void HeapRegionManager::verify_optional() { |
444 verify(); |
439 verify(); |
445 } |
440 } |
446 #endif // PRODUCT |
441 #endif // PRODUCT |
447 |
442 |
|
443 HeapRegionClaimer::HeapRegionClaimer(uint n_workers) : |
|
444 _n_workers(n_workers), _n_regions(G1CollectedHeap::heap()->_hrm._allocated_heapregions_length), _claims(NULL) { |
|
445 assert(n_workers > 0, "Need at least one worker."); |
|
446 _claims = NEW_C_HEAP_ARRAY(uint, _n_regions, mtGC); |
|
447 memset(_claims, Unclaimed, sizeof(*_claims) * _n_regions); |
|
448 } |
|
449 |
|
450 HeapRegionClaimer::~HeapRegionClaimer() { |
|
451 if (_claims != NULL) { |
|
452 FREE_C_HEAP_ARRAY(uint, _claims, mtGC); |
|
453 } |
|
454 } |
|
455 |
|
456 uint HeapRegionClaimer::start_region_for_worker(uint worker_id) const { |
|
457 assert(worker_id < _n_workers, "Invalid worker_id."); |
|
458 return _n_regions * worker_id / _n_workers; |
|
459 } |
|
460 |
|
461 bool HeapRegionClaimer::is_region_claimed(uint region_index) const { |
|
462 assert(region_index < _n_regions, "Invalid index."); |
|
463 return _claims[region_index] == Claimed; |
|
464 } |
|
465 |
|
466 bool HeapRegionClaimer::claim_region(uint region_index) { |
|
467 assert(region_index < _n_regions, "Invalid index."); |
|
468 uint old_val = Atomic::cmpxchg(Claimed, &_claims[region_index], Unclaimed); |
|
469 return old_val == Unclaimed; |
|
470 } |