8309140: ResourceHashtable failed "assert(~(_allocation_t[0] | allocation_mask) == (uintptr_t)this) failed: lost resource object"

Reviewed-by: coleenp, matsaave, dholmes
This commit is contained in:
Justin Gu 2023-06-28 17:10:16 +00:00 committed by Coleen Phillimore
parent 9f98136c3a
commit b6c789faad
11 changed files with 98 additions and 58 deletions

View file

@ -109,7 +109,8 @@ class ConstraintSet { // copied into hashtable as
}; };
ResourceHashtable<SymbolHandle, ConstraintSet, 107, AnyObj::C_HEAP, mtClass, SymbolHandle::compute_hash> _loader_constraint_table; using InternalLoaderConstraintTable = ResourceHashtable<SymbolHandle, ConstraintSet, 107, AnyObj::C_HEAP, mtClass, SymbolHandle::compute_hash>;
static InternalLoaderConstraintTable* _loader_constraint_table;
void LoaderConstraint::extend_loader_constraint(Symbol* class_name, void LoaderConstraint::extend_loader_constraint(Symbol* class_name,
ClassLoaderData* loader, ClassLoaderData* loader,
@ -134,11 +135,15 @@ void LoaderConstraint::extend_loader_constraint(Symbol* class_name,
// SystemDictionary lock held. This is true even for readers as // SystemDictionary lock held. This is true even for readers as
// entries in the table could be being dynamically resized. // entries in the table could be being dynamically resized.
void LoaderConstraintTable::initialize() {
_loader_constraint_table = new (mtClass) InternalLoaderConstraintTable();
}
LoaderConstraint* LoaderConstraintTable::find_loader_constraint( LoaderConstraint* LoaderConstraintTable::find_loader_constraint(
Symbol* name, ClassLoaderData* loader_data) { Symbol* name, ClassLoaderData* loader_data) {
assert_lock_strong(SystemDictionary_lock); assert_lock_strong(SystemDictionary_lock);
ConstraintSet* set = _loader_constraint_table.get(name); ConstraintSet* set = _loader_constraint_table->get(name);
if (set == nullptr) { if (set == nullptr) {
return nullptr; return nullptr;
} }
@ -167,7 +172,7 @@ void LoaderConstraintTable::add_loader_constraint(Symbol* name, InstanceKlass* k
// a parameter name to a method call. We impose this constraint that the // a parameter name to a method call. We impose this constraint that the
// class that is eventually loaded must match between these two loaders. // class that is eventually loaded must match between these two loaders.
bool created; bool created;
ConstraintSet* set = _loader_constraint_table.put_if_absent(name, &created); ConstraintSet* set = _loader_constraint_table->put_if_absent(name, &created);
if (created) { if (created) {
set->initialize(constraint); set->initialize(constraint);
} else { } else {
@ -249,7 +254,7 @@ void LoaderConstraintTable::purge_loader_constraints() {
assert_locked_or_safepoint(SystemDictionary_lock); assert_locked_or_safepoint(SystemDictionary_lock);
// Remove unloaded entries from constraint table // Remove unloaded entries from constraint table
PurgeUnloadedConstraints purge; PurgeUnloadedConstraints purge;
_loader_constraint_table.unlink(&purge); _loader_constraint_table->unlink(&purge);
} }
void log_ldr_constraint_msg(Symbol* class_name, const char* reason, void log_ldr_constraint_msg(Symbol* class_name, const char* reason,
@ -441,7 +446,7 @@ void LoaderConstraintTable::merge_loader_constraints(Symbol* class_name,
} }
// Remove src from set // Remove src from set
ConstraintSet* set = _loader_constraint_table.get(class_name); ConstraintSet* set = _loader_constraint_table->get(class_name);
set->remove_constraint(src); set->remove_constraint(src);
} }
@ -480,7 +485,7 @@ void LoaderConstraintTable::verify() {
} }
}; };
assert_locked_or_safepoint(SystemDictionary_lock); assert_locked_or_safepoint(SystemDictionary_lock);
_loader_constraint_table.iterate_all(check); _loader_constraint_table->iterate_all(check);
} }
void LoaderConstraintTable::print_table_statistics(outputStream* st) { void LoaderConstraintTable::print_table_statistics(outputStream* st) {
@ -494,7 +499,7 @@ void LoaderConstraintTable::print_table_statistics(outputStream* st) {
} }
return sum; return sum;
}; };
TableStatistics ts = _loader_constraint_table.statistics_calculate(size); TableStatistics ts = _loader_constraint_table->statistics_calculate(size);
ts.print(st, "LoaderConstraintTable"); ts.print(st, "LoaderConstraintTable");
} }
@ -516,8 +521,8 @@ void LoaderConstraintTable::print_on(outputStream* st) {
assert_locked_or_safepoint(SystemDictionary_lock); assert_locked_or_safepoint(SystemDictionary_lock);
ResourceMark rm; ResourceMark rm;
st->print_cr("Java loader constraints (table_size=%d, constraints=%d)", st->print_cr("Java loader constraints (table_size=%d, constraints=%d)",
_loader_constraint_table.table_size(), _loader_constraint_table.number_of_entries()); _loader_constraint_table->table_size(), _loader_constraint_table->number_of_entries());
_loader_constraint_table.iterate_all(printer); _loader_constraint_table->iterate_all(printer);
} }
void LoaderConstraintTable::print() { print_on(tty); } void LoaderConstraintTable::print() { print_on(tty); }

View file

@ -43,7 +43,7 @@ private:
static void merge_loader_constraints(Symbol* class_name, LoaderConstraint* pp1, static void merge_loader_constraints(Symbol* class_name, LoaderConstraint* pp1,
LoaderConstraint* pp2, InstanceKlass* klass); LoaderConstraint* pp2, InstanceKlass* klass);
public: public:
static void initialize();
// Check class loader constraints // Check class loader constraints
static bool add_entry(Symbol* name, InstanceKlass* klass1, ClassLoaderData* loader1, static bool add_entry(Symbol* name, InstanceKlass* klass1, ClassLoaderData* loader1,
InstanceKlass* klass2, ClassLoaderData* loader2); InstanceKlass* klass2, ClassLoaderData* loader2);

View file

@ -50,8 +50,9 @@ class PlaceholderKey {
}; };
const int _placeholder_table_size = 503; // Does this really have to be prime? const int _placeholder_table_size = 503; // Does this really have to be prime?
ResourceHashtable<PlaceholderKey, PlaceholderEntry, _placeholder_table_size, AnyObj::C_HEAP, mtClass, using InternalPlaceholderTable = ResourceHashtable<PlaceholderKey, PlaceholderEntry, _placeholder_table_size, AnyObj::C_HEAP, mtClass,
PlaceholderKey::hash, PlaceholderKey::equals> _placeholders; PlaceholderKey::hash, PlaceholderKey::equals>;
static InternalPlaceholderTable* _placeholders;
// SeenThread objects represent list of threads that are // SeenThread objects represent list of threads that are
// currently performing a load action on a class. // currently performing a load action on a class.
@ -207,7 +208,7 @@ PlaceholderEntry* add_entry(Symbol* class_name, ClassLoaderData* loader_data,
entry.set_supername(supername); entry.set_supername(supername);
PlaceholderKey key(class_name, loader_data); PlaceholderKey key(class_name, loader_data);
bool created; bool created;
PlaceholderEntry* table_copy = _placeholders.put_if_absent(key, entry, &created); PlaceholderEntry* table_copy = _placeholders->put_if_absent(key, entry, &created);
assert(created, "better be absent"); assert(created, "better be absent");
return table_copy; return table_copy;
} }
@ -217,14 +218,14 @@ void remove_entry(Symbol* class_name, ClassLoaderData* loader_data) {
assert_locked_or_safepoint(SystemDictionary_lock); assert_locked_or_safepoint(SystemDictionary_lock);
PlaceholderKey key(class_name, loader_data); PlaceholderKey key(class_name, loader_data);
_placeholders.remove(key); _placeholders->remove(key);
} }
PlaceholderEntry* PlaceholderTable::get_entry(Symbol* class_name, ClassLoaderData* loader_data) { PlaceholderEntry* PlaceholderTable::get_entry(Symbol* class_name, ClassLoaderData* loader_data) {
assert_locked_or_safepoint(SystemDictionary_lock); assert_locked_or_safepoint(SystemDictionary_lock);
PlaceholderKey key(class_name, loader_data); PlaceholderKey key(class_name, loader_data);
return _placeholders.get(key); return _placeholders->get(key);
} }
static const char* action_to_string(PlaceholderTable::classloadAction action) { static const char* action_to_string(PlaceholderTable::classloadAction action) {
@ -271,6 +272,10 @@ PlaceholderEntry* PlaceholderTable::find_and_add(Symbol* name,
return probe; return probe;
} }
void PlaceholderTable::initialize(){
_placeholders = new (mtClass) InternalPlaceholderTable();
}
// placeholder is used to track class loading internal states // placeholder is used to track class loading internal states
// superthreadQ tracks class circularity, while loading superclass/superinterface // superthreadQ tracks class circularity, while loading superclass/superinterface
@ -340,8 +345,8 @@ void PlaceholderTable::print_on(outputStream* st) {
return true; return true;
}; };
st->print_cr("Placeholder table (table_size=%d, placeholders=%d)", st->print_cr("Placeholder table (table_size=%d, placeholders=%d)",
_placeholders.table_size(), _placeholders.number_of_entries()); _placeholders->table_size(), _placeholders->number_of_entries());
_placeholders.iterate(printer); _placeholders->iterate(printer);
} }
void PlaceholderTable::print() { return print_on(tty); } void PlaceholderTable::print() { return print_on(tty); }

View file

@ -52,7 +52,7 @@ class PlaceholderTable : public AllStatic {
LOAD_SUPER = 2, // loading superclass for this class LOAD_SUPER = 2, // loading superclass for this class
DEFINE_CLASS = 3 // find_or_define class DEFINE_CLASS = 3 // find_or_define class
}; };
static void initialize();
static PlaceholderEntry* get_entry(Symbol* name, ClassLoaderData* loader_data); static PlaceholderEntry* get_entry(Symbol* name, ClassLoaderData* loader_data);
// find_and_add returns probe pointer - old or new // find_and_add returns probe pointer - old or new

View file

@ -51,13 +51,17 @@ bool ProtectionDomainCacheTable::equals(const WeakHandle& protection_domain1, co
// WeakHandle is both the key and the value. We need it as the key to compare the oops that each point to // WeakHandle is both the key and the value. We need it as the key to compare the oops that each point to
// for equality. We need it as the value to return the one that already exists to link in the DictionaryEntry. // for equality. We need it as the value to return the one that already exists to link in the DictionaryEntry.
ResourceHashtable<WeakHandle, WeakHandle, 1009, AnyObj::C_HEAP, mtClass, using InternalProtectionDomainCacheTable = ResourceHashtable<WeakHandle, WeakHandle, 1009, AnyObj::C_HEAP, mtClass,
ProtectionDomainCacheTable::compute_hash, ProtectionDomainCacheTable::compute_hash,
ProtectionDomainCacheTable::equals> _pd_cache_table; ProtectionDomainCacheTable::equals>;
static InternalProtectionDomainCacheTable* _pd_cache_table;
bool ProtectionDomainCacheTable::_dead_entries = false; bool ProtectionDomainCacheTable::_dead_entries = false;
int ProtectionDomainCacheTable::_total_oops_removed = 0; int ProtectionDomainCacheTable::_total_oops_removed = 0;
void ProtectionDomainCacheTable::initialize(){
_pd_cache_table = new (mtClass) InternalProtectionDomainCacheTable();
}
void ProtectionDomainCacheTable::trigger_cleanup() { void ProtectionDomainCacheTable::trigger_cleanup() {
MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag); MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
_dead_entries = true; _dead_entries = true;
@ -159,7 +163,7 @@ void ProtectionDomainCacheTable::unlink() {
}; };
Deleter deleter; Deleter deleter;
_pd_cache_table.unlink(&deleter); _pd_cache_table->unlink(&deleter);
_total_oops_removed += deleter._oops_removed; _total_oops_removed += deleter._oops_removed;
_dead_entries = false; _dead_entries = false;
@ -171,15 +175,15 @@ void ProtectionDomainCacheTable::print_on(outputStream* st) {
st->print_cr(" protection_domain: " PTR_FORMAT, p2i(value.peek())); st->print_cr(" protection_domain: " PTR_FORMAT, p2i(value.peek()));
}; };
st->print_cr("Protection domain cache table (table_size=%d, protection domains=%d)", st->print_cr("Protection domain cache table (table_size=%d, protection domains=%d)",
_pd_cache_table.table_size(), _pd_cache_table.number_of_entries()); _pd_cache_table->table_size(), _pd_cache_table->number_of_entries());
_pd_cache_table.iterate_all(printer); _pd_cache_table->iterate_all(printer);
} }
void ProtectionDomainCacheTable::verify() { void ProtectionDomainCacheTable::verify() {
auto verifier = [&] (WeakHandle& key, WeakHandle& value) { auto verifier = [&] (WeakHandle& key, WeakHandle& value) {
guarantee(value.peek() == nullptr || oopDesc::is_oop(value.peek()), "must be an oop"); guarantee(value.peek() == nullptr || oopDesc::is_oop(value.peek()), "must be an oop");
}; };
_pd_cache_table.iterate_all(verifier); _pd_cache_table->iterate_all(verifier);
} }
// The object_no_keepalive() call peeks at the phantomly reachable oop without // The object_no_keepalive() call peeks at the phantomly reachable oop without
@ -192,7 +196,7 @@ WeakHandle ProtectionDomainCacheTable::add_if_absent(Handle protection_domain) {
assert_locked_or_safepoint(SystemDictionary_lock); assert_locked_or_safepoint(SystemDictionary_lock);
WeakHandle w(Universe::vm_weak(), protection_domain); WeakHandle w(Universe::vm_weak(), protection_domain);
bool created; bool created;
WeakHandle* wk = _pd_cache_table.put_if_absent(w, w, &created); WeakHandle* wk = _pd_cache_table->put_if_absent(w, w, &created);
if (!created) { if (!created) {
// delete the one created since we already had it in the table // delete the one created since we already had it in the table
w.release(Universe::vm_weak()); w.release(Universe::vm_weak());
@ -215,10 +219,10 @@ void ProtectionDomainCacheTable::print_table_statistics(outputStream* st) {
// The only storage is in OopStorage for an oop // The only storage is in OopStorage for an oop
return sizeof(oop); return sizeof(oop);
}; };
TableStatistics ts = _pd_cache_table.statistics_calculate(size); TableStatistics ts = _pd_cache_table->statistics_calculate(size);
ts.print(st, "ProtectionDomainCacheTable"); ts.print(st, "ProtectionDomainCacheTable");
} }
int ProtectionDomainCacheTable::number_of_entries() { int ProtectionDomainCacheTable::number_of_entries() {
return _pd_cache_table.number_of_entries(); return _pd_cache_table->number_of_entries();
} }

View file

@ -39,6 +39,7 @@ class ProtectionDomainCacheTable : public AllStatic {
static int _total_oops_removed; static int _total_oops_removed;
public: public:
static void initialize();
static unsigned int compute_hash(const WeakHandle& protection_domain); static unsigned int compute_hash(const WeakHandle& protection_domain);
static bool equals(const WeakHandle& protection_domain1, const WeakHandle& protection_domain2); static bool equals(const WeakHandle& protection_domain1, const WeakHandle& protection_domain2);

View file

@ -54,9 +54,15 @@ class ResolutionErrorKey {
} }
}; };
ResourceHashtable<ResolutionErrorKey, ResolutionErrorEntry*, 107, AnyObj::C_HEAP, mtClass, using InternalResolutionErrorTable = ResourceHashtable<ResolutionErrorKey, ResolutionErrorEntry*, 107, AnyObj::C_HEAP, mtClass,
ResolutionErrorKey::hash, ResolutionErrorKey::hash,
ResolutionErrorKey::equals> _resolution_error_table; ResolutionErrorKey::equals>;
static InternalResolutionErrorTable* _resolution_error_table;
void ResolutionErrorTable::initialize() {
_resolution_error_table = new (mtClass) InternalResolutionErrorTable();
}
// create new error entry // create new error entry
void ResolutionErrorTable::add_entry(const constantPoolHandle& pool, int cp_index, void ResolutionErrorTable::add_entry(const constantPoolHandle& pool, int cp_index,
@ -68,7 +74,7 @@ void ResolutionErrorTable::add_entry(const constantPoolHandle& pool, int cp_inde
ResolutionErrorKey key(pool(), cp_index); ResolutionErrorKey key(pool(), cp_index);
ResolutionErrorEntry *entry = new ResolutionErrorEntry(error, message, cause, cause_msg); ResolutionErrorEntry *entry = new ResolutionErrorEntry(error, message, cause, cause_msg);
_resolution_error_table.put(key, entry); _resolution_error_table->put(key, entry);
} }
// create new nest host error entry // create new nest host error entry
@ -80,14 +86,14 @@ void ResolutionErrorTable::add_entry(const constantPoolHandle& pool, int cp_inde
ResolutionErrorKey key(pool(), cp_index); ResolutionErrorKey key(pool(), cp_index);
ResolutionErrorEntry *entry = new ResolutionErrorEntry(message); ResolutionErrorEntry *entry = new ResolutionErrorEntry(message);
_resolution_error_table.put(key, entry); _resolution_error_table->put(key, entry);
} }
// find entry in the table // find entry in the table
ResolutionErrorEntry* ResolutionErrorTable::find_entry(const constantPoolHandle& pool, int cp_index) { ResolutionErrorEntry* ResolutionErrorTable::find_entry(const constantPoolHandle& pool, int cp_index) {
assert_locked_or_safepoint(SystemDictionary_lock); assert_locked_or_safepoint(SystemDictionary_lock);
ResolutionErrorKey key(pool(), cp_index); ResolutionErrorKey key(pool(), cp_index);
ResolutionErrorEntry** entry = _resolution_error_table.get(key); ResolutionErrorEntry** entry = _resolution_error_table->get(key);
return entry == nullptr ? nullptr : *entry; return entry == nullptr ? nullptr : *entry;
} }
@ -139,7 +145,7 @@ void ResolutionErrorTable::delete_entry(ConstantPool* c) {
assert_locked_or_safepoint(SystemDictionary_lock); assert_locked_or_safepoint(SystemDictionary_lock);
ResolutionErrorDeleteIterate deleteIterator(c); ResolutionErrorDeleteIterate deleteIterator(c);
_resolution_error_table.unlink(&deleteIterator); _resolution_error_table->unlink(&deleteIterator);
} }
class ResolutionIteratePurgeErrors : StackObj { class ResolutionIteratePurgeErrors : StackObj {
@ -160,5 +166,5 @@ void ResolutionErrorTable::purge_resolution_errors() {
assert_locked_or_safepoint(SystemDictionary_lock); assert_locked_or_safepoint(SystemDictionary_lock);
ResolutionIteratePurgeErrors purgeErrorsIterator; ResolutionIteratePurgeErrors purgeErrorsIterator;
_resolution_error_table.unlink(&purgeErrorsIterator); _resolution_error_table->unlink(&purgeErrorsIterator);
} }

View file

@ -35,6 +35,7 @@ class ResolutionErrorEntry;
class ResolutionErrorTable : AllStatic { class ResolutionErrorTable : AllStatic {
public: public:
static void initialize();
static void add_entry(const constantPoolHandle& pool, int which, Symbol* error, Symbol* message, static void add_entry(const constantPoolHandle& pool, int which, Symbol* error, Symbol* message,
Symbol* cause, Symbol* cause_msg); Symbol* cause, Symbol* cause_msg);

View file

@ -113,9 +113,11 @@ class InvokeMethodKey : public StackObj {
}; };
ResourceHashtable<InvokeMethodKey, Method*, 139, AnyObj::C_HEAP, mtClass, using InvokeMethodIntrinsicTable = ResourceHashtable<InvokeMethodKey, Method*, 139, AnyObj::C_HEAP, mtClass,
InvokeMethodKey::compute_hash, InvokeMethodKey::key_comparison> _invoke_method_intrinsic_table; InvokeMethodKey::compute_hash, InvokeMethodKey::key_comparison>;
ResourceHashtable<SymbolHandle, OopHandle, 139, AnyObj::C_HEAP, mtClass, SymbolHandle::compute_hash> _invoke_method_type_table; static InvokeMethodIntrinsicTable* _invoke_method_intrinsic_table;
using InvokeMethodTypeTable = ResourceHashtable<SymbolHandle, OopHandle, 139, AnyObj::C_HEAP, mtClass, SymbolHandle::compute_hash>;
static InvokeMethodTypeTable* _invoke_method_type_table;
OopHandle SystemDictionary::_java_system_loader; OopHandle SystemDictionary::_java_system_loader;
OopHandle SystemDictionary::_java_platform_loader; OopHandle SystemDictionary::_java_platform_loader;
@ -1592,7 +1594,7 @@ void SystemDictionary::methods_do(void f(Method*)) {
{ {
MutexLocker ml(InvokeMethodIntrinsicTable_lock); MutexLocker ml(InvokeMethodIntrinsicTable_lock);
_invoke_method_intrinsic_table.iterate_all(doit); _invoke_method_intrinsic_table->iterate_all(doit);
} }
} }
@ -1601,10 +1603,15 @@ void SystemDictionary::methods_do(void f(Method*)) {
// Initialization // Initialization
void SystemDictionary::initialize(TRAPS) { void SystemDictionary::initialize(TRAPS) {
_invoke_method_intrinsic_table = new (mtClass) InvokeMethodIntrinsicTable();
_invoke_method_type_table = new (mtClass) InvokeMethodTypeTable();
ResolutionErrorTable::initialize();
LoaderConstraintTable::initialize();
PlaceholderTable::initialize();
ProtectionDomainCacheTable::initialize();
#if INCLUDE_CDS #if INCLUDE_CDS
SystemDictionaryShared::initialize(); SystemDictionaryShared::initialize();
#endif #endif
// Resolve basic classes // Resolve basic classes
vmClasses::resolve_all(CHECK); vmClasses::resolve_all(CHECK);
// Resolve classes used by archived heap objects // Resolve classes used by archived heap objects
@ -1954,7 +1961,7 @@ Method* SystemDictionary::find_method_handle_intrinsic(vmIntrinsicID iid,
MonitorLocker ml(THREAD, InvokeMethodIntrinsicTable_lock); MonitorLocker ml(THREAD, InvokeMethodIntrinsicTable_lock);
while (true) { while (true) {
bool created; bool created;
met = _invoke_method_intrinsic_table.put_if_absent(key, &created); met = _invoke_method_intrinsic_table->put_if_absent(key, &created);
assert(met != nullptr, "either created or found"); assert(met != nullptr, "either created or found");
if (*met != nullptr) { if (*met != nullptr) {
return *met; return *met;
@ -1985,7 +1992,7 @@ Method* SystemDictionary::find_method_handle_intrinsic(vmIntrinsicID iid,
MonitorLocker ml(THREAD, InvokeMethodIntrinsicTable_lock); MonitorLocker ml(THREAD, InvokeMethodIntrinsicTable_lock);
if (throw_error) { if (throw_error) {
// Remove the entry and let another thread try, or get the same exception. // Remove the entry and let another thread try, or get the same exception.
bool removed = _invoke_method_intrinsic_table.remove(key); bool removed = _invoke_method_intrinsic_table->remove(key);
assert(removed, "must be the owner"); assert(removed, "must be the owner");
ml.notify_all(); ml.notify_all();
} else { } else {
@ -2148,7 +2155,7 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature,
OopHandle* o; OopHandle* o;
{ {
MutexLocker ml(THREAD, InvokeMethodTypeTable_lock); MutexLocker ml(THREAD, InvokeMethodTypeTable_lock);
o = _invoke_method_type_table.get(signature); o = _invoke_method_type_table->get(signature);
} }
if (o != nullptr) { if (o != nullptr) {
@ -2219,11 +2226,11 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature,
MutexLocker ml(THREAD, InvokeMethodTypeTable_lock); MutexLocker ml(THREAD, InvokeMethodTypeTable_lock);
bool created = false; bool created = false;
assert(method_type != nullptr, "unexpected null"); assert(method_type != nullptr, "unexpected null");
OopHandle* h = _invoke_method_type_table.get(signature); OopHandle* h = _invoke_method_type_table->get(signature);
if (h == nullptr) { if (h == nullptr) {
signature->make_permanent(); // The signature is never unloaded. signature->make_permanent(); // The signature is never unloaded.
OopHandle elem = OopHandle(Universe::vm_global(), method_type()); OopHandle elem = OopHandle(Universe::vm_global(), method_type());
bool created = _invoke_method_type_table.put(signature, elem); bool created = _invoke_method_type_table->put(signature, elem);
assert(created, "better be created"); assert(created, "better be created");
} }
} }

View file

@ -978,8 +978,8 @@ void InstanceKlass::initialize_super_interfaces(TRAPS) {
} }
} }
ResourceHashtable<const InstanceKlass*, OopHandle, 107, AnyObj::C_HEAP, mtClass> using InitializationErrorTable = ResourceHashtable<const InstanceKlass*, OopHandle, 107, AnyObj::C_HEAP, mtClass>;
_initialization_error_table; static InitializationErrorTable* _initialization_error_table;
void InstanceKlass::add_initialization_error(JavaThread* current, Handle exception) { void InstanceKlass::add_initialization_error(JavaThread* current, Handle exception) {
// Create the same exception with a message indicating the thread name, // Create the same exception with a message indicating the thread name,
@ -1006,14 +1006,20 @@ void InstanceKlass::add_initialization_error(JavaThread* current, Handle excepti
MutexLocker ml(current, ClassInitError_lock); MutexLocker ml(current, ClassInitError_lock);
OopHandle elem = OopHandle(Universe::vm_global(), init_error()); OopHandle elem = OopHandle(Universe::vm_global(), init_error());
bool created; bool created;
_initialization_error_table.put_if_absent(this, elem, &created); if (_initialization_error_table == nullptr) {
_initialization_error_table = new (mtClass) InitializationErrorTable();
}
_initialization_error_table->put_if_absent(this, elem, &created);
assert(created, "Initialization is single threaded"); assert(created, "Initialization is single threaded");
log_trace(class, init)("Initialization error added for class %s", external_name()); log_trace(class, init)("Initialization error added for class %s", external_name());
} }
oop InstanceKlass::get_initialization_error(JavaThread* current) { oop InstanceKlass::get_initialization_error(JavaThread* current) {
MutexLocker ml(current, ClassInitError_lock); MutexLocker ml(current, ClassInitError_lock);
OopHandle* h = _initialization_error_table.get(this); if (_initialization_error_table == nullptr) {
return nullptr;
}
OopHandle* h = _initialization_error_table->get(this);
return (h != nullptr) ? h->resolve() : nullptr; return (h != nullptr) ? h->resolve() : nullptr;
} }
@ -1032,7 +1038,9 @@ void InstanceKlass::clean_initialization_error_table() {
assert_locked_or_safepoint(ClassInitError_lock); assert_locked_or_safepoint(ClassInitError_lock);
InitErrorTableCleaner cleaner; InitErrorTableCleaner cleaner;
_initialization_error_table.unlink(&cleaner); if (_initialization_error_table != nullptr) {
_initialization_error_table->unlink(&cleaner);
}
} }
void InstanceKlass::initialize_impl(TRAPS) { void InstanceKlass::initialize_impl(TRAPS) {
@ -4352,3 +4360,4 @@ void ClassHierarchyIterator::next() {
_current = _current->next_sibling(); _current = _current->next_sibling();
return; // visit next sibling subclass return; // visit next sibling subclass
} }

View file

@ -2627,17 +2627,18 @@ class AdapterFingerPrint : public CHeapObj<mtCode> {
}; };
// A hashtable mapping from AdapterFingerPrints to AdapterHandlerEntries // A hashtable mapping from AdapterFingerPrints to AdapterHandlerEntries
ResourceHashtable<AdapterFingerPrint*, AdapterHandlerEntry*, 293, using AdapterHandlerTable = ResourceHashtable<AdapterFingerPrint*, AdapterHandlerEntry*, 293,
AnyObj::C_HEAP, mtCode, AnyObj::C_HEAP, mtCode,
AdapterFingerPrint::compute_hash, AdapterFingerPrint::compute_hash,
AdapterFingerPrint::equals> _adapter_handler_table; AdapterFingerPrint::equals>;
static AdapterHandlerTable* _adapter_handler_table;
// Find a entry with the same fingerprint if it exists // Find a entry with the same fingerprint if it exists
static AdapterHandlerEntry* lookup(int total_args_passed, BasicType* sig_bt) { static AdapterHandlerEntry* lookup(int total_args_passed, BasicType* sig_bt) {
NOT_PRODUCT(_lookups++); NOT_PRODUCT(_lookups++);
assert_lock_strong(AdapterHandlerLibrary_lock); assert_lock_strong(AdapterHandlerLibrary_lock);
AdapterFingerPrint fp(total_args_passed, sig_bt); AdapterFingerPrint fp(total_args_passed, sig_bt);
AdapterHandlerEntry** entry = _adapter_handler_table.get(&fp); AdapterHandlerEntry** entry = _adapter_handler_table->get(&fp);
if (entry != nullptr) { if (entry != nullptr) {
#ifndef PRODUCT #ifndef PRODUCT
if (fp.is_compact()) _compact++; if (fp.is_compact()) _compact++;
@ -2653,10 +2654,10 @@ static void print_table_statistics() {
auto size = [&] (AdapterFingerPrint* key, AdapterHandlerEntry* a) { auto size = [&] (AdapterFingerPrint* key, AdapterHandlerEntry* a) {
return sizeof(*key) + sizeof(*a); return sizeof(*key) + sizeof(*a);
}; };
TableStatistics ts = _adapter_handler_table.statistics_calculate(size); TableStatistics ts = _adapter_handler_table->statistics_calculate(size);
ts.print(tty, "AdapterHandlerTable"); ts.print(tty, "AdapterHandlerTable");
tty->print_cr("AdapterHandlerTable (table_size=%d, entries=%d)", tty->print_cr("AdapterHandlerTable (table_size=%d, entries=%d)",
_adapter_handler_table.table_size(), _adapter_handler_table.number_of_entries()); _adapter_handler_table->table_size(), _adapter_handler_table->number_of_entries());
tty->print_cr("AdapterHandlerTable: lookups %d equals %d hits %d compact %d", tty->print_cr("AdapterHandlerTable: lookups %d equals %d hits %d compact %d",
_lookups, _equals, _hits, _compact); _lookups, _equals, _hits, _compact);
} }
@ -2704,6 +2705,7 @@ void AdapterHandlerLibrary::initialize() {
AdapterBlob* obj_int_arg_blob = nullptr; AdapterBlob* obj_int_arg_blob = nullptr;
AdapterBlob* obj_obj_arg_blob = nullptr; AdapterBlob* obj_obj_arg_blob = nullptr;
{ {
_adapter_handler_table = new (mtCode) AdapterHandlerTable();
MutexLocker mu(AdapterHandlerLibrary_lock); MutexLocker mu(AdapterHandlerLibrary_lock);
// Create a special handler for abstract methods. Abstract methods // Create a special handler for abstract methods. Abstract methods
@ -2945,7 +2947,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::create_adapter(AdapterBlob*& new_ada
ttyLocker ttyl; ttyLocker ttyl;
entry->print_adapter_on(tty); entry->print_adapter_on(tty);
tty->print_cr("i2c argument handler #%d for: %s %s (%d bytes generated)", tty->print_cr("i2c argument handler #%d for: %s %s (%d bytes generated)",
_adapter_handler_table.number_of_entries(), fingerprint->as_basic_args_string(), _adapter_handler_table->number_of_entries(), fingerprint->as_basic_args_string(),
fingerprint->as_string(), insts_size); fingerprint->as_string(), insts_size);
tty->print_cr("c2i argument handler starts at " INTPTR_FORMAT, p2i(entry->get_c2i_entry())); tty->print_cr("c2i argument handler starts at " INTPTR_FORMAT, p2i(entry->get_c2i_entry()));
if (Verbose || PrintStubCode) { if (Verbose || PrintStubCode) {
@ -2963,7 +2965,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::create_adapter(AdapterBlob*& new_ada
// The checks are inserted only if -XX:+VerifyAdapterCalls is specified. // The checks are inserted only if -XX:+VerifyAdapterCalls is specified.
if (contains_all_checks || !VerifyAdapterCalls) { if (contains_all_checks || !VerifyAdapterCalls) {
assert_lock_strong(AdapterHandlerLibrary_lock); assert_lock_strong(AdapterHandlerLibrary_lock);
_adapter_handler_table.put(fingerprint, entry); _adapter_handler_table->put(fingerprint, entry);
} }
return entry; return entry;
} }
@ -3296,7 +3298,7 @@ bool AdapterHandlerLibrary::contains(const CodeBlob* b) {
return (found = (b == CodeCache::find_blob(a->get_i2c_entry()))); return (found = (b == CodeCache::find_blob(a->get_i2c_entry())));
}; };
assert_locked_or_safepoint(AdapterHandlerLibrary_lock); assert_locked_or_safepoint(AdapterHandlerLibrary_lock);
_adapter_handler_table.iterate(findblob); _adapter_handler_table->iterate(findblob);
return found; return found;
} }
@ -3313,7 +3315,7 @@ void AdapterHandlerLibrary::print_handler_on(outputStream* st, const CodeBlob* b
} }
}; };
assert_locked_or_safepoint(AdapterHandlerLibrary_lock); assert_locked_or_safepoint(AdapterHandlerLibrary_lock);
_adapter_handler_table.iterate(findblob); _adapter_handler_table->iterate(findblob);
assert(found, "Should have found handler"); assert(found, "Should have found handler");
} }