8292596: Make SymbolHashMap a ResourceHashtable
Reviewed-by: hseigel, dholmes
This commit is contained in:
parent
aa9b8f04bf
commit
8e8ee4b6f2
src/hotspot/share
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user