8292384: Convert AdapterHandlerTable to ResourceHashtable

Reviewed-by: hseigel, rehn
This commit is contained in:
Coleen Phillimore 2022-08-17 12:53:05 +00:00
parent 0c67fba11f
commit f45b8408a0
3 changed files with 89 additions and 182 deletions

View file

@ -72,7 +72,7 @@
#include "utilities/copy.hpp" #include "utilities/copy.hpp"
#include "utilities/dtrace.hpp" #include "utilities/dtrace.hpp"
#include "utilities/events.hpp" #include "utilities/events.hpp"
#include "utilities/hashtable.inline.hpp" #include "utilities/resourceHash.hpp"
#include "utilities/macros.hpp" #include "utilities/macros.hpp"
#include "utilities/xmlstream.hpp" #include "utilities/xmlstream.hpp"
#ifdef COMPILER1 #ifdef COMPILER1
@ -2390,6 +2390,12 @@ void SharedRuntime::print_call_statistics(uint64_t comp_total) {
} }
#endif #endif
#ifndef PRODUCT
static int _lookups; // number of calls to lookup
static int _equals; // number of buckets checked with matching hash
static int _hits; // number of successful lookups
static int _compact; // number of equals calls with compact signature
#endif
// A simple wrapper class around the calling convention information // A simple wrapper class around the calling convention information
// that allows sharing of adapters for the same calling convention. // that allows sharing of adapters for the same calling convention.
@ -2576,147 +2582,55 @@ class AdapterFingerPrint : public CHeapObj<mtCode> {
} }
return true; return true;
} }
static bool equals(AdapterFingerPrint* const& fp1, AdapterFingerPrint* const& fp2) {
NOT_PRODUCT(_equals++);
return fp1->equals(fp2);
}
static unsigned int compute_hash(AdapterFingerPrint* const& fp) {
return fp->compute_hash();
}
}; };
// A hashtable mapping from AdapterFingerPrints to AdapterHandlerEntries // A hashtable mapping from AdapterFingerPrints to AdapterHandlerEntries
class AdapterHandlerTable : public BasicHashtable<mtCode> { ResourceHashtable<AdapterFingerPrint*, AdapterHandlerEntry*, 293,
friend class AdapterHandlerTableIterator; ResourceObj::C_HEAP, mtCode,
AdapterFingerPrint::compute_hash,
AdapterFingerPrint::equals> _adapter_handler_table;
private: // Find a entry with the same fingerprint if it exists
static AdapterHandlerEntry* lookup(int total_args_passed, BasicType* sig_bt) {
#ifndef PRODUCT
static int _lookups; // number of calls to lookup
static int _buckets; // number of buckets checked
static int _equals; // number of buckets checked with matching hash
static int _hits; // number of successful lookups
static int _compact; // number of equals calls with compact signature
#endif
AdapterHandlerEntry* bucket(int i) {
return (AdapterHandlerEntry*)BasicHashtable<mtCode>::bucket(i);
}
public:
AdapterHandlerTable()
: BasicHashtable<mtCode>(293, (sizeof(AdapterHandlerEntry))) { }
// Create a new entry suitable for insertion in the table
AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry, address c2i_no_clinit_check_entry) {
AdapterHandlerEntry* entry = (AdapterHandlerEntry*)BasicHashtable<mtCode>::new_entry(fingerprint->compute_hash());
entry->init(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry);
return entry;
}
// Insert an entry into the table
void add(AdapterHandlerEntry* entry) {
int index = hash_to_index(entry->hash());
add_entry(index, entry);
}
void free_entry(AdapterHandlerEntry* entry) {
entry->deallocate();
BasicHashtable<mtCode>::free_entry(entry);
}
// Find a entry with the same fingerprint if it exists
AdapterHandlerEntry* lookup(int total_args_passed, BasicType* sig_bt) {
NOT_PRODUCT(_lookups++); NOT_PRODUCT(_lookups++);
assert_lock_strong(AdapterHandlerLibrary_lock);
AdapterFingerPrint fp(total_args_passed, sig_bt); AdapterFingerPrint fp(total_args_passed, sig_bt);
unsigned int hash = fp.compute_hash(); AdapterHandlerEntry** entry = _adapter_handler_table.get(&fp);
int index = hash_to_index(hash); if (entry != nullptr) {
for (AdapterHandlerEntry* e = bucket(index); e != NULL; e = e->next()) {
NOT_PRODUCT(_buckets++);
if (e->hash() == hash) {
NOT_PRODUCT(_equals++);
if (fp.equals(e->fingerprint())) {
#ifndef PRODUCT #ifndef PRODUCT
if (fp.is_compact()) _compact++; if (fp.is_compact()) _compact++;
_hits++; _hits++;
#endif #endif
return e; return *entry;
}
}
}
return NULL;
} }
return nullptr;
}
#ifndef PRODUCT #ifndef PRODUCT
void print_statistics() { static void print_table_statistics() {
ResourceMark rm; auto size = [&] (AdapterFingerPrint* key, AdapterHandlerEntry* a) {
int longest = 0; return sizeof(*key) + sizeof(*a);
int empty = 0; };
int total = 0; TableStatistics ts = _adapter_handler_table.statistics_calculate(size);
int nonempty = 0; ts.print(tty, "AdapterHandlerTable");
for (int index = 0; index < table_size(); index++) { tty->print_cr("AdapterHandlerTable (table_size=%d, entries=%d)",
int count = 0; _adapter_handler_table.table_size(), _adapter_handler_table.number_of_entries());
for (AdapterHandlerEntry* e = bucket(index); e != NULL; e = e->next()) { tty->print_cr("AdapterHandlerTable: lookups %d equals %d hits %d compact %d",
count++; _lookups, _equals, _hits, _compact);
} }
if (count != 0) nonempty++;
if (count == 0) empty++;
if (count > longest) longest = count;
total += count;
}
tty->print_cr("AdapterHandlerTable: empty %d longest %d total %d average %f",
empty, longest, total, total / (double)nonempty);
tty->print_cr("AdapterHandlerTable: lookups %d buckets %d equals %d hits %d compact %d",
_lookups, _buckets, _equals, _hits, _compact);
}
#endif #endif
};
#ifndef PRODUCT
int AdapterHandlerTable::_lookups;
int AdapterHandlerTable::_buckets;
int AdapterHandlerTable::_equals;
int AdapterHandlerTable::_hits;
int AdapterHandlerTable::_compact;
#endif
class AdapterHandlerTableIterator : public StackObj {
private:
AdapterHandlerTable* _table;
int _index;
AdapterHandlerEntry* _current;
void scan() {
while (_index < _table->table_size()) {
AdapterHandlerEntry* a = _table->bucket(_index);
_index++;
if (a != NULL) {
_current = a;
return;
}
}
}
public:
AdapterHandlerTableIterator(AdapterHandlerTable* table): _table(table), _index(0), _current(NULL) {
scan();
}
bool has_next() {
return _current != NULL;
}
AdapterHandlerEntry* next() {
if (_current != NULL) {
AdapterHandlerEntry* result = _current;
_current = _current->next();
if (_current == NULL) scan();
return result;
} else {
return NULL;
}
}
};
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Implementation of AdapterHandlerLibrary // Implementation of AdapterHandlerLibrary
AdapterHandlerTable* AdapterHandlerLibrary::_adapters = NULL;
AdapterHandlerEntry* AdapterHandlerLibrary::_abstract_method_handler = NULL; AdapterHandlerEntry* AdapterHandlerLibrary::_abstract_method_handler = NULL;
AdapterHandlerEntry* AdapterHandlerLibrary::_no_arg_handler = NULL; AdapterHandlerEntry* AdapterHandlerLibrary::_no_arg_handler = NULL;
AdapterHandlerEntry* AdapterHandlerLibrary::_int_arg_handler = NULL; AdapterHandlerEntry* AdapterHandlerLibrary::_int_arg_handler = NULL;
@ -2734,7 +2648,8 @@ extern "C" void unexpected_adapter_call() {
ShouldNotCallThis(); ShouldNotCallThis();
} }
static void post_adapter_creation(const AdapterBlob* new_adapter, const AdapterHandlerEntry* entry) { static void post_adapter_creation(const AdapterBlob* new_adapter,
const AdapterHandlerEntry* entry) {
if (Forte::is_enabled() || JvmtiExport::should_post_dynamic_code_generated()) { if (Forte::is_enabled() || JvmtiExport::should_post_dynamic_code_generated()) {
char blob_id[256]; char blob_id[256];
jio_snprintf(blob_id, jio_snprintf(blob_id,
@ -2761,9 +2676,6 @@ void AdapterHandlerLibrary::initialize() {
AdapterBlob* obj_obj_arg_blob = NULL; AdapterBlob* obj_obj_arg_blob = NULL;
{ {
MutexLocker mu(AdapterHandlerLibrary_lock); MutexLocker mu(AdapterHandlerLibrary_lock);
assert(_adapters == NULL, "Initializing more than once");
_adapters = new AdapterHandlerTable();
// Create a special handler for abstract methods. Abstract methods // Create a special handler for abstract methods. Abstract methods
// are never compiled so an i2c entry is somewhat meaningless, but // are never compiled so an i2c entry is somewhat meaningless, but
@ -2776,7 +2688,6 @@ void AdapterHandlerLibrary::initialize() {
wrong_method_abstract, wrong_method_abstract); wrong_method_abstract, wrong_method_abstract);
_buffer = BufferBlob::create("adapters", AdapterHandlerLibrary_size); _buffer = BufferBlob::create("adapters", AdapterHandlerLibrary_size);
_no_arg_handler = create_adapter(no_arg_blob, 0, NULL, true); _no_arg_handler = create_adapter(no_arg_blob, 0, NULL, true);
BasicType obj_args[] = { T_OBJECT }; BasicType obj_args[] = { T_OBJECT };
@ -2811,7 +2722,9 @@ AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* finger
address c2i_entry, address c2i_entry,
address c2i_unverified_entry, address c2i_unverified_entry,
address c2i_no_clinit_check_entry) { address c2i_no_clinit_check_entry) {
return _adapters->new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry); // Insert an entry into the table
return new AdapterHandlerEntry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry,
c2i_no_clinit_check_entry);
} }
AdapterHandlerEntry* AdapterHandlerLibrary::get_simple_adapter(const methodHandle& method) { AdapterHandlerEntry* AdapterHandlerLibrary::get_simple_adapter(const methodHandle& method) {
@ -2897,10 +2810,9 @@ class AdapterSignatureIterator : public SignatureIterator {
AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& method) { AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& method) {
// Use customized signature handler. Need to lock around updates to // Use customized signature handler. Need to lock around updates to
// the AdapterHandlerTable (it is not safe for concurrent readers // the _adapter_handler_table (it is not safe for concurrent readers
// and a single writer: this could be fixed if it becomes a // and a single writer: this could be fixed if it becomes a
// problem). // problem).
assert(_adapters != NULL, "Uninitialized");
// Fast-path for trivial adapters // Fast-path for trivial adapters
AdapterHandlerEntry* entry = get_simple_adapter(method); AdapterHandlerEntry* entry = get_simple_adapter(method);
@ -2922,7 +2834,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& meth
MutexLocker mu(AdapterHandlerLibrary_lock); MutexLocker mu(AdapterHandlerLibrary_lock);
// Lookup method signature's fingerprint // Lookup method signature's fingerprint
entry = _adapters->lookup(total_args_passed, sig_bt); entry = lookup(total_args_passed, sig_bt);
if (entry != NULL) { if (entry != NULL) {
#ifdef ASSERT #ifdef ASSERT
@ -2932,7 +2844,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& meth
assert(comparison_blob == NULL, "no blob should be created when creating an adapter for comparison"); assert(comparison_blob == NULL, "no blob should be created when creating an adapter for comparison");
assert(comparison_entry->compare_code(entry), "code must match"); assert(comparison_entry->compare_code(entry), "code must match");
// Release the one just created and return the original // Release the one just created and return the original
_adapters->free_entry(comparison_entry); delete comparison_entry;
} }
#endif #endif
return entry; return entry;
@ -3004,7 +2916,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::create_adapter(AdapterBlob*& new_ada
ttyLocker ttyl; ttyLocker ttyl;
entry->print_adapter_on(tty); entry->print_adapter_on(tty);
tty->print_cr("i2c argument handler #%d for: %s %s (%d bytes generated)", tty->print_cr("i2c argument handler #%d for: %s %s (%d bytes generated)",
_adapters->number_of_entries(), fingerprint->as_basic_args_string(), _adapter_handler_table.number_of_entries(), fingerprint->as_basic_args_string(),
fingerprint->as_string(), insts_size); fingerprint->as_string(), insts_size);
tty->print_cr("c2i argument handler starts at " INTPTR_FORMAT, p2i(entry->get_c2i_entry())); tty->print_cr("c2i argument handler starts at " INTPTR_FORMAT, p2i(entry->get_c2i_entry()));
if (Verbose || PrintStubCode) { if (Verbose || PrintStubCode) {
@ -3021,7 +2933,8 @@ AdapterHandlerEntry* AdapterHandlerLibrary::create_adapter(AdapterBlob*& new_ada
// Add the entry only if the entry contains all required checks (see sharedRuntime_xxx.cpp) // Add the entry only if the entry contains all required checks (see sharedRuntime_xxx.cpp)
// The checks are inserted only if -XX:+VerifyAdapterCalls is specified. // The checks are inserted only if -XX:+VerifyAdapterCalls is specified.
if (contains_all_checks || !VerifyAdapterCalls) { if (contains_all_checks || !VerifyAdapterCalls) {
_adapters->add(entry); assert_lock_strong(AdapterHandlerLibrary_lock);
_adapter_handler_table.put(fingerprint, entry);
} }
return entry; return entry;
} }
@ -3051,7 +2964,7 @@ void AdapterHandlerEntry::relocate(address new_base) {
} }
void AdapterHandlerEntry::deallocate() { AdapterHandlerEntry::~AdapterHandlerEntry() {
delete _fingerprint; delete _fingerprint;
#ifdef ASSERT #ifdef ASSERT
FREE_C_HEAP_ARRAY(unsigned char, _saved_code); FREE_C_HEAP_ARRAY(unsigned char, _saved_code);
@ -3340,25 +3253,30 @@ JRT_LEAF(void, SharedRuntime::OSR_migration_end( intptr_t* buf) )
JRT_END JRT_END
bool AdapterHandlerLibrary::contains(const CodeBlob* b) { bool AdapterHandlerLibrary::contains(const CodeBlob* b) {
AdapterHandlerTableIterator iter(_adapters); bool found = false;
while (iter.has_next()) { auto findblob = [&] (AdapterFingerPrint* key, AdapterHandlerEntry* a) {
AdapterHandlerEntry* a = iter.next(); return (found = (b == CodeCache::find_blob(a->get_i2c_entry())));
if (b == CodeCache::find_blob(a->get_i2c_entry())) return true; };
} assert_locked_or_safepoint(AdapterHandlerLibrary_lock);
return false; _adapter_handler_table.iterate(findblob);
return found;
} }
void AdapterHandlerLibrary::print_handler_on(outputStream* st, const CodeBlob* b) { void AdapterHandlerLibrary::print_handler_on(outputStream* st, const CodeBlob* b) {
AdapterHandlerTableIterator iter(_adapters); bool found = false;
while (iter.has_next()) { auto findblob = [&] (AdapterFingerPrint* key, AdapterHandlerEntry* a) {
AdapterHandlerEntry* a = iter.next();
if (b == CodeCache::find_blob(a->get_i2c_entry())) { if (b == CodeCache::find_blob(a->get_i2c_entry())) {
found = true;
st->print("Adapter for signature: "); st->print("Adapter for signature: ");
a->print_adapter_on(tty); a->print_adapter_on(st);
return; return true;
} else {
return false; // keep looking
} }
} };
assert(false, "Should have found handler"); assert_locked_or_safepoint(AdapterHandlerLibrary_lock);
_adapter_handler_table.iterate(findblob);
assert(found, "Should have found handler");
} }
void AdapterHandlerEntry::print_adapter_on(outputStream* st) const { void AdapterHandlerEntry::print_adapter_on(outputStream* st) const {
@ -3381,7 +3299,7 @@ void AdapterHandlerEntry::print_adapter_on(outputStream* st) const {
#ifndef PRODUCT #ifndef PRODUCT
void AdapterHandlerLibrary::print_statistics() { void AdapterHandlerLibrary::print_statistics() {
_adapters->print_statistics(); print_table_statistics();
} }
#endif /* PRODUCT */ #endif /* PRODUCT */

View file

@ -31,11 +31,9 @@
#include "interpreter/linkResolver.hpp" #include "interpreter/linkResolver.hpp"
#include "memory/allStatic.hpp" #include "memory/allStatic.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "utilities/hashtable.hpp"
#include "utilities/macros.hpp" #include "utilities/macros.hpp"
class AdapterHandlerEntry; class AdapterHandlerEntry;
class AdapterHandlerTable;
class AdapterFingerPrint; class AdapterFingerPrint;
class vframeStream; class vframeStream;
@ -611,8 +609,7 @@ class SharedRuntime: AllStatic {
// used by the adapters. The code generation happens here because it's very // used by the adapters. The code generation happens here because it's very
// similar to what the adapters have to do. // similar to what the adapters have to do.
class AdapterHandlerEntry : public BasicHashtableEntry<mtCode> { class AdapterHandlerEntry : public CHeapObj<mtCode> {
friend class AdapterHandlerTable;
friend class AdapterHandlerLibrary; friend class AdapterHandlerLibrary;
private: private:
@ -629,21 +626,20 @@ class AdapterHandlerEntry : public BasicHashtableEntry<mtCode> {
int _saved_code_length; int _saved_code_length;
#endif #endif
void init(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry, address c2i_no_clinit_check_entry) { AdapterHandlerEntry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry,
_fingerprint = fingerprint; address c2i_unverified_entry,
_i2c_entry = i2c_entry; address c2i_no_clinit_check_entry) :
_c2i_entry = c2i_entry; _fingerprint(fingerprint),
_c2i_unverified_entry = c2i_unverified_entry; _i2c_entry(i2c_entry),
_c2i_no_clinit_check_entry = c2i_no_clinit_check_entry; _c2i_entry(c2i_entry),
_c2i_unverified_entry(c2i_unverified_entry),
_c2i_no_clinit_check_entry(c2i_no_clinit_check_entry)
#ifdef ASSERT #ifdef ASSERT
_saved_code_length = 0; , _saved_code_length(0)
#endif #endif
} { }
void deallocate(); ~AdapterHandlerEntry();
// should never be used
AdapterHandlerEntry();
public: public:
address get_i2c_entry() const { return _i2c_entry; } address get_i2c_entry() const { return _i2c_entry; }
@ -656,10 +652,6 @@ class AdapterHandlerEntry : public BasicHashtableEntry<mtCode> {
AdapterFingerPrint* fingerprint() const { return _fingerprint; } AdapterFingerPrint* fingerprint() const { return _fingerprint; }
AdapterHandlerEntry* next() {
return (AdapterHandlerEntry*)BasicHashtableEntry<mtCode>::next();
}
#ifdef ASSERT #ifdef ASSERT
// Used to verify that code generated for shared adapters is equivalent // Used to verify that code generated for shared adapters is equivalent
void save_code (unsigned char* code, int length); void save_code (unsigned char* code, int length);
@ -674,7 +666,6 @@ class AdapterHandlerLibrary: public AllStatic {
friend class SharedRuntime; friend class SharedRuntime;
private: private:
static BufferBlob* _buffer; // the temporary code buffer in CodeCache static BufferBlob* _buffer; // the temporary code buffer in CodeCache
static AdapterHandlerTable* _adapters;
static AdapterHandlerEntry* _abstract_method_handler; static AdapterHandlerEntry* _abstract_method_handler;
static AdapterHandlerEntry* _no_arg_handler; static AdapterHandlerEntry* _no_arg_handler;
static AdapterHandlerEntry* _int_arg_handler; static AdapterHandlerEntry* _int_arg_handler;

View file

@ -271,10 +271,8 @@ template class Hashtable<Symbol*, mtClass>;
template class HashtableEntry<Symbol*, mtClass>; template class HashtableEntry<Symbol*, mtClass>;
template class HashtableBucket<mtClass>; template class HashtableBucket<mtClass>;
template class BasicHashtableEntry<mtSymbol>; template class BasicHashtableEntry<mtSymbol>;
template class BasicHashtableEntry<mtCode>;
template class BasicHashtable<mtClass>; template class BasicHashtable<mtClass>;
template class BasicHashtable<mtClassShared>; template class BasicHashtable<mtClassShared>;
template class BasicHashtable<mtCode>;
template class BasicHashtable<mtInternal>; template class BasicHashtable<mtInternal>;
template class BasicHashtable<mtModule>; template class BasicHashtable<mtModule>;
template class BasicHashtable<mtCompiler>; template class BasicHashtable<mtCompiler>;