8292068: Convert ModuleEntryTable into ResourceHashtable

Reviewed-by: iklam, lfoltan
This commit is contained in:
Coleen Phillimore 2022-08-10 22:04:33 +00:00
parent 543163a03b
commit b47438cabc
8 changed files with 185 additions and 259 deletions

@ -400,13 +400,7 @@ void ClassLoaderData::modules_do(void f(ModuleEntry*)) {
f(_unnamed_module);
}
if (_modules != NULL) {
for (int i = 0; i < _modules->table_size(); i++) {
for (ModuleEntry* entry = _modules->bucket(i);
entry != NULL;
entry = entry->next()) {
f(entry);
}
}
_modules->modules_do(f);
}
}
@ -592,7 +586,7 @@ ModuleEntryTable* ClassLoaderData::modules() {
MutexLocker m1(Module_lock);
// Check if _modules got allocated while we were waiting for this lock.
if ((modules = _modules) == NULL) {
modules = new ModuleEntryTable(ModuleEntryTable::_moduletable_entry_size);
modules = new ModuleEntryTable();
{
MutexLocker m1(metaspace_lock(), Mutex::_no_safepoint_check_flag);
@ -715,7 +709,7 @@ ClassLoaderData::~ClassLoaderData() {
}
if (_unnamed_module != NULL) {
_unnamed_module->delete_unnamed_module();
delete _unnamed_module;
_unnamed_module = NULL;
}
@ -1040,6 +1034,10 @@ void ClassLoaderData::verify() {
k->verify();
assert(k != k->next_link(), "no loops!");
}
if (_modules != NULL) {
_modules->verify();
}
}
bool ClassLoaderData::contains_klass(Klass* klass) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -81,17 +81,22 @@ void ClassLoaderExt::setup_app_search_path(JavaThread* current) {
void ClassLoaderExt::process_module_table(JavaThread* current, ModuleEntryTable* met) {
ResourceMark rm(current);
for (int i = 0; i < met->table_size(); i++) {
for (ModuleEntry* m = met->bucket(i); m != NULL;) {
class Process : public ModuleClosure {
JavaThread* _current;
public:
Process(JavaThread* current) : _current(current) {}
void do_module(ModuleEntry* m) {
char* path = m->location()->as_C_string();
if (strncmp(path, "file:", 5) == 0) {
path = ClassLoader::skip_uri_protocol(path);
ClassLoader::setup_module_search_path(current, path);
ClassLoader::setup_module_search_path(_current, path);
}
m = m->next();
}
}
};
Process process(current);
met->modules_do(&process);
}
void ClassLoaderExt::setup_module_paths(JavaThread* current) {
Arguments::assert_is_dumping_archive();
_app_module_paths_start_index = ClassLoader::num_boot_classpath_entries() +

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -51,11 +51,9 @@ ModuleEntry* ModuleEntryTable::_javabase_module = NULL;
oop ModuleEntry::module() const { return _module.resolve(); }
void ModuleEntry::set_location(Symbol* location) {
if (_location != NULL) {
// _location symbol's refcounts are managed by ModuleEntry,
// must decrement the old one before updating.
_location->decrement_refcount();
}
// _location symbol's refcounts are managed by ModuleEntry,
// must decrement the old one before updating.
Symbol::maybe_decrement_refcount(_location);
_location = location;
@ -98,17 +96,13 @@ bool ModuleEntry::should_show_version() {
}
void ModuleEntry::set_version(Symbol* version) {
if (_version != NULL) {
// _version symbol's refcounts are managed by ModuleEntry,
// must decrement the old one before updating.
_version->decrement_refcount();
}
// _version symbol's refcounts are managed by ModuleEntry,
// must decrement the old one before updating.
Symbol::maybe_decrement_refcount(_version);
_version = version;
if (version != NULL) {
version->increment_refcount();
}
Symbol::maybe_increment_refcount(version);
}
// Returns the shared ProtectionDomain
@ -262,6 +256,59 @@ void ModuleEntry::delete_reads() {
_reads = NULL;
}
ModuleEntry::ModuleEntry(Handle module_handle,
bool is_open, Symbol* name,
Symbol* version, Symbol* location,
ClassLoaderData* loader_data) :
_name(name),
_loader_data(loader_data),
_reads(nullptr),
_version(nullptr),
_location(nullptr),
CDS_ONLY(_shared_path_index(-1) COMMA)
_can_read_all_unnamed(false),
_has_default_read_edges(false),
_must_walk_reads(false),
_is_open(is_open),
_is_patched(false) {
// Initialize fields specific to a ModuleEntry
if (_name == nullptr) {
// Unnamed modules can read all other unnamed modules.
set_can_read_all_unnamed();
} else {
_name->increment_refcount();
}
if (!module_handle.is_null()) {
_module = loader_data->add_handle(module_handle);
}
set_version(version);
// may need to add CDS info
set_location(location);
if (name != nullptr && ClassLoader::is_in_patch_mod_entries(name)) {
set_is_patched();
if (log_is_enabled(Trace, module, patch)) {
ResourceMark rm;
log_trace(module, patch)("Marked module %s as patched from --patch-module",
name != NULL ? name->as_C_string() : UNNAMED_MODULE);
}
}
JFR_ONLY(INIT_ID(this);)
}
ModuleEntry::~ModuleEntry() {
// Clean out the C heap allocated reads list first before freeing the entry
delete_reads();
Symbol::maybe_decrement_refcount(_name);
Symbol::maybe_decrement_refcount(_version);
Symbol::maybe_decrement_refcount(_location);
}
ModuleEntry* ModuleEntry::create_unnamed_module(ClassLoaderData* cld) {
// The java.lang.Module for this loader's
// corresponding unnamed module can be found in the java.lang.ClassLoader object.
@ -295,72 +342,36 @@ ModuleEntry* ModuleEntry::create_boot_unnamed_module(ClassLoaderData* cld) {
// This is okay because the unnamed module gets created before the ClassLoaderData
// is available to other threads.
ModuleEntry* ModuleEntry::new_unnamed_module_entry(Handle module_handle, ClassLoaderData* cld) {
ModuleEntry* entry = NEW_C_HEAP_OBJ(ModuleEntry, mtModule);
// Initialize everything BasicHashtable would
entry->set_next(NULL);
entry->set_hash(0);
entry->set_literal(NULL);
// Initialize fields specific to a ModuleEntry
entry->init();
ModuleEntry* entry = new ModuleEntry(module_handle, /*is_open*/true, /*name*/nullptr,
/*version*/ nullptr, /*location*/ nullptr,
cld);
// Unnamed modules can read all other unnamed modules.
entry->set_can_read_all_unnamed();
if (!module_handle.is_null()) {
entry->set_module(cld->add_handle(module_handle));
}
entry->set_loader_data(cld);
entry->_is_open = true;
JFR_ONLY(INIT_ID(entry);)
assert(entry->can_read_all_unnamed(), "constructor set that");
return entry;
}
void ModuleEntry::delete_unnamed_module() {
// Do not need unlink_entry() since the unnamed module is not in the hashtable
FREE_C_HEAP_OBJ(this);
}
ModuleEntryTable::ModuleEntryTable() { }
ModuleEntryTable::ModuleEntryTable(int table_size)
: Hashtable<Symbol*, mtModule>(table_size, sizeof(ModuleEntry))
{
}
class ModuleEntryTableDeleter : public StackObj {
public:
bool do_entry(const Symbol*& name, ModuleEntry*& entry) {
if (log_is_enabled(Info, module, unload) || log_is_enabled(Debug, module)) {
ResourceMark rm;
const char* str = name->as_C_string();
log_info(module, unload)("unloading module %s", str);
log_debug(module)("ModuleEntryTable: deleting module: %s", str);
}
delete entry;
return true;
}
};
ModuleEntryTable::~ModuleEntryTable() {
// Walk through all buckets and all entries in each bucket,
// freeing each entry.
for (int i = 0; i < table_size(); ++i) {
for (ModuleEntry* m = bucket(i); m != NULL;) {
ModuleEntry* to_remove = m;
// read next before freeing.
m = m->next();
ModuleEntryTableDeleter deleter;
_table.unlink(&deleter);
assert(_table.number_of_entries() == 0, "should have removed all entries");
ResourceMark rm;
if (to_remove->name() != NULL) {
log_info(module, unload)("unloading module %s", to_remove->name()->as_C_string());
}
log_debug(module)("ModuleEntryTable: deleting module: %s", to_remove->name() != NULL ?
to_remove->name()->as_C_string() : UNNAMED_MODULE);
// Clean out the C heap allocated reads list first before freeing the entry
to_remove->delete_reads();
if (to_remove->name() != NULL) {
to_remove->name()->decrement_refcount();
}
if (to_remove->version() != NULL) {
to_remove->version()->decrement_refcount();
}
if (to_remove->location() != NULL) {
to_remove->location()->decrement_refcount();
}
BasicHashtable<mtModule>::free_entry(to_remove);
}
}
assert(number_of_entries() == 0, "should have removed all entries");
}
void ModuleEntry::set_loader_data(ClassLoaderData* cld) {
@ -429,7 +440,7 @@ GrowableArray<ModuleEntry*>* ModuleEntry::restore_growable_array(Array<ModuleEnt
}
void ModuleEntry::iterate_symbols(MetaspaceClosure* closure) {
closure->push(literal_addr()); // name
closure->push(&_name);
closure->push(&_version);
closure->push(&_location);
}
@ -437,13 +448,11 @@ void ModuleEntry::iterate_symbols(MetaspaceClosure* closure) {
void ModuleEntry::init_as_archived_entry() {
Array<ModuleEntry*>* archived_reads = write_growable_array(_reads);
set_next(NULL);
set_hash(0x0); // re-init at runtime
_loader_data = NULL; // re-init at runtime
_shared_path_index = FileMapInfo::get_module_shared_path_index(_location);
if (literal() != NULL) {
set_literal(ArchiveBuilder::get_relocated_symbol(literal()));
ArchivePtrMarker::mark_pointer((address*)literal_addr());
if (name() != NULL) {
_name = ArchiveBuilder::get_relocated_symbol(_name);
ArchivePtrMarker::mark_pointer((address*)&_name);
}
_reads = (GrowableArray<ModuleEntry*>*)archived_reads;
if (_version != NULL) {
@ -503,21 +512,20 @@ static int compare_module_by_name(ModuleEntry* a, ModuleEntry* b) {
}
void ModuleEntryTable::iterate_symbols(MetaspaceClosure* closure) {
for (int i = 0; i < table_size(); ++i) {
for (ModuleEntry* m = bucket(i); m != NULL; m = m->next()) {
auto syms = [&] (const Symbol*& key, ModuleEntry*& m) {
m->iterate_symbols(closure);
}
}
};
_table.iterate_all(syms);
}
Array<ModuleEntry*>* ModuleEntryTable::allocate_archived_entries() {
Array<ModuleEntry*>* archived_modules = ArchiveBuilder::new_rw_array<ModuleEntry*>(number_of_entries());
Array<ModuleEntry*>* archived_modules = ArchiveBuilder::new_rw_array<ModuleEntry*>(_table.number_of_entries());
int n = 0;
for (int i = 0; i < table_size(); ++i) {
for (ModuleEntry* m = bucket(i); m != NULL; m = m->next()) {
archived_modules->at_put(n++, m);
}
}
auto grab = [&] (const Symbol*& key, ModuleEntry*& m) {
archived_modules->at_put(n++, m);
};
_table.iterate_all(grab);
if (n > 1) {
// Always allocate in the same order to produce deterministic archive.
QuickSort::sort(archived_modules->data(), n, (_sort_Fn)compare_module_by_name, true);
@ -552,10 +560,7 @@ void ModuleEntryTable::load_archived_entries(ClassLoaderData* loader_data,
for (int i = 0; i < archived_modules->length(); i++) {
ModuleEntry* archived_entry = archived_modules->at(i);
archived_entry->load_from_archive(loader_data);
unsigned int hash = compute_hash(archived_entry->name());
archived_entry->set_hash(hash);
add_entry(hash_to_index(hash), archived_entry);
_table.put(archived_entry->name(), archived_entry);
}
}
@ -568,50 +573,6 @@ void ModuleEntryTable::restore_archived_oops(ClassLoaderData* loader_data, Array
}
#endif // INCLUDE_CDS_JAVA_HEAP
ModuleEntry* ModuleEntryTable::new_entry(unsigned int hash, Handle module_handle,
bool is_open, Symbol* name,
Symbol* version, Symbol* location,
ClassLoaderData* loader_data) {
assert(Module_lock->owned_by_self(), "should have the Module_lock");
ModuleEntry* entry = (ModuleEntry*)Hashtable<Symbol*, mtModule>::new_entry(hash, name);
// Initialize fields specific to a ModuleEntry
entry->init();
if (name != NULL) {
name->increment_refcount();
} else {
// Unnamed modules can read all other unnamed modules.
entry->set_can_read_all_unnamed();
}
if (!module_handle.is_null()) {
entry->set_module(loader_data->add_handle(module_handle));
}
entry->set_loader_data(loader_data);
entry->set_version(version);
entry->set_location(location);
entry->set_is_open(is_open);
if (ClassLoader::is_in_patch_mod_entries(name)) {
entry->set_is_patched();
if (log_is_enabled(Trace, module, patch)) {
ResourceMark rm;
log_trace(module, patch)("Marked module %s as patched from --patch-module",
name != NULL ? name->as_C_string() : UNNAMED_MODULE);
}
}
JFR_ONLY(INIT_ID(entry);)
return entry;
}
void ModuleEntryTable::add_entry(int index, ModuleEntry* new_entry) {
assert(Module_lock->owned_by_self(), "should have the Module_lock");
Hashtable<Symbol*, mtModule>::add_entry(index, (HashtableEntry<Symbol*, mtModule>*)new_entry);
}
// Create an entry in the class loader's module_entry_table. It is the
// caller's responsibility to ensure that the entry has not already been
// created.
@ -624,35 +585,29 @@ ModuleEntry* ModuleEntryTable::locked_create_entry(Handle module_handle,
assert(module_name != NULL, "ModuleEntryTable locked_create_entry should never be called for unnamed module.");
assert(Module_lock->owned_by_self(), "should have the Module_lock");
assert(lookup_only(module_name) == NULL, "Module already exists");
ModuleEntry* entry = new_entry(compute_hash(module_name), module_handle, is_open, module_name,
module_version, module_location, loader_data);
add_entry(index_for(module_name), entry);
ModuleEntry* entry = new ModuleEntry(module_handle, is_open, module_name,
module_version, module_location, loader_data);
bool created = _table.put(module_name, entry);
assert(created, "should be");
return entry;
}
// lookup_only by Symbol* to find a ModuleEntry.
ModuleEntry* ModuleEntryTable::lookup_only(Symbol* name) {
assert_locked_or_safepoint(Module_lock);
assert(name != NULL, "name cannot be NULL");
int index = index_for(name);
for (ModuleEntry* m = bucket(index); m != NULL; m = m->next()) {
if (m->name()->fast_compare(name) == 0) {
return m;
}
}
return NULL;
ModuleEntry** entry = _table.get(name);
return (entry == nullptr) ? nullptr : *entry;
}
// Remove dead modules from all other alive modules' reads list.
// This should only occur at class unloading.
void ModuleEntryTable::purge_all_module_reads() {
assert_locked_or_safepoint(Module_lock);
for (int i = 0; i < table_size(); i++) {
for (ModuleEntry* entry = bucket(i);
entry != NULL;
entry = entry->next()) {
entry->purge_reads();
}
}
auto purge = [&] (const Symbol*& key, ModuleEntry*& entry) {
entry->purge_reads();
};
_table.iterate_all(purge);
}
void ModuleEntryTable::finalize_javabase(Handle module_handle, Symbol* version, Symbol* location) {
@ -715,31 +670,47 @@ void ModuleEntryTable::patch_javabase_entries(Handle module_handle) {
}
void ModuleEntryTable::print(outputStream* st) {
ResourceMark rm;
auto printer = [&] (const Symbol*& name, ModuleEntry*& entry) {
entry->print(st);
};
st->print_cr("Module Entry Table (table_size=%d, entries=%d)",
table_size(), number_of_entries());
for (int i = 0; i < table_size(); i++) {
for (ModuleEntry* probe = bucket(i);
probe != NULL;
probe = probe->next()) {
probe->print(st);
}
}
_table.table_size(), _table.number_of_entries());
assert_locked_or_safepoint(Module_lock);
_table.iterate_all(printer);
}
void ModuleEntryTable::modules_do(void f(ModuleEntry*)) {
auto do_f = [&] (const Symbol*& key, ModuleEntry*& entry) {
f(entry);
};
_table.iterate_all(do_f);
}
void ModuleEntryTable::modules_do(ModuleClosure* closure) {
auto do_f = [&] (const Symbol*& key, ModuleEntry*& entry) {
closure->do_module(entry);
};
_table.iterate_all(do_f);
}
void ModuleEntry::print(outputStream* st) {
ResourceMark rm;
st->print_cr("entry " PTR_FORMAT " name %s module " PTR_FORMAT " loader %s version %s location %s strict %s next " PTR_FORMAT,
st->print_cr("entry " PTR_FORMAT " name %s module " PTR_FORMAT " loader %s version %s location %s strict %s",
p2i(this),
name() == NULL ? UNNAMED_MODULE : name()->as_C_string(),
p2i(module()),
loader_data()->loader_name_and_id(),
version() != NULL ? version()->as_C_string() : "NULL",
location() != NULL ? location()->as_C_string() : "NULL",
BOOL_TO_STR(!can_read_all_unnamed()), p2i(next()));
BOOL_TO_STR(!can_read_all_unnamed()));
}
void ModuleEntryTable::verify() {
verify_table<ModuleEntry>("Module Entry Table");
auto do_f = [&] (const Symbol*& key, ModuleEntry*& entry) {
entry->verify();
};
assert_locked_or_safepoint(Module_lock);
_table.iterate_all(do_f);
}
void ModuleEntry::verify() {

@ -30,9 +30,9 @@
#include "oops/symbol.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashtable.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
#include "utilities/resourceHash.hpp"
#if INCLUDE_JFR
#include "jfr/support/jfrTraceIdExtension.hpp"
#endif
@ -59,12 +59,13 @@ class ModuleClosure;
// - a flag indicating if this module can read all unnamed modules.
//
// The Mutex Module_lock is shared between ModuleEntry and PackageEntry, to lock either
// data structure.
class ModuleEntry : public HashtableEntry<Symbol*, mtModule> {
// data structure. This lock must be taken on all accesses to either table.
class ModuleEntry : public CHeapObj<mtModule> {
private:
OopHandle _module; // java.lang.Module
OopHandle _shared_pd; // java.security.ProtectionDomain, cached
// for shared classes from this module
Symbol* _name; // name of this module
ClassLoaderData* _loader_data;
GrowableArray<ModuleEntry*>* _reads; // list of modules that are readable by this module
Symbol* _version; // module version number
@ -81,24 +82,14 @@ private:
enum {MODULE_READS_SIZE = 101}; // Initial size of list of modules that the module can read.
public:
void init() {
_module = OopHandle();
_shared_pd = OopHandle();
_loader_data = NULL;
_reads = NULL;
_version = NULL;
_location = NULL;
_can_read_all_unnamed = false;
_has_default_read_edges = false;
_must_walk_reads = false;
_is_patched = false;
_is_open = false;
CDS_ONLY(_shared_path_index = -1);
}
ModuleEntry(Handle module_handle,
bool is_open, Symbol* name,
Symbol* version, Symbol* location,
ClassLoaderData* loader_data);
Symbol* name() const { return literal(); }
void set_name(Symbol* n) { set_literal(n); }
~ModuleEntry();
Symbol* name() const { return _name; }
oop module() const;
OopHandle module_handle() const { return _module; }
void set_module(OopHandle j) { _module = j; }
@ -129,7 +120,7 @@ public:
bool is_open() const { return _is_open; }
void set_is_open(bool is_open);
bool is_named() const { return (name() != NULL); }
bool is_named() const { return (_name != NULL); }
bool can_read_all_unnamed() const {
assert(is_named() || _can_read_all_unnamed == true,
@ -160,13 +151,6 @@ public:
return _is_patched;
}
ModuleEntry* next() const {
return (ModuleEntry*)HashtableEntry<Symbol*, mtModule>::next();
}
ModuleEntry** next_addr() {
return (ModuleEntry**)HashtableEntry<Symbol*, mtModule>::next_addr();
}
// iteration support for readability
void module_reads_do(ModuleClosure* const f);
@ -178,7 +162,6 @@ public:
static ModuleEntry* create_unnamed_module(ClassLoaderData* cld);
static ModuleEntry* create_boot_unnamed_module(ClassLoaderData* cld);
static ModuleEntry* new_unnamed_module_entry(Handle module_handle, ClassLoaderData* cld);
void delete_unnamed_module();
void print(outputStream* st = tty);
void verify();
@ -219,39 +202,16 @@ class ModuleClosure: public StackObj {
// PackageEntry node's correctly pointing at java.base's ModuleEntry. No class
// outside of java.base is allowed to be loaded pre-module system initialization.
//
// The ModuleEntryTable's lookup is lock free.
//
class ModuleEntryTable : public Hashtable<Symbol*, mtModule> {
friend class VMStructs;
public:
enum Constants {
_moduletable_entry_size = 109 // number of entries in module entry table
};
class ModuleEntryTable : public CHeapObj<mtModule> {
private:
static ModuleEntry* _javabase_module;
ModuleEntry* new_entry(unsigned int hash, Handle module_handle, bool is_open,
Symbol* name, Symbol* version, Symbol* location, ClassLoaderData* loader_data);
void add_entry(int index, ModuleEntry* new_entry);
int entry_size() const { return BasicHashtable<mtModule>::entry_size(); }
ModuleEntry** bucket_addr(int i) {
return (ModuleEntry**)Hashtable<Symbol*, mtModule>::bucket_addr(i);
}
static unsigned int compute_hash(Symbol* name) { return ((name == NULL) ? 0 : (unsigned int)(name->identity_hash())); }
int index_for(Symbol* name) const { return hash_to_index(compute_hash(name)); }
ResourceHashtable<const Symbol*, ModuleEntry*, 109, ResourceObj::C_HEAP, mtModule,
Symbol::compute_hash> _table;
public:
ModuleEntryTable(int table_size);
ModuleEntryTable();
~ModuleEntryTable();
ModuleEntry* bucket(int i) {
return (ModuleEntry*)Hashtable<Symbol*, mtModule>::bucket(i);
}
// Create module in loader's module entry table. Assume Module_lock
// has been locked by caller.
ModuleEntry* locked_create_entry(Handle module_handle,
@ -261,7 +221,7 @@ public:
Symbol* module_location,
ClassLoaderData* loader_data);
// Only lookup module within loader's module entry table. The table read is lock-free.
// Only lookup module within loader's module entry table.
ModuleEntry* lookup_only(Symbol* name);
// purge dead weak references out of reads list
@ -279,6 +239,9 @@ public:
static void finalize_javabase(Handle module_handle, Symbol* version, Symbol* location);
static void patch_javabase_entries(Handle module_handle);
void modules_do(void f(ModuleEntry*));
void modules_do(ModuleClosure* closure);
void print(outputStream* st = tty);
void verify();

@ -431,9 +431,13 @@ static bool java_base_can_read_jdk_jfr() {
return false;
}
assert(java_base_module != NULL, "invariant");
ModuleEntry* const jdk_jfr_module = table->lookup_only(jdk_jfr_module_symbol);
if (jdk_jfr_module == NULL) {
return false;
ModuleEntry* jdk_jfr_module;
{
MutexLocker ml(Module_lock);
jdk_jfr_module = table->lookup_only(jdk_jfr_module_symbol);
if (jdk_jfr_module == NULL) {
return false;
}
}
assert(jdk_jfr_module != NULL, "invariant");
if (java_base_module->can_read(jdk_jfr_module)) {

@ -297,6 +297,10 @@ class Symbol : public MetaspaceObj {
return _vm_symbols[static_cast<int>(vm_symbol_id)];
}
static unsigned int compute_hash(const Symbol* const& name) {
return (unsigned int) name->identity_hash();
}
#ifndef PRODUCT
// Empty constructor to create a dummy symbol object on stack
// only for getting its vtable pointer.

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -283,7 +283,6 @@ template class BasicHashtable<mtServiceability>;
template class BasicHashtable<mtLogging>;
template void BasicHashtable<mtClass>::verify_table<DictionaryEntry>(char const*);
template void BasicHashtable<mtModule>::verify_table<ModuleEntry>(char const*);
template void BasicHashtable<mtModule>::verify_table<PackageEntry>(char const*);
template void BasicHashtable<mtClass>::verify_table<ProtectionDomainCacheEntry>(char const*);
template void BasicHashtable<mtClass>::verify_table<PlaceholderEntry>(char const*);

@ -62,20 +62,9 @@ public class CheckForProperDetailStackTrace {
to make sure it matches even if the symbol is not unmangled.
*/
private static String stackTraceDefault =
".*Hashtable.*new_entry.*\n" +
".*ModuleEntryTable.*new_entry.*\n" +
".*ModuleEntryTable.*locked_create_entry.*\n" +
".*Modules.*define_module.*\n";
/* Alternate stacktrace that we check if the default fails, because
new_entry may be inlined.
*/
private static String stackTraceAlternate =
".*Hashtable.*new_entry.*\n" +
".*ModuleEntryTable.*locked_create_entry.*\n" +
".*Modules.*define_module.*\n" +
".*JVM_DefineModule.*\n";
/* The stack trace we look for on AIX and Windows slowdebug builds.
ALWAYSINLINE is only a hint and is ignored for AllocateHeap on the
aforementioned platforms. When that happens allocate_new_entry is
@ -83,7 +72,6 @@ public class CheckForProperDetailStackTrace {
*/
private static String stackTraceAllocateHeap =
".*AllocateHeap.*\n" +
".*ModuleEntryTable.*new_entry.*\n" +
".*ModuleEntryTable.*locked_create_entry.*\n" +
".*Modules.*define_module.*\n";
@ -149,13 +137,7 @@ public class CheckForProperDetailStackTrace {
}
} else {
System.out.print(stackTraceDefault);
if (!stackTraceMatches(stackTraceDefault, output)) {
System.out.println("Looking for alternate stack matching:");
System.out.print(stackTraceAlternate);
if (stackTraceMatches(stackTraceAlternate, output)) {
return;
}
} else {
if (stackTraceMatches(stackTraceDefault, output)) {
return;
}
}