8224210: Shenandoah: Refactor ShenandoahRootScanner to support scanning CSet codecache roots

Reviewed-by: shade
This commit is contained in:
Zhengyu Gu 2019-05-20 09:42:37 -04:00
parent a0a09f03e4
commit 18a59944ef
6 changed files with 86 additions and 78 deletions

@ -81,10 +81,10 @@ ShenandoahMarkRefsSuperClosure::ShenandoahMarkRefsSuperClosure(ShenandoahObjToSc
template<UpdateRefsMode UPDATE_REFS>
class ShenandoahInitMarkRootsTask : public AbstractGangTask {
private:
ShenandoahRootScanner* _rp;
ShenandoahAllRootScanner* _rp;
bool _process_refs;
public:
ShenandoahInitMarkRootsTask(ShenandoahRootScanner* rp, bool process_refs) :
ShenandoahInitMarkRootsTask(ShenandoahAllRootScanner* rp, bool process_refs) :
AbstractGangTask("Shenandoah init mark roots task"),
_rp(rp),
_process_refs(process_refs) {
@ -251,7 +251,7 @@ void ShenandoahConcurrentMark::mark_roots(ShenandoahPhaseTimings::Phase root_pha
assert(nworkers <= task_queues()->size(), "Just check");
ShenandoahRootScanner root_proc(nworkers, root_phase);
ShenandoahAllRootScanner root_proc(nworkers, root_phase);
TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
task_queues()->reserve(nworkers);

@ -1326,7 +1326,7 @@ void ShenandoahHeap::object_iterate(ObjectClosure* cl) {
Stack<oop,mtGC> oop_stack;
// First, we process all GC roots. This populates the work stack with initial objects.
ShenandoahRootScanner rp(1, ShenandoahPhaseTimings::_num_phases);
ShenandoahAllRootScanner rp(1, ShenandoahPhaseTimings::_num_phases);
ObjectIterateScanRootClosure oops(&_aux_bit_map, &oop_stack);
rp.roots_do(0, &oops);

@ -135,23 +135,6 @@ void ShenandoahClassLoaderDataRoots::clds_do(CLDClosure* strong_clds, CLDClosure
ClassLoaderDataGraph::roots_cld_do(strong_clds, weak_clds);
}
class ShenandoahParallelOopsDoThreadClosure : public ThreadClosure {
private:
OopClosure* _f;
CodeBlobClosure* _cf;
ThreadClosure* _thread_cl;
public:
ShenandoahParallelOopsDoThreadClosure(OopClosure* f, CodeBlobClosure* cf, ThreadClosure* thread_cl) :
_f(f), _cf(cf), _thread_cl(thread_cl) {}
void do_thread(Thread* t) {
if (_thread_cl != NULL) {
_thread_cl->do_thread(t);
}
t->oops_do(_f, _cf);
}
};
ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase) :
_heap(ShenandoahHeap::heap()),
_phase(phase) {
@ -164,50 +147,6 @@ ShenandoahRootProcessor::~ShenandoahRootProcessor() {
_heap->phase_timings()->record_workers_end(_phase);
}
ShenandoahRootScanner::ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
ShenandoahRootProcessor(phase),
_thread_roots(n_workers > 1) {
}
void ShenandoahRootScanner::roots_do(uint worker_id, OopClosure* oops) {
CLDToOopClosure clds_cl(oops, ClassLoaderData::_claim_strong);
MarkingCodeBlobClosure blobs_cl(oops, !CodeBlobToOopClosure::FixRelocations);
roots_do(worker_id, oops, &clds_cl, &blobs_cl);
}
void ShenandoahRootScanner::strong_roots_do(uint worker_id, OopClosure* oops) {
CLDToOopClosure clds_cl(oops, ClassLoaderData::_claim_strong);
MarkingCodeBlobClosure blobs_cl(oops, !CodeBlobToOopClosure::FixRelocations);
strong_roots_do(worker_id, oops, &clds_cl, &blobs_cl);
}
void ShenandoahRootScanner::roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure *tc) {
assert(!ShenandoahHeap::heap()->unload_classes(), "Should be used during class unloading");
ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc);
ResourceMark rm;
_serial_roots.oops_do(oops, worker_id);
_cld_roots.clds_do(clds, clds, worker_id);
_thread_roots.threads_do(&tc_cl, worker_id);
// With ShenandoahConcurrentScanCodeRoots, we avoid scanning the entire code cache here,
// and instead do that in concurrent phase under the relevant lock. This saves init mark
// pause time.
if (code != NULL && !ShenandoahConcurrentScanCodeRoots) {
_code_roots.code_blobs_do(code, worker_id);
}
}
void ShenandoahRootScanner::strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc) {
assert(ShenandoahHeap::heap()->unload_classes(), "Should be used during class unloading");
ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc);
ResourceMark rm;
_serial_roots.oops_do(oops, worker_id);
_cld_roots.clds_do(clds, NULL, worker_id);
_thread_roots.threads_do(&tc_cl, worker_id);
}
ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
ShenandoahRootProcessor(phase),
_thread_roots(n_workers > 1),

@ -122,12 +122,13 @@ public:
ShenandoahHeap* heap() const { return _heap; }
};
template <typename ITR>
class ShenandoahRootScanner : public ShenandoahRootProcessor {
private:
ShenandoahSerialRoots _serial_roots;
ShenandoahClassLoaderDataRoots _cld_roots;
ShenandoahThreadRoots _thread_roots;
ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator> _code_roots;
ShenandoahCodeCacheRoots<ITR> _code_roots;
public:
ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase);
@ -142,6 +143,9 @@ public:
void roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL);
};
typedef ShenandoahRootScanner<ShenandoahAllCodeRootsIterator> ShenandoahAllRootScanner;
typedef ShenandoahRootScanner<ShenandoahCsetCodeRootsIterator> ShenandoahCSetRootScanner;
// Evacuate all roots at a safepoint
class ShenandoahRootEvacuator : public ShenandoahRootProcessor {
private:

@ -24,6 +24,7 @@
#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP
#define SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP
#include "gc/shenandoah/shenandoahHeuristics.hpp"
#include "gc/shenandoah/shenandoahRootProcessor.hpp"
#include "gc/shenandoah/shenandoahTimingTracker.hpp"
@ -49,6 +50,74 @@ ShenandoahCodeCacheRoots<ITR>::~ShenandoahCodeCacheRoots() {
nmethod::oops_do_marking_epilogue();
}
class ShenandoahParallelOopsDoThreadClosure : public ThreadClosure {
private:
OopClosure* _f;
CodeBlobClosure* _cf;
ThreadClosure* _thread_cl;
public:
ShenandoahParallelOopsDoThreadClosure(OopClosure* f, CodeBlobClosure* cf, ThreadClosure* thread_cl) :
_f(f), _cf(cf), _thread_cl(thread_cl) {}
void do_thread(Thread* t) {
if (_thread_cl != NULL) {
_thread_cl->do_thread(t);
}
t->oops_do(_f, _cf);
}
};
template <typename ITR>
ShenandoahRootScanner<ITR>::ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
ShenandoahRootProcessor(phase),
_thread_roots(n_workers > 1) {
}
template <typename ITR>
void ShenandoahRootScanner<ITR>::roots_do(uint worker_id, OopClosure* oops) {
CLDToOopClosure clds_cl(oops, ClassLoaderData::_claim_strong);
MarkingCodeBlobClosure blobs_cl(oops, !CodeBlobToOopClosure::FixRelocations);
roots_do(worker_id, oops, &clds_cl, &blobs_cl);
}
template <typename ITR>
void ShenandoahRootScanner<ITR>::strong_roots_do(uint worker_id, OopClosure* oops) {
CLDToOopClosure clds_cl(oops, ClassLoaderData::_claim_strong);
MarkingCodeBlobClosure blobs_cl(oops, !CodeBlobToOopClosure::FixRelocations);
strong_roots_do(worker_id, oops, &clds_cl, &blobs_cl);
}
template <typename ITR>
void ShenandoahRootScanner<ITR>::roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure *tc) {
assert(!ShenandoahHeap::heap()->unload_classes() ||
ShenandoahHeap::heap()->heuristics()->can_do_traversal_gc(),
"No class unloading or traversal GC");
ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc);
ResourceMark rm;
_serial_roots.oops_do(oops, worker_id);
_cld_roots.clds_do(clds, clds, worker_id);
_thread_roots.threads_do(&tc_cl, worker_id);
// With ShenandoahConcurrentScanCodeRoots, we avoid scanning the entire code cache here,
// and instead do that in concurrent phase under the relevant lock. This saves init mark
// pause time.
if (code != NULL && !ShenandoahConcurrentScanCodeRoots) {
_code_roots.code_blobs_do(code, worker_id);
}
}
template <typename ITR>
void ShenandoahRootScanner<ITR>::strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc) {
assert(ShenandoahHeap::heap()->unload_classes(), "Should be used during class unloading");
ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc);
ResourceMark rm;
_serial_roots.oops_do(oops, worker_id);
_cld_roots.clds_do(clds, NULL, worker_id);
_thread_roots.threads_do(&tc_cl, worker_id);
}
template <typename IsAlive, typename KeepAlive>
void ShenandoahRootUpdater::roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive) {
CodeBlobToOopClosure update_blobs(keep_alive, CodeBlobToOopClosure::FixRelocations);

@ -161,17 +161,16 @@ public:
class ShenandoahInitTraversalCollectionTask : public AbstractGangTask {
private:
ShenandoahRootScanner* _rp;
ShenandoahCSetRootScanner* _rp;
ShenandoahHeap* _heap;
ShenandoahCsetCodeRootsIterator* _cset_coderoots;
ShenandoahStringDedupRoots _dedup_roots;
public:
ShenandoahInitTraversalCollectionTask(ShenandoahRootScanner* rp, ShenandoahCsetCodeRootsIterator* cset_coderoots) :
ShenandoahInitTraversalCollectionTask(ShenandoahCSetRootScanner* rp) :
AbstractGangTask("Shenandoah Init Traversal Collection"),
_rp(rp),
_heap(ShenandoahHeap::heap()),
_cset_coderoots(cset_coderoots) {}
_heap(ShenandoahHeap::heap()) {}
void work(uint worker_id) {
ShenandoahParallelWorkerSession worker_session(worker_id);
@ -231,11 +230,11 @@ public:
class ShenandoahFinalTraversalCollectionTask : public AbstractGangTask {
private:
ShenandoahRootScanner* _rp;
ShenandoahAllRootScanner* _rp;
ShenandoahTaskTerminator* _terminator;
ShenandoahHeap* _heap;
public:
ShenandoahFinalTraversalCollectionTask(ShenandoahRootScanner* rp, ShenandoahTaskTerminator* terminator) :
ShenandoahFinalTraversalCollectionTask(ShenandoahAllRootScanner* rp, ShenandoahTaskTerminator* terminator) :
AbstractGangTask("Shenandoah Final Traversal Collection"),
_rp(rp),
_terminator(terminator),
@ -415,11 +414,8 @@ void ShenandoahTraversalGC::init_traversal_collection() {
{
uint nworkers = _heap->workers()->active_workers();
task_queues()->reserve(nworkers);
ShenandoahRootScanner rp(nworkers, ShenandoahPhaseTimings::init_traversal_gc_work);
ShenandoahCsetCodeRootsIterator cset_coderoots = ShenandoahCodeRoots::cset_iterator();
ShenandoahInitTraversalCollectionTask traversal_task(&rp, &cset_coderoots);
ShenandoahCSetRootScanner rp(nworkers, ShenandoahPhaseTimings::init_traversal_gc_work);
ShenandoahInitTraversalCollectionTask traversal_task(&rp);
_heap->workers()->run_task(&traversal_task);
}
@ -588,7 +584,7 @@ void ShenandoahTraversalGC::final_traversal_collection() {
task_queues()->reserve(nworkers);
// Finish traversal
ShenandoahRootScanner rp(nworkers, ShenandoahPhaseTimings::final_traversal_gc_work);
ShenandoahAllRootScanner rp(nworkers, ShenandoahPhaseTimings::final_traversal_gc_work);
ShenandoahTerminationTracker term(ShenandoahPhaseTimings::final_traversal_gc_termination);
ShenandoahTaskTerminator terminator(nworkers, task_queues());