diff --git a/src/hotspot/share/cds/lambdaFormInvokers.cpp b/src/hotspot/share/cds/lambdaFormInvokers.cpp index fc1e5a73ec7..b759215fe44 100644 --- a/src/hotspot/share/cds/lambdaFormInvokers.cpp +++ b/src/hotspot/share/cds/lambdaFormInvokers.cpp @@ -209,7 +209,7 @@ void LambdaFormInvokers::regenerate_class(char* class_name, ClassFileStream& st, assert(result->java_mirror() != nullptr, "must be"); add_regenerated_class(result->java_mirror()); - SystemDictionary::add_to_hierarchy(THREAD, result); + result->add_to_hierarchy(THREAD); // new class not linked yet. MetaspaceShared::try_link_class(THREAD, result); diff --git a/src/hotspot/share/ci/ciEnv.cpp b/src/hotspot/share/ci/ciEnv.cpp index d0cbd3d0dec..df5c790d748 100644 --- a/src/hotspot/share/ci/ciEnv.cpp +++ b/src/hotspot/share/ci/ciEnv.cpp @@ -1068,7 +1068,7 @@ void ciEnv::register_method(ciMethod* target, // To prevent compile queue updates. 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. // No safepoints are allowed. Otherwise, class redefinition can occur in between. MutexLocker ml(Compile_lock); diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 6420dbf7db6..d47a682305f 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -44,7 +44,6 @@ #include "classfile/systemDictionary.hpp" #include "classfile/vmClasses.hpp" #include "classfile/vmSymbols.hpp" -#include "code/codeCache.hpp" #include "gc/shared/gcTraceTime.inline.hpp" #include "interpreter/bootstrapInfo.hpp" #include "jfr/jfrEvents.hpp" @@ -70,7 +69,6 @@ #include "prims/jvmtiExport.hpp" #include "prims/methodHandles.hpp" #include "runtime/arguments.hpp" -#include "runtime/deoptimization.hpp" #include "runtime/handles.inline.hpp" #include "runtime/java.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_hierarchy(THREAD, k); + k->add_to_hierarchy(THREAD); // But, do not add to dictionary. 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_hierarchy(THREAD, k); + k->add_to_hierarchy(THREAD); { 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 diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp index ffb5a48e6c9..edfe549b9cb 100644 --- a/src/hotspot/share/classfile/systemDictionary.hpp +++ b/src/hotspot/share/classfile/systemDictionary.hpp @@ -360,8 +360,6 @@ public: // 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); - // Setup link to hierarchy and deoptimize - static void add_to_hierarchy(JavaThread* current, InstanceKlass* k); protected: // Basic find on loaded classes diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index fde858ab6a7..3bd13b1729e 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -852,7 +852,7 @@ InstanceKlass* SystemDictionaryShared::prepare_shared_lambda_proxy_class(Instanc EventClassLoad class_load_start_event; // 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. loaded_lambda->link_class(CHECK_NULL); diff --git a/src/hotspot/share/classfile/vmClasses.cpp b/src/hotspot/share/classfile/vmClasses.cpp index 67ba23cc55c..2f004f02f90 100644 --- a/src/hotspot/share/classfile/vmClasses.cpp +++ b/src/hotspot/share/classfile/vmClasses.cpp @@ -249,7 +249,7 @@ void vmClasses::resolve_shared_class(InstanceKlass* klass, ClassLoaderData* load SystemDictionary::load_shared_class_misc(klass, loader_data); Dictionary* dictionary = loader_data->dictionary(); 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"); } diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index e5cb8e793a8..4325e0d3991 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -2120,7 +2120,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV, // To prevent compile queue updates. 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. MutexLocker ml(Compile_lock); diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index cea1b2487d9..8bb3f10f868 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -1205,6 +1205,46 @@ void InstanceKlass::set_initialization_state_and_notify(ClassState state, JavaTh 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* volatile* ik = adr_implementor(); if (ik == nullptr) { @@ -2512,7 +2552,7 @@ void InstanceKlass::remove_unshareable_info() { // Reset to the 'allocated' state to prevent any premature accessing to // 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 - // being added to class hierarchy (see SystemDictionary:::add_to_hierarchy()). + // being added to class hierarchy (see InstanceKlass:::add_to_hierarchy()). _init_state = allocated; { // 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, 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 // sure the current state is * compute_secondary_supers(int num_extra_slots, Array* transitive_interfaces);