8304687: Move add_to_hierarchy

Reviewed-by: dholmes, fparain
This commit is contained in:
Coleen Phillimore 2023-03-23 13:47:06 +00:00
parent 63d4afbeb1
commit bf917ba6af
9 changed files with 53 additions and 56 deletions

View file

@ -209,7 +209,7 @@ void LambdaFormInvokers::regenerate_class(char* class_name, ClassFileStream& st,
assert(result->java_mirror() != nullptr, "must be"); assert(result->java_mirror() != nullptr, "must be");
add_regenerated_class(result->java_mirror()); add_regenerated_class(result->java_mirror());
SystemDictionary::add_to_hierarchy(THREAD, result); result->add_to_hierarchy(THREAD);
// new class not linked yet. // new class not linked yet.
MetaspaceShared::try_link_class(THREAD, result); MetaspaceShared::try_link_class(THREAD, result);

View file

@ -1068,7 +1068,7 @@ void ciEnv::register_method(ciMethod* target,
// To prevent compile queue updates. // To prevent compile queue updates.
MutexLocker locker(THREAD, MethodCompileQueue_lock); MutexLocker locker(THREAD, MethodCompileQueue_lock);
// Prevent SystemDictionary::add_to_hierarchy from running // Prevent InstanceKlass::add_to_hierarchy from running
// and invalidating our dependencies until we install this method. // and invalidating our dependencies until we install this method.
// No safepoints are allowed. Otherwise, class redefinition can occur in between. // No safepoints are allowed. Otherwise, class redefinition can occur in between.
MutexLocker ml(Compile_lock); MutexLocker ml(Compile_lock);

View file

@ -44,7 +44,6 @@
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"
#include "classfile/vmClasses.hpp" #include "classfile/vmClasses.hpp"
#include "classfile/vmSymbols.hpp" #include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
#include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/gcTraceTime.inline.hpp"
#include "interpreter/bootstrapInfo.hpp" #include "interpreter/bootstrapInfo.hpp"
#include "jfr/jfrEvents.hpp" #include "jfr/jfrEvents.hpp"
@ -70,7 +69,6 @@
#include "prims/jvmtiExport.hpp" #include "prims/jvmtiExport.hpp"
#include "prims/methodHandles.hpp" #include "prims/methodHandles.hpp"
#include "runtime/arguments.hpp" #include "runtime/arguments.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/handles.inline.hpp" #include "runtime/handles.inline.hpp"
#include "runtime/java.hpp" #include "runtime/java.hpp"
#include "runtime/javaCalls.hpp" #include "runtime/javaCalls.hpp"
@ -831,7 +829,7 @@ InstanceKlass* SystemDictionary::resolve_hidden_class_from_stream(
} }
// Add to class hierarchy, and do possible deoptimizations. // Add to class hierarchy, and do possible deoptimizations.
add_to_hierarchy(THREAD, k); k->add_to_hierarchy(THREAD);
// But, do not add to dictionary. // But, do not add to dictionary.
k->link_class(CHECK_NULL); k->link_class(CHECK_NULL);
@ -1418,7 +1416,7 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, Handle class_load
} }
// Add to class hierarchy, and do possible deoptimizations. // Add to class hierarchy, and do possible deoptimizations.
add_to_hierarchy(THREAD, k); k->add_to_hierarchy(THREAD);
{ {
MutexLocker mu_r(THREAD, Compile_lock); MutexLocker mu_r(THREAD, Compile_lock);
@ -1536,49 +1534,6 @@ InstanceKlass* SystemDictionary::find_or_define_instance_class(Symbol* class_nam
} }
// ----------------------------------------------------------------------------
// Update hierarchy. This is done before the new klass has been added to the SystemDictionary. The Compile_lock
// is grabbed, to ensure that the compiler is not using the class hierarchy.
void SystemDictionary::add_to_hierarchy(JavaThread* current, InstanceKlass* k) {
assert(k != nullptr, "just checking");
assert(!SafepointSynchronize::is_at_safepoint(), "must NOT be at safepoint");
// In case we are not using CHA based vtables we need to make sure the loaded
// deopt is completed before anyone links this class.
// Linking is done with _init_monitor held, by loading and deopting with it
// held we make sure the deopt is completed before linking.
if (!UseVtableBasedCHA) {
k->init_monitor()->lock();
}
DeoptimizationScope deopt_scope;
{
MutexLocker ml(current, Compile_lock);
k->set_init_state(InstanceKlass::loaded);
// make sure init_state store is already done.
// The compiler reads the hierarchy outside of the Compile_lock.
// Access ordering is used to add to hierarchy.
// Link into hierarchy.
k->append_to_sibling_list(); // add to superklass/sibling list
k->process_interfaces(); // handle all "implements" declarations
// Now mark all code that depended on old class hierarchy.
// Note: must be done *after* linking k into the hierarchy (was bug 12/9/97)
if (Universe::is_fully_initialized()) {
CodeCache::mark_dependents_on(&deopt_scope, k);
}
}
// Perform the deopt handshake outside Compile_lock.
deopt_scope.deoptimize_marked();
if (!UseVtableBasedCHA) {
k->init_monitor()->unlock();
}
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// GC support // GC support

View file

@ -360,8 +360,6 @@ public:
// Return Symbol or throw exception if name given is can not be a valid Symbol. // Return Symbol or throw exception if name given is can not be a valid Symbol.
static Symbol* class_name_symbol(const char* name, Symbol* exception, TRAPS); static Symbol* class_name_symbol(const char* name, Symbol* exception, TRAPS);
// Setup link to hierarchy and deoptimize
static void add_to_hierarchy(JavaThread* current, InstanceKlass* k);
protected: protected:
// Basic find on loaded classes // Basic find on loaded classes

View file

@ -852,7 +852,7 @@ InstanceKlass* SystemDictionaryShared::prepare_shared_lambda_proxy_class(Instanc
EventClassLoad class_load_start_event; EventClassLoad class_load_start_event;
// Add to class hierarchy, and do possible deoptimizations. // Add to class hierarchy, and do possible deoptimizations.
SystemDictionary::add_to_hierarchy(THREAD, loaded_lambda); loaded_lambda->add_to_hierarchy(THREAD);
// But, do not add to dictionary. // But, do not add to dictionary.
loaded_lambda->link_class(CHECK_NULL); loaded_lambda->link_class(CHECK_NULL);

View file

@ -249,7 +249,7 @@ void vmClasses::resolve_shared_class(InstanceKlass* klass, ClassLoaderData* load
SystemDictionary::load_shared_class_misc(klass, loader_data); SystemDictionary::load_shared_class_misc(klass, loader_data);
Dictionary* dictionary = loader_data->dictionary(); Dictionary* dictionary = loader_data->dictionary();
dictionary->add_klass(THREAD, klass->name(), klass); dictionary->add_klass(THREAD, klass->name(), klass);
SystemDictionary::add_to_hierarchy(THREAD, klass); klass->add_to_hierarchy(THREAD);
assert(klass->is_loaded(), "Must be in at least loaded state"); assert(klass->is_loaded(), "Must be in at least loaded state");
} }

View file

@ -2120,7 +2120,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV,
// To prevent compile queue updates. // To prevent compile queue updates.
MutexLocker locker(THREAD, MethodCompileQueue_lock); MutexLocker locker(THREAD, MethodCompileQueue_lock);
// Prevent SystemDictionary::add_to_hierarchy from running // Prevent InstanceKlass::add_to_hierarchy from running
// and invalidating our dependencies until we install this method. // and invalidating our dependencies until we install this method.
MutexLocker ml(Compile_lock); MutexLocker ml(Compile_lock);

View file

@ -1205,6 +1205,46 @@ void InstanceKlass::set_initialization_state_and_notify(ClassState state, JavaTh
ml.notify_all(); ml.notify_all();
} }
// Update hierarchy. This is done before the new klass has been added to the SystemDictionary. The Compile_lock
// is grabbed, to ensure that the compiler is not using the class hierarchy.
void InstanceKlass::add_to_hierarchy(JavaThread* current) {
assert(!SafepointSynchronize::is_at_safepoint(), "must NOT be at safepoint");
// In case we are not using CHA based vtables we need to make sure the loaded
// deopt is completed before anyone links this class.
// Linking is done with _init_monitor held, by loading and deopting with it
// held we make sure the deopt is completed before linking.
if (!UseVtableBasedCHA) {
init_monitor()->lock();
}
DeoptimizationScope deopt_scope;
{
MutexLocker ml(current, Compile_lock);
set_init_state(InstanceKlass::loaded);
// make sure init_state store is already done.
// The compiler reads the hierarchy outside of the Compile_lock.
// Access ordering is used to add to hierarchy.
// Link into hierarchy.
append_to_sibling_list(); // add to superklass/sibling list
process_interfaces(); // handle all "implements" declarations
// Now mark all code that depended on old class hierarchy.
// Note: must be done *after* linking k into the hierarchy (was bug 12/9/97)
if (Universe::is_fully_initialized()) {
CodeCache::mark_dependents_on(&deopt_scope, this);
}
}
// Perform the deopt handshake outside Compile_lock.
deopt_scope.deoptimize_marked();
if (!UseVtableBasedCHA) {
init_monitor()->unlock();
}
}
InstanceKlass* InstanceKlass::implementor() const { InstanceKlass* InstanceKlass::implementor() const {
InstanceKlass* volatile* ik = adr_implementor(); InstanceKlass* volatile* ik = adr_implementor();
if (ik == nullptr) { if (ik == nullptr) {
@ -2512,7 +2552,7 @@ void InstanceKlass::remove_unshareable_info() {
// Reset to the 'allocated' state to prevent any premature accessing to // Reset to the 'allocated' state to prevent any premature accessing to
// a shared class at runtime while the class is still being loaded and // a shared class at runtime while the class is still being loaded and
// restored. A class' init_state is set to 'loaded' at runtime when it's // restored. A class' init_state is set to 'loaded' at runtime when it's
// being added to class hierarchy (see SystemDictionary:::add_to_hierarchy()). // being added to class hierarchy (see InstanceKlass:::add_to_hierarchy()).
_init_state = allocated; _init_state = allocated;
{ // Otherwise this needs to take out the Compile_lock. { // Otherwise this needs to take out the Compile_lock.
@ -2586,7 +2626,7 @@ void InstanceKlass::init_shared_package_entry() {
void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain,
PackageEntry* pkg_entry, TRAPS) { PackageEntry* pkg_entry, TRAPS) {
// SystemDictionary::add_to_hierarchy() sets the init_state to loaded // InstanceKlass::add_to_hierarchy() sets the init_state to loaded
// before the InstanceKlass is added to the SystemDictionary. Make // before the InstanceKlass is added to the SystemDictionary. Make
// sure the current state is <loaded. // sure the current state is <loaded.
assert(!is_loaded(), "invalid init state"); assert(!is_loaded(), "invalid init state");

View file

@ -856,6 +856,8 @@ public:
void mark_dependent_nmethods(DeoptimizationScope* deopt_scope, KlassDepChange& changes); void mark_dependent_nmethods(DeoptimizationScope* deopt_scope, KlassDepChange& changes);
void add_dependent_nmethod(nmethod* nm); void add_dependent_nmethod(nmethod* nm);
void clean_dependency_context(); void clean_dependency_context();
// Setup link to hierarchy and deoptimize
void add_to_hierarchy(JavaThread* current);
// On-stack replacement support // On-stack replacement support
nmethod* osr_nmethods_head() const { return _osr_nmethods_head; }; nmethod* osr_nmethods_head() const { return _osr_nmethods_head; };
@ -892,9 +894,11 @@ public:
void add_implementor(InstanceKlass* ik); // ik is a new class that implements this interface void add_implementor(InstanceKlass* ik); // ik is a new class that implements this interface
void init_implementor(); // initialize void init_implementor(); // initialize
private:
// link this class into the implementors list of every interface it implements // link this class into the implementors list of every interface it implements
void process_interfaces(); void process_interfaces();
public:
// virtual operations from Klass // virtual operations from Klass
GrowableArray<Klass*>* compute_secondary_supers(int num_extra_slots, GrowableArray<Klass*>* compute_secondary_supers(int num_extra_slots,
Array<InstanceKlass*>* transitive_interfaces); Array<InstanceKlass*>* transitive_interfaces);