< prev index next > src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp
Print this page
{
// The rest of code performs region moves, where region status is undefined
// until all phases run together.
ShenandoahHeapLocker lock(heap->lock());
+ FullGCForwarding::begin();
+
phase2_calculate_target_addresses(worker_slices);
OrderAccess::fence();
phase3_update_references();
phase4_compact_objects(worker_slices);
phase5_epilog();
+
+ FullGCForwarding::end();
}
heap->start_idle_span();
// Resize metaspace
MetaspaceGC::compute_new_size();
assert(_from_region != nullptr, "must set before work");
assert(_heap->global_generation()->is_mark_complete(), "marking must be finished");
assert(_heap->marking_context()->is_marked(p), "must be marked");
assert(!_heap->marking_context()->allocated_after_mark_start(p), "must be truly marked");
! size_t obj_size = p->size();
if (_compact_point + obj_size > _to_region->end()) {
finish();
// Object doesn't fit. Pick next empty region and start compacting there.
ShenandoahHeapRegion* new_to_region;
assert(_from_region != nullptr, "must set before work");
assert(_heap->global_generation()->is_mark_complete(), "marking must be finished");
assert(_heap->marking_context()->is_marked(p), "must be marked");
assert(!_heap->marking_context()->allocated_after_mark_start(p), "must be truly marked");
! size_t old_size = p->size();
+ size_t new_size = p->copy_size(old_size, p->mark());
+ size_t obj_size = _compact_point == cast_from_oop<HeapWord*>(p) ? old_size : new_size;
if (_compact_point + obj_size > _to_region->end()) {
finish();
// Object doesn't fit. Pick next empty region and start compacting there.
ShenandoahHeapRegion* new_to_region;
assert(new_to_region != _to_region, "must not reuse same to-region");
assert(new_to_region != nullptr, "must not be null");
_to_region = new_to_region;
_compact_point = _to_region->bottom();
+ obj_size = _compact_point == cast_from_oop<HeapWord*>(p) ? old_size : new_size;
}
// Object fits into current region, record new location, if object does not move:
assert(_compact_point + obj_size <= _to_region->end(), "must fit");
shenandoah_assert_not_forwarded(nullptr, p);
}
if (r->is_humongous_start() && r->is_stw_move_allowed()) {
// From-region candidate: movable humongous region
oop old_obj = cast_to_oop(r->bottom());
! size_t words_size = old_obj->size();
! size_t num_regions = ShenandoahHeapRegion::required_regions(words_size * HeapWordSize);
!
! size_t start = to_end - num_regions;
!
! if (start >= to_begin && start != r->index()) {
! // Fits into current window, and the move is non-trivial. Record the move then, and continue scan.
! _preserved_marks->get(0)->push_if_necessary(old_obj, old_obj->mark());
! FullGCForwarding::forward_to(old_obj, cast_to_oop(heap->get_region(start)->bottom()));
! to_end = start;
! continue;
}
}
// Failed to fit. Scan starting from current region.
to_begin = r->index();
}
if (r->is_humongous_start() && r->is_stw_move_allowed()) {
// From-region candidate: movable humongous region
oop old_obj = cast_to_oop(r->bottom());
! size_t new_words_size = old_obj->copy_size(old_obj->size(), old_obj->mark());
! size_t num_regions = ShenandoahHeapRegion::required_regions(new_words_size * HeapWordSize);
!
! // Test the fit before computing the slide target. With compact object headers
! // the expanded size can require one region more than the object currently
! // occupies, so num_regions may exceed the available window. Comparing against
! // the window size (to_end - to_begin) avoids the unsigned underflow that
! // "to_end - num_regions" would suffer when the object does not fit.
! if (num_regions <= to_end - to_begin) {
! size_t start = to_end - num_regions;
! if (start != r->index()) {
+ // Fits into current window, and the move is non-trivial. Record the move then, and continue scan.
+ _preserved_marks->get(0)->push_if_necessary(old_obj, old_obj->mark());
+ FullGCForwarding::forward_to(old_obj, cast_to_oop(heap->get_region(start)->bottom()));
+ to_end = start;
+ continue;
+ }
}
}
// Failed to fit. Scan starting from current region.
to_begin = r->index();
oop new_obj = cast_to_oop(compact_to);
// Restore the mark word before relativizing the stack chunk. The copy's
// mark word contains the full GC forwarding encoding, which would cause
// is_stackChunk() to read garbage (especially with compact headers).
! new_obj->init_mark();
ContinuationGCSupport::relativize_stack_chunk(new_obj);
}
}
};
oop new_obj = cast_to_oop(compact_to);
// Restore the mark word before relativizing the stack chunk. The copy's
// mark word contains the full GC forwarding encoding, which would cause
// is_stackChunk() to read garbage (especially with compact headers).
! new_obj->reinit_mark();
+ new_obj->initialize_hash_if_necessary(p);
ContinuationGCSupport::relativize_stack_chunk(new_obj);
}
}
};
oop old_obj = cast_to_oop(r->bottom());
if (!FullGCForwarding::is_forwarded(old_obj)) {
// No need to move the object, it stays at the same slot
continue;
}
! size_t words_size = old_obj->size();
! size_t num_regions = ShenandoahHeapRegion::required_regions(words_size * HeapWordSize);
size_t old_start = r->index();
! size_t old_end = old_start + num_regions - 1;
size_t new_start = heap->heap_region_index_containing(FullGCForwarding::forwardee(old_obj));
! size_t new_end = new_start + num_regions - 1;
assert(old_start != new_start, "must be real move");
assert(r->is_stw_move_allowed(), "Region %zu should be movable", r->index());
log_debug(gc)("Full GC compaction moves humongous object from region %zu to region %zu", old_start, new_start);
! Copy::aligned_conjoint_words(r->bottom(), heap->get_region(new_start)->bottom(), words_size);
ContinuationGCSupport::relativize_stack_chunk(cast_to_oop<HeapWord*>(r->bottom()));
oop new_obj = cast_to_oop(heap->get_region(new_start)->bottom());
! new_obj->init_mark();
{
ShenandoahAffiliation original_affiliation = r->affiliation();
for (size_t c = old_start; c <= old_end; c++) {
ShenandoahHeapRegion* r = heap->get_region(c);
oop old_obj = cast_to_oop(r->bottom());
if (!FullGCForwarding::is_forwarded(old_obj)) {
// No need to move the object, it stays at the same slot
continue;
}
! size_t old_words_size = old_obj->size();
! size_t new_words_size = old_obj->copy_size(old_words_size, old_obj->mark());
+ size_t old_num_regions = ShenandoahHeapRegion::required_regions(old_words_size * HeapWordSize);
+ size_t new_num_regions = ShenandoahHeapRegion::required_regions(new_words_size * HeapWordSize);
size_t old_start = r->index();
! size_t old_end = old_start + old_num_regions - 1;
size_t new_start = heap->heap_region_index_containing(FullGCForwarding::forwardee(old_obj));
! size_t new_end = new_start + new_num_regions - 1;
assert(old_start != new_start, "must be real move");
assert(r->is_stw_move_allowed(), "Region %zu should be movable", r->index());
log_debug(gc)("Full GC compaction moves humongous object from region %zu to region %zu", old_start, new_start);
! Copy::aligned_conjoint_words(r->bottom(), heap->get_region(new_start)->bottom(), old_words_size);
ContinuationGCSupport::relativize_stack_chunk(cast_to_oop<HeapWord*>(r->bottom()));
oop new_obj = cast_to_oop(heap->get_region(new_start)->bottom());
! new_obj->reinit_mark();
+ new_obj->initialize_hash_if_necessary(old_obj);
{
ShenandoahAffiliation original_affiliation = r->affiliation();
for (size_t c = old_start; c <= old_end; c++) {
ShenandoahHeapRegion* r = heap->get_region(c);
} else {
r->make_humongous_cont_bypass(original_affiliation);
}
// Trailing region may be non-full, record the remainder there
! size_t remainder = words_size & ShenandoahHeapRegion::region_size_words_mask();
if ((c == new_end) && (remainder != 0)) {
r->set_top(r->bottom() + remainder);
} else {
r->set_top(r->end());
}
} else {
r->make_humongous_cont_bypass(original_affiliation);
}
// Trailing region may be non-full, record the remainder there
! size_t remainder = new_words_size & ShenandoahHeapRegion::region_size_words_mask();
if ((c == new_end) && (remainder != 0)) {
r->set_top(r->bottom() + remainder);
} else {
r->set_top(r->end());
}
< prev index next >