Skip to content

Commit 13f0f12

Browse files
gujustin1coleenp
authored andcommitted
8290370: Convert SymbolPropertyTable to ResourceHashtable
Reviewed-by: coleenp, iklam
1 parent 67f0011 commit 13f0f12

File tree

6 files changed

+93
-230
lines changed

6 files changed

+93
-230
lines changed

src/hotspot/share/classfile/dictionary.cpp

Lines changed: 0 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -481,89 +481,6 @@ void Dictionary::clean_cached_protection_domains(GrowableArray<ProtectionDomainE
481481
}
482482
}
483483

484-
oop SymbolPropertyEntry::method_type() const {
485-
return _method_type.resolve();
486-
}
487-
488-
void SymbolPropertyEntry::set_method_type(oop p) {
489-
_method_type = OopHandle(Universe::vm_global(), p);
490-
}
491-
492-
void SymbolPropertyEntry::free_entry() {
493-
// decrement Symbol refcount here because hashtable doesn't.
494-
literal()->decrement_refcount();
495-
// Free OopHandle
496-
_method_type.release(Universe::vm_global());
497-
}
498-
499-
void SymbolPropertyEntry::print_entry(outputStream* st) const {
500-
symbol()->print_value_on(st);
501-
st->print("/mode=" INTX_FORMAT, symbol_mode());
502-
st->print(" -> ");
503-
bool printed = false;
504-
if (method() != NULL) {
505-
method()->print_value_on(st);
506-
printed = true;
507-
}
508-
if (method_type() != NULL) {
509-
if (printed) st->print(" and ");
510-
st->print(INTPTR_FORMAT, p2i((void *)method_type()));
511-
printed = true;
512-
}
513-
st->print_cr(printed ? "" : "(empty)");
514-
}
515-
516-
SymbolPropertyTable::SymbolPropertyTable(int table_size)
517-
: Hashtable<Symbol*, mtSymbol>(table_size, sizeof(SymbolPropertyEntry))
518-
{
519-
}
520-
SymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket<mtSymbol>* t,
521-
int number_of_entries)
522-
: Hashtable<Symbol*, mtSymbol>(table_size, sizeof(SymbolPropertyEntry), t, number_of_entries)
523-
{
524-
}
525-
526-
527-
SymbolPropertyEntry* SymbolPropertyTable::find_entry(int index, unsigned int hash,
528-
Symbol* sym,
529-
intptr_t sym_mode) {
530-
assert(index == index_for(sym, sym_mode), "incorrect index?");
531-
for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
532-
if (p->hash() == hash && p->symbol() == sym && p->symbol_mode() == sym_mode) {
533-
return p;
534-
}
535-
}
536-
return NULL;
537-
}
538-
539-
540-
SymbolPropertyEntry* SymbolPropertyTable::add_entry(int index, unsigned int hash,
541-
Symbol* sym, intptr_t sym_mode) {
542-
assert_locked_or_safepoint(SystemDictionary_lock);
543-
assert(index == index_for(sym, sym_mode), "incorrect index?");
544-
assert(find_entry(index, hash, sym, sym_mode) == NULL, "no double entry");
545-
546-
SymbolPropertyEntry* p = new_entry(hash, sym, sym_mode);
547-
Hashtable<Symbol*, mtSymbol>::add_entry(index, p);
548-
return p;
549-
}
550-
551-
void SymbolPropertyTable::methods_do(void f(Method*)) {
552-
for (int index = 0; index < table_size(); index++) {
553-
for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
554-
Method* prop = p->method();
555-
if (prop != NULL) {
556-
f((Method*)prop);
557-
}
558-
}
559-
}
560-
}
561-
562-
void SymbolPropertyTable::free_entry(SymbolPropertyEntry* entry) {
563-
entry->free_entry();
564-
BasicHashtable<mtSymbol>::free_entry(entry);
565-
}
566-
567484
void DictionaryEntry::verify_protection_domain_set() {
568485
assert(SafepointSynchronize::is_at_safepoint(), "must only be called as safepoint");
569486
for (ProtectionDomainEntry* current = pd_set_acquire(); // accessed at a safepoint

src/hotspot/share/classfile/dictionary.hpp

Lines changed: 0 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -153,98 +153,4 @@ class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
153153
void verify();
154154
};
155155

156-
// Entry in a SymbolPropertyTable, mapping a single Symbol*
157-
// to a managed and an unmanaged pointer.
158-
class SymbolPropertyEntry : public HashtableEntry<Symbol*, mtSymbol> {
159-
friend class VMStructs;
160-
private:
161-
intptr_t _symbol_mode; // secondary key
162-
Method* _method;
163-
OopHandle _method_type;
164-
165-
public:
166-
Symbol* symbol() const { return literal(); }
167-
168-
intptr_t symbol_mode() const { return _symbol_mode; }
169-
void set_symbol_mode(intptr_t m) { _symbol_mode = m; }
170-
171-
Method* method() const { return _method; }
172-
void set_method(Method* p) { _method = p; }
173-
174-
oop method_type() const;
175-
void set_method_type(oop p);
176-
177-
// We need to clear the OopHandle because these hashtable entries are not constructed properly.
178-
void clear_method_type() { _method_type = OopHandle(); }
179-
180-
void free_entry();
181-
182-
SymbolPropertyEntry* next() const {
183-
return (SymbolPropertyEntry*)HashtableEntry<Symbol*, mtSymbol>::next();
184-
}
185-
186-
SymbolPropertyEntry** next_addr() {
187-
return (SymbolPropertyEntry**)HashtableEntry<Symbol*, mtSymbol>::next_addr();
188-
}
189-
190-
void print_entry(outputStream* st) const;
191-
};
192-
193-
// A system-internal mapping of symbols to pointers, both managed
194-
// and unmanaged. Used to record the auto-generation of each method
195-
// MethodHandle.invoke(S)T, for all signatures (S)T.
196-
class SymbolPropertyTable : public Hashtable<Symbol*, mtSymbol> {
197-
friend class VMStructs;
198-
private:
199-
// The following method is not MT-safe and must be done under lock.
200-
SymbolPropertyEntry** bucket_addr(int i) {
201-
return (SymbolPropertyEntry**) Hashtable<Symbol*, mtSymbol>::bucket_addr(i);
202-
}
203-
204-
void add_entry(int index, SymbolPropertyEntry* new_entry) {
205-
ShouldNotReachHere();
206-
}
207-
void set_entry(int index, SymbolPropertyEntry* new_entry) {
208-
ShouldNotReachHere();
209-
}
210-
211-
SymbolPropertyEntry* new_entry(unsigned int hash, Symbol* symbol, intptr_t symbol_mode) {
212-
SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable<Symbol*, mtSymbol>::new_entry(hash, symbol);
213-
// Hashtable with Symbol* literal must increment and decrement refcount.
214-
symbol->increment_refcount();
215-
entry->set_symbol_mode(symbol_mode);
216-
entry->set_method(NULL);
217-
entry->clear_method_type();
218-
return entry;
219-
}
220-
221-
public:
222-
SymbolPropertyTable(int table_size);
223-
SymbolPropertyTable(int table_size, HashtableBucket<mtSymbol>* t, int number_of_entries);
224-
225-
void free_entry(SymbolPropertyEntry* entry);
226-
227-
unsigned int compute_hash(Symbol* sym, intptr_t symbol_mode) {
228-
// Use the regular identity_hash.
229-
return Hashtable<Symbol*, mtSymbol>::compute_hash(sym) ^ symbol_mode;
230-
}
231-
232-
int index_for(Symbol* name, intptr_t symbol_mode) {
233-
return hash_to_index(compute_hash(name, symbol_mode));
234-
}
235-
236-
// need not be locked; no state change
237-
SymbolPropertyEntry* find_entry(int index, unsigned int hash, Symbol* name, intptr_t name_mode);
238-
239-
// must be done under SystemDictionary_lock
240-
SymbolPropertyEntry* add_entry(int index, unsigned int hash, Symbol* name, intptr_t name_mode);
241-
242-
void methods_do(void f(Method*));
243-
244-
void verify();
245-
246-
SymbolPropertyEntry* bucket(int i) {
247-
return (SymbolPropertyEntry*) Hashtable<Symbol*, mtSymbol>::bucket(i);
248-
}
249-
};
250156
#endif // SHARE_CLASSFILE_DICTIONARY_HPP

src/hotspot/share/classfile/systemDictionary.cpp

Lines changed: 88 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@
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"
@@ -87,7 +89,32 @@
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;
91118
ProtectionDomainCacheTable* SystemDictionary::_pd_cache_table = NULL;
92119

93120
OopHandle SystemDictionary::_java_system_loader;
@@ -1633,10 +1660,21 @@ bool SystemDictionary::do_unloading(GCTimer* gc_timer) {
16331660

16341661
void 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,
19942031
Method* 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

Comments
 (0)