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() { CodeCache::UnloadingScope::~UnloadingScope() {
IsUnloadingBehaviour::set_current(_saved_behaviour); IsUnloadingBehaviour::set_current(_saved_behaviour);
DependencyContext::cleaning_end(); DependencyContext::cleaning_end();
CodeCache::flush_unlinked_nmethods();
} }
void CodeCache::verify_oops() { void CodeCache::verify_oops() {

View File

@ -179,10 +179,7 @@ class CodeCache : AllStatic {
// GC support // GC support
static void verify_oops(); static void verify_oops();
// If any oops are not marked this method unloads (i.e., breaks root links // Scope object managing code cache unloading behavior.
// 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.
class UnloadingScope: StackObj { class UnloadingScope: StackObj {
ClosureIsUnloadingBehaviour _is_unloading_behaviour; ClosureIsUnloadingBehaviour _is_unloading_behaviour;
IsUnloadingBehaviour* _saved_behaviour; IsUnloadingBehaviour* _saved_behaviour;

View File

@ -1694,9 +1694,12 @@ void G1ConcurrentMark::weak_refs_work() {
// Unload Klasses, String, Code Cache, etc. // Unload Klasses, String, Code Cache, etc.
if (ClassUnloadingWithConcurrentMark) { if (ClassUnloadingWithConcurrentMark) {
GCTraceTime(Debug, gc, phases) debug("Class Unloading", _gc_timer_cm); 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); CodeCache::UnloadingScope scope(&g1_is_alive);
_g1h->complete_cleaning(purged_classes); 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. // Class unloading and cleanup.
if (ClassUnloading) { if (ClassUnloading) {
GCTraceTime(Debug, gc, phases) debug("Phase 1: Class Unloading and Cleanup", scope()->timer()); 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. CodeCache::UnloadingScope unloading_scope(&_is_alive);
bool purged_class = SystemDictionary::do_unloading(scope()->timer()); // Unload classes and purge the SystemDictionary.
_heap->complete_cleaning(purged_class); 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); GCTraceTime(Debug, gc, phases) tm_m("Class Unloading", &_gc_timer);
CodeCache::UnloadingScope scope(is_alive_closure());
// Follow system dictionary roots and unload classes. bool unloading_occurred;
bool purged_class = SystemDictionary::do_unloading(&_gc_timer); {
CodeCache::UnloadingScope scope(is_alive_closure());
// Unload nmethods. // Follow system dictionary roots and unload classes.
CodeCache::do_unloading(purged_class); 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. // 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. // 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()); GCTraceTime(Debug, gc, phases) tm_m("Class Unloading", gc_timer());
CodeCache::UnloadingScope scope(&is_alive);
// Unload classes and purge the SystemDictionary. bool unloading_occurred;
bool purged_class = SystemDictionary::do_unloading(gc_timer()); {
CodeCache::UnloadingScope scope(&is_alive);
// Unload nmethods. // Unload classes and purge the SystemDictionary.
CodeCache::do_unloading(purged_class); 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. // 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. // 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::full_gc_purge_class_unload :
ShenandoahPhaseTimings::degen_gc_purge_class_unload; ShenandoahPhaseTimings::degen_gc_purge_class_unload;
ShenandoahIsAliveSelector is_alive; ShenandoahIsAliveSelector is_alive;
CodeCache::UnloadingScope scope(is_alive.is_alive_closure()); {
ShenandoahGCPhase gc_phase(phase); CodeCache::UnloadingScope scope(is_alive.is_alive_closure());
ShenandoahGCWorkerPhase worker_phase(phase); ShenandoahGCPhase gc_phase(phase);
bool purged_class = SystemDictionary::do_unloading(gc_timer()); ShenandoahGCWorkerPhase worker_phase(phase);
bool unloading_occurred = SystemDictionary::do_unloading(gc_timer());
uint num_workers = _workers->active_workers(); uint num_workers = _workers->active_workers();
ShenandoahClassUnloadingTask unlink_task(phase, num_workers, purged_class); ShenandoahClassUnloadingTask unlink_task(phase, num_workers, unloading_occurred);
_workers->run_task(&unlink_task); _workers->run_task(&unlink_task);
}
// Release unloaded nmethods's memory.
CodeCache::flush_unlinked_nmethods();
} }
{ {