8226310: Shenandoah: Concurrent evacuation of CLDG

Reviewed-by: rkennke
This commit is contained in:
Zhengyu Gu 2019-06-24 14:13:49 -04:00
parent cfb99c9382
commit 13d3c63405
4 changed files with 42 additions and 17 deletions

View file

@ -1524,6 +1524,7 @@ void ShenandoahHeap::op_final_mark() {
if (ShenandoahVerify) { if (ShenandoahVerify) {
if (ShenandoahConcurrentRoots::should_do_concurrent_roots()) { if (ShenandoahConcurrentRoots::should_do_concurrent_roots()) {
ShenandoahRootVerifier::RootTypes types = ShenandoahRootVerifier::combine(ShenandoahRootVerifier::JNIHandleRoots, ShenandoahRootVerifier::WeakRoots); ShenandoahRootVerifier::RootTypes types = ShenandoahRootVerifier::combine(ShenandoahRootVerifier::JNIHandleRoots, ShenandoahRootVerifier::WeakRoots);
types = ShenandoahRootVerifier::combine(types, ShenandoahRootVerifier::CLDGRoots);
verifier()->verify_roots_no_forwarded_except(types); verifier()->verify_roots_no_forwarded_except(types);
} else { } else {
verifier()->verify_roots_no_forwarded(); verifier()->verify_roots_no_forwarded();
@ -1592,6 +1593,7 @@ class ShenandoahConcurrentRootsEvacUpdateTask : public AbstractGangTask {
private: private:
ShenandoahJNIHandleRoots<true /*concurrent*/> _jni_roots; ShenandoahJNIHandleRoots<true /*concurrent*/> _jni_roots;
ShenandoahWeakRoots<true /*concurrent*/> _weak_roots; ShenandoahWeakRoots<true /*concurrent*/> _weak_roots;
ShenandoahClassLoaderDataRoots<true /*concurrent*/, false /*single threaded*/> _cld_roots;
public: public:
ShenandoahConcurrentRootsEvacUpdateTask() : ShenandoahConcurrentRootsEvacUpdateTask() :
@ -1601,8 +1603,10 @@ public:
void work(uint worker_id) { void work(uint worker_id) {
ShenandoahEvacOOMScope oom; ShenandoahEvacOOMScope oom;
ShenandoahEvacuateUpdateRootsClosure cl; ShenandoahEvacuateUpdateRootsClosure cl;
CLDToOopClosure clds(&cl, ClassLoaderData::_claim_strong);
_jni_roots.oops_do<ShenandoahEvacuateUpdateRootsClosure>(&cl); _jni_roots.oops_do<ShenandoahEvacuateUpdateRootsClosure>(&cl);
_cld_roots.cld_do(&clds);
_weak_roots.oops_do<ShenandoahEvacuateUpdateRootsClosure>(&cl); _weak_roots.oops_do<ShenandoahEvacuateUpdateRootsClosure>(&cl);
} }
}; };

View file

@ -162,18 +162,18 @@ ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers, ShenandoahPhase
void ShenandoahRootEvacuator::roots_do(uint worker_id, OopClosure* oops) { void ShenandoahRootEvacuator::roots_do(uint worker_id, OopClosure* oops) {
MarkingCodeBlobClosure blobsCl(oops, CodeBlobToOopClosure::FixRelocations); MarkingCodeBlobClosure blobsCl(oops, CodeBlobToOopClosure::FixRelocations);
CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong);
AlwaysTrueClosure always_true; AlwaysTrueClosure always_true;
_serial_roots.oops_do(oops, worker_id); _serial_roots.oops_do(oops, worker_id);
_serial_weak_roots.weak_oops_do(oops, worker_id); _serial_weak_roots.weak_oops_do(oops, worker_id);
if (_include_concurrent_roots) { if (_include_concurrent_roots) {
CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong);
_jni_roots.oops_do<OopClosure>(oops, worker_id); _jni_roots.oops_do<OopClosure>(oops, worker_id);
_cld_roots.cld_do(&clds, worker_id);
_weak_roots.oops_do<OopClosure>(oops, worker_id); _weak_roots.oops_do<OopClosure>(oops, worker_id);
} }
_thread_roots.oops_do(oops, NULL, worker_id); _thread_roots.oops_do(oops, NULL, worker_id);
_cld_roots.cld_do(&clds, worker_id);
_code_roots.code_blobs_do(&blobsCl, worker_id); _code_roots.code_blobs_do(&blobsCl, worker_id);
_dedup_roots.oops_do(&always_true, oops, worker_id); _dedup_roots.oops_do(&always_true, oops, worker_id);

View file

@ -190,13 +190,14 @@ public:
void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id); void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id);
}; };
template <bool SINGLE_THREADED> template <bool CONCURRENT, bool SINGLE_THREADED>
class ShenandoahClassLoaderDataRoots { class ShenandoahClassLoaderDataRoots {
public: public:
ShenandoahClassLoaderDataRoots(); ShenandoahClassLoaderDataRoots();
~ShenandoahClassLoaderDataRoots();
void always_strong_cld_do(CLDClosure* clds, uint worker_id); void always_strong_cld_do(CLDClosure* clds, uint worker_id = 0);
void cld_do(CLDClosure* clds, uint worker_id); void cld_do(CLDClosure* clds, uint worker_id = 0);
}; };
class ShenandoahRootProcessor : public StackObj { class ShenandoahRootProcessor : public StackObj {
@ -217,7 +218,8 @@ private:
ShenandoahThreadRoots _thread_roots; ShenandoahThreadRoots _thread_roots;
ShenandoahCodeCacheRoots<ITR> _code_roots; ShenandoahCodeCacheRoots<ITR> _code_roots;
ShenandoahJNIHandleRoots<false /*concurrent*/ > _jni_roots; ShenandoahJNIHandleRoots<false /*concurrent*/ > _jni_roots;
ShenandoahClassLoaderDataRoots<false /*single threaded*/> _cld_roots; ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
_cld_roots;
public: public:
ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase); ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase);
@ -242,7 +244,8 @@ private:
ShenandoahSerialRoots _serial_roots; ShenandoahSerialRoots _serial_roots;
ShenandoahThreadRoots _thread_roots; ShenandoahThreadRoots _thread_roots;
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots; ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
ShenandoahClassLoaderDataRoots<true /*single threaded*/> _cld_roots; ShenandoahClassLoaderDataRoots<false /*concurrent*/, true /*single threaded*/>
_cld_roots;
ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator> _code_roots; ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator> _code_roots;
public: public:
@ -257,7 +260,8 @@ class ShenandoahRootEvacuator : public ShenandoahRootProcessor {
private: private:
ShenandoahSerialRoots _serial_roots; ShenandoahSerialRoots _serial_roots;
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots; ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
ShenandoahClassLoaderDataRoots<false /*single threaded*/> _cld_roots; ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
_cld_roots;
ShenandoahThreadRoots _thread_roots; ShenandoahThreadRoots _thread_roots;
ShenandoahSerialWeakRoots _serial_weak_roots; ShenandoahSerialWeakRoots _serial_weak_roots;
ShenandoahWeakRoots<false /*concurrent*/> _weak_roots; ShenandoahWeakRoots<false /*concurrent*/> _weak_roots;
@ -276,7 +280,8 @@ class ShenandoahRootUpdater : public ShenandoahRootProcessor {
private: private:
ShenandoahSerialRoots _serial_roots; ShenandoahSerialRoots _serial_roots;
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots; ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
ShenandoahClassLoaderDataRoots<false /*single threaded*/> _cld_roots; ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
_cld_roots;
ShenandoahThreadRoots _thread_roots; ShenandoahThreadRoots _thread_roots;
ShenandoahSerialWeakRoots _serial_weak_roots; ShenandoahSerialWeakRoots _serial_weak_roots;
ShenandoahWeakRoots<false /*concurrent*/> _weak_roots; ShenandoahWeakRoots<false /*concurrent*/> _weak_roots;
@ -296,7 +301,8 @@ class ShenandoahRootAdjuster : public ShenandoahRootProcessor {
private: private:
ShenandoahSerialRoots _serial_roots; ShenandoahSerialRoots _serial_roots;
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots; ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
ShenandoahClassLoaderDataRoots<false /*single threaded*/> _cld_roots; ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
_cld_roots;
ShenandoahThreadRoots _thread_roots; ShenandoahThreadRoots _thread_roots;
ShenandoahSerialWeakRoots _serial_weak_roots; ShenandoahSerialWeakRoots _serial_weak_roots;
ShenandoahWeakRoots<false /*concurrent*/> _weak_roots; ShenandoahWeakRoots<false /*concurrent*/> _weak_roots;

View file

@ -119,19 +119,32 @@ void ShenandoahJNIHandleRoots<CONCURRENT>::oops_do(T* cl, uint worker_id) {
} }
} }
template <bool SINGLE_THREADED> template <bool CONCURRENT, bool SINGLE_THREADED>
ShenandoahClassLoaderDataRoots<SINGLE_THREADED>::ShenandoahClassLoaderDataRoots() { ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::ShenandoahClassLoaderDataRoots() {
if (!SINGLE_THREADED) { if (!SINGLE_THREADED) {
ClassLoaderDataGraph::clear_claimed_marks(); ClassLoaderDataGraph::clear_claimed_marks();
} }
if (CONCURRENT) {
ClassLoaderDataGraph_lock->lock();
}
} }
template <bool SINGLE_THREADED> template <bool CONCURRENT, bool SINGLE_THREADED>
void ShenandoahClassLoaderDataRoots<SINGLE_THREADED>::always_strong_cld_do(CLDClosure* clds, uint worker_id) { 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) { if (SINGLE_THREADED) {
assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); 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"); assert(Thread::current()->is_VM_thread(), "Single threaded CLDG iteration can only be done by VM thread");
ClassLoaderDataGraph::always_strong_cld_do(clds); ClassLoaderDataGraph::always_strong_cld_do(clds);
} else if (CONCURRENT) {
ClassLoaderDataGraph::always_strong_cld_do(clds);
} else { } else {
ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id); ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id);
@ -139,13 +152,15 @@ void ShenandoahClassLoaderDataRoots<SINGLE_THREADED>::always_strong_cld_do(CLDCl
} }
} }
template <bool SINGLE_THREADED> template <bool CONCURRENT, bool SINGLE_THREADED>
void ShenandoahClassLoaderDataRoots<SINGLE_THREADED>::cld_do(CLDClosure* clds, uint worker_id) { void ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::cld_do(CLDClosure* clds, uint worker_id) {
if (SINGLE_THREADED) { if (SINGLE_THREADED) {
assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); 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"); assert(Thread::current()->is_VM_thread(), "Single threaded CLDG iteration can only be done by VM thread");
ClassLoaderDataGraph::cld_do(clds); ClassLoaderDataGraph::cld_do(clds);
} else { } else if (CONCURRENT) {
ClassLoaderDataGraph::cld_do(clds);
} else {
ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id); ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id);
ClassLoaderDataGraph::cld_do(clds); ClassLoaderDataGraph::cld_do(clds);