< prev index next >

src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp

Print this page

261 void ShenandoahPrepareForGenerationalCompactionObjectClosure::finish_young_region() {
262   if (_young_to_region != nullptr) {
263     log_debug(gc)("Worker %u planned compaction into Young Region %zu, used: %zu",
264             _worker_id, _young_to_region->index(), _young_compact_point - _young_to_region->bottom());
265     _young_to_region->set_new_top(_young_compact_point);
266     _young_to_region = nullptr;
267   }
268 }
269 
270 bool ShenandoahPrepareForGenerationalCompactionObjectClosure::is_compact_same_region() {
271   return (_from_region == _old_to_region) || (_from_region == _young_to_region);
272 }
273 
274 void ShenandoahPrepareForGenerationalCompactionObjectClosure::do_object(oop p) {
275   assert(_from_region != nullptr, "must set before work");
276   assert((_from_region->bottom() <= cast_from_oop<HeapWord*>(p)) && (cast_from_oop<HeapWord*>(p) < _from_region->top()),
277          "Object must reside in _from_region");
278   assert(_heap->complete_marking_context()->is_marked(p), "must be marked");
279   assert(!_heap->complete_marking_context()->allocated_after_mark_start(p), "must be truly marked");
280 
281   size_t obj_size = p->size();

282   uint from_region_age = _from_region->age();
283   uint object_age = p->age();
284 
285   bool promote_object = false;
286   if ((_from_affiliation == ShenandoahAffiliation::YOUNG_GENERATION) &&
287       (from_region_age + object_age >= _tenuring_threshold)) {
288     if ((_old_to_region != nullptr) && (_old_compact_point + obj_size > _old_to_region->end())) {
289       finish_old_region();
290       _old_to_region = nullptr;
291     }
292     if (_old_to_region == nullptr) {
293       if (_empty_regions_pos < _empty_regions.length()) {
294         ShenandoahHeapRegion* new_to_region = _empty_regions.at(_empty_regions_pos);
295         _empty_regions_pos++;
296         new_to_region->set_affiliation(OLD_GENERATION);
297         _old_to_region = new_to_region;
298         _old_compact_point = _old_to_region->bottom();
299         promote_object = true;
300       }
301       // Else this worker thread does not yet have any empty regions into which this aged object can be promoted so
302       // we leave promote_object as false, deferring the promotion.
303     } else {
304       promote_object = true;
305     }
306   }
307 
308   if (promote_object || (_from_affiliation == ShenandoahAffiliation::OLD_GENERATION)) {
309     assert(_old_to_region != nullptr, "_old_to_region should not be nullptr when evacuating to OLD region");

310     if (_old_compact_point + obj_size > _old_to_region->end()) {
311       ShenandoahHeapRegion* new_to_region;
312 
313       log_debug(gc)("Worker %u finishing old region %zu, compact_point: " PTR_FORMAT ", obj_size: %zu"
314       ", &compact_point[obj_size]: " PTR_FORMAT ", region end: " PTR_FORMAT,  _worker_id, _old_to_region->index(),
315               p2i(_old_compact_point), obj_size, p2i(_old_compact_point + obj_size), p2i(_old_to_region->end()));
316 
317       // Object does not fit.  Get a new _old_to_region.
318       finish_old_region();
319       if (_empty_regions_pos < _empty_regions.length()) {
320         new_to_region = _empty_regions.at(_empty_regions_pos);
321         _empty_regions_pos++;
322         new_to_region->set_affiliation(OLD_GENERATION);
323       } else {
324         // If we've exhausted the previously selected _old_to_region, we know that the _old_to_region is distinct
325         // from _from_region.  That's because there is always room for _from_region to be compacted into itself.
326         // Since we're out of empty regions, let's use _from_region to hold the results of its own compaction.
327         new_to_region = _from_region;
328       }
329 
330       assert(new_to_region != _old_to_region, "must not reuse same OLD to-region");
331       assert(new_to_region != nullptr, "must not be nullptr");
332       _old_to_region = new_to_region;
333       _old_compact_point = _old_to_region->bottom();

334     }
335 
336     // Object fits into current region, record new location, if object does not move:
337     assert(_old_compact_point + obj_size <= _old_to_region->end(), "must fit");
338     shenandoah_assert_not_forwarded(nullptr, p);
339     if (_old_compact_point != cast_from_oop<HeapWord*>(p)) {
340       _preserved_marks->push_if_necessary(p, p->mark());
341       FullGCForwarding::forward_to(p, cast_to_oop(_old_compact_point));
342     }
343     _old_compact_point += obj_size;
344   } else {
345     assert(_from_affiliation == ShenandoahAffiliation::YOUNG_GENERATION,
346            "_from_region must be OLD_GENERATION or YOUNG_GENERATION");
347     assert(_young_to_region != nullptr, "_young_to_region should not be nullptr when compacting YOUNG _from_region");
348 
349     // After full gc compaction, all regions have age 0.  Embed the region's age into the object's age in order to preserve
350     // tenuring progress.
351     if (_heap->is_aging_cycle()) {
352       ShenandoahHeap::increase_object_age(p, from_region_age + 1);
353     } else {
354       ShenandoahHeap::increase_object_age(p, from_region_age);
355     }
356 

357     if (_young_compact_point + obj_size > _young_to_region->end()) {
358       ShenandoahHeapRegion* new_to_region;
359 
360       log_debug(gc)("Worker %u finishing young region %zu, compact_point: " PTR_FORMAT ", obj_size: %zu"
361       ", &compact_point[obj_size]: " PTR_FORMAT ", region end: " PTR_FORMAT,  _worker_id, _young_to_region->index(),
362               p2i(_young_compact_point), obj_size, p2i(_young_compact_point + obj_size), p2i(_young_to_region->end()));
363 
364       // Object does not fit.  Get a new _young_to_region.
365       finish_young_region();
366       if (_empty_regions_pos < _empty_regions.length()) {
367         new_to_region = _empty_regions.at(_empty_regions_pos);
368         _empty_regions_pos++;
369         new_to_region->set_affiliation(YOUNG_GENERATION);
370       } else {
371         // If we've exhausted the previously selected _young_to_region, we know that the _young_to_region is distinct
372         // from _from_region.  That's because there is always room for _from_region to be compacted into itself.
373         // Since we're out of empty regions, let's use _from_region to hold the results of its own compaction.
374         new_to_region = _from_region;
375       }
376 
377       assert(new_to_region != _young_to_region, "must not reuse same OLD to-region");
378       assert(new_to_region != nullptr, "must not be nullptr");
379       _young_to_region = new_to_region;

380       _young_compact_point = _young_to_region->bottom();
381     }
382 
383     // Object fits into current region, record new location, if object does not move:
384     assert(_young_compact_point + obj_size <= _young_to_region->end(), "must fit");
385     shenandoah_assert_not_forwarded(nullptr, p);
386 
387     if (_young_compact_point != cast_from_oop<HeapWord*>(p)) {
388       _preserved_marks->push_if_necessary(p, p->mark());
389       FullGCForwarding::forward_to(p, cast_to_oop(_young_compact_point));
390     }
391     _young_compact_point += obj_size;
392   }
393 }

261 void ShenandoahPrepareForGenerationalCompactionObjectClosure::finish_young_region() {
262   if (_young_to_region != nullptr) {
263     log_debug(gc)("Worker %u planned compaction into Young Region %zu, used: %zu",
264             _worker_id, _young_to_region->index(), _young_compact_point - _young_to_region->bottom());
265     _young_to_region->set_new_top(_young_compact_point);
266     _young_to_region = nullptr;
267   }
268 }
269 
270 bool ShenandoahPrepareForGenerationalCompactionObjectClosure::is_compact_same_region() {
271   return (_from_region == _old_to_region) || (_from_region == _young_to_region);
272 }
273 
274 void ShenandoahPrepareForGenerationalCompactionObjectClosure::do_object(oop p) {
275   assert(_from_region != nullptr, "must set before work");
276   assert((_from_region->bottom() <= cast_from_oop<HeapWord*>(p)) && (cast_from_oop<HeapWord*>(p) < _from_region->top()),
277          "Object must reside in _from_region");
278   assert(_heap->complete_marking_context()->is_marked(p), "must be marked");
279   assert(!_heap->complete_marking_context()->allocated_after_mark_start(p), "must be truly marked");
280 
281   size_t old_size = p->size();
282   size_t new_size = p->copy_size(old_size, p->mark());
283   uint from_region_age = _from_region->age();
284   uint object_age = p->age();
285 
286   bool promote_object = false;
287   if ((_from_affiliation == ShenandoahAffiliation::YOUNG_GENERATION) &&
288       (from_region_age + object_age >= _tenuring_threshold)) {
289     if ((_old_to_region != nullptr) && (_old_compact_point + new_size > _old_to_region->end())) {
290       finish_old_region();
291       _old_to_region = nullptr;
292     }
293     if (_old_to_region == nullptr) {
294       if (_empty_regions_pos < _empty_regions.length()) {
295         ShenandoahHeapRegion* new_to_region = _empty_regions.at(_empty_regions_pos);
296         _empty_regions_pos++;
297         new_to_region->set_affiliation(OLD_GENERATION);
298         _old_to_region = new_to_region;
299         _old_compact_point = _old_to_region->bottom();
300         promote_object = true;
301       }
302       // Else this worker thread does not yet have any empty regions into which this aged object can be promoted so
303       // we leave promote_object as false, deferring the promotion.
304     } else {
305       promote_object = true;
306     }
307   }
308 
309   if (promote_object || (_from_affiliation == ShenandoahAffiliation::OLD_GENERATION)) {
310     assert(_old_to_region != nullptr, "_old_to_region should not be nullptr when evacuating to OLD region");
311     size_t obj_size = _old_compact_point == cast_from_oop<HeapWord*>(p) ? old_size : new_size;
312     if (_old_compact_point + obj_size > _old_to_region->end()) {
313       ShenandoahHeapRegion* new_to_region;
314 
315       log_debug(gc)("Worker %u finishing old region %zu, compact_point: " PTR_FORMAT ", obj_size: %zu"
316       ", &compact_point[obj_size]: " PTR_FORMAT ", region end: " PTR_FORMAT,  _worker_id, _old_to_region->index(),
317               p2i(_old_compact_point), obj_size, p2i(_old_compact_point + obj_size), p2i(_old_to_region->end()));
318 
319       // Object does not fit.  Get a new _old_to_region.
320       finish_old_region();
321       if (_empty_regions_pos < _empty_regions.length()) {
322         new_to_region = _empty_regions.at(_empty_regions_pos);
323         _empty_regions_pos++;
324         new_to_region->set_affiliation(OLD_GENERATION);
325       } else {
326         // If we've exhausted the previously selected _old_to_region, we know that the _old_to_region is distinct
327         // from _from_region.  That's because there is always room for _from_region to be compacted into itself.
328         // Since we're out of empty regions, let's use _from_region to hold the results of its own compaction.
329         new_to_region = _from_region;
330       }
331 
332       assert(new_to_region != _old_to_region, "must not reuse same OLD to-region");
333       assert(new_to_region != nullptr, "must not be nullptr");
334       _old_to_region = new_to_region;
335       _old_compact_point = _old_to_region->bottom();
336       obj_size = _old_compact_point == cast_from_oop<HeapWord*>(p) ? old_size : new_size;
337     }
338 
339     // Object fits into current region, record new location, if object does not move:
340     assert(_old_compact_point + obj_size <= _old_to_region->end(), "must fit");
341     shenandoah_assert_not_forwarded(nullptr, p);
342     if (_old_compact_point != cast_from_oop<HeapWord*>(p)) {
343       _preserved_marks->push_if_necessary(p, p->mark());
344       FullGCForwarding::forward_to(p, cast_to_oop(_old_compact_point));
345     }
346     _old_compact_point += obj_size;
347   } else {
348     assert(_from_affiliation == ShenandoahAffiliation::YOUNG_GENERATION,
349            "_from_region must be OLD_GENERATION or YOUNG_GENERATION");
350     assert(_young_to_region != nullptr, "_young_to_region should not be nullptr when compacting YOUNG _from_region");
351 
352     // After full gc compaction, all regions have age 0.  Embed the region's age into the object's age in order to preserve
353     // tenuring progress.
354     if (_heap->is_aging_cycle()) {
355       ShenandoahHeap::increase_object_age(p, from_region_age + 1);
356     } else {
357       ShenandoahHeap::increase_object_age(p, from_region_age);
358     }
359 
360     size_t obj_size = _young_compact_point == cast_from_oop<HeapWord*>(p) ? old_size : new_size;
361     if (_young_compact_point + obj_size > _young_to_region->end()) {
362       ShenandoahHeapRegion* new_to_region;
363 
364       log_debug(gc)("Worker %u finishing young region %zu, compact_point: " PTR_FORMAT ", obj_size: %zu"
365       ", &compact_point[obj_size]: " PTR_FORMAT ", region end: " PTR_FORMAT,  _worker_id, _young_to_region->index(),
366               p2i(_young_compact_point), obj_size, p2i(_young_compact_point + obj_size), p2i(_young_to_region->end()));
367 
368       // Object does not fit.  Get a new _young_to_region.
369       finish_young_region();
370       if (_empty_regions_pos < _empty_regions.length()) {
371         new_to_region = _empty_regions.at(_empty_regions_pos);
372         _empty_regions_pos++;
373         new_to_region->set_affiliation(YOUNG_GENERATION);
374       } else {
375         // If we've exhausted the previously selected _young_to_region, we know that the _young_to_region is distinct
376         // from _from_region.  That's because there is always room for _from_region to be compacted into itself.
377         // Since we're out of empty regions, let's use _from_region to hold the results of its own compaction.
378         new_to_region = _from_region;
379       }
380 
381       assert(new_to_region != _young_to_region, "must not reuse same OLD to-region");
382       assert(new_to_region != nullptr, "must not be nullptr");
383       _young_to_region = new_to_region;
384       obj_size = _young_compact_point == cast_from_oop<HeapWord*>(p) ? old_size : new_size;
385       _young_compact_point = _young_to_region->bottom();
386     }
387 
388     // Object fits into current region, record new location, if object does not move:
389     assert(_young_compact_point + obj_size <= _young_to_region->end(), "must fit");
390     shenandoah_assert_not_forwarded(nullptr, p);
391 
392     if (_young_compact_point != cast_from_oop<HeapWord*>(p)) {
393       _preserved_marks->push_if_necessary(p, p->mark());
394       FullGCForwarding::forward_to(p, cast_to_oop(_young_compact_point));
395     }
396     _young_compact_point += obj_size;
397   }
398 }
< prev index next >