--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp Thu Oct 17 20:27:44 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp Thu Oct 17 20:53:35 2019 +0100
@@ -24,15 +24,148 @@
#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP
#define SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP
+#include "classfile/classLoaderDataGraph.hpp"
+#include "classfile/stringTable.hpp"
+#include "classfile/systemDictionary.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"
+#include "prims/resolvedMethodTable.hpp"
+#include "runtime/safepoint.hpp"
-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);
+template <bool CONCURRENT>
+inline ShenandoahVMRoot<CONCURRENT>::ShenandoahVMRoot(OopStorage* storage, ShenandoahPhaseTimings::GCParPhases phase) :
+ _itr(storage), _phase(phase) {
+}
+
+template <bool CONCURRENT>
+template <typename Closure>
+inline void ShenandoahVMRoot<CONCURRENT>::oops_do(Closure* cl, uint worker_id) {
+ if (CONCURRENT) {
+ _itr.oops_do(cl);
+ } else {
+ ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
+ ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id);
+ _itr.oops_do(cl);
+ }
+}
+
+template <bool CONCURRENT>
+inline ShenandoahWeakRoot<CONCURRENT>::ShenandoahWeakRoot(OopStorage* storage, ShenandoahPhaseTimings::GCParPhases phase) :
+ ShenandoahVMRoot<CONCURRENT>(storage, phase) {
+}
+
+inline ShenandoahWeakRoot<false>::ShenandoahWeakRoot(OopStorage* storage, ShenandoahPhaseTimings::GCParPhases phase) :
+ _itr(storage), _phase(phase) {
+}
+
+template <typename IsAliveClosure, typename KeepAliveClosure>
+void ShenandoahWeakRoot<false /* concurrent */>::weak_oops_do(IsAliveClosure* is_alive, KeepAliveClosure* keep_alive, uint worker_id) {
+ ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
+ ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id);
+ _itr.weak_oops_do(is_alive, keep_alive);
+}
+
+template <bool CONCURRENT>
+ShenandoahWeakRoots<CONCURRENT>::ShenandoahWeakRoots() :
+ _jni_roots(OopStorageSet::jni_weak(), ShenandoahPhaseTimings::JNIWeakRoots),
+ _string_table_roots(OopStorageSet::string_table_weak(), ShenandoahPhaseTimings::StringTableRoots),
+ _resolved_method_table_roots(OopStorageSet::resolved_method_table_weak(), ShenandoahPhaseTimings::ResolvedMethodTableRoots),
+ _vm_roots(OopStorageSet::vm_weak(), ShenandoahPhaseTimings::VMWeakRoots) {
+}
+
+template <bool CONCURRENT>
+template <typename Closure>
+void ShenandoahWeakRoots<CONCURRENT>::oops_do(Closure* cl, uint worker_id) {
+ _jni_roots.oops_do(cl, worker_id);
+ _string_table_roots.oops_do(cl, worker_id);
+ _resolved_method_table_roots.oops_do(cl, worker_id);
+ _vm_roots.oops_do(cl, worker_id);
+}
+
+inline ShenandoahWeakRoots<false /* concurrent */>::ShenandoahWeakRoots() :
+ _jni_roots(OopStorageSet::jni_weak(), ShenandoahPhaseTimings::JNIWeakRoots),
+ _string_table_roots(OopStorageSet::string_table_weak(), ShenandoahPhaseTimings::StringTableRoots),
+ _resolved_method_table_roots(OopStorageSet::resolved_method_table_weak(), ShenandoahPhaseTimings::ResolvedMethodTableRoots),
+ _vm_roots(OopStorageSet::vm_weak(), ShenandoahPhaseTimings::VMWeakRoots) {
+}
+
+template <typename IsAliveClosure, typename KeepAliveClosure>
+void ShenandoahWeakRoots<false /* concurrent*/>::weak_oops_do(IsAliveClosure* is_alive, KeepAliveClosure* keep_alive, uint worker_id) {
+ _jni_roots.weak_oops_do(is_alive, keep_alive, worker_id);
+ _string_table_roots.weak_oops_do(is_alive, keep_alive, worker_id);
+ _resolved_method_table_roots.weak_oops_do(is_alive, keep_alive, worker_id);
+ _vm_roots.weak_oops_do(is_alive, keep_alive, worker_id);
+}
+
+template <typename Closure>
+void ShenandoahWeakRoots<false /* concurrent */>::oops_do(Closure* cl, uint worker_id) {
+ AlwaysTrueClosure always_true;
+ weak_oops_do<AlwaysTrueClosure, Closure>(&always_true, cl, worker_id);
+}
+
+template <bool CONCURRENT>
+ShenandoahVMRoots<CONCURRENT>::ShenandoahVMRoots() :
+ _jni_handle_roots(OopStorageSet::jni_global(), ShenandoahPhaseTimings::JNIRoots),
+ _vm_global_roots(OopStorageSet::vm_global(), ShenandoahPhaseTimings::VMGlobalRoots) {
+}
+
+template <bool CONCURRENT>
+template <typename T>
+void ShenandoahVMRoots<CONCURRENT>::oops_do(T* cl, uint worker_id) {
+ _jni_handle_roots.oops_do(cl, worker_id);
+ _vm_global_roots.oops_do(cl, worker_id);
+}
+
+template <bool CONCURRENT, bool SINGLE_THREADED>
+ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::ShenandoahClassLoaderDataRoots() {
+ if (!SINGLE_THREADED) {
+ ClassLoaderDataGraph::clear_claimed_marks();
+ }
+ if (CONCURRENT) {
+ ClassLoaderDataGraph_lock->lock();
+ }
+}
+
+template <bool CONCURRENT, bool SINGLE_THREADED>
+ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::~ShenandoahClassLoaderDataRoots() {
+ if (CONCURRENT) {
+ ClassLoaderDataGraph_lock->unlock();
+ }
+}
+
+
+template <bool CONCURRENT, bool SINGLE_THREADED>
+void ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::always_strong_cld_do(CLDClosure* clds, uint worker_id) {
+ if (SINGLE_THREADED) {
+ assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
+ assert(Thread::current()->is_VM_thread(), "Single threaded CLDG iteration can only be done by VM thread");
+ ClassLoaderDataGraph::always_strong_cld_do(clds);
+ } else if (CONCURRENT) {
+ ClassLoaderDataGraph::always_strong_cld_do(clds);
+ } else {
+ ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
+ ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id);
+ ClassLoaderDataGraph::always_strong_cld_do(clds);
+ }
+}
+
+template <bool CONCURRENT, bool SINGLE_THREADED>
+void ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::cld_do(CLDClosure* clds, uint worker_id) {
+ if (SINGLE_THREADED) {
+ assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
+ assert(Thread::current()->is_VM_thread(), "Single threaded CLDG iteration can only be done by VM thread");
+ ClassLoaderDataGraph::cld_do(clds);
+ } else if (CONCURRENT) {
+ ClassLoaderDataGraph::cld_do(clds);
+ } else {
+ ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
+ ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id);
+ ClassLoaderDataGraph::cld_do(clds);
+ }
}
template <typename ITR>
@@ -93,13 +226,20 @@
void ShenandoahRootScanner<ITR>::roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure *tc) {
assert(!ShenandoahSafepoint::is_at_shenandoah_safepoint() ||
!ShenandoahHeap::heap()->unload_classes() ||
- ShenandoahHeap::heap()->heuristics()->can_do_traversal_gc(),
+ ShenandoahHeap::heap()->is_traversal_mode(),
"Expect class unloading or traversal when Shenandoah cycle is running");
ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc);
ResourceMark rm;
_serial_roots.oops_do(oops, worker_id);
- _cld_roots.clds_do(clds, clds, worker_id);
+ _vm_roots.oops_do(oops, worker_id);
+
+ if (clds != NULL) {
+ _cld_roots.cld_do(clds, worker_id);
+ } else {
+ assert(ShenandoahHeap::heap()->is_concurrent_traversal_in_progress(), "Only possible with traversal GC");
+ }
+
_thread_roots.threads_do(&tc_cl, worker_id);
// With ShenandoahConcurrentScanCodeRoots, we avoid scanning the entire code cache here,
@@ -117,7 +257,8 @@
ResourceMark rm;
_serial_roots.oops_do(oops, worker_id);
- _cld_roots.clds_do(clds, NULL, worker_id);
+ _vm_roots.oops_do(oops, worker_id);
+ _cld_roots.always_strong_cld_do(clds, worker_id);
_thread_roots.threads_do(&tc_cl, worker_id);
}
@@ -125,18 +266,16 @@
void ShenandoahRootUpdater::roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive) {
CodeBlobToOopClosure update_blobs(keep_alive, CodeBlobToOopClosure::FixRelocations);
CLDToOopClosure clds(keep_alive, ClassLoaderData::_claim_strong);
- CLDToOopClosure* weak_clds = ShenandoahHeap::heap()->unload_classes() ? NULL : &clds;
_serial_roots.oops_do(keep_alive, worker_id);
+ _vm_roots.oops_do(keep_alive, worker_id);
_thread_roots.oops_do(keep_alive, NULL, worker_id);
- _cld_roots.clds_do(&clds, weak_clds, worker_id);
+ _cld_roots.cld_do(&clds, worker_id);
+ _code_roots.code_blobs_do(&update_blobs, worker_id);
- if(_update_code_cache) {
- _code_roots.code_blobs_do(&update_blobs, worker_id);
- }
-
- _weak_roots.oops_do<IsAlive, KeepAlive>(is_alive, keep_alive, worker_id);
+ _serial_weak_roots.weak_oops_do(is_alive, keep_alive, worker_id);
+ _weak_roots.weak_oops_do(is_alive, keep_alive, worker_id);
_dedup_roots.oops_do(is_alive, keep_alive, worker_id);
}