8255019: Shenandoah: Split STW and concurrent mark into separate classes

Reviewed-by: rkennke, shade
This commit is contained in:
Zhengyu Gu 2021-01-14 17:42:52 +00:00
parent aba3431c4e
commit da6bcf966a
20 changed files with 943 additions and 631 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2020, Red Hat, Inc. All rights reserved.
* Copyright (c) 2019, 2021, Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -116,7 +116,6 @@ void ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::cld_do_impl(Cl
}
}
template <bool CONCURRENT, bool SINGLE_THREADED>
void ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::always_strong_cld_do(CLDClosure* clds, uint worker_id) {
cld_do_impl(&ClassLoaderDataGraph::always_strong_cld_do, clds, worker_id);
@ -144,48 +143,33 @@ public:
}
};
template <bool CONCURRENT>
ShenandoahConcurrentRootScanner<CONCURRENT>::ShenandoahConcurrentRootScanner(uint n_workers,
ShenandoahPhaseTimings::Phase phase) :
_vm_roots(phase),
_cld_roots(phase, n_workers),
_codecache_snapshot(NULL),
_phase(phase) {
if (!ShenandoahHeap::heap()->unload_classes()) {
if (CONCURRENT) {
CodeCache_lock->lock_without_safepoint_check();
} else {
assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
}
_codecache_snapshot = ShenandoahCodeRoots::table()->snapshot_for_iteration();
}
assert(!CONCURRENT || !ShenandoahHeap::heap()->has_forwarded_objects(), "Not expecting forwarded pointers during concurrent marking");
}
// The rationale for selecting the roots to scan is as follows:
// a. With unload_classes = true, we only want to scan the actual strong roots from the
// code cache. This will allow us to identify the dead classes, unload them, *and*
// invalidate the relevant code cache blobs. This could be only done together with
// class unloading.
// b. With unload_classes = false, we have to nominally retain all the references from code
// cache, because there could be the case of embedded class/oop in the generated code,
// which we will never visit during mark. Without code cache invalidation, as in (a),
// we risk executing that code cache blob, and crashing.
template <typename T>
void ShenandoahSTWRootScanner::roots_do(T* oops, uint worker_id) {
MarkingCodeBlobClosure blobs_cl(oops, !CodeBlobToOopClosure::FixRelocations);
CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong);
ResourceMark rm;
template <bool CONCURRENT>
ShenandoahConcurrentRootScanner<CONCURRENT>::~ShenandoahConcurrentRootScanner() {
if (!ShenandoahHeap::heap()->unload_classes()) {
ShenandoahCodeRoots::table()->finish_iteration(_codecache_snapshot);
if (CONCURRENT) {
CodeCache_lock->unlock();
}
}
}
template <bool CONCURRENT>
void ShenandoahConcurrentRootScanner<CONCURRENT>::oops_do(OopClosure* oops, uint worker_id) {
ShenandoahHeap* const heap = ShenandoahHeap::heap();
CLDToOopClosure clds_cl(oops, CONCURRENT ? ClassLoaderData::_claim_strong : ClassLoaderData::_claim_none);
_vm_roots.oops_do(oops, worker_id);
if (!heap->unload_classes()) {
_cld_roots.cld_do(&clds_cl, worker_id);
ShenandoahWorkerTimingsTracker timer(_phase, ShenandoahPhaseTimings::CodeCacheRoots, worker_id);
CodeBlobToOopClosure blobs(oops, !CodeBlobToOopClosure::FixRelocations);
_codecache_snapshot->parallel_blobs_do(&blobs);
if (_unload_classes) {
_thread_roots.oops_do(oops, &blobs_cl, worker_id);
_cld_roots.always_strong_cld_do(&clds, worker_id);
} else {
_cld_roots.always_strong_cld_do(&clds_cl, worker_id);
AlwaysTrueClosure always_true;
_thread_roots.oops_do(oops, NULL, worker_id);
_code_roots.code_blobs_do(&blobs_cl, worker_id);
_cld_roots.cld_do(&clds, worker_id);
_dedup_roots.oops_do(&always_true, oops, worker_id);
}
_vm_roots.oops_do<T>(oops, worker_id);
}
template <typename IsAlive, typename KeepAlive>