diff --git a/src/hotspot/share/classfile/loaderConstraints.cpp b/src/hotspot/share/classfile/loaderConstraints.cpp index 14951b2dc91cd..f5b745a60ab05 100644 --- a/src/hotspot/share/classfile/loaderConstraints.cpp +++ b/src/hotspot/share/classfile/loaderConstraints.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -429,7 +429,7 @@ void LoaderConstraintTable::merge_loader_constraints( } -void LoaderConstraintTable::verify(PlaceholderTable* placeholders) { +void LoaderConstraintTable::verify() { Thread *thread = Thread::current(); for (int cindex = 0; cindex < table_size(); cindex++) { for (LoaderConstraintEntry* probe = bucket(cindex); @@ -450,7 +450,7 @@ void LoaderConstraintTable::verify(PlaceholderTable* placeholders) { } else { // If we don't find the class in the dictionary, it // has to be in the placeholders table. - PlaceholderEntry* entry = placeholders->get_entry(name_hash, name, loader_data); + PlaceholderEntry* entry = PlaceholderTable::get_entry(name, loader_data); // The InstanceKlass might not be on the entry, so the only // thing we can check here is whether we were successful in diff --git a/src/hotspot/share/classfile/loaderConstraints.hpp b/src/hotspot/share/classfile/loaderConstraints.hpp index 5e211635fdc05..80a9fdc1105b1 100644 --- a/src/hotspot/share/classfile/loaderConstraints.hpp +++ b/src/hotspot/share/classfile/loaderConstraints.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -79,7 +79,7 @@ class LoaderConstraintTable : public Hashtable { void purge_loader_constraints(); - void verify(PlaceholderTable* placeholders); + void verify(); void print() const; void print_on(outputStream* st) const; }; diff --git a/src/hotspot/share/classfile/placeholders.cpp b/src/hotspot/share/classfile/placeholders.cpp index b2f960443c359..f1b146033e4f2 100644 --- a/src/hotspot/share/classfile/placeholders.cpp +++ b/src/hotspot/share/classfile/placeholders.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -31,7 +31,26 @@ #include "memory/resourceArea.hpp" #include "runtime/javaThread.hpp" #include "runtime/mutexLocker.hpp" -#include "utilities/hashtable.inline.hpp" +#include "utilities/resourceHash.hpp" + +class PlaceholderKey { + Symbol* _name; + ClassLoaderData* _loader_data; + public: + PlaceholderKey(Symbol* name, ClassLoaderData* l) : _name(name), _loader_data(l) {} + + static bool equals(PlaceholderKey const& k1, PlaceholderKey const& k2) { + return (k1._name == k2._name && k1._loader_data == k2._loader_data); + } + static unsigned hash(PlaceholderKey const& k) { + return (unsigned) k._name->identity_hash() ^ (int)((intptr_t)k._loader_data >> 3); + } + void print_on(outputStream* st) const; +}; + +const int _placeholder_table_size = 503; // Does this really have to be prime? +ResourceHashtable _placeholders; // SeenThread objects represent list of threads that are // currently performing a load action on a class. @@ -173,90 +192,41 @@ bool PlaceholderEntry::remove_seen_thread(JavaThread* thread, PlaceholderTable:: // Placeholder methods -PlaceholderEntry* PlaceholderTable::new_entry(int hash, Symbol* name, - ClassLoaderData* loader_data, - Symbol* supername) { - PlaceholderEntry* entry = (PlaceholderEntry*)Hashtable::new_entry(hash, name); - // Hashtable with Symbol* literal must increment and decrement refcount. - name->increment_refcount(); - entry->set_loader_data(loader_data); - entry->set_supername(supername); - entry->set_superThreadQ(NULL); - entry->set_loadInstanceThreadQ(NULL); - entry->set_defineThreadQ(NULL); - entry->set_definer(NULL); - entry->set_instance_klass(NULL); - return entry; -} - -void PlaceholderTable::free_entry(PlaceholderEntry* entry) { - // decrement Symbol refcount here because Hashtable doesn't. - entry->literal()->decrement_refcount(); - if (entry->supername() != NULL) entry->supername()->decrement_refcount(); - BasicHashtable::free_entry(entry); -} - - // Placeholder objects represent classes currently being loaded. // All threads examining the placeholder table must hold the // SystemDictionary_lock, so we don't need special precautions // on store ordering here. -PlaceholderEntry* PlaceholderTable::add_entry(unsigned int hash, - Symbol* class_name, ClassLoaderData* loader_data, - Symbol* supername){ +PlaceholderEntry* add_entry(Symbol* class_name, ClassLoaderData* loader_data, + Symbol* supername){ assert_locked_or_safepoint(SystemDictionary_lock); assert(class_name != NULL, "adding NULL obj"); - // Both readers and writers are locked so it's safe to just - // create the placeholder and insert it in the list without a membar. - PlaceholderEntry* entry = new_entry(hash, class_name, loader_data, supername); - int index = hash_to_index(hash); - Hashtable::add_entry(index, entry); - return entry; + PlaceholderEntry entry; + entry.set_supername(supername); + PlaceholderKey key(class_name, loader_data); + // Since we're storing this key in the hashtable, we need to increment the refcount. + class_name->increment_refcount(); + bool created; + PlaceholderEntry* table_copy = _placeholders.put_if_absent(key, entry, &created); + assert(created, "better be absent"); + return table_copy; } - // Remove a placeholder object. -void PlaceholderTable::remove_entry(unsigned int hash, - Symbol* class_name, - ClassLoaderData* loader_data) { - assert_locked_or_safepoint(SystemDictionary_lock); - int index = hash_to_index(hash); - PlaceholderEntry** p = bucket_addr(index); - while (*p != NULL) { - PlaceholderEntry *probe = *p; - if (probe->hash() == hash && probe->equals(class_name, loader_data)) { - // Delete entry - *p = probe->next(); - free_entry(probe); - return; - } - p = probe->next_addr(); - } -} - -PlaceholderEntry* PlaceholderTable::get_entry(unsigned int hash, - Symbol* class_name, - ClassLoaderData* loader_data) { +void remove_entry(Symbol* class_name, ClassLoaderData* loader_data) { assert_locked_or_safepoint(SystemDictionary_lock); - int index = hash_to_index(hash); - for (PlaceholderEntry *place_probe = bucket(index); - place_probe != NULL; - place_probe = place_probe->next()) { - if (place_probe->hash() == hash && - place_probe->equals(class_name, loader_data)) { - return place_probe; - } - } - return NULL; + PlaceholderKey key(class_name, loader_data); + _placeholders.remove(key); + // Decrement the refcount in key, since it's no longer in the table. + class_name->decrement_refcount(); } -Symbol* PlaceholderTable::find_entry(unsigned int hash, - Symbol* class_name, - ClassLoaderData* loader_data) { - PlaceholderEntry* probe = get_entry(hash, class_name, loader_data); - return (probe != NULL ? probe->klassname() : NULL); + +PlaceholderEntry* PlaceholderTable::get_entry(Symbol* class_name, ClassLoaderData* loader_data) { + assert_locked_or_safepoint(SystemDictionary_lock); + PlaceholderKey key(class_name, loader_data); + return _placeholders.get(key); } static const char* action_to_string(PlaceholderTable::classloadAction action) { @@ -274,7 +244,7 @@ inline void log(PlaceholderEntry* entry, const char* function, PlaceholderTable: ResourceMark rm; LogStream ls(lt); ls.print("%s %s ", function, action_to_string(action)); - entry->print_entry(&ls); + entry->print_on(&ls); } } @@ -283,17 +253,16 @@ inline void log(PlaceholderEntry* entry, const char* function, PlaceholderTable: // If entry exists, reuse entry // For both, push SeenThread for classloadAction // If LOAD_SUPER, this is used for circularity detection for instanceklass loading. -PlaceholderEntry* PlaceholderTable::find_and_add(unsigned int hash, - Symbol* name, +PlaceholderEntry* PlaceholderTable::find_and_add(Symbol* name, ClassLoaderData* loader_data, classloadAction action, Symbol* supername, JavaThread* thread) { assert(action != LOAD_SUPER || supername != NULL, "must have a super class name"); - PlaceholderEntry* probe = get_entry(hash, name, loader_data); + PlaceholderEntry* probe = get_entry(name, loader_data); if (probe == NULL) { // Nothing found, add place holder - probe = add_entry(hash, name, loader_data, supername); + probe = add_entry(name, loader_data, supername); } else { if (action == LOAD_SUPER) { probe->set_supername(supername); @@ -318,50 +287,30 @@ PlaceholderEntry* PlaceholderTable::find_and_add(unsigned int hash, // Note: you can be in both placeholders and systemDictionary // Therefore - must always check SD first // Ignores the case where entry is not found -void PlaceholderTable::find_and_remove(unsigned int hash, - Symbol* name, ClassLoaderData* loader_data, +void PlaceholderTable::find_and_remove(Symbol* name, ClassLoaderData* loader_data, classloadAction action, JavaThread* thread) { - assert_locked_or_safepoint(SystemDictionary_lock); - PlaceholderEntry *probe = get_entry(hash, name, loader_data); - if (probe != NULL) { - log(probe, "find_and_remove", action); - probe->remove_seen_thread(thread, action); - // If no other threads using this entry, and this thread is not using this entry for other states - if ((probe->superThreadQ() == NULL) && (probe->loadInstanceThreadQ() == NULL) - && (probe->defineThreadQ() == NULL) && (probe->definer() == NULL)) { - remove_entry(hash, name, loader_data); - } + assert_locked_or_safepoint(SystemDictionary_lock); + PlaceholderEntry* probe = get_entry(name, loader_data); + if (probe != NULL) { + log(probe, "find_and_remove", action); + probe->remove_seen_thread(thread, action); + // If no other threads using this entry, and this thread is not using this entry for other states + if ((probe->superThreadQ() == NULL) && (probe->loadInstanceThreadQ() == NULL) + && (probe->defineThreadQ() == NULL) && (probe->definer() == NULL)) { + probe->clear_supername(); + remove_entry(name, loader_data); } } - -PlaceholderTable::PlaceholderTable(int table_size) - : Hashtable(table_size, sizeof(PlaceholderEntry)) { } -void PlaceholderEntry::verify() const { - guarantee(loader_data() != NULL, "Must have been setup."); - guarantee(loader_data()->class_loader() == NULL || loader_data()->class_loader()->is_instance(), - "checking type of _loader"); - guarantee(instance_klass() == NULL - || instance_klass()->is_instance_klass(), - "checking type of instance_klass result"); +void PlaceholderKey::print_on(outputStream* st) const { + _name->print_value_on(st); + st->print(", loader "); + _loader_data->print_value_on(st); } -void PlaceholderTable::verify() { - verify_table("Placeholder Table"); -} - - -// Note, doesn't append a cr -// Can't call this print_on because HashtableEntry doesn't initialize its vptr -// and print_on is a virtual function so the vptr call crashes. -void PlaceholderEntry::print_entry(outputStream* st) const { - klassname()->print_value_on(st); - if (loader_data() != NULL) { - st->print(", loader "); - loader_data()->print_value_on(st); - } +void PlaceholderEntry::print_on(outputStream* st) const { if (supername() != NULL) { st->print(", supername "); supername()->print_value_on(st); @@ -386,17 +335,16 @@ void PlaceholderEntry::print_entry(outputStream* st) const { st->cr(); } -void PlaceholderTable::print_on(outputStream* st) const { +void PlaceholderTable::print_on(outputStream* st) { + auto printer = [&] (PlaceholderKey& key, PlaceholderEntry& entry) { + st->print("placeholder "); + key.print_on(st); + entry.print_on(st); + return true; + }; st->print_cr("Placeholder table (table_size=%d, placeholders=%d)", - table_size(), number_of_entries()); - for (int pindex = 0; pindex < table_size(); pindex++) { - for (PlaceholderEntry* probe = bucket(pindex); - probe != NULL; - probe = probe->next()) { - st->print("%4d: placeholder ", pindex); - probe->print_entry(st); - } - } + _placeholders.table_size(), _placeholders.number_of_entries()); + _placeholders.iterate(printer); } -void PlaceholderTable::print() const { return print_on(tty); } +void PlaceholderTable::print() { return print_on(tty); } diff --git a/src/hotspot/share/classfile/placeholders.hpp b/src/hotspot/share/classfile/placeholders.hpp index f96a80133bb5e..4e05136e00b6e 100644 --- a/src/hotspot/share/classfile/placeholders.hpp +++ b/src/hotspot/share/classfile/placeholders.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -25,8 +25,6 @@ #ifndef SHARE_CLASSFILE_PLACEHOLDERS_HPP #define SHARE_CLASSFILE_PLACEHOLDERS_HPP -#include "utilities/hashtable.hpp" - class PlaceholderEntry; class Thread; class ClassLoaderData; @@ -36,69 +34,40 @@ class Symbol; // being loaded, as well as arrays of primitives. // -class PlaceholderTable : public Hashtable { - -public: - PlaceholderTable(int table_size); - - PlaceholderEntry* new_entry(int hash, Symbol* name, ClassLoaderData* loader_data, Symbol* supername); - void free_entry(PlaceholderEntry* entry); - - PlaceholderEntry* bucket(int i) const { - return (PlaceholderEntry*)Hashtable::bucket(i); - } - - PlaceholderEntry** bucket_addr(int i) { - return (PlaceholderEntry**)Hashtable::bucket_addr(i); - } - - PlaceholderEntry* add_entry(unsigned int hash, Symbol* name, - ClassLoaderData* loader_data, - Symbol* supername); - - // This returns a Symbol* to match type for SystemDictionary - Symbol* find_entry(unsigned int hash, - Symbol* name, ClassLoaderData* loader_data); - - PlaceholderEntry* get_entry(unsigned int hash, - Symbol* name, ClassLoaderData* loader_data); - -// caller to create a placeholder entry must enumerate an action -// caller claims ownership of that action -// For parallel classloading: -// multiple LOAD_INSTANCE threads can proceed in parallel -// multiple LOAD_SUPER threads can proceed in parallel -// LOAD_SUPER needed to check for class circularity -// DEFINE_CLASS: ultimately define class must be single threaded -// on a class/classloader basis -// so the head of that queue owns the token -// and the rest of the threads return the result the first thread gets - enum classloadAction { +class PlaceholderTable : public AllStatic { + public: + // caller to create a placeholder entry must enumerate an action + // caller claims ownership of that action + // For parallel classloading: + // multiple LOAD_INSTANCE threads can proceed in parallel + // multiple LOAD_SUPER threads can proceed in parallel + // LOAD_SUPER needed to check for class circularity + // DEFINE_CLASS: ultimately define class must be single threaded + // on a class/classloader basis + // so the head of that queue owns the token + // and the rest of the threads return the result the first thread gets + enum classloadAction { LOAD_INSTANCE = 1, // calling load_instance_class LOAD_SUPER = 2, // loading superclass for this class DEFINE_CLASS = 3 // find_or_define class - }; + }; + + static PlaceholderEntry* get_entry(Symbol* name, ClassLoaderData* loader_data); // find_and_add returns probe pointer - old or new // If no entry exists, add a placeholder entry and push SeenThread for classloadAction // If entry exists, reuse entry and push SeenThread for classloadAction - PlaceholderEntry* find_and_add(unsigned int hash, - Symbol* name, ClassLoaderData* loader_data, - classloadAction action, Symbol* supername, - JavaThread* thread); - - void remove_entry(unsigned int hash, - Symbol* name, ClassLoaderData* loader_data); + static PlaceholderEntry* find_and_add(Symbol* name, ClassLoaderData* loader_data, + classloadAction action, Symbol* supername, + JavaThread* thread); // find_and_remove first removes SeenThread for classloadAction // If all queues are empty and definer is null, remove the PlacheholderEntry completely - void find_and_remove(unsigned int hash, - Symbol* name, ClassLoaderData* loader_data, + static void find_and_remove(Symbol* name, ClassLoaderData* loader_data, classloadAction action, JavaThread* thread); - void print_on(outputStream* st) const; - void print() const; - void verify(); + static void print_on(outputStream* st); + static void print(); }; class SeenThread; @@ -108,13 +77,9 @@ class SeenThread; // SystemDictionary_lock, so we don't need special precautions // on store ordering here. // The system dictionary is the only user of this class. - -class PlaceholderEntry : public HashtableEntry { - +class PlaceholderEntry { friend class PlaceholderTable; - private: - ClassLoaderData* _loader_data; // initiating loader Symbol* _supername; JavaThread* _definer; // owner of define token InstanceKlass* _instanceKlass; // InstanceKlass from successful define @@ -134,16 +99,19 @@ class PlaceholderEntry : public HashtableEntry { bool remove_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action); public: - // Simple accessors, used only by SystemDictionary - Symbol* klassname() const { return literal(); } - - ClassLoaderData* loader_data() const { return _loader_data; } - void set_loader_data(ClassLoaderData* loader_data) { _loader_data = loader_data; } + PlaceholderEntry() : + _supername(nullptr), _definer(nullptr), _instanceKlass(nullptr), + _superThreadQ(nullptr), _loadInstanceThreadQ(nullptr), _defineThreadQ(nullptr) { } Symbol* supername() const { return _supername; } void set_supername(Symbol* supername) { + Symbol::maybe_decrement_refcount(_supername); _supername = supername; - if (_supername != NULL) _supername->increment_refcount(); + Symbol::maybe_increment_refcount(_supername); + } + void clear_supername() { + Symbol::maybe_decrement_refcount(_supername); + _supername = nullptr; } JavaThread* definer() const {return _definer; } @@ -161,20 +129,6 @@ class PlaceholderEntry : public HashtableEntry { SeenThread* defineThreadQ() const { return _defineThreadQ; } void set_defineThreadQ(SeenThread* SeenThread) { _defineThreadQ = SeenThread; } - PlaceholderEntry* next() const { - return (PlaceholderEntry*)HashtableEntry::next(); - } - - PlaceholderEntry** next_addr() { - return (PlaceholderEntry**)HashtableEntry::next_addr(); - } - - // Test for equality - // Entries are unique for class/classloader name pair - bool equals(Symbol* class_name, ClassLoaderData* loader) const { - return (klassname() == class_name && loader_data() == loader); - } - bool super_load_in_progress() { return (_superThreadQ != NULL); } @@ -190,9 +144,7 @@ class PlaceholderEntry : public HashtableEntry { // Used for ClassCircularityError checking bool check_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action); - // Print method doesn't append a cr - void print_entry(outputStream* st) const; - void verify() const; + void print_on(outputStream* st) const; }; #endif // SHARE_CLASSFILE_PLACEHOLDERS_HPP diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 71b4ebc093435..8076d8dd5a576 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -126,11 +126,6 @@ const int defaultProtectionDomainCacheSize = 1009; const int _resolution_error_size = 107; // number of entries in resolution error table const int _invoke_method_size = 139; // number of entries in invoke method table -// Hashtable holding placeholders for classes being loaded. -const int _placeholder_table_size = 1009; -static PlaceholderTable* _placeholders = NULL; -static PlaceholderTable* placeholders() { return _placeholders; } - // Constraints on class loaders const int _loader_constraint_size = 107; // number of entries in constraint table static LoaderConstraintTable* _loader_constraints; @@ -389,7 +384,7 @@ static inline void log_circularity_error(Thread* thread, PlaceholderEntry* probe ResourceMark rm(thread); LogStream ls(lt); ls.print("ClassCircularityError detected for placeholder "); - probe->print_entry(&ls); + probe->print_on(&ls); ls.cr(); } } @@ -442,7 +437,6 @@ InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* class_name, ClassLoaderData* loader_data = class_loader_data(class_loader); Dictionary* dictionary = loader_data->dictionary(); unsigned int name_hash = dictionary->compute_hash(class_name); - assert(placeholders()->compute_hash(class_name) == name_hash, "they're the same hashcode"); // can't throw error holding a lock bool throw_circularity_error = false; @@ -460,7 +454,7 @@ InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* class_name, return quicksuperk; } else { // Must check ClassCircularity before checking if superclass is already loaded. - PlaceholderEntry* probe = placeholders()->get_entry(name_hash, class_name, loader_data); + PlaceholderEntry* probe = PlaceholderTable::get_entry(class_name, loader_data); if (probe && probe->check_seen_thread(THREAD, PlaceholderTable::LOAD_SUPER)) { log_circularity_error(THREAD, probe); throw_circularity_error = true; @@ -469,11 +463,10 @@ InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* class_name, if (!throw_circularity_error) { // Be careful not to exit resolve_super without removing this placeholder. - PlaceholderEntry* newprobe = placeholders()->find_and_add(name_hash, - class_name, - loader_data, - PlaceholderTable::LOAD_SUPER, - super_name, THREAD); + PlaceholderEntry* newprobe = PlaceholderTable::find_and_add(class_name, + loader_data, + PlaceholderTable::LOAD_SUPER, + super_name, THREAD); } } @@ -492,7 +485,7 @@ InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* class_name, // Clean up placeholder entry. { MutexLocker mu(THREAD, SystemDictionary_lock); - placeholders()->find_and_remove(name_hash, class_name, loader_data, PlaceholderTable::LOAD_SUPER, THREAD); + PlaceholderTable::find_and_remove(class_name, loader_data, PlaceholderTable::LOAD_SUPER, THREAD); SystemDictionary_lock->notify_all(); } @@ -579,7 +572,7 @@ InstanceKlass* SystemDictionary::handle_parallel_loading(JavaThread* current, ClassLoaderData* loader_data, Handle lockObject, bool* throw_circularity_error) { - PlaceholderEntry* oldprobe = placeholders()->get_entry(name_hash, name, loader_data); + PlaceholderEntry* oldprobe = PlaceholderTable::get_entry(name, loader_data); if (oldprobe != NULL) { // only need check_seen_thread once, not on each loop // 6341374 java/lang/Instrument with -Xcomp @@ -620,7 +613,7 @@ InstanceKlass* SystemDictionary::handle_parallel_loading(JavaThread* current, return check; } // check if other thread failed to load and cleaned up - oldprobe = placeholders()->get_entry(name_hash, name, loader_data); + oldprobe = PlaceholderTable::get_entry(name, loader_data); } } } @@ -689,8 +682,6 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, name->as_C_string(), class_loader.is_null() ? "null" : class_loader->klass()->name()->as_C_string()); - assert(placeholders()->compute_hash(name) == name_hash, "they're the same hashcode"); - // Check again (after locking) if the class already exists in SystemDictionary { MutexLocker mu(THREAD, SystemDictionary_lock); @@ -699,7 +690,7 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, // InstanceKlass is already loaded, but we still need to check protection domain below. loaded_class = check; } else { - PlaceholderEntry* placeholder = placeholders()->get_entry(name_hash, name, loader_data); + PlaceholderEntry* placeholder = PlaceholderTable::get_entry(name, loader_data); if (placeholder != NULL && placeholder->super_load_in_progress()) { super_load_in_progress = true; superclassname = placeholder->supername(); @@ -757,10 +748,10 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, loaded_class = check; } else if (should_wait_for_loading(class_loader)) { // Add the LOAD_INSTANCE token. Threads will wait on loading to complete for this thread. - PlaceholderEntry* newprobe = placeholders()->find_and_add(name_hash, name, loader_data, - PlaceholderTable::LOAD_INSTANCE, - NULL, - THREAD); + PlaceholderEntry* newprobe = PlaceholderTable::find_and_add(name, loader_data, + PlaceholderTable::LOAD_INSTANCE, + NULL, + THREAD); load_placeholder_added = true; } } @@ -774,7 +765,7 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, } // Be careful when modifying this code: once you have run - // placeholders()->find_and_add(PlaceholderTable::LOAD_INSTANCE), + // PlaceholderTable::find_and_add(PlaceholderTable::LOAD_INSTANCE), // you need to find_and_remove it before returning. // So be careful to not exit with a CHECK_ macro between these calls. @@ -788,7 +779,7 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, // This brackets the SystemDictionary updates for both defining // and initiating loaders MutexLocker mu(THREAD, SystemDictionary_lock); - placeholders()->find_and_remove(name_hash, name, loader_data, PlaceholderTable::LOAD_INSTANCE, THREAD); + PlaceholderTable::find_and_remove(name, loader_data, PlaceholderTable::LOAD_INSTANCE, THREAD); SystemDictionary_lock->notify_all(); } } @@ -1538,7 +1529,7 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, Handle class_load // potentially waste time reading and parsing the bytestream. // Note: VM callers should ensure consistency of k/class_name,class_loader // Be careful when modifying this code: once you have run -// placeholders()->find_and_add(PlaceholderTable::DEFINE_CLASS), +// PlaceholderTable::find_and_add(PlaceholderTable::DEFINE_CLASS), // you need to find_and_remove it before returning. // So be careful to not exit with a CHECK_ macro between these calls. InstanceKlass* SystemDictionary::find_or_define_helper(Symbol* class_name, Handle class_loader, @@ -1562,9 +1553,8 @@ InstanceKlass* SystemDictionary::find_or_define_helper(Symbol* class_name, Handl } // Acquire define token for this class/classloader - assert(placeholders()->compute_hash(name_h) == name_hash, "they're the same hashcode"); - PlaceholderEntry* probe = placeholders()->find_and_add(name_hash, name_h, loader_data, - PlaceholderTable::DEFINE_CLASS, NULL, THREAD); + PlaceholderEntry* probe = PlaceholderTable::find_and_add(name_h, loader_data, + PlaceholderTable::DEFINE_CLASS, NULL, THREAD); // Wait if another thread defining in parallel // All threads wait - even those that will throw duplicate class: otherwise // caller is surprised by LinkageError: duplicate, but findLoadedClass fails @@ -1577,7 +1567,7 @@ InstanceKlass* SystemDictionary::find_or_define_helper(Symbol* class_name, Handl // caught by finding an entry in the SystemDictionary if (is_parallelDefine(class_loader) && (probe->instance_klass() != NULL)) { InstanceKlass* ik = probe->instance_klass(); - placeholders()->find_and_remove(name_hash, name_h, loader_data, PlaceholderTable::DEFINE_CLASS, THREAD); + PlaceholderTable::find_and_remove(name_h, loader_data, PlaceholderTable::DEFINE_CLASS, THREAD); SystemDictionary_lock->notify_all(); #ifdef ASSERT InstanceKlass* check = dictionary->find_class(name_hash, name_h); @@ -1595,13 +1585,13 @@ InstanceKlass* SystemDictionary::find_or_define_helper(Symbol* class_name, Handl // definer must notify any waiting threads { MutexLocker mu(THREAD, SystemDictionary_lock); - PlaceholderEntry* probe = placeholders()->get_entry(name_hash, name_h, loader_data); + PlaceholderEntry* probe = PlaceholderTable::get_entry(name_h, loader_data); assert(probe != NULL, "DEFINE_CLASS placeholder lost?"); if (!HAS_PENDING_EXCEPTION) { probe->set_instance_klass(k); } probe->set_definer(NULL); - placeholders()->find_and_remove(name_hash, name_h, loader_data, PlaceholderTable::DEFINE_CLASS, THREAD); + PlaceholderTable::find_and_remove(name_h, loader_data, PlaceholderTable::DEFINE_CLASS, THREAD); SystemDictionary_lock->notify_all(); } @@ -1724,7 +1714,6 @@ void SystemDictionary::methods_do(void f(Method*)) { void SystemDictionary::initialize(TRAPS) { // Allocate arrays - _placeholders = new PlaceholderTable(_placeholder_table_size); _loader_constraints = new LoaderConstraintTable(_loader_constraint_size); _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize); @@ -2489,7 +2478,7 @@ void SystemDictionary::print_on(outputStream *st) { ClassLoaderDataGraph::print_dictionary(st); // Placeholders - placeholders()->print_on(st); + PlaceholderTable::print_on(st); st->cr(); // loader constraints - print under SD_lock @@ -2505,19 +2494,15 @@ void SystemDictionary::print() { print_on(tty); } void SystemDictionary::verify() { guarantee(constraints() != NULL, "Verify of loader constraints failed"); - guarantee(placeholders()->number_of_entries() >= 0, - "Verify of placeholders failed"); GCMutexLocker mu(SystemDictionary_lock); // Verify dictionary ClassLoaderDataGraph::verify_dictionary(); - placeholders()->verify(); - // Verify constraint table guarantee(constraints() != NULL, "Verify of loader constraints failed"); - constraints()->verify(placeholders()); + constraints()->verify(); _pd_cache_table->verify(); } @@ -2529,7 +2514,6 @@ void SystemDictionary::dump(outputStream *st, bool verbose) { } else { CDS_ONLY(SystemDictionaryShared::print_table_statistics(st)); ClassLoaderDataGraph::print_table_statistics(st); - placeholders()->print_table_statistics(st, "Placeholder Table"); constraints()->print_table_statistics(st, "LoaderConstraints Table"); pd_cache_table()->print_table_statistics(st, "ProtectionDomainCache Table"); } diff --git a/src/hotspot/share/utilities/hashtable.cpp b/src/hotspot/share/utilities/hashtable.cpp index fa2c8d666dd39..cd8fa94629c48 100644 --- a/src/hotspot/share/utilities/hashtable.cpp +++ b/src/hotspot/share/utilities/hashtable.cpp @@ -284,4 +284,3 @@ template class BasicHashtable; template void BasicHashtable::verify_table(char const*); template void BasicHashtable::verify_table(char const*); -template void BasicHashtable::verify_table(char const*);