8317350: Move code cache purging out of CodeCache::UnloadingScope

Reviewed-by: ayang, iwalulya
This commit is contained in:
Thomas Schatzl 2023-10-20 07:30:11 +00:00
parent 292aad2c49
commit bd3bc2c618
7 changed files with 53 additions and 33 deletions

View File

@ -1036,7 +1036,6 @@ CodeCache::UnloadingScope::UnloadingScope(BoolObjectClosure* is_alive)
CodeCache::UnloadingScope::~UnloadingScope() {
IsUnloadingBehaviour::set_current(_saved_behaviour);
DependencyContext::cleaning_end();
CodeCache::flush_unlinked_nmethods();
}
void CodeCache::verify_oops() {

View File

@ -179,10 +179,7 @@ class CodeCache : AllStatic {
// GC support
static void verify_oops();
// If any oops are not marked this method unloads (i.e., breaks root links
// to) any unmarked codeBlobs in the cache. Sets "marked_for_unloading"
// to "true" iff some code got unloaded.
// "unloading_occurred" controls whether metadata should be cleaned because of class unloading.
// Scope object managing code cache unloading behavior.
class UnloadingScope: StackObj {
ClosureIsUnloadingBehaviour _is_unloading_behaviour;
IsUnloadingBehaviour* _saved_behaviour;

View File

@ -1694,9 +1694,12 @@ void G1ConcurrentMark::weak_refs_work() {
// Unload Klasses, String, Code Cache, etc.
if (ClassUnloadingWithConcurrentMark) {
GCTraceTime(Debug, gc, phases) debug("Class Unloading", _gc_timer_cm);
CodeCache::UnloadingScope scope(&g1_is_alive);
bool purged_classes = SystemDictionary::do_unloading(_gc_timer_cm);
_g1h->complete_cleaning(purged_classes);
{
CodeCache::UnloadingScope scope(&g1_is_alive);
bool unloading_occurred = SystemDictionary::do_unloading(_gc_timer_cm);
_g1h->complete_cleaning(unloading_occurred);
}
CodeCache::flush_unlinked_nmethods();
}
}

View File

@ -319,10 +319,13 @@ void G1FullCollector::phase1_mark_live_objects() {
// Class unloading and cleanup.
if (ClassUnloading) {
GCTraceTime(Debug, gc, phases) debug("Phase 1: Class Unloading and Cleanup", scope()->timer());
CodeCache::UnloadingScope unloading_scope(&_is_alive);
// Unload classes and purge the SystemDictionary.
bool purged_class = SystemDictionary::do_unloading(scope()->timer());
_heap->complete_cleaning(purged_class);
{
CodeCache::UnloadingScope unloading_scope(&_is_alive);
// Unload classes and purge the SystemDictionary.
bool unloading_occurred = SystemDictionary::do_unloading(scope()->timer());
_heap->complete_cleaning(unloading_occurred);
}
CodeCache::flush_unlinked_nmethods();
}
{

View File

@ -2052,19 +2052,26 @@ void PSParallelCompact::marking_phase(ParallelOldTracer *gc_tracer) {
{
GCTraceTime(Debug, gc, phases) tm_m("Class Unloading", &_gc_timer);
CodeCache::UnloadingScope scope(is_alive_closure());
// Follow system dictionary roots and unload classes.
bool purged_class = SystemDictionary::do_unloading(&_gc_timer);
bool unloading_occurred;
{
CodeCache::UnloadingScope scope(is_alive_closure());
// Unload nmethods.
CodeCache::do_unloading(purged_class);
// Follow system dictionary roots and unload classes.
unloading_occurred = SystemDictionary::do_unloading(&_gc_timer);
// Unload nmethods.
CodeCache::do_unloading(unloading_occurred);
}
// Release unloaded nmethods's memory.
CodeCache::flush_unlinked_nmethods();
// Prune dead klasses from subklass/sibling/implementor lists.
Klass::clean_weak_klass_links(purged_class);
Klass::clean_weak_klass_links(unloading_occurred);
// Clean JVMCI metadata handles.
JVMCI_ONLY(JVMCI::do_unloading(purged_class));
JVMCI_ONLY(JVMCI::do_unloading(unloading_occurred));
}
{

View File

@ -199,19 +199,26 @@ void GenMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
{
GCTraceTime(Debug, gc, phases) tm_m("Class Unloading", gc_timer());
CodeCache::UnloadingScope scope(&is_alive);
// Unload classes and purge the SystemDictionary.
bool purged_class = SystemDictionary::do_unloading(gc_timer());
bool unloading_occurred;
{
CodeCache::UnloadingScope scope(&is_alive);
// Unload nmethods.
CodeCache::do_unloading(purged_class);
// Unload classes and purge the SystemDictionary.
unloading_occurred = SystemDictionary::do_unloading(gc_timer());
// Unload nmethods.
CodeCache::do_unloading(unloading_occurred);
}
// Release unloaded nmethod's memory.
CodeCache::flush_unlinked_nmethods();
// Prune dead klasses from subklass/sibling/implementor lists.
Klass::clean_weak_klass_links(purged_class);
Klass::clean_weak_klass_links(unloading_occurred);
// Clean JVMCI metadata handles.
JVMCI_ONLY(JVMCI::do_unloading(purged_class));
JVMCI_ONLY(JVMCI::do_unloading(unloading_occurred));
}
{

View File

@ -1811,14 +1811,18 @@ void ShenandoahHeap::stw_unload_classes(bool full_gc) {
ShenandoahPhaseTimings::full_gc_purge_class_unload :
ShenandoahPhaseTimings::degen_gc_purge_class_unload;
ShenandoahIsAliveSelector is_alive;
CodeCache::UnloadingScope scope(is_alive.is_alive_closure());
ShenandoahGCPhase gc_phase(phase);
ShenandoahGCWorkerPhase worker_phase(phase);
bool purged_class = SystemDictionary::do_unloading(gc_timer());
{
CodeCache::UnloadingScope scope(is_alive.is_alive_closure());
ShenandoahGCPhase gc_phase(phase);
ShenandoahGCWorkerPhase worker_phase(phase);
bool unloading_occurred = SystemDictionary::do_unloading(gc_timer());
uint num_workers = _workers->active_workers();
ShenandoahClassUnloadingTask unlink_task(phase, num_workers, purged_class);
_workers->run_task(&unlink_task);
uint num_workers = _workers->active_workers();
ShenandoahClassUnloadingTask unlink_task(phase, num_workers, unloading_occurred);
_workers->run_task(&unlink_task);
}
// Release unloaded nmethods's memory.
CodeCache::flush_unlinked_nmethods();
}
{