< prev index next >

src/share/vm/gc_implementation/shenandoah/shenandoahHeap.cpp

Print this page
rev 11461 : [backport] 8226757: Shenandoah: Make traversal and passive modes explicit
rev 11463 : Backport Traversal GC

*** 49,58 **** --- 49,59 ---- #include "gc_implementation/shenandoah/shenandoahOopClosures.inline.hpp" #include "gc_implementation/shenandoah/shenandoahPacer.inline.hpp" #include "gc_implementation/shenandoah/shenandoahPassiveMode.hpp" #include "gc_implementation/shenandoah/shenandoahRootProcessor.hpp" #include "gc_implementation/shenandoah/shenandoahTaskqueue.hpp" + #include "gc_implementation/shenandoah/shenandoahTraversalMode.hpp" #include "gc_implementation/shenandoah/shenandoahUtils.hpp" #include "gc_implementation/shenandoah/shenandoahVerifier.hpp" #include "gc_implementation/shenandoah/shenandoahCodeRoots.hpp" #include "gc_implementation/shenandoah/shenandoahVMOperations.hpp" #include "gc_implementation/shenandoah/shenandoahWorkGroup.hpp"
*** 355,364 **** --- 356,369 ---- _pacer->setup_for_idle(); } else { _pacer = NULL; } + _traversal_gc = strcmp(ShenandoahGCMode, "traversal") == 0 ? + new ShenandoahTraversalGC(this, _num_regions) : + NULL; + _control_thread = new ShenandoahControlThread(); log_info(gc, init)("Initialize Shenandoah heap: " SIZE_FORMAT "%s initial, " SIZE_FORMAT "%s min, " SIZE_FORMAT "%s max", byte_size_in_proper_unit(_initial_size), proper_unit_for_byte_size(_initial_size), byte_size_in_proper_unit(_minimum_size), proper_unit_for_byte_size(_minimum_size),
*** 373,383 **** #pragma warning( disable:4355 ) // 'this' : used in base member initializer list #endif void ShenandoahHeap::initialize_heuristics() { if (ShenandoahGCMode != NULL) { ! if (strcmp(ShenandoahGCMode, "normal") == 0) { _gc_mode = new ShenandoahNormalMode(); } else if (strcmp(ShenandoahGCMode, "passive") == 0) { _gc_mode = new ShenandoahPassiveMode(); } else { vm_exit_during_initialization("Unknown -XX:ShenandoahGCMode option"); --- 378,390 ---- #pragma warning( disable:4355 ) // 'this' : used in base member initializer list #endif void ShenandoahHeap::initialize_heuristics() { if (ShenandoahGCMode != NULL) { ! if (strcmp(ShenandoahGCMode, "traversal") == 0) { ! _gc_mode = new ShenandoahTraversalMode(); ! } else if (strcmp(ShenandoahGCMode, "normal") == 0) { _gc_mode = new ShenandoahNormalMode(); } else if (strcmp(ShenandoahGCMode, "passive") == 0) { _gc_mode = new ShenandoahPassiveMode(); } else { vm_exit_during_initialization("Unknown -XX:ShenandoahGCMode option");
*** 407,416 **** --- 414,424 ---- _shenandoah_policy(policy), _heap_region_special(false), _regions(NULL), _free_set(NULL), _collection_set(NULL), + _traversal_gc(NULL), _update_refs_iterator(this), _bytes_allocated_since_gc_start(0), _max_workers((uint)MAX2(ConcGCThreads, ParallelGCThreads)), _ref_processor(NULL), _marking_context(NULL),
*** 429,438 **** --- 437,447 ---- { log_info(gc, init)("GC threads: " UINTX_FORMAT " parallel, " UINTX_FORMAT " concurrent", ParallelGCThreads, ConcGCThreads); log_info(gc, init)("Reference processing: %s", ParallelRefProcEnabled ? "parallel" : "serial"); _scm = new ShenandoahConcurrentMark(); + _full_gc = new ShenandoahMarkCompact(); _used = 0; _max_workers = MAX2(_max_workers, 1U);
*** 496,505 **** --- 505,515 ---- 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_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, "); if (cancelled_gc()) {
*** 1578,1587 **** --- 1588,1609 ---- void ShenandoahHeap::op_preclean() { concurrent_mark()->preclean_weak_refs(); } + void ShenandoahHeap::op_init_traversal() { + traversal_gc()->init_traversal_collection(); + } + + void ShenandoahHeap::op_traversal() { + traversal_gc()->concurrent_traversal_collection(); + } + + void ShenandoahHeap::op_final_traversal() { + traversal_gc()->final_traversal_collection(); + } + void ShenandoahHeap::op_full(GCCause::Cause cause) { ShenandoahMetricsSnapshot metrics; metrics.snap_before(); full_gc()->do_it(cause);
*** 1606,1615 **** --- 1628,1655 ---- ShenandoahMetricsSnapshot metrics; metrics.snap_before(); switch (point) { + case _degenerated_traversal: + { + // Drop the collection set. Note: this leaves some already forwarded objects + // behind, which may be problematic, see comments for ShenandoahEvacAssist + // workarounds in ShenandoahTraversalHeuristics. + + ShenandoahHeapLocker locker(lock()); + collection_set()->clear_current_index(); + for (size_t i = 0; i < collection_set()->count(); i++) { + ShenandoahHeapRegion* r = collection_set()->next(); + r->make_regular_bypass(); + } + collection_set()->clear(); + } + op_final_traversal(); + op_cleanup(); + return; + // The cases below form the Duff's-like device: it describes the actual GC cycle, // but enters it at different points, depending on which concurrent phase had // degenerated. case _degenerated_outside_cycle:
*** 1622,1631 **** --- 1662,1678 ---- // Note that we can only do this for "outside-cycle" degens, otherwise we would risk // changing the cycle parameters mid-cycle during concurrent -> degenerated handover. set_process_references(heuristics()->can_process_references()); set_unload_classes(heuristics()->can_unload_classes()); + if (is_traversal_mode()) { + // Not possible to degenerate from here, upgrade to Full GC right away. + cancel_gc(GCCause::_shenandoah_upgrade_to_full_gc); + op_degenerated_fail(); + return; + } + op_reset(); op_init_mark(); if (cancelled_gc()) { op_degenerated_fail();
*** 1751,1761 **** } set_concurrent_mark_in_progress(false); } void ShenandoahHeap::force_satb_flush_all_threads() { ! if (!is_concurrent_mark_in_progress()) { // No need to flush SATBs return; } // Do not block if Threads lock is busy. This avoids the potential deadlock --- 1798,1808 ---- } set_concurrent_mark_in_progress(false); } void ShenandoahHeap::force_satb_flush_all_threads() { ! if (!is_concurrent_mark_in_progress() && !is_concurrent_traversal_in_progress()) { // No need to flush SATBs return; } // Do not block if Threads lock is busy. This avoids the potential deadlock
*** 1785,1794 **** --- 1832,1846 ---- void ShenandoahHeap::set_concurrent_mark_in_progress(bool in_progress) { set_gc_state_mask(MARKING, in_progress); JavaThread::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 | UPDATEREFS, in_progress); + JavaThread::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress); + } + void ShenandoahHeap::set_evacuation_in_progress(bool in_progress) { assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Only call this at safepoint"); set_gc_state_mask(EVACUATION, in_progress); }
*** 2308,2317 **** --- 2360,2389 ---- try_inject_alloc_failure(); VM_ShenandoahFinalUpdateRefs 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); + + try_inject_alloc_failure(); + VM_ShenandoahInitTraversalGC op; + VMThread::execute(&op); + } + + void ShenandoahHeap::vmop_entry_final_traversal() { + TraceCollectorStats tcs(monitoring_support()->stw_collection_counters()); + ShenandoahGCPhase total(ShenandoahPhaseTimings::total_pause_gross); + ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_traversal_gc_gross); + + try_inject_alloc_failure(); + VM_ShenandoahFinalTraversalGC op; + VMThread::execute(&op); + } + void ShenandoahHeap::vmop_entry_full(GCCause::Cause cause) { TraceCollectorStats tcs(monitoring_support()->full_stw_collection_counters()); ShenandoahGCPhase total(ShenandoahPhaseTimings::total_pause_gross); ShenandoahGCPhase phase(ShenandoahPhaseTimings::full_gc_gross);
*** 2396,2405 **** --- 2468,2507 ---- "final reference update"); op_final_updaterefs(); } + void ShenandoahHeap::entry_init_traversal() { + ShenandoahGCPhase total_phase(ShenandoahPhaseTimings::total_pause); + ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_traversal_gc); + + static const char* msg = "Pause Init Traversal"; + GCTraceTime time(msg, PrintGC, _gc_timer, tracer()->gc_id()); + EventMark em("%s", msg); + + ShenandoahWorkerScope scope(workers(), + ShenandoahWorkerPolicy::calc_workers_for_stw_traversal(), + "init traversal"); + + op_init_traversal(); + } + + void ShenandoahHeap::entry_final_traversal() { + ShenandoahGCPhase total_phase(ShenandoahPhaseTimings::total_pause); + ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_traversal_gc); + + static const char* msg = "Pause Final Traversal"; + GCTraceTime time(msg, PrintGC, _gc_timer, tracer()->gc_id()); + EventMark em("%s", msg); + + ShenandoahWorkerScope scope(workers(), + ShenandoahWorkerPolicy::calc_workers_for_stw_traversal(), + "final traversal"); + + op_final_traversal(); + } + void ShenandoahHeap::entry_full(GCCause::Cause cause) { ShenandoahGCPhase total_phase(ShenandoahPhaseTimings::total_pause); ShenandoahGCPhase phase(ShenandoahPhaseTimings::full_gc); static const char* msg = "Pause Full";
*** 2521,2530 **** --- 2623,2647 ---- try_inject_alloc_failure(); op_preclean(); } } + void ShenandoahHeap::entry_traversal() { + static const char* msg = "Concurrent traversal"; + GCTraceTime time(msg, PrintGC, NULL, tracer()->gc_id(), true); + EventMark em("%s", msg); + + TraceCollectorStats tcs(monitoring_support()->concurrent_collection_counters()); + + ShenandoahWorkerScope scope(workers(), + ShenandoahWorkerPolicy::calc_workers_for_conc_traversal(), + "concurrent traversal"); + + try_inject_alloc_failure(); + op_traversal(); + } + void ShenandoahHeap::entry_uncommit(double shrink_before) { static const char *msg = "Concurrent uncommit"; GCTraceTime time(msg, PrintGC, NULL, tracer()->gc_id(), true); EventMark em("%s", msg);
*** 2649,2658 **** --- 2766,2777 ---- const char* ShenandoahHeap::degen_event_message(ShenandoahDegenPoint point) const { switch (point) { case _degenerated_unset: return "Pause Degenerated GC (<UNSET>)"; + case _degenerated_traversal: + return "Pause Degenerated GC (Traversal)"; case _degenerated_outside_cycle: return "Pause Degenerated GC (Outside of Cycle)"; case _degenerated_mark: return "Pause Degenerated GC (Mark)"; case _degenerated_evac:
< prev index next >