6262#include " oops/objArrayKlass.hpp"
6363#include " oops/objArrayOop.inline.hpp"
6464#include " oops/oop.inline.hpp"
65+ #include " oops/oop.hpp"
66+ #include " oops/oopHandle.hpp"
6567#include " oops/oopHandle.inline.hpp"
6668#include " oops/symbol.hpp"
6769#include " oops/typeArrayKlass.hpp"
8789#include " jfr/jfr.hpp"
8890#endif
8991
90- SymbolPropertyTable* SystemDictionary::_invoke_method_table = NULL ;
92+ class InvokeMethodKey : public StackObj {
93+ private:
94+ Symbol* _symbol;
95+ intptr_t _iid;
96+
97+ public:
98+ InvokeMethodKey (Symbol* symbol, intptr_t iid) :
99+ _symbol (symbol),
100+ _iid (iid) {}
101+
102+ static bool key_comparison (InvokeMethodKey const &k1, InvokeMethodKey const &k2){
103+ return k1._symbol == k2._symbol && k1._iid == k2._iid ;
104+ }
105+
106+ static unsigned int compute_hash (const InvokeMethodKey &k) {
107+ Symbol* sym = k._symbol ;
108+ intptr_t iid = k._iid ;
109+ unsigned int hash = (unsigned int ) sym -> identity_hash ();
110+ return (unsigned int ) (hash ^ iid);
111+ }
112+
113+ };
114+
115+ ResourceHashtable<InvokeMethodKey, Method*, 139 , ResourceObj::C_HEAP, mtClass,
116+ InvokeMethodKey::compute_hash, InvokeMethodKey::key_comparison> _invoke_method_intrinsic_table;
117+ ResourceHashtable<Symbol*, OopHandle, 139 , ResourceObj::C_HEAP, mtClass> _invoke_method_type_table;
91118ProtectionDomainCacheTable* SystemDictionary::_pd_cache_table = NULL ;
92119
93120OopHandle SystemDictionary::_java_system_loader;
@@ -1633,10 +1660,21 @@ bool SystemDictionary::do_unloading(GCTimer* gc_timer) {
16331660
16341661void SystemDictionary::methods_do (void f (Method*)) {
16351662 // Walk methods in loaded classes
1636- MutexLocker ml (ClassLoaderDataGraph_lock);
1637- ClassLoaderDataGraph::methods_do (f);
1638- // Walk method handle intrinsics
1639- invoke_method_table ()->methods_do (f);
1663+
1664+ {
1665+ MutexLocker ml (ClassLoaderDataGraph_lock);
1666+ ClassLoaderDataGraph::methods_do (f);
1667+ }
1668+
1669+ auto doit = [&] (InvokeMethodKey key, Method* method) {
1670+ f (method);
1671+ };
1672+
1673+ {
1674+ MutexLocker ml (InvokeMethodTable_lock);
1675+ _invoke_method_intrinsic_table.iterate_all (doit);
1676+ }
1677+
16401678}
16411679
16421680// ----------------------------------------------------------------------------
@@ -1646,7 +1684,6 @@ void SystemDictionary::initialize(TRAPS) {
16461684 // Allocate arrays
16471685 _placeholders = new PlaceholderTable (_placeholder_table_size);
16481686 _loader_constraints = new LoaderConstraintTable (_loader_constraint_size);
1649- _invoke_method_table = new SymbolPropertyTable (_invoke_method_size);
16501687 _pd_cache_table = new ProtectionDomainCacheTable (defaultProtectionDomainCacheSize);
16511688
16521689#if INCLUDE_CDS
@@ -1994,48 +2031,48 @@ Symbol* SystemDictionary::check_signature_loaders(Symbol* signature,
19942031Method* SystemDictionary::find_method_handle_intrinsic (vmIntrinsicID iid,
19952032 Symbol* signature,
19962033 TRAPS) {
2034+
19972035 methodHandle empty;
19982036 const int iid_as_int = vmIntrinsics::as_int (iid);
19992037 assert (MethodHandles::is_signature_polymorphic (iid) &&
20002038 MethodHandles::is_signature_polymorphic_intrinsic (iid) &&
20012039 iid != vmIntrinsics::_invokeGeneric,
20022040 " must be a known MH intrinsic iid=%d: %s" , iid_as_int, vmIntrinsics::name_at (iid));
20032041
2004- unsigned int hash = invoke_method_table ()->compute_hash (signature, iid_as_int);
2005- int index = invoke_method_table ()->hash_to_index (hash);
2006- SymbolPropertyEntry* spe = invoke_method_table ()->find_entry (index, hash, signature, iid_as_int);
2007- methodHandle m;
2008- if (spe == NULL || spe->method () == NULL ) {
2009- spe = NULL ;
2010- // Must create lots of stuff here, but outside of the SystemDictionary lock.
2011- m = Method::make_method_handle_intrinsic (iid, signature, CHECK_NULL);
2012- if (!Arguments::is_interpreter_only () || iid == vmIntrinsics::_linkToNative) {
2013- // Generate a compiled form of the MH intrinsic.
2042+ Method** met;
2043+ InvokeMethodKey key (signature, iid_as_int);
2044+ {
2045+ MutexLocker ml (THREAD, InvokeMethodTable_lock);
2046+ met = _invoke_method_intrinsic_table.get (key);
2047+ if (met != nullptr ) {
2048+ return *met;
2049+ }
2050+ }
2051+
2052+ methodHandle m = Method::make_method_handle_intrinsic (iid, signature, CHECK_NULL);
2053+ if (!Arguments::is_interpreter_only () || iid == vmIntrinsics::_linkToNative) {
2054+ // Generate a compiled form of the MH intrinsic
20142055 // linkToNative doesn't have interpreter-specific implementation, so always has to go through compiled version.
20152056 AdapterHandlerLibrary::create_native_wrapper (m);
20162057 // Check if have the compiled code.
20172058 if (!m->has_compiled_code ()) {
20182059 THROW_MSG_NULL (vmSymbols::java_lang_VirtualMachineError (),
20192060 " Out of space in CodeCache for method handle intrinsic" );
20202061 }
2021- }
2022- // Now grab the lock. We might have to throw away the new method,
2023- // if a racing thread has managed to install one at the same time.
2024- {
2025- MutexLocker ml (THREAD, SystemDictionary_lock);
2026- spe = invoke_method_table ()->find_entry (index, hash, signature, iid_as_int);
2027- if (spe == NULL )
2028- spe = invoke_method_table ()->add_entry (index, hash, signature, iid_as_int);
2029- if (spe->method () == NULL )
2030- spe->set_method (m ());
2031- }
20322062 }
2033-
2034- assert (spe != NULL && spe->method () != NULL , " " );
2035- assert (Arguments::is_interpreter_only () || (spe->method ()->has_compiled_code () &&
2036- spe->method ()->code ()->entry_point () == spe->method ()->from_compiled_entry ()),
2063+ // Now grab the lock. We might have to throw away the new method,
2064+ // if a racing thread has managed to install one at the same time.
2065+ {
2066+ MutexLocker ml (THREAD, InvokeMethodTable_lock);
2067+ signature->make_permanent (); // The signature is never unloaded.
2068+ bool created;
2069+ met = _invoke_method_intrinsic_table.put_if_absent (key, m (), &created);
2070+ Method* saved_method = *met;
2071+ assert (Arguments::is_interpreter_only () || (saved_method->has_compiled_code () &&
2072+ saved_method->code ()->entry_point () == saved_method->from_compiled_entry ()),
20372073 " MH intrinsic invariant" );
2038- return spe->method ();
2074+ return saved_method;
2075+ }
20392076}
20402077
20412078// Helper for unpacking the return value from linkMethod and linkCallSite.
@@ -2176,13 +2213,16 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature,
21762213 Klass* accessing_klass,
21772214 TRAPS) {
21782215 Handle empty;
2179- int null_iid = vmIntrinsics::as_int (vmIntrinsics::_none); // distinct from all method handle invoker intrinsics
2180- unsigned int hash = invoke_method_table ()->compute_hash (signature, null_iid);
2181- int index = invoke_method_table ()->hash_to_index (hash);
2182- SymbolPropertyEntry* spe = invoke_method_table ()->find_entry (index, hash, signature, null_iid);
2183- if (spe != NULL && spe->method_type () != NULL ) {
2184- assert (java_lang_invoke_MethodType::is_instance (spe->method_type ()), " " );
2185- return Handle (THREAD, spe->method_type ());
2216+ OopHandle* o;
2217+ {
2218+ MutexLocker ml (THREAD, InvokeMethodTable_lock);
2219+ o = _invoke_method_type_table.get (signature);
2220+ }
2221+
2222+ if (o != nullptr ) {
2223+ oop mt = o->resolve ();
2224+ assert (java_lang_invoke_MethodType::is_instance (mt), " " );
2225+ return Handle (THREAD, mt);
21862226 } else if (!THREAD->can_call_java ()) {
21872227 warning (" SystemDictionary::find_method_handle_type called from compiler thread" ); // FIXME
21882228 return Handle (); // do not attempt from within compiler, unless it was cached
@@ -2244,15 +2284,17 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature,
22442284
22452285 if (can_be_cached) {
22462286 // We can cache this MethodType inside the JVM.
2247- MutexLocker ml (THREAD, SystemDictionary_lock);
2248- spe = invoke_method_table ()->find_entry (index, hash, signature, null_iid);
2249- if (spe == NULL )
2250- spe = invoke_method_table ()->add_entry (index, hash, signature, null_iid);
2251- if (spe->method_type () == NULL ) {
2252- spe->set_method_type (method_type ());
2287+ MutexLocker ml (THREAD, InvokeMethodTable_lock);
2288+ bool created = false ;
2289+ assert (method_type != NULL , " unexpected null" );
2290+ OopHandle* h = _invoke_method_type_table.get (signature);
2291+ if (h == nullptr ) {
2292+ signature->make_permanent (); // The signature is never unloaded.
2293+ OopHandle elem = OopHandle (Universe::vm_global (), method_type ());
2294+ bool created = _invoke_method_type_table.put (signature, elem);
2295+ assert (created, " better be created" );
22532296 }
22542297 }
2255-
22562298 // report back to the caller with the MethodType
22572299 return method_type;
22582300}
0 commit comments