Skip to content

Commit

Permalink
8289164: Convert ResolutionErrorTable to use ResourceHashtable
Browse files Browse the repository at this point in the history
Reviewed-by: iklam, coleenp
  • Loading branch information
gujustin1 authored and coleenp committed Jul 7, 2022
1 parent 013a5ee commit 86f63f9
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 179 deletions.
181 changes: 80 additions & 101 deletions src/hotspot/share/classfile/resolutionErrors.cpp
Expand Up @@ -25,162 +25,141 @@
#include "precompiled.hpp"
#include "classfile/resolutionErrors.hpp"
#include "memory/allocation.hpp"
#include "memory/resourceArea.hpp"
#include "oops/constantPool.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klass.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/safepoint.hpp"
#include "utilities/hashtable.inline.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/resourceHash.hpp"

ResourceHashtable<uintptr_t, ResolutionErrorEntry*, 107, ResourceObj::C_HEAP, mtClass> _resolution_error_table;

// create new error entry
void ResolutionErrorTable::add_entry(int index, unsigned int hash,
const constantPoolHandle& pool, int cp_index,
void ResolutionErrorTable::add_entry(const constantPoolHandle& pool, int cp_index,
Symbol* error, Symbol* message,
Symbol* cause, Symbol* cause_msg)
{
assert_locked_or_safepoint(SystemDictionary_lock);
assert(!pool.is_null() && error != NULL, "adding NULL obj");

ResolutionErrorEntry* entry = (ResolutionErrorEntry*)Hashtable<ConstantPool*, mtClass>::new_entry(hash, pool());
entry->set_cp_index(cp_index);
entry->set_error(error);
entry->set_message(message);
entry->set_nest_host_error(NULL);
entry->set_cause(cause);
entry->set_cause_msg(cause_msg);

add_entry(index, entry);
ResolutionErrorEntry* entry = new ResolutionErrorEntry(pool(), cp_index, error, message, cause, cause_msg);
_resolution_error_table.put(convert_key(pool, cp_index), entry);
}

// create new nest host error entry
void ResolutionErrorTable::add_entry(int index, unsigned int hash,
const constantPoolHandle& pool, int cp_index,
void ResolutionErrorTable::add_entry(const constantPoolHandle& pool, int cp_index,
const char* message)
{
assert_locked_or_safepoint(SystemDictionary_lock);
assert(!pool.is_null() && message != NULL, "adding NULL obj");

ResolutionErrorEntry* entry = (ResolutionErrorEntry*)Hashtable<ConstantPool*, mtClass>::new_entry(hash, pool());
entry->set_cp_index(cp_index);
entry->set_nest_host_error(message);
entry->set_error(NULL);
entry->set_message(NULL);
entry->set_cause(NULL);
entry->set_cause_msg(NULL);

add_entry(index, entry);
ResolutionErrorEntry* entry = new ResolutionErrorEntry(pool(), cp_index, message);
_resolution_error_table.put(convert_key(pool, cp_index), entry);
}

// find entry in the table
ResolutionErrorEntry* ResolutionErrorTable::find_entry(int index, unsigned int hash,
const constantPoolHandle& pool, int cp_index)
{
ResolutionErrorEntry* ResolutionErrorTable::find_entry(const constantPoolHandle& pool, int cp_index) {
assert_locked_or_safepoint(SystemDictionary_lock);

for (ResolutionErrorEntry *error_probe = bucket(index);
error_probe != NULL;
error_probe = error_probe->next()) {
if (error_probe->hash() == hash && error_probe->pool() == pool()) {
return error_probe;;
}
ResolutionErrorEntry** entry = _resolution_error_table.get(convert_key(pool, cp_index));
if (entry != nullptr) {
return *entry;
} else {
return nullptr;
}
return NULL;

}

void ResolutionErrorEntry::set_error(Symbol* e) {
_error = e;
if (_error != NULL) {
ResolutionErrorEntry::ResolutionErrorEntry(ConstantPool* pool, int cp_index, Symbol* error, Symbol* message,
Symbol* cause, Symbol* cause_msg):
_cp_index(cp_index),
_error(error),
_message(message),
_cause(cause),
_cause_msg(cause_msg),
_pool(pool),
_nest_host_error(nullptr) {

if (_error != nullptr) {
_error->increment_refcount();
}
}

void ResolutionErrorEntry::set_message(Symbol* c) {
_message = c;
if (_message != NULL) {
if (_message != nullptr) {
_message->increment_refcount();
}
}

void ResolutionErrorEntry::set_cause(Symbol* c) {
_cause = c;
if (_cause != NULL) {
if (_cause != nullptr) {
_cause->increment_refcount();
}
}

void ResolutionErrorEntry::set_cause_msg(Symbol* c) {
_cause_msg = c;
if (_cause_msg != NULL) {
if (_cause_msg != nullptr) {
_cause_msg->increment_refcount();
}
}

void ResolutionErrorEntry::set_nest_host_error(const char* message) {
_nest_host_error = message;
}

void ResolutionErrorTable::free_entry(ResolutionErrorEntry *entry) {
ResolutionErrorEntry::~ResolutionErrorEntry() {
// decrement error refcount
if (entry->error() != NULL) {
entry->error()->decrement_refcount();
if (error() != NULL) {
error()->decrement_refcount();
}
if (entry->message() != NULL) {
entry->message()->decrement_refcount();
if (message() != NULL) {
message()->decrement_refcount();
}
if (entry->cause() != NULL) {
entry->cause()->decrement_refcount();
if (cause() != NULL) {
cause()->decrement_refcount();
}
if (entry->cause_msg() != NULL) {
entry->cause_msg()->decrement_refcount();
if (cause_msg() != NULL) {
cause_msg()->decrement_refcount();
}
if (entry->nest_host_error() != NULL) {
FREE_C_HEAP_ARRAY(char, entry->nest_host_error());
if (nest_host_error() != NULL) {
FREE_C_HEAP_ARRAY(char, nest_host_error());
}
BasicHashtable<mtClass>::free_entry(entry);
}

class ResolutionErrorDeleteIterate : StackObj{
private:
ConstantPool* p;

// create resolution error table
ResolutionErrorTable::ResolutionErrorTable(int table_size)
: Hashtable<ConstantPool*, mtClass>(table_size, sizeof(ResolutionErrorEntry)) {
}
public:
ResolutionErrorDeleteIterate(ConstantPool* pool):
p(pool) {};

// RedefineClasses support - remove matching entry of a
// constant pool that is going away
void ResolutionErrorTable::delete_entry(ConstantPool* c) {
assert_locked_or_safepoint(SystemDictionary_lock);
for (int i = 0; i < table_size(); i++) {
for (ResolutionErrorEntry** p = bucket_addr(i); *p != NULL; ) {
ResolutionErrorEntry* entry = *p;
assert(entry->pool() != NULL, "resolution error table is corrupt");
if (entry->pool() == c) {
*p = entry->next();
free_entry(entry);
} else {
p = entry->next_addr();
}
bool do_entry(uintptr_t key, ResolutionErrorEntry* value){
if (value -> pool() == p) {
delete value;
return true;
} else {
return false;
}
}
};

// Delete entries in the table that match with ConstantPool c
void ResolutionErrorTable::delete_entry(ConstantPool* c) {
assert_locked_or_safepoint(SystemDictionary_lock);

ResolutionErrorDeleteIterate deleteIterator(c);
_resolution_error_table.unlink(&deleteIterator);
}

class ResolutionIteratePurgeErrors : StackObj{
public:
bool do_entry(uintptr_t key, ResolutionErrorEntry* value) {
ConstantPool* pool = value -> pool();
if (!(pool->pool_holder()->is_loader_alive())) {
delete value;
return true;
} else {
return false;
}
}
};

// Remove unloaded entries from the table
void ResolutionErrorTable::purge_resolution_errors() {
assert_locked_or_safepoint(SystemDictionary_lock);
for (int i = 0; i < table_size(); i++) {
for (ResolutionErrorEntry** p = bucket_addr(i); *p != NULL; ) {
ResolutionErrorEntry* entry = *p;
assert(entry->pool() != (ConstantPool*)NULL, "resolution error table is corrupt");
ConstantPool* pool = entry->pool();
assert(pool->pool_holder() != NULL, "Constant pool without a class?");

if (pool->pool_holder()->is_loader_alive()) {
p = entry->next_addr();
} else {
*p = entry->next();
free_entry(entry);
}
}
}

ResolutionIteratePurgeErrors purgeErrorsIterator;
_resolution_error_table.unlink(&purgeErrorsIterator);
}

84 changes: 32 additions & 52 deletions src/hotspot/share/classfile/resolutionErrors.hpp
Expand Up @@ -26,7 +26,6 @@
#define SHARE_CLASSFILE_RESOLUTIONERRORS_HPP

#include "oops/constantPool.hpp"
#include "utilities/hashtable.hpp"

class ResolutionErrorEntry;

Expand All @@ -39,48 +38,23 @@ class ResolutionErrorEntry;
// index of another entry in the table.
const int CPCACHE_INDEX_MANGLE_VALUE = 1000000;

class ResolutionErrorTable : public Hashtable<ConstantPool*, mtClass> {

private:
void free_entry(ResolutionErrorEntry *entry);
class ResolutionErrorTable : AllStatic {

public:
ResolutionErrorTable(int table_size);

ResolutionErrorEntry* bucket(int i) {
return (ResolutionErrorEntry*)Hashtable<ConstantPool*, mtClass>::bucket(i);
}

ResolutionErrorEntry** bucket_addr(int i) {
return (ResolutionErrorEntry**)Hashtable<ConstantPool*, mtClass>::bucket_addr(i);
}

void add_entry(int index, ResolutionErrorEntry* new_entry) {
Hashtable<ConstantPool*, mtClass>::add_entry(index,
(HashtableEntry<ConstantPool*, mtClass>*)new_entry);
}

void add_entry(int index, unsigned int hash,
const constantPoolHandle& pool, int which, Symbol* error, Symbol* message,
static void add_entry(const constantPoolHandle& pool, int which, Symbol* error, Symbol* message,
Symbol* cause, Symbol* cause_msg);

void add_entry(int index, unsigned int hash,
const constantPoolHandle& pool, int which, const char* message);
static void add_entry(const constantPoolHandle& pool, int which, const char* message);

// find error given the constant pool and constant pool index
ResolutionErrorEntry* find_entry(int index, unsigned int hash,
const constantPoolHandle& pool, int cp_index);


unsigned int compute_hash(const constantPoolHandle& pool, int cp_index) {
return (unsigned int) pool->identity_hash() + cp_index;
}
static ResolutionErrorEntry* find_entry(const constantPoolHandle& pool, int cp_index);

// purges unloaded entries from the table
void purge_resolution_errors();
static void purge_resolution_errors();

// RedefineClasses support - remove obsolete constant pool entry
void delete_entry(ConstantPool* c);
static void delete_entry(ConstantPool* c);

// This function is used to encode an index to differentiate it from a
// constant pool index. It assumes it is being called with a cpCache index
Expand All @@ -89,46 +63,52 @@ class ResolutionErrorTable : public Hashtable<ConstantPool*, mtClass> {
assert(index < 0, "Unexpected non-negative cpCache index");
return index + CPCACHE_INDEX_MANGLE_VALUE;
}

static uintptr_t convert_key(const constantPoolHandle& pool, int cp_index) {
return (uintptr_t) (pool() + cp_index);
}
};


class ResolutionErrorEntry : public HashtableEntry<ConstantPool*, mtClass> {
class ResolutionErrorEntry : public CHeapObj<mtClass> {
private:
int _cp_index;
Symbol* _error;
Symbol* _message;
Symbol* _cause;
Symbol* _cause_msg;
ConstantPool* _pool;
const char* _nest_host_error;

public:
ConstantPool* pool() const { return literal(); }

int cp_index() const { return _cp_index; }
void set_cp_index(int cp_index) { _cp_index = cp_index; }
ResolutionErrorEntry(ConstantPool* pool, int cp_index, Symbol* error, Symbol* message,
Symbol* cause, Symbol* cause_msg);

Symbol* error() const { return _error; }
void set_error(Symbol* e);
ResolutionErrorEntry(ConstantPool* pool, int cp_index, const char* message):
_cp_index(cp_index),
_error(nullptr),
_message(nullptr),
_cause(nullptr),
_cause_msg(nullptr),
_pool(pool),
_nest_host_error(message) {}

Symbol* message() const { return _message; }
void set_message(Symbol* c);
~ResolutionErrorEntry();

Symbol* cause() const { return _cause; }
void set_cause(Symbol* c);
void set_nest_host_error(const char* message) {
_nest_host_error = message;
}

Symbol* cause_msg() const { return _cause_msg; }
void set_cause_msg(Symbol* c);

ConstantPool* pool() const { return _pool; }
int cp_index() const { return _cp_index; }
Symbol* error() const { return _error; }
Symbol* message() const { return _message; }
Symbol* cause() const { return _cause; }
Symbol* cause_msg() const { return _cause_msg; }
const char* nest_host_error() const { return _nest_host_error; }
void set_nest_host_error(const char* message);

ResolutionErrorEntry* next() const {
return (ResolutionErrorEntry*)HashtableEntry<ConstantPool*, mtClass>::next();
}

ResolutionErrorEntry** next_addr() {
return (ResolutionErrorEntry**)HashtableEntry<ConstantPool*, mtClass>::next_addr();
}
};

#endif // SHARE_CLASSFILE_RESOLUTIONERRORS_HPP

1 comment on commit 86f63f9

@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.