< prev index next >
src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
Print this page
rev 50076 : Fold Partial GC into Traversal GC
@@ -43,11 +43,10 @@
#include "gc/shenandoah/shenandoahHeapRegionSet.hpp"
#include "gc/shenandoah/shenandoahMarkCompact.hpp"
#include "gc/shenandoah/shenandoahMemoryPool.hpp"
#include "gc/shenandoah/shenandoahMonitoringSupport.hpp"
#include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
-#include "gc/shenandoah/shenandoahPartialGC.hpp"
#include "gc/shenandoah/shenandoahPacer.hpp"
#include "gc/shenandoah/shenandoahPacer.inline.hpp"
#include "gc/shenandoah/shenandoahRootProcessor.hpp"
#include "gc/shenandoah/shenandoahStringDedup.hpp"
#include "gc/shenandoah/shenandoahUtils.hpp"
@@ -200,20 +199,10 @@
}
assert((((size_t) base()) & ShenandoahHeapRegion::region_size_bytes_mask()) == 0,
"misaligned heap: "PTR_FORMAT, p2i(base()));
- LogTarget(Trace, gc, region) lt;
- if (lt.is_enabled()) {
- ResourceMark rm;
- LogStream ls(lt);
- log_trace(gc, region)("All Regions");
- print_heap_regions_on(&ls);
- log_trace(gc, region)("Free Regions");
- _free_set->print_on(&ls);
- }
-
// The call below uses stuff (the SATB* things) that are in G1, but probably
// belong into a shared location.
ShenandoahBarrierSet::satb_mark_queue_set().initialize(SATB_Q_CBL_mon,
SATB_Q_FL_lock,
20 /*G1SATBProcessCompletedThreshold */,
@@ -305,14 +294,10 @@
_connection_matrix = new ShenandoahConnectionMatrix(_num_regions);
} else {
_connection_matrix = NULL;
}
- _partial_gc = _shenandoah_policy->can_do_partial_gc() ?
- new ShenandoahPartialGC(this, _num_regions) :
- NULL;
-
_traversal_gc = _shenandoah_policy->can_do_traversal_gc() ?
new ShenandoahTraversalGC(this, _num_regions) :
NULL;
_monitoring_support = new ShenandoahMonitoringSupport(this);
@@ -327,10 +312,20 @@
_concurrent_gc_thread = new ShenandoahConcurrentThread();
ShenandoahCodeRoots::initialize();
+ LogTarget(Trace, gc, region) lt;
+ if (lt.is_enabled()) {
+ ResourceMark rm;
+ LogStream ls(lt);
+ log_trace(gc, region)("All Regions");
+ print_heap_regions_on(&ls);
+ log_trace(gc, region)("Free Regions");
+ _free_set->print_on(&ls);
+ }
+
log_info(gc, init)("Safepointing mechanism: %s",
SafepointMechanism::uses_thread_local_poll() ? "thread-local poll" :
(SafepointMechanism::uses_global_page_poll() ? "global-page poll" : "unknown"));
return JNI_OK;
@@ -359,10 +354,11 @@
_pacer(NULL),
_used_at_last_gc(0),
_alloc_seq_at_last_gc_start(0),
_alloc_seq_at_last_gc_end(0),
_safepoint_workers(NULL),
+ _gc_cycle_mode(),
#ifdef ASSERT
_heap_expansion_count(0),
#endif
_gc_timer(new (ResourceObj::C_HEAP, mtGC) ConcurrentGCTimer()),
_phase_timings(NULL),
@@ -428,10 +424,55 @@
ShenandoahResetNextBitmapTask task(region_iterator());
_workers->run_task(&task);
}
+class ShenandoahResetNextBitmapTraversalTask : public AbstractGangTask {
+private:
+ ShenandoahRegionIterator _regions;
+
+public:
+ ShenandoahResetNextBitmapTraversalTask(ShenandoahRegionIterator regions) :
+ AbstractGangTask("Parallel Reset Bitmap Task for Traversal"),
+ _regions(regions) {
+ }
+
+ void work(uint worker_id) {
+ ShenandoahHeap* heap = ShenandoahHeap::heap();
+ ShenandoahHeapRegionSet* traversal_set = heap->traversal_gc()->traversal_set();
+ ShenandoahHeapRegion* region = _regions.next();
+ while (region != NULL) {
+ if (heap->is_bitmap_slice_committed(region)) {
+ if (traversal_set->is_in(region) && !region->is_trash()) {
+ ShenandoahHeapLocker locker(heap->lock());
+ HeapWord* bottom = region->bottom();
+ HeapWord* top = heap->next_top_at_mark_start(bottom);
+ assert(top <= region->top(),
+ "TAMS must smaller/equals than top: TAMS: "PTR_FORMAT", top: "PTR_FORMAT,
+ p2i(top), p2i(region->top()));
+ if (top > bottom) {
+ heap->complete_mark_bit_map()->copy_from(heap->next_mark_bit_map(), MemRegion(bottom, top));
+ heap->set_complete_top_at_mark_start(bottom, top);
+ heap->next_mark_bit_map()->clear_range_large(MemRegion(bottom, top));
+ heap->set_next_top_at_mark_start(bottom, bottom);
+ }
+ }
+ assert(heap->is_next_bitmap_clear_range(region->bottom(), region->end()),
+ "need clear next bitmap");
+ }
+ region = _regions.next();
+ }
+ }
+};
+
+void ShenandoahHeap::reset_next_mark_bitmap_traversal() {
+ assert_gc_workers(_workers->active_workers());
+
+ ShenandoahResetNextBitmapTraversalTask task(region_iterator());
+ _workers->run_task(&task);
+}
+
bool ShenandoahHeap::is_next_bitmap_clear() {
for (size_t idx = 0; idx < _num_regions; idx++) {
ShenandoahHeapRegion* r = get_region(idx);
if (is_bitmap_slice_committed(r) && !is_next_bitmap_clear_range(r->bottom(), r->end())) {
return false;
@@ -458,11 +499,10 @@
st->print("Status: ");
if (has_forwarded_objects()) st->print("has forwarded objects, ");
if (is_concurrent_mark_in_progress()) st->print("marking, ");
if (is_evacuation_in_progress()) st->print("evacuating, ");
if (is_update_refs_in_progress()) st->print("updating refs, ");
- if (is_concurrent_partial_in_progress()) st->print("partial, ");
if (is_concurrent_traversal_in_progress()) st->print("traversal, ");
if (is_degenerated_gc_in_progress()) st->print("degenerated gc, ");
if (is_full_gc_in_progress()) st->print("full gc, ");
if (is_full_gc_move_in_progress()) st->print("full gc move, ");
@@ -798,12 +838,11 @@
oop obj = CompressedOops::decode_not_null(o);
if (_heap->in_collection_set(obj)) {
shenandoah_assert_marked_complete(p, obj);
oop resolved = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
if (oopDesc::unsafe_equals(resolved, obj)) {
- bool evac;
- resolved = _heap->evacuate_object(obj, _thread, evac);
+ resolved = _heap->evacuate_object(obj, _thread);
}
RawAccess<OOP_NOT_NULL>::oop_store(p, resolved);
}
}
}
@@ -833,12 +872,11 @@
if (! CompressedOops::is_null(o)) {
oop obj = CompressedOops::decode_not_null(o);
if (_heap->in_collection_set(obj)) {
oop resolved = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
if (oopDesc::unsafe_equals(resolved, obj)) {
- bool evac;
- _heap->evacuate_object(obj, _thread, evac);
+ _heap->evacuate_object(obj, _thread);
}
}
}
}
@@ -860,12 +898,11 @@
_heap(heap), _thread(Thread::current()) {}
void do_object(oop p) {
shenandoah_assert_marked_complete(NULL, p);
if (oopDesc::unsafe_equals(p, ShenandoahBarrierSet::resolve_forwarded_not_null(p))) {
- bool evac;
- _heap->evacuate_object(p, _thread, evac);
+ _heap->evacuate_object(p, _thread);
}
}
};
class ShenandoahParallelEvacuationTask : public AbstractGangTask {
@@ -1611,27 +1648,28 @@
// Allocations happen during bitmap cleanup, record peak after the phase:
shenandoahPolicy()->record_peak_occupancy();
}
-void ShenandoahHeap::op_preclean() {
- concurrentMark()->preclean_weak_refs();
+void ShenandoahHeap::op_cleanup_traversal() {
- // Allocations happen during concurrent preclean, record peak after the phase:
- shenandoahPolicy()->record_peak_occupancy();
-}
+ {
+ ShenandoahGCPhase phase_reset(ShenandoahPhaseTimings::conc_cleanup_reset_bitmaps);
+ reset_next_mark_bitmap_traversal();
+ }
-void ShenandoahHeap::op_init_partial() {
- partial_gc()->init_partial_collection();
-}
+ op_cleanup();
-void ShenandoahHeap::op_partial() {
- partial_gc()->concurrent_partial_collection();
+ // Allocations happen during bitmap cleanup, record peak after the phase:
+ shenandoahPolicy()->record_peak_occupancy();
}
-void ShenandoahHeap::op_final_partial() {
- partial_gc()->final_partial_collection();
+void ShenandoahHeap::op_preclean() {
+ concurrentMark()->preclean_weak_refs();
+
+ // Allocations happen during concurrent preclean, record peak after the phase:
+ shenandoahPolicy()->record_peak_occupancy();
}
void ShenandoahHeap::op_init_traversal() {
traversal_gc()->init_traversal_collection();
}
@@ -1656,11 +1694,10 @@
clear_cancelled_concgc();
size_t used_before = used();
switch (point) {
- case _degenerated_partial:
case _degenerated_evac:
// Not possible to degenerate from here, upgrade to Full GC right away.
cancel_concgc(GCCause::_shenandoah_upgrade_to_full_gc);
op_degenerated_fail();
return;
@@ -1678,11 +1715,11 @@
r->make_regular_bypass();
}
collection_set()->clear();
}
op_final_traversal();
- op_cleanup_bitmaps();
+ op_cleanup_traversal();
return;
case _degenerated_outside_cycle:
if (shenandoahPolicy()->can_do_traversal_gc()) {
// Not possible to degenerate from here, upgrade to Full GC right away.
@@ -1818,16 +1855,10 @@
void ShenandoahHeap::set_concurrent_mark_in_progress(bool in_progress) {
set_gc_state_mask(MARKING, in_progress);
ShenandoahBarrierSet::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress);
}
-void ShenandoahHeap::set_concurrent_partial_in_progress(bool in_progress) {
-
- set_gc_state_mask(PARTIAL | HAS_FORWARDED, in_progress);
- ShenandoahBarrierSet::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress);
-}
-
void ShenandoahHeap::set_concurrent_traversal_in_progress(bool in_progress) {
set_gc_state_mask(TRAVERSAL | HAS_FORWARDED, in_progress);
ShenandoahBarrierSet::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress);
}
@@ -2195,14 +2226,10 @@
ShenandoahConnectionMatrix* ShenandoahHeap::connection_matrix() const {
return _connection_matrix;
}
-ShenandoahPartialGC* ShenandoahHeap::partial_gc() {
- return _partial_gc;
-}
-
ShenandoahTraversalGC* ShenandoahHeap::traversal_gc() {
return _traversal_gc;
}
ShenandoahVerifier* ShenandoahHeap::verifier() {
@@ -2511,30 +2538,10 @@
try_inject_alloc_failure();
VM_ShenandoahFinalUpdateRefs op;
VMThread::execute(&op);
}
-void ShenandoahHeap::vmop_entry_init_partial() {
- TraceCollectorStats tcs(monitoring_support()->stw_collection_counters());
- ShenandoahGCPhase total(ShenandoahPhaseTimings::total_pause_gross);
- ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_partial_gc_gross);
-
- try_inject_alloc_failure();
- VM_ShenandoahInitPartialGC op;
- VMThread::execute(&op);
-}
-
-void ShenandoahHeap::vmop_entry_final_partial() {
- TraceCollectorStats tcs(monitoring_support()->stw_collection_counters());
- ShenandoahGCPhase total(ShenandoahPhaseTimings::total_pause_gross);
- ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_partial_gc_gross);
-
- try_inject_alloc_failure();
- VM_ShenandoahFinalPartialGC op;
- VMThread::execute(&op);
-}
-
void ShenandoahHeap::vmop_entry_init_traversal() {
TraceCollectorStats tcs(monitoring_support()->stw_collection_counters());
ShenandoahGCPhase total(ShenandoahPhaseTimings::total_pause_gross);
ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_traversal_gc_gross);
@@ -2639,36 +2646,10 @@
ShenandoahWorkerScope scope(workers(), ShenandoahWorkerPolicy::calc_workers_for_final_update_ref());
op_final_updaterefs();
}
-void ShenandoahHeap::entry_init_partial() {
- ShenandoahGCPhase total_phase(ShenandoahPhaseTimings::total_pause);
- ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_partial_gc);
-
- static const char* msg = "Pause Init Partial";
- GCTraceTime(Info, gc) time(msg, gc_timer());
- EventMark em("%s", msg);
-
- ShenandoahWorkerScope scope(workers(), ShenandoahWorkerPolicy::calc_workers_for_stw_partial());
-
- op_init_partial();
-}
-
-void ShenandoahHeap::entry_final_partial() {
- ShenandoahGCPhase total_phase(ShenandoahPhaseTimings::total_pause);
- ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_partial_gc);
-
- static const char* msg = "Pause Final Partial";
- GCTraceTime(Info, gc) time(msg, gc_timer());
- EventMark em("%s", msg);
-
- ShenandoahWorkerScope scope(workers(), ShenandoahWorkerPolicy::calc_workers_for_stw_partial());
-
- op_final_partial();
-}
-
void ShenandoahHeap::entry_init_traversal() {
ShenandoahGCPhase total_phase(ShenandoahPhaseTimings::total_pause);
ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_traversal_gc);
static const char* msg = "Pause Init Traversal";
@@ -2775,10 +2756,23 @@
try_inject_alloc_failure();
op_cleanup();
}
+void ShenandoahHeap::entry_cleanup_traversal() {
+ ShenandoahGCPhase phase(ShenandoahPhaseTimings::conc_cleanup);
+
+ static const char* msg = "Concurrent cleanup";
+ GCTraceTime(Info, gc) time(msg, gc_timer(), GCCause::_no_gc, true);
+ EventMark em("%s", msg);
+
+ ShenandoahWorkerScope scope(workers(), ShenandoahWorkerPolicy::calc_workers_for_conc_traversal());
+
+ try_inject_alloc_failure();
+ op_cleanup_traversal();
+}
+
void ShenandoahHeap::entry_cleanup_bitmaps() {
ShenandoahGCPhase phase(ShenandoahPhaseTimings::conc_cleanup);
static const char* msg = "Concurrent cleanup";
GCTraceTime(Info, gc) time(msg, gc_timer(), GCCause::_no_gc, true);
@@ -2803,29 +2797,17 @@
try_inject_alloc_failure();
op_preclean();
}
}
-void ShenandoahHeap::entry_partial() {
- static const char* msg = "Concurrent partial";
- GCTraceTime(Info, gc) time(msg, gc_timer(), GCCause::_no_gc, true);
- EventMark em("%s", msg);
-
- TraceCollectorStats tcs(monitoring_support()->concurrent_collection_counters());
-
- ShenandoahWorkerScope scope(workers(), ShenandoahWorkerPolicy::calc_workers_for_conc_partial());
-
- try_inject_alloc_failure();
- op_partial();
-}
-
void ShenandoahHeap::entry_traversal() {
static const char* msg = "Concurrent traversal";
GCTraceTime(Info, gc) time(msg, gc_timer(), GCCause::_no_gc, true);
EventMark em("%s", msg);
- TraceCollectorStats tcs(monitoring_support()->concurrent_collection_counters());
+ TraceCollectorStats tcs(is_minor_gc() ? monitoring_support()->partial_collection_counters()
+ : monitoring_support()->concurrent_collection_counters());
ShenandoahWorkerScope scope(workers(), ShenandoahWorkerPolicy::calc_workers_for_conc_traversal());
try_inject_alloc_failure();
op_traversal();
@@ -2901,8 +2883,20 @@
}
r = regions.next();
}
}
+bool ShenandoahHeap::is_minor_gc() const {
+ return _gc_cycle_mode.get() == MINOR;
+}
+
+bool ShenandoahHeap::is_major_gc() const {
+ return _gc_cycle_mode.get() == MAJOR;
+}
+
+void ShenandoahHeap::set_cycle_mode(GCCycleMode gc_cycle_mode) {
+ _gc_cycle_mode.set(gc_cycle_mode);
+}
+
char ShenandoahHeap::gc_state() const {
return _gc_state.raw_value();
}
< prev index next >