8302108: Clean up placeholder supername code

Reviewed-by: dholmes, iklam
This commit is contained in:
Coleen Phillimore 2023-02-13 20:57:01 +00:00
parent d503c66400
commit abbeb7e4d2
4 changed files with 32 additions and 43 deletions

View File

@ -191,7 +191,11 @@ bool PlaceholderEntry::remove_seen_thread(JavaThread* thread, PlaceholderTable::
}
// Placeholder methods
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
@ -272,7 +276,6 @@ PlaceholderEntry* PlaceholderTable::find_and_add(Symbol* name,
// placeholder is used to track class loading internal states
// placeholder existence now for loading superclass/superinterface
// superthreadQ tracks class circularity, while loading superclass/superinterface
// loadInstanceThreadQ tracks load_instance_class calls
// definer() tracks the single thread that owns define token
@ -283,21 +286,21 @@ PlaceholderEntry* PlaceholderTable::find_and_add(Symbol* name,
// On removal: if definer and all queues empty, remove entry
// 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(Symbol* name, ClassLoaderData* loader_data,
classloadAction action,
JavaThread* thread) {
assert_locked_or_safepoint(SystemDictionary_lock);
PlaceholderEntry* probe = get_entry(name, loader_data);
if (probe != nullptr) {
log(name, 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() == nullptr) && (probe->loadInstanceThreadQ() == nullptr)
&& (probe->defineThreadQ() == nullptr) && (probe->definer() == nullptr)) {
probe->clear_supername();
remove_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);
}
}

View File

@ -25,7 +25,7 @@
#ifndef SHARE_CLASSFILE_PLACEHOLDERS_HPP
#define SHARE_CLASSFILE_PLACEHOLDERS_HPP
#include "oops/symbol.hpp"
#include "oops/symbolHandle.hpp"
class PlaceholderEntry;
class Thread;
@ -81,7 +81,7 @@ class SeenThread;
class PlaceholderEntry {
friend class PlaceholderTable;
private:
Symbol* _supername;
SymbolHandle _supername;
JavaThread* _definer; // owner of define token
InstanceKlass* _instanceKlass; // InstanceKlass from successful define
SeenThread* _superThreadQ; // doubly-linked queue of Threads loading a superclass for this class
@ -99,30 +99,6 @@ class PlaceholderEntry {
void add_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action);
bool remove_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action);
public:
PlaceholderEntry() :
_supername(nullptr), _definer(nullptr), _instanceKlass(nullptr),
_superThreadQ(nullptr), _loadInstanceThreadQ(nullptr), _defineThreadQ(nullptr) { }
Symbol* supername() const { return _supername; }
void set_supername(Symbol* supername) {
if (supername != _supername) {
Symbol::maybe_decrement_refcount(_supername);
_supername = supername;
Symbol::maybe_increment_refcount(_supername);
}
}
void clear_supername() {
Symbol::maybe_decrement_refcount(_supername);
_supername = nullptr;
}
JavaThread* definer() const {return _definer; }
void set_definer(JavaThread* definer) { _definer = definer; }
InstanceKlass* instance_klass() const {return _instanceKlass; }
void set_instance_klass(InstanceKlass* ik) { _instanceKlass = ik; }
SeenThread* superThreadQ() const { return _superThreadQ; }
void set_superThreadQ(SeenThread* SeenThread) { _superThreadQ = SeenThread; }
@ -131,6 +107,19 @@ class PlaceholderEntry {
SeenThread* defineThreadQ() const { return _defineThreadQ; }
void set_defineThreadQ(SeenThread* SeenThread) { _defineThreadQ = SeenThread; }
public:
PlaceholderEntry() :
_definer(nullptr), _instanceKlass(nullptr),
_superThreadQ(nullptr), _loadInstanceThreadQ(nullptr), _defineThreadQ(nullptr) { }
Symbol* supername() const { return _supername; }
void set_supername(Symbol* supername);
JavaThread* definer() const {return _definer; }
void set_definer(JavaThread* definer) { _definer = definer; }
InstanceKlass* instance_klass() const {return _instanceKlass; }
void set_instance_klass(InstanceKlass* ik) { _instanceKlass = ik; }
bool super_load_in_progress() {
return (_superThreadQ != nullptr);

View File

@ -52,8 +52,7 @@ public:
// Does not increment the current reference count if temporary.
SymbolHandleBase(Symbol *s) : _temp(s) {
if (!TEMP) {
assert(s != nullptr, "must not be null");
s->increment_refcount();
Symbol::maybe_increment_refcount(_temp);
}
}

View File

@ -63,14 +63,12 @@ TEST_VM(PlaceholderTable, supername) {
PlaceholderTable::find_and_add(D, loader_data, super_action, interf, T2);
PlaceholderTable::find_and_remove(D, loader_data, super_action, T2);
ASSERT_EQ(interf->refcount(), 3) << "supername isn't replaced until super set";
ASSERT_EQ(interf->refcount(), 1) << "supername is replaced with null";
// Add placeholder to the table for loading A and super, and D also loading super
PlaceholderTable::find_and_add(A, loader_data, super_action, super, THREAD);
PlaceholderTable::find_and_add(D, loader_data, super_action, super, T2);
ASSERT_EQ(interf->refcount(), 1) << "now should be one";
// Another thread comes in and finds A loading Super
PlaceholderEntry* placeholder = PlaceholderTable::get_entry(A, loader_data);
SymbolHandle supername = placeholder->supername();