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:
Coleen Phillimore 2018-04-18 13:37:39 -04:00
parent 4ffd5d45c1
commit c215aa5889
18 changed files with 130 additions and 174 deletions

View File

@ -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

View File

@ -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();

View File

@ -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;
}

View File

@ -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.

View File

@ -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.

View File

@ -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();
}
{

View File

@ -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() {
}

View File

@ -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();
}
{

View File

@ -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();
}
{

View File

@ -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();
}
{

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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();
}
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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; }

View File

@ -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();