8202813: Move vm_weak processing from SystemDictionary to WeakProcessor
SystemDictionary has all strong roots. The weak oop_storage is processed by the WeakProcessor so it can be scanned and cleared concurrently and/or by parallel threads. Reviewed-by: kbarrett, sjohanss
This commit is contained in:
parent
92b31787a2
commit
e3a3941c9a
src/hotspot/share
classfile
gc
cms
g1
parallel
serial
shared
jfr/leakprofiler/chains
prims
@ -1817,22 +1817,11 @@ void SystemDictionary::add_to_hierarchy(InstanceKlass* k, TRAPS) {
|
||||
// ----------------------------------------------------------------------------
|
||||
// GC support
|
||||
|
||||
void SystemDictionary::always_strong_oops_do(OopClosure* blk) {
|
||||
roots_oops_do(blk, NULL);
|
||||
}
|
||||
|
||||
|
||||
// Assumes classes in the SystemDictionary are only unloaded at a safepoint
|
||||
// Note: anonymous classes are not in the SD.
|
||||
bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive,
|
||||
GCTimer* gc_timer,
|
||||
bool SystemDictionary::do_unloading(GCTimer* gc_timer,
|
||||
bool do_cleaning) {
|
||||
|
||||
{
|
||||
GCTraceTime(Debug, gc, phases) t("SystemDictionary WeakHandle cleaning", gc_timer);
|
||||
vm_weak_oop_storage()->weak_oops_do(is_alive, &do_nothing_cl);
|
||||
}
|
||||
|
||||
bool unloading_occurred;
|
||||
{
|
||||
GCTraceTime(Debug, gc, phases) t("ClassLoaderData", gc_timer);
|
||||
@ -1863,27 +1852,6 @@ bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive,
|
||||
return unloading_occurred;
|
||||
}
|
||||
|
||||
void SystemDictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) {
|
||||
strong->do_oop(&_java_system_loader);
|
||||
strong->do_oop(&_java_platform_loader);
|
||||
strong->do_oop(&_system_loader_lock_obj);
|
||||
CDS_ONLY(SystemDictionaryShared::roots_oops_do(strong);)
|
||||
|
||||
// Do strong roots marking if the closures are the same.
|
||||
if (strong == weak || !ClassUnloading) {
|
||||
// Only the protection domain oops contain references into the heap. Iterate
|
||||
// over all of them.
|
||||
vm_weak_oop_storage()->oops_do(strong);
|
||||
} else {
|
||||
if (weak != NULL) {
|
||||
vm_weak_oop_storage()->oops_do(weak);
|
||||
}
|
||||
}
|
||||
|
||||
// Visit extra methods
|
||||
invoke_method_table()->oops_do(strong);
|
||||
}
|
||||
|
||||
void SystemDictionary::oops_do(OopClosure* f) {
|
||||
f->do_oop(&_java_system_loader);
|
||||
f->do_oop(&_java_platform_loader);
|
||||
@ -1892,8 +1860,6 @@ void SystemDictionary::oops_do(OopClosure* f) {
|
||||
|
||||
// Visit extra methods
|
||||
invoke_method_table()->oops_do(f);
|
||||
|
||||
vm_weak_oop_storage()->oops_do(f);
|
||||
}
|
||||
|
||||
// CDS: scan and relocate all classes in the system dictionary.
|
||||
|
@ -357,14 +357,9 @@ public:
|
||||
|
||||
// Garbage collection support
|
||||
|
||||
// This method applies "blk->do_oop" to all the pointers to "system"
|
||||
// classes and loaders.
|
||||
static void always_strong_oops_do(OopClosure* blk);
|
||||
|
||||
// Unload (that is, break root links to) all unmarked classes and
|
||||
// loaders. Returns "true" iff something was unloaded.
|
||||
static bool do_unloading(BoolObjectClosure* is_alive,
|
||||
GCTimer* gc_timer,
|
||||
static bool do_unloading(GCTimer* gc_timer,
|
||||
bool do_cleaning = true);
|
||||
|
||||
// Used by DumpSharedSpaces only to remove classes that failed verification
|
||||
@ -374,7 +369,6 @@ public:
|
||||
|
||||
// Applies "f->do_oop" to all root oops in the system dictionary.
|
||||
static void oops_do(OopClosure* f);
|
||||
static void roots_oops_do(OopClosure* strong, OopClosure* weak);
|
||||
|
||||
// System loader lock
|
||||
static oop system_loader_lock() { return _system_loader_lock_obj; }
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. 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
|
||||
@ -222,10 +222,9 @@ void CMSHeap::cms_process_roots(StrongRootsScope* scope,
|
||||
OopsInGenClosure* root_closure,
|
||||
CLDClosure* cld_closure) {
|
||||
MarkingCodeBlobClosure mark_code_closure(root_closure, !CodeBlobToOopClosure::FixRelocations);
|
||||
OopsInGenClosure* weak_roots = only_strong_roots ? NULL : root_closure;
|
||||
CLDClosure* weak_cld_closure = only_strong_roots ? NULL : cld_closure;
|
||||
|
||||
process_roots(scope, so, root_closure, weak_roots, cld_closure, weak_cld_closure, &mark_code_closure);
|
||||
process_roots(scope, so, root_closure, cld_closure, weak_cld_closure, &mark_code_closure);
|
||||
if (!only_strong_roots) {
|
||||
process_string_table_roots(scope, root_closure);
|
||||
}
|
||||
|
@ -5201,7 +5201,7 @@ void CMSCollector::refProcessingWork() {
|
||||
GCTraceTime(Debug, gc, phases) t("Class Unloading", _gc_timer_cm);
|
||||
|
||||
// Unload classes and purge the SystemDictionary.
|
||||
bool purged_class = SystemDictionary::do_unloading(&_is_alive_closure, _gc_timer_cm);
|
||||
bool purged_class = SystemDictionary::do_unloading(_gc_timer_cm);
|
||||
|
||||
// Unload nmethods.
|
||||
CodeCache::do_unloading(&_is_alive_closure, purged_class);
|
||||
|
@ -1665,7 +1665,7 @@ void G1ConcurrentMark::weak_refs_work(bool clear_all_soft_refs) {
|
||||
// Unload Klasses, String, Symbols, Code Cache, etc.
|
||||
if (ClassUnloadingWithConcurrentMark) {
|
||||
GCTraceTime(Debug, gc, phases) debug("Class Unloading", _gc_timer_cm);
|
||||
bool purged_classes = SystemDictionary::do_unloading(&g1_is_alive, _gc_timer_cm, false /* Defer cleaning */);
|
||||
bool purged_classes = SystemDictionary::do_unloading(_gc_timer_cm, false /* Defer cleaning */);
|
||||
_g1h->complete_cleaning(&g1_is_alive, purged_classes);
|
||||
} else {
|
||||
GCTraceTime(Debug, gc, phases) debug("Cleanup", _gc_timer_cm);
|
||||
|
@ -222,7 +222,7 @@ void G1FullCollector::phase1_mark_live_objects() {
|
||||
if (ClassUnloading) {
|
||||
GCTraceTime(Debug, gc, phases) debug("Phase 1: Class Unloading and Cleanup", scope()->timer());
|
||||
// Unload classes and purge the SystemDictionary.
|
||||
bool purged_class = SystemDictionary::do_unloading(&_is_alive, scope()->timer());
|
||||
bool purged_class = SystemDictionary::do_unloading(scope()->timer());
|
||||
_heap->complete_cleaning(&_is_alive, purged_class);
|
||||
} else {
|
||||
GCTraceTime(Debug, gc, phases) debug("Phase 1: String and Symbol Tables Cleanup", scope()->timer());
|
||||
|
@ -241,7 +241,6 @@ void G1RootProcessor::process_vm_roots(G1RootClosures* closures,
|
||||
G1GCPhaseTimes* phase_times,
|
||||
uint worker_i) {
|
||||
OopClosure* strong_roots = closures->strong_oops();
|
||||
OopClosure* weak_roots = closures->weak_oops();
|
||||
|
||||
{
|
||||
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::UniverseRoots, worker_i);
|
||||
@ -290,7 +289,7 @@ void G1RootProcessor::process_vm_roots(G1RootClosures* closures,
|
||||
{
|
||||
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::SystemDictionaryRoots, worker_i);
|
||||
if (!_process_strong_tasks.is_task_claimed(G1RP_PS_SystemDictionary_oops_do)) {
|
||||
SystemDictionary::roots_oops_do(strong_roots, weak_roots);
|
||||
SystemDictionary::oops_do(strong_roots);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ void MarkFromRootsTask::do_it(GCTaskManager* manager, uint which) {
|
||||
break;
|
||||
|
||||
case system_dictionary:
|
||||
SystemDictionary::always_strong_oops_do(&mark_and_push_closure);
|
||||
SystemDictionary::oops_do(&mark_and_push_closure);
|
||||
break;
|
||||
|
||||
case class_loader_data:
|
||||
|
@ -521,7 +521,7 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
|
||||
ObjectSynchronizer::oops_do(mark_and_push_closure());
|
||||
Management::oops_do(mark_and_push_closure());
|
||||
JvmtiExport::oops_do(mark_and_push_closure());
|
||||
SystemDictionary::always_strong_oops_do(mark_and_push_closure());
|
||||
SystemDictionary::oops_do(mark_and_push_closure());
|
||||
ClassLoaderDataGraph::always_strong_cld_do(follow_cld_closure());
|
||||
// Do not treat nmethods as strong roots for mark/sweep, since we can unload them.
|
||||
//CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure(mark_and_push_closure()));
|
||||
@ -556,7 +556,7 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
|
||||
GCTraceTime(Debug, gc, phases) t("Class Unloading", _gc_timer);
|
||||
|
||||
// Unload classes and purge the SystemDictionary.
|
||||
bool purged_class = SystemDictionary::do_unloading(is_alive_closure(), _gc_timer);
|
||||
bool purged_class = SystemDictionary::do_unloading(_gc_timer);
|
||||
|
||||
// Unload nmethods.
|
||||
CodeCache::do_unloading(is_alive_closure(), purged_class);
|
||||
|
@ -2139,7 +2139,7 @@ void PSParallelCompact::marking_phase(ParCompactionManager* cm,
|
||||
GCTraceTime(Debug, gc, phases) tm_m("Class Unloading", &_gc_timer);
|
||||
|
||||
// Follow system dictionary roots and unload classes.
|
||||
bool purged_class = SystemDictionary::do_unloading(is_alive_closure(), &_gc_timer);
|
||||
bool purged_class = SystemDictionary::do_unloading(&_gc_timer);
|
||||
|
||||
// Unload nmethods.
|
||||
CodeCache::do_unloading(is_alive_closure(), purged_class);
|
||||
|
@ -228,7 +228,7 @@ void GenMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
|
||||
GCTraceTime(Debug, gc, phases) tm_m("Class Unloading", gc_timer());
|
||||
|
||||
// Unload classes and purge the SystemDictionary.
|
||||
bool purged_class = SystemDictionary::do_unloading(&is_alive, gc_timer());
|
||||
bool purged_class = SystemDictionary::do_unloading(gc_timer());
|
||||
|
||||
// Unload nmethods.
|
||||
CodeCache::do_unloading(&is_alive, purged_class);
|
||||
|
@ -783,7 +783,6 @@ static AssertNonScavengableClosure assert_is_non_scavengable_closure;
|
||||
void GenCollectedHeap::process_roots(StrongRootsScope* scope,
|
||||
ScanningOption so,
|
||||
OopClosure* strong_roots,
|
||||
OopClosure* weak_roots,
|
||||
CLDClosure* strong_cld_closure,
|
||||
CLDClosure* weak_cld_closure,
|
||||
CodeBlobToOopClosure* code_roots) {
|
||||
@ -827,7 +826,7 @@ void GenCollectedHeap::process_roots(StrongRootsScope* scope,
|
||||
}
|
||||
|
||||
if (!_process_strong_tasks->is_task_claimed(GCH_PS_SystemDictionary_oops_do)) {
|
||||
SystemDictionary::roots_oops_do(strong_roots, weak_roots);
|
||||
SystemDictionary::oops_do(strong_roots);
|
||||
}
|
||||
|
||||
if (!_process_strong_tasks->is_task_claimed(GCH_PS_CodeCache_oops_do)) {
|
||||
@ -869,7 +868,7 @@ void GenCollectedHeap::young_process_roots(StrongRootsScope* scope,
|
||||
CLDClosure* cld_closure) {
|
||||
MarkingCodeBlobClosure mark_code_closure(root_closure, CodeBlobToOopClosure::FixRelocations);
|
||||
|
||||
process_roots(scope, SO_ScavengeCodeCache, root_closure, root_closure,
|
||||
process_roots(scope, SO_ScavengeCodeCache, root_closure,
|
||||
cld_closure, cld_closure, &mark_code_closure);
|
||||
process_string_table_roots(scope, root_closure);
|
||||
|
||||
@ -893,10 +892,9 @@ void GenCollectedHeap::full_process_roots(StrongRootsScope* scope,
|
||||
OopsInGenClosure* root_closure,
|
||||
CLDClosure* cld_closure) {
|
||||
MarkingCodeBlobClosure mark_code_closure(root_closure, is_adjust_phase);
|
||||
OopsInGenClosure* weak_roots = only_strong_roots ? NULL : root_closure;
|
||||
CLDClosure* weak_cld_closure = only_strong_roots ? NULL : cld_closure;
|
||||
|
||||
process_roots(scope, so, root_closure, weak_roots, cld_closure, weak_cld_closure, &mark_code_closure);
|
||||
process_roots(scope, so, root_closure, cld_closure, weak_cld_closure, &mark_code_closure);
|
||||
if (is_adjust_phase) {
|
||||
// We never treat the string table as roots during marking
|
||||
// for the full gc, so we only need to process it during
|
||||
|
@ -396,7 +396,6 @@ public:
|
||||
void process_roots(StrongRootsScope* scope,
|
||||
ScanningOption so,
|
||||
OopClosure* strong_roots,
|
||||
OopClosure* weak_roots,
|
||||
CLDClosure* strong_cld_closure,
|
||||
CLDClosure* weak_cld_closure,
|
||||
CodeBlobToOopClosure* code_roots);
|
||||
|
@ -23,6 +23,8 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "gc/shared/oopStorage.inline.hpp"
|
||||
#include "gc/shared/weakProcessor.hpp"
|
||||
#include "prims/jvmtiExport.hpp"
|
||||
#include "runtime/jniHandles.hpp"
|
||||
@ -34,6 +36,7 @@
|
||||
void WeakProcessor::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive) {
|
||||
JNIHandles::weak_oops_do(is_alive, keep_alive);
|
||||
JvmtiExport::weak_oops_do(is_alive, keep_alive);
|
||||
SystemDictionary::vm_weak_oop_storage()->weak_oops_do(is_alive, keep_alive);
|
||||
JFR_ONLY(Jfr::weak_oops_do(is_alive, keep_alive);)
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ void RootSetClosure::process_roots(OopClosure* closure) {
|
||||
Universe::oops_do(closure);
|
||||
JNIHandles::oops_do(closure);
|
||||
JvmtiExport::oops_do(closure);
|
||||
SystemDictionary::always_strong_oops_do(closure);
|
||||
SystemDictionary::oops_do(closure);
|
||||
Management::oops_do(closure);
|
||||
StringTable::oops_do(closure);
|
||||
AOTLoader::oops_do(closure);
|
||||
|
@ -2577,7 +2577,7 @@ class SimpleRootsClosure : public OopClosure {
|
||||
|
||||
jvmtiHeapReferenceKind kind = root_kind();
|
||||
if (kind == JVMTI_HEAP_REFERENCE_SYSTEM_CLASS) {
|
||||
// SystemDictionary::always_strong_oops_do reports the application
|
||||
// SystemDictionary::oops_do reports the application
|
||||
// class loader as a root. We want this root to be reported as
|
||||
// a root kind of "OTHER" rather than "SYSTEM_CLASS".
|
||||
if (!o->is_instance() || !InstanceKlass::cast(o->klass())->is_mirror_instance_klass()) {
|
||||
@ -3003,7 +3003,7 @@ inline bool VM_HeapWalkOperation::collect_simple_roots() {
|
||||
|
||||
// Preloaded classes and loader from the system dictionary
|
||||
blk.set_kind(JVMTI_HEAP_REFERENCE_SYSTEM_CLASS);
|
||||
SystemDictionary::always_strong_oops_do(&blk);
|
||||
SystemDictionary::oops_do(&blk);
|
||||
ClassLoaderDataGraph::always_strong_oops_do(&blk, false);
|
||||
if (blk.stopped()) {
|
||||
return false;
|
||||
|
Loading…
x
Reference in New Issue
Block a user