< prev index next > src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp
Print this page
#include "precompiled.hpp"
#include "compiler/oopMap.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/preservedMarks.inline.hpp"
+ #include "gc/shared/slidingForwarding.inline.hpp"
#include "gc/shared/tlab_globals.hpp"
#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
#include "gc/shenandoah/shenandoahConcurrentGC.hpp"
#include "gc/shenandoah/shenandoahCollectionSet.hpp"
#include "gc/shenandoah/shenandoahFreeSet.hpp"
heap->sync_pinned_region_status();
// The rest of prologue:
BiasedLocking::preserve_marks();
_preserved_marks->init(heap->workers()->active_workers());
+ heap->forwarding()->clear();
assert(heap->has_forwarded_objects() == has_forwarded_objects, "This should not change");
}
if (UseTLAB) {
heap->parallel_cleaning(true /* full_gc */);
}
class ShenandoahPrepareForCompactionObjectClosure : public ObjectClosure {
private:
! PreservedMarks* const _preserved_marks;
! ShenandoahHeap* const _heap;
GrowableArray<ShenandoahHeapRegion*>& _empty_regions;
int _empty_regions_pos;
ShenandoahHeapRegion* _to_region;
ShenandoahHeapRegion* _from_region;
HeapWord* _compact_point;
heap->parallel_cleaning(true /* full_gc */);
}
class ShenandoahPrepareForCompactionObjectClosure : public ObjectClosure {
private:
! PreservedMarks* const _preserved_marks;
! SlidingForwarding* const _forwarding;
+ ShenandoahHeap* const _heap;
GrowableArray<ShenandoahHeapRegion*>& _empty_regions;
int _empty_regions_pos;
ShenandoahHeapRegion* _to_region;
ShenandoahHeapRegion* _from_region;
HeapWord* _compact_point;
public:
ShenandoahPrepareForCompactionObjectClosure(PreservedMarks* preserved_marks,
GrowableArray<ShenandoahHeapRegion*>& empty_regions,
ShenandoahHeapRegion* to_region) :
_preserved_marks(preserved_marks),
+ _forwarding(ShenandoahHeap::heap()->forwarding()),
_heap(ShenandoahHeap::heap()),
_empty_regions(empty_regions),
_empty_regions_pos(0),
_to_region(to_region),
_from_region(NULL),
// Object fits into current region, record new location:
assert(_compact_point + obj_size <= _to_region->end(), "must fit");
shenandoah_assert_not_forwarded(NULL, p);
_preserved_marks->push_if_necessary(p, p->mark());
! p->forward_to(cast_to_oop(_compact_point));
_compact_point += obj_size;
}
};
class ShenandoahPrepareForCompactionTask : public AbstractGangTask {
// Object fits into current region, record new location:
assert(_compact_point + obj_size <= _to_region->end(), "must fit");
shenandoah_assert_not_forwarded(NULL, p);
_preserved_marks->push_if_necessary(p, p->mark());
! _forwarding->forward_to(p, cast_to_oop(_compact_point));
_compact_point += obj_size;
}
};
class ShenandoahPrepareForCompactionTask : public AbstractGangTask {
}
};
void ShenandoahFullGC::calculate_target_humongous_objects() {
ShenandoahHeap* heap = ShenandoahHeap::heap();
+ SlidingForwarding* forwarding = heap->forwarding();
// Compute the new addresses for humongous objects. We need to do this after addresses
// for regular objects are calculated, and we know what regions in heap suffix are
// available for humongous moves.
//
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());
! old_obj->forward_to(cast_to_oop(heap->get_region(start)->bottom()));
to_end = start;
continue;
}
}
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());
! forwarding->forward_to(old_obj, cast_to_oop(heap->get_region(start)->bottom()));
to_end = start;
continue;
}
}
}
}
class ShenandoahAdjustPointersClosure : public MetadataVisitingOopIterateClosure {
private:
! ShenandoahHeap* const _heap;
ShenandoahMarkingContext* const _ctx;
template <class T>
inline void do_oop_work(T* p) {
T o = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(o)) {
oop obj = CompressedOops::decode_not_null(o);
assert(_ctx->is_marked(obj), "must be marked");
if (obj->is_forwarded()) {
! oop forw = obj->forwardee();
RawAccess<IS_NOT_NULL>::oop_store(p, forw);
}
}
}
public:
ShenandoahAdjustPointersClosure() :
_heap(ShenandoahHeap::heap()),
_ctx(ShenandoahHeap::heap()->complete_marking_context()) {}
void do_oop(oop* p) { do_oop_work(p); }
void do_oop(narrowOop* p) { do_oop_work(p); }
};
}
}
class ShenandoahAdjustPointersClosure : public MetadataVisitingOopIterateClosure {
private:
! ShenandoahHeap* const _heap;
+ const SlidingForwarding* const _forwarding;
ShenandoahMarkingContext* const _ctx;
template <class T>
inline void do_oop_work(T* p) {
T o = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(o)) {
oop obj = CompressedOops::decode_not_null(o);
assert(_ctx->is_marked(obj), "must be marked");
if (obj->is_forwarded()) {
! oop forw = _forwarding->forwardee(obj);
RawAccess<IS_NOT_NULL>::oop_store(p, forw);
}
}
}
public:
ShenandoahAdjustPointersClosure() :
_heap(ShenandoahHeap::heap()),
+ _forwarding(_heap->forwarding()),
_ctx(ShenandoahHeap::heap()->complete_marking_context()) {}
void do_oop(oop* p) { do_oop_work(p); }
void do_oop(narrowOop* p) { do_oop_work(p); }
};
void work(uint worker_id) {
ShenandoahParallelWorkerSession worker_session(worker_id);
ShenandoahAdjustPointersClosure cl;
_rp->roots_do(worker_id, &cl);
! _preserved_marks->get(worker_id)->adjust_during_full_gc();
}
};
void ShenandoahFullGC::phase3_update_references() {
GCTraceTime(Info, gc, phases) time("Phase 3: Adjust pointers", _gc_timer);
void work(uint worker_id) {
ShenandoahParallelWorkerSession worker_session(worker_id);
ShenandoahAdjustPointersClosure cl;
_rp->roots_do(worker_id, &cl);
! const SlidingForwarding* const forwarding = ShenandoahHeap::heap()->forwarding();
+ _preserved_marks->get(worker_id)->adjust_during_full_gc(forwarding);
}
};
void ShenandoahFullGC::phase3_update_references() {
GCTraceTime(Info, gc, phases) time("Phase 3: Adjust pointers", _gc_timer);
workers->run_task(&adjust_pointers_task);
}
class ShenandoahCompactObjectsClosure : public ObjectClosure {
private:
! ShenandoahHeap* const _heap;
! uint const _worker_id;
public:
ShenandoahCompactObjectsClosure(uint worker_id) :
! _heap(ShenandoahHeap::heap()), _worker_id(worker_id) {}
void do_object(oop p) {
assert(_heap->complete_marking_context()->is_marked(p), "must be marked");
size_t size = (size_t)p->size();
if (p->is_forwarded()) {
HeapWord* compact_from = cast_from_oop<HeapWord*>(p);
! HeapWord* compact_to = cast_from_oop<HeapWord*>(p->forwardee());
Copy::aligned_conjoint_words(compact_from, compact_to, size);
oop new_obj = cast_to_oop(compact_to);
new_obj->init_mark();
}
}
workers->run_task(&adjust_pointers_task);
}
class ShenandoahCompactObjectsClosure : public ObjectClosure {
private:
! ShenandoahHeap* const _heap;
! const SlidingForwarding* const _forwarding;
+ uint const _worker_id;
public:
ShenandoahCompactObjectsClosure(uint worker_id) :
! _heap(ShenandoahHeap::heap()), _forwarding(_heap->forwarding()), _worker_id(worker_id) {}
void do_object(oop p) {
assert(_heap->complete_marking_context()->is_marked(p), "must be marked");
size_t size = (size_t)p->size();
if (p->is_forwarded()) {
HeapWord* compact_from = cast_from_oop<HeapWord*>(p);
! HeapWord* compact_to = cast_from_oop<HeapWord*>(_forwarding->forwardee(p));
Copy::aligned_conjoint_words(compact_from, compact_to, size);
oop new_obj = cast_to_oop(compact_to);
new_obj->init_mark();
}
}
// This code is serial, because doing the in-slice parallel sliding is tricky. In most cases,
// humongous regions are already compacted, and do not require further moves, which alleviates
// sliding costs. We may consider doing this in parallel in future.
ShenandoahHeap* heap = ShenandoahHeap::heap();
+ const SlidingForwarding* const forwarding = heap->forwarding();
for (size_t c = heap->num_regions(); c > 0; c--) {
ShenandoahHeapRegion* r = heap->get_region(c - 1);
if (r->is_humongous_start()) {
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 old_start = r->index();
size_t old_end = old_start + num_regions - 1;
! size_t new_start = heap->heap_region_index_containing(old_obj->forwardee());
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 " SIZE_FORMAT " should be movable", r->index());
Copy::aligned_conjoint_words(heap->get_region(old_start)->bottom(),
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(forwarding->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 " SIZE_FORMAT " should be movable", r->index());
Copy::aligned_conjoint_words(heap->get_region(old_start)->bottom(),
< prev index next >