< prev index next > src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp
Print this page
// Update references freed up collection set, kick the cleanup to reclaim the space.
entry_cleanup_complete();
} else {
_abbreviated = true;
! if (!entry_final_roots()) {
! assert(_degen_point != _degenerated_unset, "Need to know where to start degenerated cycle");
! return false;
}
// In normal cycle, final-update-refs would verify at the end of the cycle.
// In abbreviated cycle, we need to verify separately.
! if (ShenandoahVerify) {
! vmop_entry_final_verify();
- }
}
// We defer generation resizing actions until after cset regions have been recycled. We do this even following an
// abbreviated cycle.
if (heap->mode()->is_generational()) {
// Update references freed up collection set, kick the cleanup to reclaim the space.
entry_cleanup_complete();
} else {
_abbreviated = true;
!
! if (heap->mode()->is_generational()) {
! if (!complete_abbreviated_cycle()) {
+ assert(_degen_point != _degenerated_unset, "Need to know where to start degenerated cycle");
+ return false;
+ }
}
// In normal cycle, final-update-refs would verify at the end of the cycle.
// In abbreviated cycle, we need to verify separately.
! // This is now also puts the barriers down at the end of the cycle. TODO: Refine.
! vmop_entry_final_roots();
}
// We defer generation resizing actions until after cset regions have been recycled. We do this even following an
// abbreviated cycle.
if (heap->mode()->is_generational()) {
heap->try_inject_alloc_failure();
VM_ShenandoahFinalUpdateRefs op(this);
VMThread::execute(&op);
}
! void ShenandoahConcurrentGC::vmop_entry_final_verify() {
ShenandoahHeap* const heap = ShenandoahHeap::heap();
TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
! ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_verify_gross);
// This phase does not use workers, no need for setup
heap->try_inject_alloc_failure();
! VM_ShenandoahFinalVerify op(this);
VMThread::execute(&op);
}
void ShenandoahConcurrentGC::entry_init_mark() {
const char* msg = init_mark_event_message();
heap->try_inject_alloc_failure();
VM_ShenandoahFinalUpdateRefs op(this);
VMThread::execute(&op);
}
! void ShenandoahConcurrentGC::vmop_entry_final_roots() {
ShenandoahHeap* const heap = ShenandoahHeap::heap();
TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
! ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_roots_gross);
// This phase does not use workers, no need for setup
heap->try_inject_alloc_failure();
! VM_ShenandoahFinalRoots op(this);
VMThread::execute(&op);
}
void ShenandoahConcurrentGC::entry_init_mark() {
const char* msg = init_mark_event_message();
"final reference update");
op_final_update_refs();
}
- void ShenandoahConcurrentGC::entry_final_verify() {
- const char* msg = verify_final_event_message();
- ShenandoahPausePhase gc_phase(msg, ShenandoahPhaseTimings::final_verify);
- EventMark em("%s", msg);
-
- op_verify_final();
- }
-
void ShenandoahConcurrentGC::entry_reset() {
ShenandoahHeap* const heap = ShenandoahHeap::heap();
heap->try_inject_alloc_failure();
TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters());
assert(_generation->is_bitmap_clear(), "need clear marking bitmap");
assert(!_generation->is_mark_complete(), "should not be complete");
assert(!heap->has_forwarded_objects(), "No forwarded objects on this path");
+ // First pause in cycle, check that barriers were not left enabled.
+ ShenandoahCodeRoots::check_barriers();
+
if (heap->mode()->is_generational()) {
if (_generation->is_global()) {
heap->old_generation()->cancel_gc();
}
}
heap->set_evacuation_in_progress(true);
// From here on, we need to update references.
heap->set_has_forwarded_objects(true);
-
- // Arm nmethods/stack for concurrent processing
- ShenandoahCodeRoots::arm_nmethods();
- ShenandoahStackWatermark::change_epoch_id();
-
} else {
if (ShenandoahVerify) {
ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_mark_verify);
if (has_in_place_promotions(heap)) {
heap->verifier()->verify_after_concmark_with_promotions(_generation);
}
}
}
}
+ // Arm nmethods/stack for concurrent processing
+ ShenandoahCodeRoots::arm_nmethods();
+ ShenandoahStackWatermark::change_epoch_id();
+
{
ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_mark_propagate_gc_state);
heap->propagate_gc_state_to_all_threads();
}
}
void do_nmethod(nmethod* n) {
ShenandoahNMethod* data = ShenandoahNMethod::gc_data(n);
ShenandoahNMethodLocker locker(data->lock());
data->oops_do(&_cl, /* fix_relocations = */ true);
! ShenandoahNMethod::disarm_nmethod(n);
}
};
class ShenandoahConcurrentRootsEvacUpdateTask : public WorkerTask {
private:
void do_nmethod(nmethod* n) {
ShenandoahNMethod* data = ShenandoahNMethod::gc_data(n);
ShenandoahNMethodLocker locker(data->lock());
data->oops_do(&_cl, /* fix_relocations = */ true);
! ShenandoahNMethod::disarm_nmethod_unlocked(n);
}
};
class ShenandoahConcurrentRootsEvacUpdateTask : public WorkerTask {
private:
}
heap->rebuild_free_set(true /*concurrent*/);
_generation->heuristics()->start_idle_span();
{
ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_update_refs_propagate_gc_state);
heap->propagate_gc_state_to_all_threads();
}
}
! bool ShenandoahConcurrentGC::entry_final_roots() {
ShenandoahHeap* const heap = ShenandoahHeap::heap();
TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters());
!
! const char* msg = conc_final_roots_event_message();
- ShenandoahConcurrentPhase gc_phase(msg, ShenandoahPhaseTimings::conc_final_roots);
EventMark em("%s", msg);
ShenandoahWorkerScope scope(heap->workers(),
! ShenandoahWorkerPolicy::calc_workers_for_conc_evac(),
msg);
! if (heap->mode()->is_generational()) {
- if (!complete_abbreviated_cycle()) {
- return false;
- }
- }
-
- heap->concurrent_final_roots();
- return true;
- }
-
- void ShenandoahConcurrentGC::op_verify_final() {
- assert(ShenandoahVerify, "Should have been checked before");
- ShenandoahHeap* const heap = ShenandoahHeap::heap();
- heap->verifier()->verify_after_gc(_generation);
}
void ShenandoahConcurrentGC::op_cleanup_complete() {
ShenandoahWorkerScope scope(ShenandoahHeap::heap()->workers(),
ShenandoahWorkerPolicy::calc_workers_for_conc_cleanup(),
}
heap->rebuild_free_set(true /*concurrent*/);
_generation->heuristics()->start_idle_span();
+ {
+ // Final pause: update GC barriers to idle state.
+ ShenandoahCodeRoots::arm_nmethods();
+ ShenandoahStackWatermark::change_epoch_id();
+ }
+
{
ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_update_refs_propagate_gc_state);
heap->propagate_gc_state_to_all_threads();
}
}
! void ShenandoahConcurrentGC::entry_final_roots() {
ShenandoahHeap* const heap = ShenandoahHeap::heap();
TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters());
! const char* msg = final_roots_event_message();
! ShenandoahConcurrentPhase gc_phase(msg, ShenandoahPhaseTimings::final_roots);
EventMark em("%s", msg);
ShenandoahWorkerScope scope(heap->workers(),
! ParallelGCThreads,
msg);
! heap->op_final_roots();
}
void ShenandoahConcurrentGC::op_cleanup_complete() {
ShenandoahWorkerScope scope(ShenandoahHeap::heap()->workers(),
ShenandoahWorkerPolicy::calc_workers_for_conc_cleanup(),
void ShenandoahConcurrentGC::op_reset_after_collect() {
ShenandoahWorkerScope scope(ShenandoahHeap::heap()->workers(),
ShenandoahWorkerPolicy::calc_workers_for_conc_reset(),
"reset after collection.");
+ // Final concurrent phase: complete disabling all barriers.
+ ShenandoahCodeRoots::disarm_nmethods();
+
+ // Check that barriers were not left enabled.
+ ShenandoahCodeRoots::check_barriers();
+
ShenandoahHeap* const heap = ShenandoahHeap::heap();
if (heap->mode()->is_generational()) {
// If we are in the midst of an old gc bootstrap or an old marking, we want to leave the mark bit map of
// the young generation intact. In particular, reference processing in the old generation may potentially
// need the reachability of a young generation referent of a Reference object in the old generation.
} else {
SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent reset after collect", "");
}
}
! const char* ShenandoahConcurrentGC::verify_final_event_message() const {
- if (ShenandoahHeap::heap()->unload_classes()) {
- SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Pause Verify Final", " (unload classes)");
- } else {
- SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Pause Verify Final", "");
- }
- }
-
- const char* ShenandoahConcurrentGC::conc_final_roots_event_message() const {
if (ShenandoahHeap::heap()->unload_classes()) {
! SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent Final Roots", " (unload classes)");
} else {
! SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent Final Roots", "");
}
}
const char* ShenandoahConcurrentGC::conc_weak_refs_event_message() const {
if (ShenandoahHeap::heap()->unload_classes()) {
} else {
SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent reset after collect", "");
}
}
! const char* ShenandoahConcurrentGC::final_roots_event_message() const {
if (ShenandoahHeap::heap()->unload_classes()) {
! SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Pause Final Roots", " (unload classes)");
} else {
! SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Pause Final Roots", "");
}
}
const char* ShenandoahConcurrentGC::conc_weak_refs_event_message() const {
if (ShenandoahHeap::heap()->unload_classes()) {
< prev index next >