Skip to content

Commit

Permalink
8292384: Convert AdapterHandlerTable to ResourceHashtable
Browse files Browse the repository at this point in the history
Reviewed-by: hseigel, rehn
  • Loading branch information
coleenp committed Aug 17, 2022
1 parent 0c67fba commit f45b840
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 178 deletions.
228 changes: 73 additions & 155 deletions src/hotspot/share/runtime/sharedRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
#include "utilities/copy.hpp"
#include "utilities/dtrace.hpp"
#include "utilities/events.hpp"
#include "utilities/hashtable.inline.hpp"
#include "utilities/resourceHash.hpp"
#include "utilities/macros.hpp"
#include "utilities/xmlstream.hpp"
#ifdef COMPILER1
Expand Down Expand Up @@ -2390,6 +2390,12 @@ void SharedRuntime::print_call_statistics(uint64_t comp_total) {
}
#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
// that allows sharing of adapters for the same calling convention.
Expand Down Expand Up @@ -2576,147 +2582,55 @@ class AdapterFingerPrint : public CHeapObj<mtCode> {
}
return true;
}
};


// A hashtable mapping from AdapterFingerPrints to AdapterHandlerEntries
class AdapterHandlerTable : public BasicHashtable<mtCode> {
friend class AdapterHandlerTableIterator;

private:

#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);
static bool equals(AdapterFingerPrint* const& fp1, AdapterFingerPrint* const& fp2) {
NOT_PRODUCT(_equals++);
return fp1->equals(fp2);
}

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;
static unsigned int compute_hash(AdapterFingerPrint* const& fp) {
return fp->compute_hash();
}
};

// 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++);
AdapterFingerPrint fp(total_args_passed, sig_bt);
unsigned int hash = fp.compute_hash();
int index = hash_to_index(hash);
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())) {
// A hashtable mapping from AdapterFingerPrints to AdapterHandlerEntries
ResourceHashtable<AdapterFingerPrint*, AdapterHandlerEntry*, 293,
ResourceObj::C_HEAP, mtCode,
AdapterFingerPrint::compute_hash,
AdapterFingerPrint::equals> _adapter_handler_table;

// Find a entry with the same fingerprint if it exists
static AdapterHandlerEntry* lookup(int total_args_passed, BasicType* sig_bt) {
NOT_PRODUCT(_lookups++);
assert_lock_strong(AdapterHandlerLibrary_lock);
AdapterFingerPrint fp(total_args_passed, sig_bt);
AdapterHandlerEntry** entry = _adapter_handler_table.get(&fp);
if (entry != nullptr) {
#ifndef PRODUCT
if (fp.is_compact()) _compact++;
_hits++;
if (fp.is_compact()) _compact++;
_hits++;
#endif
return e;
}
}
}
return NULL;
return *entry;
}
return nullptr;
}

#ifndef PRODUCT
void print_statistics() {
ResourceMark rm;
int longest = 0;
int empty = 0;
int total = 0;
int nonempty = 0;
for (int index = 0; index < table_size(); index++) {
int count = 0;
for (AdapterHandlerEntry* e = bucket(index); e != NULL; e = e->next()) {
count++;
}
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
};


#ifndef PRODUCT

int AdapterHandlerTable::_lookups;
int AdapterHandlerTable::_buckets;
int AdapterHandlerTable::_equals;
int AdapterHandlerTable::_hits;
int AdapterHandlerTable::_compact;

static void print_table_statistics() {
auto size = [&] (AdapterFingerPrint* key, AdapterHandlerEntry* a) {
return sizeof(*key) + sizeof(*a);
};
TableStatistics ts = _adapter_handler_table.statistics_calculate(size);
ts.print(tty, "AdapterHandlerTable");
tty->print_cr("AdapterHandlerTable (table_size=%d, entries=%d)",
_adapter_handler_table.table_size(), _adapter_handler_table.number_of_entries());
tty->print_cr("AdapterHandlerTable: lookups %d equals %d hits %d compact %d",
_lookups, _equals, _hits, _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
AdapterHandlerTable* AdapterHandlerLibrary::_adapters = NULL;
AdapterHandlerEntry* AdapterHandlerLibrary::_abstract_method_handler = NULL;
AdapterHandlerEntry* AdapterHandlerLibrary::_no_arg_handler = NULL;
AdapterHandlerEntry* AdapterHandlerLibrary::_int_arg_handler = NULL;
Expand All @@ -2734,7 +2648,8 @@ extern "C" void unexpected_adapter_call() {
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()) {
char blob_id[256];
jio_snprintf(blob_id,
Expand All @@ -2761,9 +2676,6 @@ void AdapterHandlerLibrary::initialize() {
AdapterBlob* obj_obj_arg_blob = NULL;
{
MutexLocker mu(AdapterHandlerLibrary_lock);
assert(_adapters == NULL, "Initializing more than once");

_adapters = new AdapterHandlerTable();

// Create a special handler for abstract methods. Abstract methods
// are never compiled so an i2c entry is somewhat meaningless, but
Expand All @@ -2776,7 +2688,6 @@ void AdapterHandlerLibrary::initialize() {
wrong_method_abstract, wrong_method_abstract);

_buffer = BufferBlob::create("adapters", AdapterHandlerLibrary_size);

_no_arg_handler = create_adapter(no_arg_blob, 0, NULL, true);

BasicType obj_args[] = { T_OBJECT };
Expand Down Expand Up @@ -2811,7 +2722,9 @@ AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* finger
address c2i_entry,
address c2i_unverified_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) {
Expand Down Expand Up @@ -2897,10 +2810,9 @@ class AdapterSignatureIterator : public SignatureIterator {

AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& method) {
// 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
// problem).
assert(_adapters != NULL, "Uninitialized");

// Fast-path for trivial adapters
AdapterHandlerEntry* entry = get_simple_adapter(method);
Expand All @@ -2922,7 +2834,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& meth
MutexLocker mu(AdapterHandlerLibrary_lock);

// Lookup method signature's fingerprint
entry = _adapters->lookup(total_args_passed, sig_bt);
entry = lookup(total_args_passed, sig_bt);

if (entry != NULL) {
#ifdef ASSERT
Expand All @@ -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_entry->compare_code(entry), "code must match");
// Release the one just created and return the original
_adapters->free_entry(comparison_entry);
delete comparison_entry;
}
#endif
return entry;
Expand Down Expand Up @@ -3004,7 +2916,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::create_adapter(AdapterBlob*& new_ada
ttyLocker ttyl;
entry->print_adapter_on(tty);
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);
tty->print_cr("c2i argument handler starts at " INTPTR_FORMAT, p2i(entry->get_c2i_entry()));
if (Verbose || PrintStubCode) {
Expand All @@ -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)
// The checks are inserted only if -XX:+VerifyAdapterCalls is specified.
if (contains_all_checks || !VerifyAdapterCalls) {
_adapters->add(entry);
assert_lock_strong(AdapterHandlerLibrary_lock);
_adapter_handler_table.put(fingerprint, entry);
}
return entry;
}
Expand Down Expand Up @@ -3051,7 +2964,7 @@ void AdapterHandlerEntry::relocate(address new_base) {
}


void AdapterHandlerEntry::deallocate() {
AdapterHandlerEntry::~AdapterHandlerEntry() {
delete _fingerprint;
#ifdef ASSERT
FREE_C_HEAP_ARRAY(unsigned char, _saved_code);
Expand Down Expand Up @@ -3340,25 +3253,30 @@ JRT_LEAF(void, SharedRuntime::OSR_migration_end( intptr_t* buf) )
JRT_END

bool AdapterHandlerLibrary::contains(const CodeBlob* b) {
AdapterHandlerTableIterator iter(_adapters);
while (iter.has_next()) {
AdapterHandlerEntry* a = iter.next();
if (b == CodeCache::find_blob(a->get_i2c_entry())) return true;
}
return false;
bool found = false;
auto findblob = [&] (AdapterFingerPrint* key, AdapterHandlerEntry* a) {
return (found = (b == CodeCache::find_blob(a->get_i2c_entry())));
};
assert_locked_or_safepoint(AdapterHandlerLibrary_lock);
_adapter_handler_table.iterate(findblob);
return found;
}

void AdapterHandlerLibrary::print_handler_on(outputStream* st, const CodeBlob* b) {
AdapterHandlerTableIterator iter(_adapters);
while (iter.has_next()) {
AdapterHandlerEntry* a = iter.next();
bool found = false;
auto findblob = [&] (AdapterFingerPrint* key, AdapterHandlerEntry* a) {
if (b == CodeCache::find_blob(a->get_i2c_entry())) {
found = true;
st->print("Adapter for signature: ");
a->print_adapter_on(tty);
return;
a->print_adapter_on(st);
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 {
Expand All @@ -3381,7 +3299,7 @@ void AdapterHandlerEntry::print_adapter_on(outputStream* st) const {
#ifndef PRODUCT

void AdapterHandlerLibrary::print_statistics() {
_adapters->print_statistics();
print_table_statistics();
}

#endif /* PRODUCT */
Expand Down

1 comment on commit f45b840

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.