< prev index next >

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

Print this page

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

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

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

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

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

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

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