8292596: Make SymbolHashMap a ResourceHashtable

Reviewed-by: hseigel, dholmes
This commit is contained in:
Coleen Phillimore 2022-08-22 18:43:51 +00:00
parent aa9b8f04bf
commit 8e8ee4b6f2
4 changed files with 30 additions and 156 deletions

@ -2007,11 +2007,11 @@ jint ConstantPool::cpool_entry_size(jint idx) {
} /* end cpool_entry_size */
// SymbolHashMap is used to find a constant pool index from a string.
// This function fills in SymbolHashMaps, one for utf8s and one for
// SymbolHash is used to find a constant pool index from a string.
// This function fills in SymbolHashs, one for utf8s and one for
// class names, returns size of the cpool raw bytes.
jint ConstantPool::hash_entries_to(SymbolHashMap *symmap,
SymbolHashMap *classmap) {
jint ConstantPool::hash_entries_to(SymbolHash *symmap,
SymbolHash *classmap) {
jint size = 0;
for (u2 idx = 1; idx < length(); idx++) {
@ -2021,7 +2021,7 @@ jint ConstantPool::hash_entries_to(SymbolHashMap *symmap,
switch(tag) {
case JVM_CONSTANT_Utf8: {
Symbol* sym = symbol_at(idx);
symmap->add_entry(sym, idx);
symmap->add_if_absent(sym, idx);
DBG(printf("adding symbol entry %s = %d\n", sym->as_utf8(), idx));
break;
}
@ -2029,7 +2029,7 @@ jint ConstantPool::hash_entries_to(SymbolHashMap *symmap,
case JVM_CONSTANT_UnresolvedClass:
case JVM_CONSTANT_UnresolvedClassInError: {
Symbol* sym = klass_name_at(idx);
classmap->add_entry(sym, idx);
classmap->add_if_absent(sym, idx);
DBG(printf("adding class entry %s = %d\n", sym->as_utf8(), idx));
break;
}
@ -2050,8 +2050,8 @@ jint ConstantPool::hash_entries_to(SymbolHashMap *symmap,
// -1, in case of internal error
// > 0, count of the raw cpool bytes that have been copied
int ConstantPool::copy_cpool_bytes(int cpool_size,
SymbolHashMap* tbl,
unsigned char *bytes) {
SymbolHash* tbl,
unsigned char *bytes) {
u2 idx1, idx2;
jint size = 0;
jint cnt = length();
@ -2428,59 +2428,3 @@ void ConstantPool::verify_on(outputStream* st) {
guarantee(pool_holder()->is_klass(), "should be klass");
}
}
SymbolHashMap::~SymbolHashMap() {
SymbolHashMapEntry* next;
for (int i = 0; i < _table_size; i++) {
for (SymbolHashMapEntry* cur = bucket(i); cur != NULL; cur = next) {
next = cur->next();
delete(cur);
}
}
FREE_C_HEAP_ARRAY(SymbolHashMapBucket, _buckets);
}
void SymbolHashMap::add_entry(Symbol* sym, u2 value) {
char *str = sym->as_utf8();
unsigned int hash = compute_hash(str, sym->utf8_length());
unsigned int index = hash % table_size();
// check if already in map
// we prefer the first entry since it is more likely to be what was used in
// the class file
for (SymbolHashMapEntry *en = bucket(index); en != NULL; en = en->next()) {
assert(en->symbol() != NULL, "SymbolHashMapEntry symbol is NULL");
if (en->hash() == hash && en->symbol() == sym) {
return; // already there
}
}
SymbolHashMapEntry* entry = new SymbolHashMapEntry(hash, sym, value);
entry->set_next(bucket(index));
_buckets[index].set_entry(entry);
assert(entry->symbol() != NULL, "SymbolHashMapEntry symbol is NULL");
}
SymbolHashMapEntry* SymbolHashMap::find_entry(Symbol* sym) {
assert(sym != NULL, "SymbolHashMap::find_entry - symbol is NULL");
char *str = sym->as_utf8();
int len = sym->utf8_length();
unsigned int hash = SymbolHashMap::compute_hash(str, len);
unsigned int index = hash % table_size();
for (SymbolHashMapEntry *en = bucket(index); en != NULL; en = en->next()) {
assert(en->symbol() != NULL, "SymbolHashMapEntry symbol is NULL");
if (en->hash() == hash && en->symbol() == sym) {
return en;
}
}
return NULL;
}
void SymbolHashMap::initialize_table(int table_size) {
_table_size = table_size;
_buckets = NEW_C_HEAP_ARRAY(SymbolHashMapBucket, table_size, mtSymbol);
for (int index = 0; index < table_size; index++) {
_buckets[index].clear();
}
}

@ -47,8 +47,6 @@
// entry is read without a lock, only the resolved state guarantees that
// the entry in the constant pool is a klass object and not a Symbol*.
class SymbolHashMap;
// This represents a JVM_CONSTANT_Class, JVM_CONSTANT_UnresolvedClass, or
// JVM_CONSTANT_UnresolvedClassInError slot in the constant pool.
class CPKlassSlot {
@ -890,8 +888,23 @@ class ConstantPool : public Metadata {
friend class JvmtiConstantPoolReconstituter;
private:
class SymbolHash: public CHeapObj<mtSymbol> {
ResourceHashtable<const Symbol*, u2, 256, ResourceObj::C_HEAP, mtSymbol, Symbol::compute_hash> _table;
public:
void add_if_absent(const Symbol* sym, u2 value) {
bool created;
_table.put_if_absent(sym, value, &created);
}
u2 symbol_to_value(const Symbol* sym) {
u2* value = _table.get(sym);
return (value == nullptr) ? 0 : *value;
}
}; // End SymbolHash class
jint cpool_entry_size(jint idx);
jint hash_entries_to(SymbolHashMap *symmap, SymbolHashMap *classmap);
jint hash_entries_to(SymbolHash *symmap, SymbolHash *classmap);
// Copy cpool bytes into byte array.
// Returns:
@ -899,7 +912,7 @@ class ConstantPool : public Metadata {
// 0, OutOfMemory error
// -1, Internal error
int copy_cpool_bytes(int cpool_size,
SymbolHashMap* tbl,
SymbolHash* tbl,
unsigned char *bytes);
public:
@ -914,88 +927,4 @@ class ConstantPool : public Metadata {
const char* internal_name() const { return "{constant pool}"; }
};
class SymbolHashMapEntry : public CHeapObj<mtSymbol> {
private:
SymbolHashMapEntry* _next; // Next element in the linked list for this bucket
Symbol* _symbol; // 1-st part of the mapping: symbol => value
unsigned int _hash; // 32-bit hash for item
u2 _value; // 2-nd part of the mapping: symbol => value
public:
unsigned int hash() const { return _hash; }
void set_hash(unsigned int hash) { _hash = hash; }
SymbolHashMapEntry* next() const { return _next; }
void set_next(SymbolHashMapEntry* next) { _next = next; }
Symbol* symbol() const { return _symbol; }
void set_symbol(Symbol* sym) { _symbol = sym; }
u2 value() const { return _value; }
void set_value(u2 value) { _value = value; }
SymbolHashMapEntry(unsigned int hash, Symbol* symbol, u2 value)
: _next(NULL), _symbol(symbol), _hash(hash), _value(value) {}
}; // End SymbolHashMapEntry class
class SymbolHashMapBucket : public CHeapObj<mtSymbol> {
private:
SymbolHashMapEntry* _entry;
public:
SymbolHashMapEntry* entry() const { return _entry; }
void set_entry(SymbolHashMapEntry* entry) { _entry = entry; }
void clear() { _entry = NULL; }
}; // End SymbolHashMapBucket class
class SymbolHashMap: public CHeapObj<mtSymbol> {
private:
// Default number of entries in the table
enum SymbolHashMap_Constants {
_Def_HashMap_Size = 256
};
int _table_size;
SymbolHashMapBucket* _buckets;
void initialize_table(int table_size);
public:
int table_size() const { return _table_size; }
SymbolHashMap() { initialize_table(_Def_HashMap_Size); }
SymbolHashMap(int table_size) { initialize_table(table_size); }
// hash P(31) from Kernighan & Ritchie
static unsigned int compute_hash(const char* str, int len) {
unsigned int hash = 0;
while (len-- > 0) {
hash = 31*hash + (unsigned) *str;
str++;
}
return hash;
}
SymbolHashMapEntry* bucket(int i) {
return _buckets[i].entry();
}
void add_entry(Symbol* sym, u2 value);
SymbolHashMapEntry* find_entry(Symbol* sym);
u2 symbol_to_value(Symbol* sym) {
SymbolHashMapEntry *entry = find_entry(sym);
return (entry == NULL) ? 0 : entry->value();
}
~SymbolHashMap();
}; // End SymbolHashMap class
#endif // SHARE_OOPS_CONSTANTPOOL_HPP

@ -41,8 +41,8 @@ JvmtiConstantPoolReconstituter::JvmtiConstantPoolReconstituter(InstanceKlass* ik
set_error(JVMTI_ERROR_NONE);
_ik = ik;
_cpool = constantPoolHandle(Thread::current(), ik->constants());
_symmap = new SymbolHashMap();
_classmap = new SymbolHashMap();
_symmap = new ConstantPool::SymbolHash();
_classmap = new ConstantPool::SymbolHash();
_cpool_size = _cpool->hash_entries_to(_symmap, _classmap);
if (_cpool_size == 0) {
set_error(JVMTI_ERROR_OUT_OF_MEMORY);

@ -26,13 +26,14 @@
#define SHARE_PRIMS_JVMTICLASSFILERECONSTITUTER_HPP
#include "jvmtifiles/jvmtiEnv.hpp"
#include "oops/constantPool.hpp"
class JvmtiConstantPoolReconstituter : public StackObj {
private:
int _cpool_size;
SymbolHashMap* _symmap;
SymbolHashMap* _classmap;
ConstantPool::SymbolHash* _symmap;
ConstantPool::SymbolHash* _classmap;
constantPoolHandle _cpool;
InstanceKlass* _ik;
jvmtiError _err;