< prev index next > src/hotspot/share/classfile/placeholders.cpp
Print this page
// For bootclasssearchpath, set before calling load_instance_class.
// Defining must be single threaded on a class/classloader basis
// For DEFINE_CLASS, the head of the queue owns the
// define token and the rest of the threads wait to return the
// result the first thread gets.
+ // For INLINE_FIELD, set when loading inline type fields for
+ // class circularity checking.
class SeenThread: public CHeapObj<mtInternal> {
private:
JavaThread* _thread;
SeenThread* _stnext;
SeenThread* _stprev;
SeenThread* queuehead = nullptr;
switch (action) {
case PlaceholderTable::LOAD_INSTANCE:
queuehead = _loadInstanceThreadQ;
break;
! case PlaceholderTable::LOAD_SUPER:
! queuehead = _superThreadQ;
break;
case PlaceholderTable::DEFINE_CLASS:
queuehead = _defineThreadQ;
break;
default: Unimplemented();
SeenThread* queuehead = nullptr;
switch (action) {
case PlaceholderTable::LOAD_INSTANCE:
queuehead = _loadInstanceThreadQ;
break;
! case PlaceholderTable::DETECT_CIRCULARITY:
! queuehead = _circularityThreadQ;
break;
case PlaceholderTable::DEFINE_CLASS:
queuehead = _defineThreadQ;
break;
default: Unimplemented();
void PlaceholderEntry::set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action) {
switch (action) {
case PlaceholderTable::LOAD_INSTANCE:
_loadInstanceThreadQ = seenthread;
break;
! case PlaceholderTable::LOAD_SUPER:
! _superThreadQ = seenthread;
break;
case PlaceholderTable::DEFINE_CLASS:
_defineThreadQ = seenthread;
break;
default: Unimplemented();
void PlaceholderEntry::set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action) {
switch (action) {
case PlaceholderTable::LOAD_INSTANCE:
_loadInstanceThreadQ = seenthread;
break;
! case PlaceholderTable::DETECT_CIRCULARITY:
! _circularityThreadQ = seenthread;
break;
case PlaceholderTable::DEFINE_CLASS:
_defineThreadQ = seenthread;
break;
default: Unimplemented();
}
return (actionToQueue(action) == nullptr);
}
! void PlaceholderEntry::set_supername(Symbol* supername) {
assert_locked_or_safepoint(SystemDictionary_lock);
! assert(_supername == nullptr || _supername->refcount() > 1, "must be referenced also by the loader");
! _supername = supername;
}
// 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.
static PlaceholderEntry* add_entry(Symbol* class_name, ClassLoaderData* loader_data,
! Symbol* supername){
assert_locked_or_safepoint(SystemDictionary_lock);
assert(class_name != nullptr, "adding nullptr obj");
PlaceholderEntry entry;
! entry.set_supername(supername);
PlaceholderKey key(class_name, loader_data);
bool created;
PlaceholderEntry* table_copy = _placeholders->put_if_absent(key, entry, &created);
assert(created, "better be absent");
return table_copy;
}
return (actionToQueue(action) == nullptr);
}
! void PlaceholderEntry::set_next_klass_name(Symbol* next_klass_name) {
assert_locked_or_safepoint(SystemDictionary_lock);
! assert(_next_klass_name == nullptr || _next_klass_name->refcount() > 1, "must be referenced also by the loader");
! _next_klass_name = next_klass_name;
}
// 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.
static PlaceholderEntry* add_entry(Symbol* class_name, ClassLoaderData* loader_data,
! Symbol* next_klass_name){
assert_locked_or_safepoint(SystemDictionary_lock);
assert(class_name != nullptr, "adding nullptr obj");
PlaceholderEntry entry;
! entry.set_next_klass_name(next_klass_name);
PlaceholderKey key(class_name, loader_data);
bool created;
PlaceholderEntry* table_copy = _placeholders->put_if_absent(key, entry, &created);
assert(created, "better be absent");
return table_copy;
}
static const char* action_to_string(PlaceholderTable::classloadAction action) {
switch (action) {
case PlaceholderTable::LOAD_INSTANCE: return "LOAD_INSTANCE";
! case PlaceholderTable::LOAD_SUPER: return "LOAD_SUPER";
case PlaceholderTable::DEFINE_CLASS: return "DEFINE_CLASS";
}
return "";
}
}
static const char* action_to_string(PlaceholderTable::classloadAction action) {
switch (action) {
case PlaceholderTable::LOAD_INSTANCE: return "LOAD_INSTANCE";
! case PlaceholderTable::DETECT_CIRCULARITY: return "DETECT_CIRCULARITY";
case PlaceholderTable::DEFINE_CLASS: return "DEFINE_CLASS";
}
return "";
}
// find_and_add returns probe pointer - old or new
// If no entry exists, add a placeholder entry
// 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(Symbol* name,
ClassLoaderData* loader_data,
classloadAction action,
! Symbol* supername,
JavaThread* thread) {
! assert(action != LOAD_SUPER || supername != nullptr, "must have a super class name");
PlaceholderEntry* probe = get_entry(name, loader_data);
if (probe == nullptr) {
// Nothing found, add place holder
! probe = add_entry(name, loader_data, supername);
} else {
! if (action == LOAD_SUPER) {
! probe->set_supername(supername);
}
}
probe->add_seen_thread(thread, action);
log(name, probe, "find_and_add", action);
return probe;
// find_and_add returns probe pointer - old or new
// If no entry exists, add a placeholder entry
// If entry exists, reuse entry
// For both, push SeenThread for classloadAction
! // If DETECT_CIRCULARITY, this is used for circularity detection for instanceklass loading.
PlaceholderEntry* PlaceholderTable::find_and_add(Symbol* name,
ClassLoaderData* loader_data,
classloadAction action,
! Symbol* next_klass_name,
JavaThread* thread) {
! assert(action != DETECT_CIRCULARITY || next_klass_name != nullptr, "must have a super class name");
PlaceholderEntry* probe = get_entry(name, loader_data);
if (probe == nullptr) {
// Nothing found, add place holder
! probe = add_entry(name, loader_data, next_klass_name);
} else {
! if (action == DETECT_CIRCULARITY) {
! probe->set_next_klass_name(next_klass_name);
}
}
probe->add_seen_thread(thread, action);
log(name, probe, "find_and_add", action);
return probe;
PlaceholderEntry* probe = get_entry(name, loader_data);
assert(probe != nullptr, "must find an entry");
log(name, probe, "find_and_remove", action);
probe->remove_seen_thread(thread, action);
if (probe->superThreadQ() == nullptr) {
! probe->set_supername(nullptr);
}
// If no other threads using this entry, and this thread is not using this entry for other states
if ((probe->superThreadQ() == nullptr) && (probe->loadInstanceThreadQ() == nullptr)
&& (probe->defineThreadQ() == nullptr) && (probe->definer() == nullptr)) {
remove_entry(name, loader_data);
PlaceholderEntry* probe = get_entry(name, loader_data);
assert(probe != nullptr, "must find an entry");
log(name, probe, "find_and_remove", action);
probe->remove_seen_thread(thread, action);
if (probe->superThreadQ() == nullptr) {
! probe->set_next_klass_name(nullptr);
}
// If no other threads using this entry, and this thread is not using this entry for other states
if ((probe->superThreadQ() == nullptr) && (probe->loadInstanceThreadQ() == nullptr)
&& (probe->defineThreadQ() == nullptr) && (probe->definer() == nullptr)) {
remove_entry(name, loader_data);
st->print(", loader ");
_loader_data->print_value_on(st);
}
void PlaceholderEntry::print_on(outputStream* st) const {
! if (supername() != nullptr) {
! st->print(", supername ");
! supername()->print_value_on(st);
}
if (definer() != nullptr) {
st->print(", definer ");
definer()->print_value_on(st);
}
st->print(", loader ");
_loader_data->print_value_on(st);
}
void PlaceholderEntry::print_on(outputStream* st) const {
! if (next_klass_name() != nullptr) {
! st->print(", next_klass_name ");
! next_klass_name()->print_value_on(st);
}
if (definer() != nullptr) {
st->print(", definer ");
definer()->print_value_on(st);
}
< prev index next >