8304069: ClassFileParser has ad-hoc hashtables
Reviewed-by: coleenp, dholmes
This commit is contained in:
parent
9a8a60f7d6
commit
d8ba227aa4
@ -771,52 +771,27 @@ class NameSigHash: public ResourceObj {
|
|||||||
public:
|
public:
|
||||||
const Symbol* _name; // name
|
const Symbol* _name; // name
|
||||||
const Symbol* _sig; // signature
|
const Symbol* _sig; // signature
|
||||||
NameSigHash* _next; // Next entry in hash table
|
|
||||||
};
|
|
||||||
|
|
||||||
static const int HASH_ROW_SIZE = 256;
|
static const int HASH_ROW_SIZE = 256;
|
||||||
|
|
||||||
static unsigned int hash(const Symbol* name, const Symbol* sig) {
|
NameSigHash(Symbol* name, Symbol* sig) :
|
||||||
unsigned int raw_hash = 0;
|
_name(name),
|
||||||
raw_hash += ((unsigned int)(uintptr_t)name) >> (LogHeapWordSize + 2);
|
_sig(sig) {}
|
||||||
raw_hash += ((unsigned int)(uintptr_t)sig) >> LogHeapWordSize;
|
|
||||||
|
|
||||||
return (raw_hash + (unsigned int)(uintptr_t)name) % HASH_ROW_SIZE;
|
static unsigned int hash(NameSigHash const& namesig) {
|
||||||
}
|
return namesig._name->identity_hash() ^ namesig._sig->identity_hash();
|
||||||
|
|
||||||
|
|
||||||
static void initialize_hashtable(NameSigHash** table) {
|
|
||||||
memset((void*)table, 0, sizeof(NameSigHash*) * HASH_ROW_SIZE);
|
|
||||||
}
|
|
||||||
// Return false if the name/sig combination is found in table.
|
|
||||||
// Return true if no duplicate is found. And name/sig is added as a new entry in table.
|
|
||||||
// The old format checker uses heap sort to find duplicates.
|
|
||||||
// NOTE: caller should guarantee that GC doesn't happen during the life cycle
|
|
||||||
// of table since we don't expect Symbol*'s to move.
|
|
||||||
static bool put_after_lookup(const Symbol* name, const Symbol* sig, NameSigHash** table) {
|
|
||||||
assert(name != nullptr, "name in constant pool is null");
|
|
||||||
|
|
||||||
// First lookup for duplicates
|
|
||||||
int index = hash(name, sig);
|
|
||||||
NameSigHash* entry = table[index];
|
|
||||||
while (entry != nullptr) {
|
|
||||||
if (entry->_name == name && entry->_sig == sig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
entry = entry->_next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// No duplicate is found, allocate a new entry and fill it.
|
static bool equals(NameSigHash const& e0, NameSigHash const& e1) {
|
||||||
entry = new NameSigHash();
|
return (e0._name == e1._name) &&
|
||||||
entry->_name = name;
|
(e0._sig == e1._sig);
|
||||||
entry->_sig = sig;
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Insert into hash table
|
using NameSigHashtable = ResourceHashtable<NameSigHash, int,
|
||||||
entry->_next = table[index];
|
NameSigHash::HASH_ROW_SIZE,
|
||||||
table[index] = entry;
|
AnyObj::RESOURCE_AREA, mtInternal,
|
||||||
|
&NameSigHash::hash, &NameSigHash::equals>;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Side-effects: populates the _local_interfaces field
|
// Side-effects: populates the _local_interfaces field
|
||||||
void ClassFileParser::parse_interfaces(const ClassFileStream* const stream,
|
void ClassFileParser::parse_interfaces(const ClassFileStream* const stream,
|
||||||
@ -882,28 +857,17 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream,
|
|||||||
|
|
||||||
// Check if there's any duplicates in interfaces
|
// Check if there's any duplicates in interfaces
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
NameSigHash** interface_names = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD,
|
// Set containing interface names
|
||||||
NameSigHash*,
|
ResourceHashtable<Symbol*, int>* interface_names = new ResourceHashtable<Symbol*, int>();
|
||||||
HASH_ROW_SIZE);
|
for (index = 0; index < itfs_len; index++) {
|
||||||
initialize_hashtable(interface_names);
|
const InstanceKlass* const k = _local_interfaces->at(index);
|
||||||
bool dup = false;
|
Symbol* interface_name = k->name();
|
||||||
const Symbol* name = nullptr;
|
// If no duplicates, add (name, nullptr) in hashtable interface_names.
|
||||||
{
|
if (!interface_names->put(interface_name, 0)) {
|
||||||
debug_only(NoSafepointVerifier nsv;)
|
classfile_parse_error("Duplicate interface name \"%s\" in class file %s",
|
||||||
for (index = 0; index < itfs_len; index++) {
|
interface_name->as_C_string(), THREAD);
|
||||||
const InstanceKlass* const k = _local_interfaces->at(index);
|
|
||||||
name = k->name();
|
|
||||||
// If no duplicates, add (name, nullptr) in hashtable interface_names.
|
|
||||||
if (!put_after_lookup(name, nullptr, interface_names)) {
|
|
||||||
dup = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dup) {
|
|
||||||
classfile_parse_error("Duplicate interface name \"%s\" in class file %s",
|
|
||||||
name->as_C_string(), THREAD);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1621,28 +1585,17 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
|
|||||||
if (_need_verify && length > 1) {
|
if (_need_verify && length > 1) {
|
||||||
// Check duplicated fields
|
// Check duplicated fields
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
NameSigHash** names_and_sigs = NEW_RESOURCE_ARRAY_IN_THREAD(
|
// Set containing name-signature pairs
|
||||||
THREAD, NameSigHash*, HASH_ROW_SIZE);
|
NameSigHashtable* names_and_sigs = new NameSigHashtable();
|
||||||
initialize_hashtable(names_and_sigs);
|
for (int i = 0; i < _temp_field_info->length(); i++) {
|
||||||
bool dup = false;
|
NameSigHash name_and_sig(_temp_field_info->adr_at(i)->name(_cp),
|
||||||
const Symbol* name = nullptr;
|
_temp_field_info->adr_at(i)->signature(_cp));
|
||||||
const Symbol* sig = nullptr;
|
// If no duplicates, add name/signature in hashtable names_and_sigs.
|
||||||
{
|
if(!names_and_sigs->put(name_and_sig, 0)) {
|
||||||
debug_only(NoSafepointVerifier nsv;)
|
classfile_parse_error("Duplicate field name \"%s\" with signature \"%s\" in class file %s",
|
||||||
for (int i = 0; i < _temp_field_info->length(); i++) {
|
name_and_sig._name->as_C_string(), name_and_sig._sig->as_klass_external_name(), THREAD);
|
||||||
name = _temp_field_info->adr_at(i)->name(_cp);
|
|
||||||
sig = _temp_field_info->adr_at(i)->signature(_cp);
|
|
||||||
// If no duplicates, add name/signature in hashtable names_and_sigs.
|
|
||||||
if (!put_after_lookup(name, sig, names_and_sigs)) {
|
|
||||||
dup = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dup) {
|
|
||||||
classfile_parse_error("Duplicate field name \"%s\" with signature \"%s\" in class file %s",
|
|
||||||
name->as_C_string(), sig->as_klass_external_name(), THREAD);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2871,29 +2824,17 @@ void ClassFileParser::parse_methods(const ClassFileStream* const cfs,
|
|||||||
if (_need_verify && length > 1) {
|
if (_need_verify && length > 1) {
|
||||||
// Check duplicated methods
|
// Check duplicated methods
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
NameSigHash** names_and_sigs = NEW_RESOURCE_ARRAY_IN_THREAD(
|
// Set containing name-signature pairs
|
||||||
THREAD, NameSigHash*, HASH_ROW_SIZE);
|
NameSigHashtable* names_and_sigs = new NameSigHashtable();
|
||||||
initialize_hashtable(names_and_sigs);
|
for (int i = 0; i < length; i++) {
|
||||||
bool dup = false;
|
const Method* const m = _methods->at(i);
|
||||||
const Symbol* name = nullptr;
|
NameSigHash name_and_sig(m->name(), m->signature());
|
||||||
const Symbol* sig = nullptr;
|
// If no duplicates, add name/signature in hashtable names_and_sigs.
|
||||||
{
|
if(!names_and_sigs->put(name_and_sig, 0)) {
|
||||||
debug_only(NoSafepointVerifier nsv;)
|
classfile_parse_error("Duplicate method name \"%s\" with signature \"%s\" in class file %s",
|
||||||
for (int i = 0; i < length; i++) {
|
name_and_sig._name->as_C_string(), name_and_sig._sig->as_klass_external_name(), THREAD);
|
||||||
const Method* const m = _methods->at(i);
|
|
||||||
name = m->name();
|
|
||||||
sig = m->signature();
|
|
||||||
// If no duplicates, add name/signature in hashtable names_and_sigs.
|
|
||||||
if (!put_after_lookup(name, sig, names_and_sigs)) {
|
|
||||||
dup = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dup) {
|
|
||||||
classfile_parse_error("Duplicate method name \"%s\" with signature \"%s\" in class file %s",
|
|
||||||
name->as_C_string(), sig->as_klass_external_name(), THREAD);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user