mirror of
https://github.com/darlinghq/darling-openjdk.git
synced 2025-03-01 12:38:27 +00:00
8201537: Remove is_alive closure from Klass::is_loader_alive()
Remove is_alive closure from callers of Klass::is_loader_alive so that cleaning metadata doesn't require GC closure. Reviewed-by: adinn, stefank
This commit is contained in:
parent
4ffd5d45c1
commit
c215aa5889
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 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
|
||||
@ -99,7 +99,7 @@ void LoaderConstraintTable::purge_loader_constraints() {
|
||||
InstanceKlass* klass = probe->klass();
|
||||
// Remove klass that is no longer alive
|
||||
if (klass != NULL &&
|
||||
klass->class_loader_data()->is_unloading()) {
|
||||
!klass->is_loader_alive()) {
|
||||
probe->set_klass(NULL);
|
||||
if (lt.is_enabled()) {
|
||||
ResourceMark rm;
|
||||
@ -116,31 +116,31 @@ void LoaderConstraintTable::purge_loader_constraints() {
|
||||
int n = 0;
|
||||
while (n < probe->num_loaders()) {
|
||||
if (probe->loader_data(n)->is_unloading()) {
|
||||
if (lt.is_enabled()) {
|
||||
ResourceMark rm;
|
||||
lt.print("purging loader %s from constraint for name %s",
|
||||
probe->loader_data(n)->loader_name(),
|
||||
probe->name()->as_C_string()
|
||||
);
|
||||
}
|
||||
if (lt.is_enabled()) {
|
||||
ResourceMark rm;
|
||||
lt.print("purging loader %s from constraint for name %s",
|
||||
probe->loader_data(n)->loader_name(),
|
||||
probe->name()->as_C_string()
|
||||
);
|
||||
}
|
||||
|
||||
// Compact array
|
||||
int num = probe->num_loaders() - 1;
|
||||
probe->set_num_loaders(num);
|
||||
// Compact array
|
||||
int num = probe->num_loaders() - 1;
|
||||
probe->set_num_loaders(num);
|
||||
probe->set_loader_data(n, probe->loader_data(num));
|
||||
probe->set_loader_data(num, NULL);
|
||||
|
||||
if (lt.is_enabled()) {
|
||||
ResourceMark rm;
|
||||
lt.print("new loader list:");
|
||||
for (int i = 0; i < probe->num_loaders(); i++) {
|
||||
lt.print(" [%d]: %s", i,
|
||||
probe->loader_data(i)->loader_name());
|
||||
}
|
||||
if (lt.is_enabled()) {
|
||||
ResourceMark rm;
|
||||
lt.print("new loader list:");
|
||||
for (int i = 0; i < probe->num_loaders(); i++) {
|
||||
lt.print(" [%d]: %s", i,
|
||||
probe->loader_data(i)->loader_name());
|
||||
}
|
||||
}
|
||||
|
||||
continue; // current element replaced, so restart without
|
||||
// incrementing n
|
||||
continue; // current element replaced, so restart without
|
||||
// incrementing n
|
||||
}
|
||||
n++;
|
||||
}
|
||||
@ -159,9 +159,7 @@ void LoaderConstraintTable::purge_loader_constraints() {
|
||||
} else {
|
||||
#ifdef ASSERT
|
||||
if (probe->klass() != NULL) {
|
||||
ClassLoaderData* loader_data =
|
||||
probe->klass()->class_loader_data();
|
||||
assert(!loader_data->is_unloading(), "klass should be live");
|
||||
assert(probe->klass()->is_loader_alive(), "klass should be live");
|
||||
}
|
||||
#endif
|
||||
// Go to next entry
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 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
|
||||
@ -125,9 +125,8 @@ void ResolutionErrorTable::purge_resolution_errors() {
|
||||
assert(entry->pool() != (ConstantPool*)NULL, "resolution error table is corrupt");
|
||||
ConstantPool* pool = entry->pool();
|
||||
assert(pool->pool_holder() != NULL, "Constant pool without a class?");
|
||||
ClassLoaderData* loader_data =
|
||||
pool->pool_holder()->class_loader_data();
|
||||
if (!loader_data->is_unloading()) {
|
||||
|
||||
if (pool->pool_holder()->is_loader_alive()) {
|
||||
p = entry->next_addr();
|
||||
} else {
|
||||
*p = entry->next();
|
||||
|
@ -99,7 +99,7 @@ void CompiledMethod::add_exception_cache_entry(ExceptionCache* new_entry) {
|
||||
release_set_exception_cache(new_entry);
|
||||
}
|
||||
|
||||
void CompiledMethod::clean_exception_cache(BoolObjectClosure* is_alive) {
|
||||
void CompiledMethod::clean_exception_cache() {
|
||||
ExceptionCache* prev = NULL;
|
||||
ExceptionCache* curr = exception_cache();
|
||||
|
||||
@ -107,7 +107,7 @@ void CompiledMethod::clean_exception_cache(BoolObjectClosure* is_alive) {
|
||||
ExceptionCache* next = curr->next();
|
||||
|
||||
Klass* ex_klass = curr->exception_type();
|
||||
if (ex_klass != NULL && !ex_klass->is_loader_alive(is_alive)) {
|
||||
if (ex_klass != NULL && !ex_klass->is_loader_alive()) {
|
||||
if (prev == NULL) {
|
||||
set_exception_cache(next);
|
||||
} else {
|
||||
@ -369,56 +369,42 @@ void CompiledMethod::clear_ic_stubs() {
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
|
||||
class CheckClass : AllStatic {
|
||||
static BoolObjectClosure* _is_alive;
|
||||
|
||||
// Check class_loader is alive for this bit of metadata.
|
||||
static void check_class(Metadata* md) {
|
||||
Klass* klass = NULL;
|
||||
if (md->is_klass()) {
|
||||
klass = ((Klass*)md);
|
||||
} else if (md->is_method()) {
|
||||
klass = ((Method*)md)->method_holder();
|
||||
} else if (md->is_methodData()) {
|
||||
klass = ((MethodData*)md)->method()->method_holder();
|
||||
} else {
|
||||
md->print();
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
assert(klass->is_loader_alive(_is_alive), "must be alive");
|
||||
}
|
||||
public:
|
||||
static void do_check_class(BoolObjectClosure* is_alive, CompiledMethod* nm) {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "this is only ok at safepoint");
|
||||
_is_alive = is_alive;
|
||||
nm->metadata_do(check_class);
|
||||
}
|
||||
};
|
||||
|
||||
// This is called during a safepoint so can use static data
|
||||
BoolObjectClosure* CheckClass::_is_alive = NULL;
|
||||
// Check class_loader is alive for this bit of metadata.
|
||||
static void check_class(Metadata* md) {
|
||||
Klass* klass = NULL;
|
||||
if (md->is_klass()) {
|
||||
klass = ((Klass*)md);
|
||||
} else if (md->is_method()) {
|
||||
klass = ((Method*)md)->method_holder();
|
||||
} else if (md->is_methodData()) {
|
||||
klass = ((MethodData*)md)->method()->method_holder();
|
||||
} else {
|
||||
md->print();
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
assert(klass->is_loader_alive(), "must be alive");
|
||||
}
|
||||
#endif // ASSERT
|
||||
|
||||
|
||||
void CompiledMethod::clean_ic_if_metadata_is_dead(CompiledIC *ic, BoolObjectClosure *is_alive) {
|
||||
void CompiledMethod::clean_ic_if_metadata_is_dead(CompiledIC *ic) {
|
||||
if (ic->is_icholder_call()) {
|
||||
// The only exception is compiledICHolder oops which may
|
||||
// yet be marked below. (We check this further below).
|
||||
CompiledICHolder* cichk_oop = ic->cached_icholder();
|
||||
|
||||
if (cichk_oop->is_loader_alive(is_alive)) {
|
||||
if (cichk_oop->is_loader_alive()) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Metadata* ic_oop = ic->cached_metadata();
|
||||
if (ic_oop != NULL) {
|
||||
if (ic_oop->is_klass()) {
|
||||
if (((Klass*)ic_oop)->is_loader_alive(is_alive)) {
|
||||
if (((Klass*)ic_oop)->is_loader_alive()) {
|
||||
return;
|
||||
}
|
||||
} else if (ic_oop->is_method()) {
|
||||
if (((Method*)ic_oop)->method_holder()->is_loader_alive(is_alive)) {
|
||||
if (((Method*)ic_oop)->method_holder()->is_loader_alive()) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@ -453,7 +439,7 @@ unsigned char CompiledMethod::unloading_clock() {
|
||||
// all strong references alive. Any weak references should have been
|
||||
// cleared as well. Visit all the metadata and ensure that it's
|
||||
// really alive.
|
||||
void CompiledMethod::verify_metadata_loaders(address low_boundary, BoolObjectClosure* is_alive) {
|
||||
void CompiledMethod::verify_metadata_loaders(address low_boundary) {
|
||||
#ifdef ASSERT
|
||||
RelocIterator iter(this, low_boundary);
|
||||
while (iter.next()) {
|
||||
@ -483,7 +469,7 @@ void CompiledMethod::verify_metadata_loaders(address low_boundary, BoolObjectClo
|
||||
}
|
||||
}
|
||||
// Check that the metadata embedded in the nmethod is alive
|
||||
CheckClass::do_check_class(is_alive, this);
|
||||
metadata_do(check_class);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -518,7 +504,7 @@ void CompiledMethod::do_unloading(BoolObjectClosure* is_alive, bool unloading_oc
|
||||
}
|
||||
|
||||
// Exception cache
|
||||
clean_exception_cache(is_alive);
|
||||
clean_exception_cache();
|
||||
|
||||
// If class unloading occurred we first iterate over all inline caches and
|
||||
// clear ICs where the cached oop is referring to an unloaded klass or method.
|
||||
@ -529,7 +515,7 @@ void CompiledMethod::do_unloading(BoolObjectClosure* is_alive, bool unloading_oc
|
||||
while(iter.next()) {
|
||||
if (iter.type() == relocInfo::virtual_call_type) {
|
||||
CompiledIC *ic = CompiledIC_at(&iter);
|
||||
clean_ic_if_metadata_is_dead(ic, is_alive);
|
||||
clean_ic_if_metadata_is_dead(ic);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -545,7 +531,7 @@ void CompiledMethod::do_unloading(BoolObjectClosure* is_alive, bool unloading_oc
|
||||
#endif
|
||||
|
||||
// Ensure that all metadata is still alive
|
||||
verify_metadata_loaders(low_boundary, is_alive);
|
||||
verify_metadata_loaders(low_boundary);
|
||||
}
|
||||
|
||||
template <class CompiledICorStaticCall>
|
||||
@ -606,7 +592,7 @@ bool CompiledMethod::do_unloading_parallel(BoolObjectClosure* is_alive, bool unl
|
||||
}
|
||||
|
||||
// Exception cache
|
||||
clean_exception_cache(is_alive);
|
||||
clean_exception_cache();
|
||||
|
||||
bool postponed = false;
|
||||
|
||||
@ -619,7 +605,7 @@ bool CompiledMethod::do_unloading_parallel(BoolObjectClosure* is_alive, bool unl
|
||||
if (unloading_occurred) {
|
||||
// If class unloading occurred we first iterate over all inline caches and
|
||||
// clear ICs where the cached oop is referring to an unloaded klass or method.
|
||||
clean_ic_if_metadata_is_dead(CompiledIC_at(&iter), is_alive);
|
||||
clean_ic_if_metadata_is_dead(CompiledIC_at(&iter));
|
||||
}
|
||||
|
||||
postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
|
||||
@ -656,7 +642,7 @@ bool CompiledMethod::do_unloading_parallel(BoolObjectClosure* is_alive, bool unl
|
||||
#endif
|
||||
|
||||
// Ensure that all metadata is still alive
|
||||
verify_metadata_loaders(low_boundary, is_alive);
|
||||
verify_metadata_loaders(low_boundary);
|
||||
|
||||
return postponed;
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ public:
|
||||
void release_set_exception_cache(ExceptionCache *ec);
|
||||
address handler_for_exception_and_pc(Handle exception, address pc);
|
||||
void add_handler_for_exception_and_pc(Handle exception, address pc, address handler);
|
||||
void clean_exception_cache(BoolObjectClosure* is_alive);
|
||||
void clean_exception_cache();
|
||||
|
||||
void add_exception_cache_entry(ExceptionCache* new_entry);
|
||||
ExceptionCache* exception_cache_entry_for_exception(Handle exception);
|
||||
@ -364,10 +364,10 @@ public:
|
||||
void set_unloading_next(CompiledMethod* next) { _unloading_next = next; }
|
||||
CompiledMethod* unloading_next() { return _unloading_next; }
|
||||
|
||||
void static clean_ic_if_metadata_is_dead(CompiledIC *ic, BoolObjectClosure *is_alive);
|
||||
void static clean_ic_if_metadata_is_dead(CompiledIC *ic);
|
||||
|
||||
// Check that all metadata is still alive
|
||||
void verify_metadata_loaders(address low_boundary, BoolObjectClosure* is_alive);
|
||||
void verify_metadata_loaders(address low_boundary);
|
||||
|
||||
virtual void do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred);
|
||||
// The parallel versions are used by G1.
|
||||
|
@ -1365,7 +1365,7 @@ void nmethod::flush_dependencies(BoolObjectClosure* is_alive) {
|
||||
}
|
||||
// During GC the is_alive closure is non-NULL, and is used to
|
||||
// determine liveness of dependees that need to be updated.
|
||||
if (is_alive == NULL || klass->is_loader_alive(is_alive)) {
|
||||
if (is_alive == NULL || klass->is_loader_alive()) {
|
||||
// The GC defers deletion of this entry, since there might be multiple threads
|
||||
// iterating over the _dependencies graph. Other call paths are single-threaded
|
||||
// and may delete it immediately.
|
||||
|
@ -5244,7 +5244,7 @@ void CMSCollector::refProcessingWork() {
|
||||
CodeCache::do_unloading(&_is_alive_closure, purged_class);
|
||||
|
||||
// Prune dead klasses from subklass/sibling/implementor lists.
|
||||
Klass::clean_weak_klass_links(&_is_alive_closure);
|
||||
Klass::clean_weak_klass_links();
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -3457,13 +3457,11 @@ private:
|
||||
Monitor* G1CodeCacheUnloadingTask::_lock = new Monitor(Mutex::leaf, "Code Cache Unload lock", false, Monitor::_safepoint_check_never);
|
||||
|
||||
class G1KlassCleaningTask : public StackObj {
|
||||
BoolObjectClosure* _is_alive;
|
||||
volatile int _clean_klass_tree_claimed;
|
||||
ClassLoaderDataGraphKlassIteratorAtomic _klass_iterator;
|
||||
|
||||
public:
|
||||
G1KlassCleaningTask(BoolObjectClosure* is_alive) :
|
||||
_is_alive(is_alive),
|
||||
G1KlassCleaningTask() :
|
||||
_clean_klass_tree_claimed(0),
|
||||
_klass_iterator() {
|
||||
}
|
||||
@ -3490,7 +3488,7 @@ class G1KlassCleaningTask : public StackObj {
|
||||
public:
|
||||
|
||||
void clean_klass(InstanceKlass* ik) {
|
||||
ik->clean_weak_instanceklass_links(_is_alive);
|
||||
ik->clean_weak_instanceklass_links();
|
||||
}
|
||||
|
||||
void work() {
|
||||
@ -3498,7 +3496,7 @@ public:
|
||||
|
||||
// One worker will clean the subklass/sibling klass tree.
|
||||
if (claim_clean_klass_tree_task()) {
|
||||
Klass::clean_subklass_tree(_is_alive);
|
||||
Klass::clean_subklass_tree();
|
||||
}
|
||||
|
||||
// All workers will help cleaning the classes,
|
||||
@ -3545,7 +3543,7 @@ public:
|
||||
AbstractGangTask("Parallel Cleaning"),
|
||||
_string_symbol_task(is_alive, true, true, G1StringDedup::is_enabled()),
|
||||
_code_cache_task(num_workers, is_alive, unloading_occurred),
|
||||
_klass_cleaning_task(is_alive),
|
||||
_klass_cleaning_task(),
|
||||
_resolved_method_cleaning_task() {
|
||||
}
|
||||
|
||||
|
@ -562,7 +562,7 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
|
||||
CodeCache::do_unloading(is_alive_closure(), purged_class);
|
||||
|
||||
// Prune dead klasses from subklass/sibling/implementor lists.
|
||||
Klass::clean_weak_klass_links(is_alive_closure());
|
||||
Klass::clean_weak_klass_links();
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -2139,7 +2139,7 @@ void PSParallelCompact::marking_phase(ParCompactionManager* cm,
|
||||
CodeCache::do_unloading(is_alive_closure(), purged_class);
|
||||
|
||||
// Prune dead klasses from subklass/sibling/implementor lists.
|
||||
Klass::clean_weak_klass_links(is_alive_closure());
|
||||
Klass::clean_weak_klass_links();
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 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
|
||||
@ -234,7 +234,7 @@ void GenMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
|
||||
CodeCache::do_unloading(&is_alive, purged_class);
|
||||
|
||||
// Prune dead klasses from subklass/sibling/implementor lists.
|
||||
Klass::clean_weak_klass_links(&is_alive);
|
||||
Klass::clean_weak_klass_links();
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -74,12 +74,12 @@ class CompiledICHolder : public CHeapObj<mtCompiler> {
|
||||
CompiledICHolder* next() { return _next; }
|
||||
void set_next(CompiledICHolder* n) { _next = n; }
|
||||
|
||||
inline bool is_loader_alive(BoolObjectClosure* is_alive) {
|
||||
inline bool is_loader_alive() {
|
||||
Klass* k = _is_metadata_method ? ((Method*)_holder_metadata)->method_holder() : (Klass*)_holder_metadata;
|
||||
if (!k->is_loader_alive(is_alive)) {
|
||||
if (!k->is_loader_alive()) {
|
||||
return false;
|
||||
}
|
||||
if (!_holder_klass->is_loader_alive(is_alive)) {
|
||||
if (!_holder_klass->is_loader_alive()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -1891,22 +1891,22 @@ bool InstanceKlass::is_dependent_nmethod(nmethod* nm) {
|
||||
}
|
||||
#endif //PRODUCT
|
||||
|
||||
void InstanceKlass::clean_weak_instanceklass_links(BoolObjectClosure* is_alive) {
|
||||
clean_implementors_list(is_alive);
|
||||
clean_method_data(is_alive);
|
||||
void InstanceKlass::clean_weak_instanceklass_links() {
|
||||
clean_implementors_list();
|
||||
clean_method_data();
|
||||
|
||||
// Since GC iterates InstanceKlasses sequentially, it is safe to remove stale entries here.
|
||||
DependencyContext dep_context(&_dep_context);
|
||||
dep_context.expunge_stale_entries();
|
||||
}
|
||||
|
||||
void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) {
|
||||
assert(class_loader_data()->is_alive(), "this klass should be live");
|
||||
void InstanceKlass::clean_implementors_list() {
|
||||
assert(is_loader_alive(), "this klass should be live");
|
||||
if (is_interface()) {
|
||||
if (ClassUnloading) {
|
||||
Klass* impl = implementor();
|
||||
if (impl != NULL) {
|
||||
if (!impl->is_loader_alive(is_alive)) {
|
||||
if (!impl->is_loader_alive()) {
|
||||
// remove this guy
|
||||
Klass** klass = adr_implementor();
|
||||
assert(klass != NULL, "null klass");
|
||||
@ -1919,11 +1919,11 @@ void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) {
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceKlass::clean_method_data(BoolObjectClosure* is_alive) {
|
||||
void InstanceKlass::clean_method_data() {
|
||||
for (int m = 0; m < methods()->length(); m++) {
|
||||
MethodData* mdo = methods()->at(m)->method_data();
|
||||
if (mdo != NULL) {
|
||||
mdo->clean_method_data(is_alive);
|
||||
mdo->clean_method_data(/*always_clean*/false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1148,9 +1148,9 @@ public:
|
||||
void adjust_default_methods(InstanceKlass* holder, bool* trace_name_printed);
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
||||
void clean_weak_instanceklass_links(BoolObjectClosure* is_alive);
|
||||
void clean_implementors_list(BoolObjectClosure* is_alive);
|
||||
void clean_method_data(BoolObjectClosure* is_alive);
|
||||
void clean_weak_instanceklass_links();
|
||||
void clean_implementors_list();
|
||||
void clean_method_data();
|
||||
|
||||
// Explicit metaspace deallocation of fields
|
||||
// For RedefineClasses and class file parsing errors, we need to deallocate
|
||||
|
@ -381,22 +381,7 @@ void Klass::append_to_sibling_list() {
|
||||
debug_only(verify();)
|
||||
}
|
||||
|
||||
bool Klass::is_loader_alive(BoolObjectClosure* is_alive) {
|
||||
#ifdef ASSERT
|
||||
// The class is alive iff the class loader is alive.
|
||||
oop loader = class_loader();
|
||||
bool loader_alive = (loader == NULL) || is_alive->do_object_b(loader);
|
||||
#endif // ASSERT
|
||||
|
||||
// The class is alive if it's mirror is alive (which should be marked if the
|
||||
// loader is alive) unless it's an anoymous class.
|
||||
bool mirror_alive = is_alive->do_object_b(java_mirror());
|
||||
assert(!mirror_alive || loader_alive, "loader must be alive if the mirror is"
|
||||
" but not the other way around with anonymous classes");
|
||||
return mirror_alive;
|
||||
}
|
||||
|
||||
void Klass::clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive_klasses) {
|
||||
void Klass::clean_weak_klass_links(bool clean_alive_klasses) {
|
||||
if (!ClassUnloading) {
|
||||
return;
|
||||
}
|
||||
@ -408,11 +393,11 @@ void Klass::clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive
|
||||
while (!stack.is_empty()) {
|
||||
Klass* current = stack.pop();
|
||||
|
||||
assert(current->is_loader_alive(is_alive), "just checking, this should be live");
|
||||
assert(current->is_loader_alive(), "just checking, this should be live");
|
||||
|
||||
// Find and set the first alive subklass
|
||||
Klass* sub = current->subklass();
|
||||
while (sub != NULL && !sub->is_loader_alive(is_alive)) {
|
||||
while (sub != NULL && !sub->is_loader_alive()) {
|
||||
#ifndef PRODUCT
|
||||
if (log_is_enabled(Trace, class, unload)) {
|
||||
ResourceMark rm;
|
||||
@ -428,7 +413,7 @@ void Klass::clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive
|
||||
|
||||
// Find and set the first alive sibling
|
||||
Klass* sibling = current->next_sibling();
|
||||
while (sibling != NULL && !sibling->is_loader_alive(is_alive)) {
|
||||
while (sibling != NULL && !sibling->is_loader_alive()) {
|
||||
if (log_is_enabled(Trace, class, unload)) {
|
||||
ResourceMark rm;
|
||||
log_trace(class, unload)("[Unlinking class (sibling) %s]", sibling->external_name());
|
||||
@ -443,12 +428,12 @@ void Klass::clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive
|
||||
// Clean the implementors list and method data.
|
||||
if (clean_alive_klasses && current->is_instance_klass()) {
|
||||
InstanceKlass* ik = InstanceKlass::cast(current);
|
||||
ik->clean_weak_instanceklass_links(is_alive);
|
||||
ik->clean_weak_instanceklass_links();
|
||||
|
||||
// JVMTI RedefineClasses creates previous versions that are not in
|
||||
// the class hierarchy, so process them here.
|
||||
while ((ik = ik->previous_versions()) != NULL) {
|
||||
ik->clean_weak_instanceklass_links(is_alive);
|
||||
ik->clean_weak_instanceklass_links();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
#ifndef SHARE_VM_OOPS_KLASS_HPP
|
||||
#define SHARE_VM_OOPS_KLASS_HPP
|
||||
|
||||
#include "classfile/classLoaderData.hpp"
|
||||
#include "gc/shared/specialized_oop_closures.hpp"
|
||||
#include "memory/iterator.hpp"
|
||||
#include "memory/memRegion.hpp"
|
||||
@ -52,7 +53,6 @@
|
||||
// Forward declarations.
|
||||
template <class T> class Array;
|
||||
template <class T> class GrowableArray;
|
||||
class ClassLoaderData;
|
||||
class fieldDescriptor;
|
||||
class KlassSizeStats;
|
||||
class klassVtable;
|
||||
@ -634,13 +634,12 @@ protected:
|
||||
virtual MetaspaceObj::Type type() const { return ClassType; }
|
||||
|
||||
// Iff the class loader (or mirror for anonymous classes) is alive the
|
||||
// Klass is considered alive.
|
||||
// The is_alive closure passed in depends on the Garbage Collector used.
|
||||
bool is_loader_alive(BoolObjectClosure* is_alive);
|
||||
// Klass is considered alive. Has already been marked as unloading.
|
||||
bool is_loader_alive() const { return !class_loader_data()->is_unloading(); }
|
||||
|
||||
static void clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive_klasses = true);
|
||||
static void clean_subklass_tree(BoolObjectClosure* is_alive) {
|
||||
clean_weak_klass_links(is_alive, false /* clean_alive_klasses */);
|
||||
static void clean_weak_klass_links(bool clean_alive_klasses = true);
|
||||
static void clean_subklass_tree() {
|
||||
clean_weak_klass_links(false /* clean_alive_klasses */);
|
||||
}
|
||||
|
||||
// GC specific object visitors
|
||||
|
@ -71,9 +71,9 @@ void DataLayout::initialize(u1 tag, u2 bci, int cell_count) {
|
||||
}
|
||||
}
|
||||
|
||||
void DataLayout::clean_weak_klass_links(BoolObjectClosure* cl) {
|
||||
void DataLayout::clean_weak_klass_links(bool always_clean) {
|
||||
ResourceMark m;
|
||||
data_in()->clean_weak_klass_links(cl);
|
||||
data_in()->clean_weak_klass_links(always_clean);
|
||||
}
|
||||
|
||||
|
||||
@ -315,23 +315,20 @@ void VirtualCallTypeData::post_initialize(BytecodeStream* stream, MethodData* md
|
||||
}
|
||||
}
|
||||
|
||||
bool TypeEntries::is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p) {
|
||||
Klass* k = (Klass*)klass_part(p);
|
||||
return k != NULL && k->is_loader_alive(is_alive_cl);
|
||||
}
|
||||
|
||||
void TypeStackSlotEntries::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) {
|
||||
void TypeStackSlotEntries::clean_weak_klass_links(bool always_clean) {
|
||||
for (int i = 0; i < _number_of_entries; i++) {
|
||||
intptr_t p = type(i);
|
||||
if (!is_loader_alive(is_alive_cl, p)) {
|
||||
Klass* k = (Klass*)klass_part(p);
|
||||
if (k != NULL && (always_clean || !k->is_loader_alive())) {
|
||||
set_type(i, with_status((Klass*)NULL, p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReturnTypeEntry::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) {
|
||||
void ReturnTypeEntry::clean_weak_klass_links(bool always_clean) {
|
||||
intptr_t p = type();
|
||||
if (!is_loader_alive(is_alive_cl, p)) {
|
||||
Klass* k = (Klass*)klass_part(p);
|
||||
if (k != NULL && (always_clean || !k->is_loader_alive())) {
|
||||
set_type(with_status((Klass*)NULL, p));
|
||||
}
|
||||
}
|
||||
@ -408,21 +405,21 @@ void VirtualCallTypeData::print_data_on(outputStream* st, const char* extra) con
|
||||
// that the check is reached, and a series of (Klass*, count) pairs
|
||||
// which are used to store a type profile for the receiver of the check.
|
||||
|
||||
void ReceiverTypeData::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) {
|
||||
void ReceiverTypeData::clean_weak_klass_links(bool always_clean) {
|
||||
for (uint row = 0; row < row_limit(); row++) {
|
||||
Klass* p = receiver(row);
|
||||
if (p != NULL && !p->is_loader_alive(is_alive_cl)) {
|
||||
if (p != NULL && (always_clean || !p->is_loader_alive())) {
|
||||
clear_row(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if INCLUDE_JVMCI
|
||||
void VirtualCallData::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) {
|
||||
ReceiverTypeData::clean_weak_klass_links(is_alive_cl);
|
||||
void VirtualCallData::clean_weak_klass_links(bool always_clean) {
|
||||
ReceiverTypeData::clean_weak_klass_links(always_clean);
|
||||
for (uint row = 0; row < method_row_limit(); row++) {
|
||||
Method* p = method(row);
|
||||
if (p != NULL && !p->method_holder()->is_loader_alive(is_alive_cl)) {
|
||||
if (p != NULL && (always_clean || !p->method_holder()->is_loader_alive())) {
|
||||
clear_method_row(row);
|
||||
}
|
||||
}
|
||||
@ -1669,12 +1666,11 @@ public:
|
||||
|
||||
// Check for entries that reference an unloaded method
|
||||
class CleanExtraDataKlassClosure : public CleanExtraDataClosure {
|
||||
private:
|
||||
BoolObjectClosure* _is_alive;
|
||||
bool _always_clean;
|
||||
public:
|
||||
CleanExtraDataKlassClosure(BoolObjectClosure* is_alive) : _is_alive(is_alive) {}
|
||||
CleanExtraDataKlassClosure(bool always_clean) : _always_clean(always_clean) {}
|
||||
bool is_live(Method* m) {
|
||||
return m->method_holder()->is_loader_alive(_is_alive);
|
||||
return !(_always_clean) && m->method_holder()->is_loader_alive();
|
||||
}
|
||||
};
|
||||
|
||||
@ -1757,19 +1753,19 @@ void MethodData::verify_extra_data_clean(CleanExtraDataClosure* cl) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void MethodData::clean_method_data(BoolObjectClosure* is_alive) {
|
||||
void MethodData::clean_method_data(bool always_clean) {
|
||||
ResourceMark rm;
|
||||
for (ProfileData* data = first_data();
|
||||
is_valid(data);
|
||||
data = next_data(data)) {
|
||||
data->clean_weak_klass_links(is_alive);
|
||||
data->clean_weak_klass_links(always_clean);
|
||||
}
|
||||
ParametersTypeData* parameters = parameters_type_data();
|
||||
if (parameters != NULL) {
|
||||
parameters->clean_weak_klass_links(is_alive);
|
||||
parameters->clean_weak_klass_links(always_clean);
|
||||
}
|
||||
|
||||
CleanExtraDataKlassClosure cl(is_alive);
|
||||
CleanExtraDataKlassClosure cl(always_clean);
|
||||
clean_extra_data(&cl);
|
||||
verify_extra_data_clean(&cl);
|
||||
}
|
||||
|
@ -254,7 +254,7 @@ public:
|
||||
ProfileData* data_in();
|
||||
|
||||
// GC support
|
||||
void clean_weak_klass_links(BoolObjectClosure* cl);
|
||||
void clean_weak_klass_links(bool always_clean);
|
||||
|
||||
// Redefinition support
|
||||
void clean_weak_method_links();
|
||||
@ -505,7 +505,7 @@ public:
|
||||
virtual void post_initialize(BytecodeStream* stream, MethodData* mdo) {}
|
||||
|
||||
// GC support
|
||||
virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {}
|
||||
virtual void clean_weak_klass_links(bool always_clean) {}
|
||||
|
||||
// Redefinition support
|
||||
virtual void clean_weak_method_links() {}
|
||||
@ -820,9 +820,6 @@ public:
|
||||
|
||||
static void print_klass(outputStream* st, intptr_t k);
|
||||
|
||||
// GC support
|
||||
static bool is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p);
|
||||
|
||||
protected:
|
||||
// ProfileData object these entries are part of
|
||||
ProfileData* _pd;
|
||||
@ -930,7 +927,7 @@ public:
|
||||
}
|
||||
|
||||
// GC support
|
||||
void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
|
||||
void clean_weak_klass_links(bool always_clean);
|
||||
|
||||
void print_data_on(outputStream* st) const;
|
||||
};
|
||||
@ -973,7 +970,7 @@ public:
|
||||
}
|
||||
|
||||
// GC support
|
||||
void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
|
||||
void clean_weak_klass_links(bool always_clean);
|
||||
|
||||
void print_data_on(outputStream* st) const;
|
||||
};
|
||||
@ -1157,12 +1154,12 @@ public:
|
||||
}
|
||||
|
||||
// GC support
|
||||
virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {
|
||||
virtual void clean_weak_klass_links(bool always_clean) {
|
||||
if (has_arguments()) {
|
||||
_args.clean_weak_klass_links(is_alive_closure);
|
||||
_args.clean_weak_klass_links(always_clean);
|
||||
}
|
||||
if (has_return()) {
|
||||
_ret.clean_weak_klass_links(is_alive_closure);
|
||||
_ret.clean_weak_klass_links(always_clean);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1303,7 +1300,7 @@ public:
|
||||
}
|
||||
|
||||
// GC support
|
||||
virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
|
||||
virtual void clean_weak_klass_links(bool always_clean);
|
||||
|
||||
#ifdef CC_INTERP
|
||||
static int receiver_type_data_size_in_bytes() {
|
||||
@ -1433,7 +1430,7 @@ public:
|
||||
}
|
||||
|
||||
// GC support
|
||||
virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
|
||||
virtual void clean_weak_klass_links(bool always_clean);
|
||||
|
||||
// Redefinition support
|
||||
virtual void clean_weak_method_links();
|
||||
@ -1562,13 +1559,13 @@ public:
|
||||
}
|
||||
|
||||
// GC support
|
||||
virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {
|
||||
ReceiverTypeData::clean_weak_klass_links(is_alive_closure);
|
||||
virtual void clean_weak_klass_links(bool always_clean) {
|
||||
ReceiverTypeData::clean_weak_klass_links(always_clean);
|
||||
if (has_arguments()) {
|
||||
_args.clean_weak_klass_links(is_alive_closure);
|
||||
_args.clean_weak_klass_links(always_clean);
|
||||
}
|
||||
if (has_return()) {
|
||||
_ret.clean_weak_klass_links(is_alive_closure);
|
||||
_ret.clean_weak_klass_links(always_clean);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2021,8 +2018,8 @@ public:
|
||||
_parameters.set_type(i, TypeEntries::with_status((intptr_t)k, current));
|
||||
}
|
||||
|
||||
virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {
|
||||
_parameters.clean_weak_klass_links(is_alive_closure);
|
||||
virtual void clean_weak_klass_links(bool always_clean) {
|
||||
_parameters.clean_weak_klass_links(always_clean);
|
||||
}
|
||||
|
||||
virtual void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
@ -2610,7 +2607,7 @@ public:
|
||||
static bool profile_parameters();
|
||||
static bool profile_return_jsr292_only();
|
||||
|
||||
void clean_method_data(BoolObjectClosure* is_alive);
|
||||
void clean_method_data(bool always_clean);
|
||||
void clean_weak_method_links();
|
||||
DEBUG_ONLY(void verify_clean_weak_method_links();)
|
||||
Mutex* extra_data_lock() { return &_extra_data_lock; }
|
||||
|
@ -933,8 +933,6 @@ WB_ENTRY(jint, WB_MatchesMethod(JNIEnv* env, jobject o, jobject method, jstring
|
||||
return result;
|
||||
WB_END
|
||||
|
||||
static AlwaysFalseClosure always_false;
|
||||
|
||||
WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
|
||||
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
|
||||
CHECK_JNI_EXCEPTION(env);
|
||||
@ -951,7 +949,7 @@ WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
|
||||
mdo->set_arg_modified(i, 0);
|
||||
}
|
||||
MutexLockerEx mu(mdo->extra_data_lock());
|
||||
mdo->clean_method_data(&always_false);
|
||||
mdo->clean_method_data(/*always_clean*/true);
|
||||
}
|
||||
|
||||
mh->clear_not_c1_compilable();
|
||||
|
Loading…
x
Reference in New Issue
Block a user