8225582: Shenandoah: Enable concurrent evacuation of JNIHandles
Reviewed-by: rkennke, shade
This commit is contained in:
parent
b870874d22
commit
fe66fd327f
src/hotspot/share/gc/shenandoah
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#include "gc/shenandoah/shenandoahConcurrentRoots.hpp"
|
||||
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
|
||||
|
||||
bool ShenandoahConcurrentRoots::can_do_concurrent_roots() {
|
||||
// Don't support traversal GC at this moment
|
||||
return !ShenandoahHeap::heap()->is_concurrent_traversal_in_progress();
|
||||
}
|
||||
|
||||
bool ShenandoahConcurrentRoots::should_do_concurrent_roots() {
|
||||
ShenandoahHeap* const heap = ShenandoahHeap::heap();
|
||||
bool stw_gc_in_progress = heap->is_full_gc_in_progress() ||
|
||||
heap->is_degenerated_gc_in_progress();
|
||||
return can_do_concurrent_roots() &&
|
||||
!stw_gc_in_progress;
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHCONCURRENTROOTS_HPP
|
||||
#define SHARE_GC_SHENANDOAH_SHENANDOAHCONCURRENTROOTS_HPP
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
|
||||
class ShenandoahConcurrentRoots : public AllStatic {
|
||||
public:
|
||||
// Can GC settings allow concurrent root processing
|
||||
static bool can_do_concurrent_roots();
|
||||
// If current GC cycle can process roots concurrently
|
||||
static bool should_do_concurrent_roots();
|
||||
};
|
||||
|
||||
|
||||
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHCONCURRENTROOTS_HPP
|
@ -377,6 +377,9 @@ void ShenandoahControlThread::service_concurrent_normal_cycle(GCCause::Cause cau
|
||||
// Complete marking under STW, and start evacuation
|
||||
heap->vmop_entry_final_mark();
|
||||
|
||||
// Evacuate concurrent roots
|
||||
heap->entry_roots();
|
||||
|
||||
// Final mark might have reclaimed some immediate garbage, kick cleanup to reclaim
|
||||
// the space. This would be the last action if there is nothing to evacuate.
|
||||
heap->entry_cleanup();
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "gc/shenandoah/shenandoahCollectionSet.hpp"
|
||||
#include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
|
||||
#include "gc/shenandoah/shenandoahConcurrentMark.inline.hpp"
|
||||
#include "gc/shenandoah/shenandoahConcurrentRoots.hpp"
|
||||
#include "gc/shenandoah/shenandoahControlThread.hpp"
|
||||
#include "gc/shenandoah/shenandoahFreeSet.hpp"
|
||||
#include "gc/shenandoah/shenandoahPhaseTimings.hpp"
|
||||
@ -1071,9 +1072,11 @@ void ShenandoahHeap::evacuate_and_update_roots() {
|
||||
DerivedPointerTable::clear();
|
||||
#endif
|
||||
assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Only iterate roots while world is stopped");
|
||||
|
||||
{
|
||||
ShenandoahRootEvacuator rp(workers()->active_workers(), ShenandoahPhaseTimings::init_evac);
|
||||
// Include concurrent roots if current cycle can not process those roots concurrently
|
||||
ShenandoahRootEvacuator rp(workers()->active_workers(),
|
||||
ShenandoahPhaseTimings::init_evac,
|
||||
!ShenandoahConcurrentRoots::should_do_concurrent_roots());
|
||||
ShenandoahEvacuateUpdateRootsTask roots_task(&rp);
|
||||
workers()->run_task(&roots_task);
|
||||
}
|
||||
@ -1517,7 +1520,11 @@ void ShenandoahHeap::op_final_mark() {
|
||||
}
|
||||
|
||||
if (ShenandoahVerify) {
|
||||
verifier()->verify_roots_no_forwarded();
|
||||
if (ShenandoahConcurrentRoots::should_do_concurrent_roots()) {
|
||||
verifier()->verify_roots_no_forwarded_except(ShenandoahRootVerifier::JNIHandleRoots);
|
||||
} else {
|
||||
verifier()->verify_roots_no_forwarded();
|
||||
}
|
||||
verifier()->verify_during_evacuation();
|
||||
}
|
||||
} else {
|
||||
@ -1578,6 +1585,30 @@ void ShenandoahHeap::op_cleanup() {
|
||||
free_set()->recycle_trash();
|
||||
}
|
||||
|
||||
class ShenandoahConcurrentRootsEvacUpdateTask : public AbstractGangTask {
|
||||
private:
|
||||
ShenandoahJNIHandleRoots<true /*concurrent*/> _jni_roots;
|
||||
|
||||
public:
|
||||
ShenandoahConcurrentRootsEvacUpdateTask() :
|
||||
AbstractGangTask("Shenandoah Evacuate/Update Concurrent Roots Task") {
|
||||
}
|
||||
|
||||
void work(uint worker_id) {
|
||||
ShenandoahEvacOOMScope oom;
|
||||
ShenandoahEvacuateUpdateRootsClosure cl;
|
||||
_jni_roots.oops_do<ShenandoahEvacuateUpdateRootsClosure>(&cl);
|
||||
}
|
||||
};
|
||||
|
||||
void ShenandoahHeap::op_roots() {
|
||||
if (is_evacuation_in_progress() &&
|
||||
ShenandoahConcurrentRoots::should_do_concurrent_roots()) {
|
||||
ShenandoahConcurrentRootsEvacUpdateTask task;
|
||||
workers()->run_task(&task);
|
||||
}
|
||||
}
|
||||
|
||||
void ShenandoahHeap::op_reset() {
|
||||
reset_mark_bitmap();
|
||||
}
|
||||
@ -2559,6 +2590,22 @@ void ShenandoahHeap::entry_updaterefs() {
|
||||
try_inject_alloc_failure();
|
||||
op_updaterefs();
|
||||
}
|
||||
|
||||
void ShenandoahHeap::entry_roots() {
|
||||
ShenandoahGCPhase phase(ShenandoahPhaseTimings::conc_roots);
|
||||
|
||||
static const char* msg = "Concurrent roots processing";
|
||||
GCTraceTime(Info, gc) time(msg, NULL, GCCause::_no_gc, true);
|
||||
EventMark em("%s", msg);
|
||||
|
||||
ShenandoahWorkerScope scope(workers(),
|
||||
ShenandoahWorkerPolicy::calc_workers_for_conc_root_processing(),
|
||||
"concurrent root processing");
|
||||
|
||||
try_inject_alloc_failure();
|
||||
op_roots();
|
||||
}
|
||||
|
||||
void ShenandoahHeap::entry_cleanup() {
|
||||
ShenandoahGCPhase phase(ShenandoahPhaseTimings::conc_cleanup);
|
||||
|
||||
|
@ -391,6 +391,7 @@ public:
|
||||
void entry_reset();
|
||||
void entry_mark();
|
||||
void entry_preclean();
|
||||
void entry_roots();
|
||||
void entry_cleanup();
|
||||
void entry_evac();
|
||||
void entry_updaterefs();
|
||||
@ -414,6 +415,7 @@ private:
|
||||
void op_reset();
|
||||
void op_mark();
|
||||
void op_preclean();
|
||||
void op_roots();
|
||||
void op_cleanup();
|
||||
void op_conc_evac();
|
||||
void op_stw_evac();
|
||||
|
@ -306,6 +306,7 @@ class outputStream;
|
||||
f(conc_mark, "Concurrent Marking") \
|
||||
f(conc_termination, " Termination") \
|
||||
f(conc_preclean, "Concurrent Precleaning") \
|
||||
f(conc_roots, "Concurrent Roots") \
|
||||
f(conc_evac, "Concurrent Evacuation") \
|
||||
f(conc_update_refs, "Concurrent Update Refs") \
|
||||
f(conc_cleanup, "Concurrent Cleanup") \
|
||||
|
@ -71,10 +71,6 @@ void ShenandoahSerialRoots::oops_do(OopClosure* cl, uint worker_id) {
|
||||
_jvmti_root.oops_do(cl, worker_id);
|
||||
}
|
||||
|
||||
ShenandoahJNIHandleRoots::ShenandoahJNIHandleRoots() :
|
||||
ShenandoahSerialRoot(&JNIHandles::oops_do, ShenandoahPhaseTimings::JNIRoots) {
|
||||
}
|
||||
|
||||
ShenandoahThreadRoots::ShenandoahThreadRoots(bool is_par) : _is_par(is_par) {
|
||||
Threads::change_thread_claim_token();
|
||||
}
|
||||
@ -148,21 +144,22 @@ ShenandoahRootProcessor::~ShenandoahRootProcessor() {
|
||||
_heap->phase_timings()->record_workers_end(_phase);
|
||||
}
|
||||
|
||||
ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
|
||||
ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool include_concurrent_roots) :
|
||||
ShenandoahRootProcessor(phase),
|
||||
_thread_roots(n_workers > 1),
|
||||
_weak_roots(n_workers) {
|
||||
_weak_roots(n_workers),
|
||||
_include_concurrent_roots(include_concurrent_roots) {
|
||||
}
|
||||
|
||||
void ShenandoahRootEvacuator::roots_do(uint worker_id, OopClosure* oops) {
|
||||
MarkingCodeBlobClosure blobsCl(oops, CodeBlobToOopClosure::FixRelocations);
|
||||
CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong);
|
||||
CLDToOopClosure* weak_clds = ShenandoahHeap::heap()->unload_classes() ? NULL : &clds;
|
||||
|
||||
AlwaysTrueClosure always_true;
|
||||
|
||||
_serial_roots.oops_do(oops, worker_id);
|
||||
_jni_roots.oops_do(oops, worker_id);
|
||||
if (_include_concurrent_roots) {
|
||||
_jni_roots.oops_do<OopClosure>(oops, worker_id);
|
||||
}
|
||||
|
||||
_thread_roots.oops_do(oops, NULL, worker_id);
|
||||
_cld_roots.clds_do(&clds, &clds, worker_id);
|
||||
|
@ -61,9 +61,15 @@ public:
|
||||
void oops_do(OopClosure* cl, uint worker_id);
|
||||
};
|
||||
|
||||
class ShenandoahJNIHandleRoots : public ShenandoahSerialRoot {
|
||||
template <bool CONCURRENT>
|
||||
class ShenandoahJNIHandleRoots {
|
||||
private:
|
||||
OopStorage::ParState<CONCURRENT, false /* is_const */> _itr;
|
||||
public:
|
||||
ShenandoahJNIHandleRoots();
|
||||
|
||||
template <typename T>
|
||||
void oops_do(T* cl, uint worker_id = 0);
|
||||
};
|
||||
|
||||
class ShenandoahThreadRoots {
|
||||
@ -129,11 +135,11 @@ public:
|
||||
template <typename ITR>
|
||||
class ShenandoahRootScanner : public ShenandoahRootProcessor {
|
||||
private:
|
||||
ShenandoahSerialRoots _serial_roots;
|
||||
ShenandoahJNIHandleRoots _jni_roots;
|
||||
ShenandoahClassLoaderDataRoots _cld_roots;
|
||||
ShenandoahThreadRoots _thread_roots;
|
||||
ShenandoahCodeCacheRoots<ITR> _code_roots;
|
||||
ShenandoahSerialRoots _serial_roots;
|
||||
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
|
||||
ShenandoahClassLoaderDataRoots _cld_roots;
|
||||
ShenandoahThreadRoots _thread_roots;
|
||||
ShenandoahCodeCacheRoots<ITR> _code_roots;
|
||||
public:
|
||||
ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase);
|
||||
|
||||
@ -157,16 +163,17 @@ typedef ShenandoahRootScanner<ShenandoahCsetCodeRootsIterator> ShenandoahCSetRoo
|
||||
// Evacuate all roots at a safepoint
|
||||
class ShenandoahRootEvacuator : public ShenandoahRootProcessor {
|
||||
private:
|
||||
ShenandoahSerialRoots _serial_roots;
|
||||
ShenandoahJNIHandleRoots _jni_roots;
|
||||
ShenandoahClassLoaderDataRoots _cld_roots;
|
||||
ShenandoahThreadRoots _thread_roots;
|
||||
ShenandoahWeakRoots _weak_roots;
|
||||
ShenandoahStringDedupRoots _dedup_roots;
|
||||
ShenandoahSerialRoots _serial_roots;
|
||||
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
|
||||
ShenandoahClassLoaderDataRoots _cld_roots;
|
||||
ShenandoahThreadRoots _thread_roots;
|
||||
ShenandoahWeakRoots _weak_roots;
|
||||
ShenandoahStringDedupRoots _dedup_roots;
|
||||
ShenandoahCodeCacheRoots<ShenandoahCsetCodeRootsIterator> _code_roots;
|
||||
bool _include_concurrent_roots;
|
||||
|
||||
public:
|
||||
ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase);
|
||||
ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool include_concurrent_roots);
|
||||
|
||||
void roots_do(uint worker_id, OopClosure* oops);
|
||||
};
|
||||
@ -174,14 +181,14 @@ public:
|
||||
// Update all roots at a safepoint
|
||||
class ShenandoahRootUpdater : public ShenandoahRootProcessor {
|
||||
private:
|
||||
ShenandoahSerialRoots _serial_roots;
|
||||
ShenandoahJNIHandleRoots _jni_roots;
|
||||
ShenandoahClassLoaderDataRoots _cld_roots;
|
||||
ShenandoahThreadRoots _thread_roots;
|
||||
ShenandoahWeakRoots _weak_roots;
|
||||
ShenandoahStringDedupRoots _dedup_roots;
|
||||
ShenandoahSerialRoots _serial_roots;
|
||||
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
|
||||
ShenandoahClassLoaderDataRoots _cld_roots;
|
||||
ShenandoahThreadRoots _thread_roots;
|
||||
ShenandoahWeakRoots _weak_roots;
|
||||
ShenandoahStringDedupRoots _dedup_roots;
|
||||
ShenandoahCodeCacheRoots<ShenandoahCsetCodeRootsIterator> _code_roots;
|
||||
const bool _update_code_cache;
|
||||
const bool _update_code_cache;
|
||||
|
||||
public:
|
||||
ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool update_code_cache);
|
||||
@ -193,12 +200,12 @@ public:
|
||||
// Adjuster all roots at a safepoint during full gc
|
||||
class ShenandoahRootAdjuster : public ShenandoahRootProcessor {
|
||||
private:
|
||||
ShenandoahSerialRoots _serial_roots;
|
||||
ShenandoahJNIHandleRoots _jni_roots;
|
||||
ShenandoahClassLoaderDataRoots _cld_roots;
|
||||
ShenandoahThreadRoots _thread_roots;
|
||||
ShenandoahWeakRoots _weak_roots;
|
||||
ShenandoahStringDedupRoots _dedup_roots;
|
||||
ShenandoahSerialRoots _serial_roots;
|
||||
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
|
||||
ShenandoahClassLoaderDataRoots _cld_roots;
|
||||
ShenandoahThreadRoots _thread_roots;
|
||||
ShenandoahWeakRoots _weak_roots;
|
||||
ShenandoahStringDedupRoots _dedup_roots;
|
||||
ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator> _code_roots;
|
||||
|
||||
public:
|
||||
|
@ -24,12 +24,31 @@
|
||||
#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP
|
||||
#define SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP
|
||||
|
||||
#include "classfile/classLoaderDataGraph.hpp"
|
||||
#include "gc/shared/oopStorageParState.inline.hpp"
|
||||
#include "gc/shenandoah/shenandoahHeuristics.hpp"
|
||||
#include "gc/shenandoah/shenandoahRootProcessor.hpp"
|
||||
#include "gc/shenandoah/shenandoahTimingTracker.hpp"
|
||||
#include "gc/shenandoah/shenandoahUtils.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
|
||||
template <bool CONCURRENT>
|
||||
ShenandoahJNIHandleRoots<CONCURRENT>::ShenandoahJNIHandleRoots() :
|
||||
_itr(JNIHandles::global_handles()) {
|
||||
}
|
||||
|
||||
template <bool CONCURRENT>
|
||||
template <typename T>
|
||||
void ShenandoahJNIHandleRoots<CONCURRENT>::oops_do(T* cl, uint worker_id) {
|
||||
if (CONCURRENT) {
|
||||
_itr.oops_do(cl);
|
||||
} else {
|
||||
ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
|
||||
ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JNIRoots, worker_id);
|
||||
_itr.oops_do(cl);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename IsAlive, typename KeepAlive>
|
||||
void ShenandoahWeakRoots::oops_do(IsAlive* is_alive, KeepAlive* keep_alive, uint worker_id) {
|
||||
_task.work<IsAlive, KeepAlive>(worker_id, is_alive, keep_alive);
|
||||
|
@ -30,6 +30,7 @@
|
||||
uint ShenandoahWorkerPolicy::_prev_par_marking = 0;
|
||||
uint ShenandoahWorkerPolicy::_prev_conc_marking = 0;
|
||||
uint ShenandoahWorkerPolicy::_prev_conc_evac = 0;
|
||||
uint ShenandoahWorkerPolicy::_prev_conc_root_proc = 0;
|
||||
uint ShenandoahWorkerPolicy::_prev_fullgc = 0;
|
||||
uint ShenandoahWorkerPolicy::_prev_degengc = 0;
|
||||
uint ShenandoahWorkerPolicy::_prev_stw_traversal = 0;
|
||||
@ -63,6 +64,16 @@ uint ShenandoahWorkerPolicy::calc_workers_for_final_marking() {
|
||||
return _prev_par_marking;
|
||||
}
|
||||
|
||||
// Calculate workers for concurrent root processing
|
||||
uint ShenandoahWorkerPolicy::calc_workers_for_conc_root_processing() {
|
||||
uint active_workers = (_prev_conc_root_proc == 0) ? ConcGCThreads : _prev_conc_root_proc;
|
||||
_prev_conc_root_proc =
|
||||
WorkerPolicy::calc_active_conc_workers(ConcGCThreads,
|
||||
active_workers,
|
||||
Threads::number_of_non_daemon_threads());
|
||||
return _prev_conc_root_proc;
|
||||
}
|
||||
|
||||
// Calculate workers for concurrent evacuation (concurrent GC)
|
||||
uint ShenandoahWorkerPolicy::calc_workers_for_conc_evac() {
|
||||
uint active_workers = (_prev_conc_evac == 0) ? ConcGCThreads : _prev_conc_evac;
|
||||
|
@ -30,6 +30,7 @@ class ShenandoahWorkerPolicy : AllStatic {
|
||||
private:
|
||||
static uint _prev_par_marking;
|
||||
static uint _prev_conc_marking;
|
||||
static uint _prev_conc_root_proc;
|
||||
static uint _prev_conc_evac;
|
||||
static uint _prev_fullgc;
|
||||
static uint _prev_degengc;
|
||||
@ -50,6 +51,9 @@ public:
|
||||
// Calculate the number of workers for final marking
|
||||
static uint calc_workers_for_final_marking();
|
||||
|
||||
// Calculate workers for concurrent root processing
|
||||
static uint calc_workers_for_conc_root_processing();
|
||||
|
||||
// Calculate workers for concurrent evacuation (concurrent GC)
|
||||
static uint calc_workers_for_conc_evac();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user