8292286: Convert PlaceholderTable to ResourceHashtable

Reviewed-by: hseigel, iklam
This commit is contained in:
Coleen Phillimore 2022-08-15 21:53:02 +00:00
parent ea2c82e74f
commit 6e6ae596d6
6 changed files with 135 additions and 252 deletions

View File

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

View File

@ -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 @@ public:
void purge_loader_constraints();
void verify(PlaceholderTable* placeholders);
void verify();
void print() const;
void print_on(outputStream* st) const;
};

View File

@ -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<PlaceholderKey, PlaceholderEntry, _placeholder_table_size, ResourceObj::C_HEAP, mtClass,
PlaceholderKey::hash, PlaceholderKey::equals> _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<Symbol*, mtClass>::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<mtClass>::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<Symbol*, mtClass>::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<Symbol*, mtClass>(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<PlaceholderEntry>("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); }

View File

@ -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<Symbol*, mtClass> {
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<Symbol*, mtClass>::bucket(i);
}
PlaceholderEntry** bucket_addr(int i) {
return (PlaceholderEntry**)Hashtable<Symbol*, mtClass>::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<Symbol*, mtClass> {
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<Symbol*, mtClass> {
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<Symbol*, mtClass> {
SeenThread* defineThreadQ() const { return _defineThreadQ; }
void set_defineThreadQ(SeenThread* SeenThread) { _defineThreadQ = SeenThread; }
PlaceholderEntry* next() const {
return (PlaceholderEntry*)HashtableEntry<Symbol*, mtClass>::next();
}
PlaceholderEntry** next_addr() {
return (PlaceholderEntry**)HashtableEntry<Symbol*, mtClass>::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<Symbol*, mtClass> {
// 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

View File

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

View File

@ -284,4 +284,3 @@ template class BasicHashtable<mtLogging>;
template void BasicHashtable<mtClass>::verify_table<DictionaryEntry>(char const*);
template void BasicHashtable<mtClass>::verify_table<ProtectionDomainCacheEntry>(char const*);
template void BasicHashtable<mtClass>::verify_table<PlaceholderEntry>(char const*);