8292218: Convert PackageEntryTable to ResourceHashtable
Reviewed-by: lfoltan, iklam, dholmes
This commit is contained in:
parent
871b7dab14
commit
9f8cc42135
@ -1011,25 +1011,9 @@ oop ClassLoader::get_system_package(const char* name, TRAPS) {
|
||||
objArrayOop ClassLoader::get_system_packages(TRAPS) {
|
||||
ResourceMark rm(THREAD);
|
||||
// List of pointers to PackageEntrys that have loaded classes.
|
||||
GrowableArray<PackageEntry*>* loaded_class_pkgs = new GrowableArray<PackageEntry*>(50);
|
||||
{
|
||||
MutexLocker ml(THREAD, Module_lock);
|
||||
|
||||
PackageEntryTable* pe_table =
|
||||
PackageEntryTable* pe_table =
|
||||
ClassLoaderData::the_null_class_loader_data()->packages();
|
||||
|
||||
// Collect the packages that have at least one loaded class.
|
||||
for (int x = 0; x < pe_table->table_size(); x++) {
|
||||
for (PackageEntry* package_entry = pe_table->bucket(x);
|
||||
package_entry != NULL;
|
||||
package_entry = package_entry->next()) {
|
||||
if (package_entry->has_loaded_class()) {
|
||||
loaded_class_pkgs->append(package_entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GrowableArray<PackageEntry*>* loaded_class_pkgs = pe_table->get_system_packages();
|
||||
|
||||
// Allocate objArray and fill with java.lang.String
|
||||
objArrayOop r = oopFactory::new_objArray(vmClasses::String_klass(),
|
||||
|
@ -163,7 +163,7 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool has_class_mirror_ho
|
||||
|
||||
// A ClassLoaderData created solely for a non-strong hidden class should never
|
||||
// have a ModuleEntryTable or PackageEntryTable created for it.
|
||||
_packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size);
|
||||
_packages = new PackageEntryTable();
|
||||
if (h_class_loader.is_null()) {
|
||||
// Create unnamed module for boot loader
|
||||
_unnamed_module = ModuleEntry::create_boot_unnamed_module(this);
|
||||
@ -407,13 +407,7 @@ void ClassLoaderData::modules_do(void f(ModuleEntry*)) {
|
||||
void ClassLoaderData::packages_do(void f(PackageEntry*)) {
|
||||
assert_locked_or_safepoint(Module_lock);
|
||||
if (_packages != NULL) {
|
||||
for (int i = 0; i < _packages->table_size(); i++) {
|
||||
for (PackageEntry* entry = _packages->bucket(i);
|
||||
entry != NULL;
|
||||
entry = entry->next()) {
|
||||
f(entry);
|
||||
}
|
||||
}
|
||||
_packages->packages_do(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -353,21 +353,21 @@ ModuleEntry* ModuleEntry::new_unnamed_module_entry(Handle module_handle, ClassLo
|
||||
|
||||
ModuleEntryTable::ModuleEntryTable() { }
|
||||
|
||||
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() {
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
ModuleEntryTableDeleter deleter;
|
||||
_table.unlink(&deleter);
|
||||
assert(_table.number_of_entries() == 0, "should have removed all entries");
|
||||
|
@ -214,8 +214,8 @@ static void define_javabase_module(Handle module_handle, jstring version, jstrin
|
||||
// loop through and add any new packages for java.base
|
||||
for (int x = 0; x < pkg_list->length(); x++) {
|
||||
// Some of java.base's packages were added early in bootstrapping, ignore duplicates.
|
||||
package_table->locked_create_entry_if_not_exist(pkg_list->at(x),
|
||||
ModuleEntryTable::javabase_moduleEntry());
|
||||
package_table->locked_create_entry_if_absent(pkg_list->at(x),
|
||||
ModuleEntryTable::javabase_moduleEntry());
|
||||
assert(package_table->locked_lookup_only(pkg_list->at(x)) != NULL,
|
||||
"Unable to create a " JAVA_BASE_NAME " package entry");
|
||||
// Unable to have a GrowableArray of TempNewSymbol. Must decrement the refcount of
|
||||
|
@ -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
|
||||
@ -37,11 +37,30 @@
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "utilities/events.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/hashtable.inline.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
#include "utilities/quickSort.hpp"
|
||||
#include "utilities/resourceHash.hpp"
|
||||
|
||||
PackageEntry::PackageEntry(Symbol* name, ModuleEntry* module) :
|
||||
_name(name),
|
||||
_module(module),
|
||||
_export_flags(0),
|
||||
_classpath_index(-1),
|
||||
_must_walk_exports(false),
|
||||
_qualified_exports(NULL),
|
||||
_defined_by_cds_in_class_path(0)
|
||||
{
|
||||
// name can't be null
|
||||
_name->increment_refcount();
|
||||
|
||||
JFR_ONLY(INIT_ID(this);)
|
||||
}
|
||||
|
||||
PackageEntry::~PackageEntry() {
|
||||
delete_qualified_exports();
|
||||
_name->decrement_refcount();
|
||||
}
|
||||
|
||||
// Returns true if this package specifies m as a qualified export, including through an unnamed export
|
||||
bool PackageEntry::is_qexported_to(ModuleEntry* m) const {
|
||||
assert(Module_lock->owned_by_self(), "should have the Module_lock");
|
||||
@ -169,28 +188,26 @@ void PackageEntry::delete_qualified_exports() {
|
||||
_qualified_exports = NULL;
|
||||
}
|
||||
|
||||
PackageEntryTable::PackageEntryTable(int table_size)
|
||||
: Hashtable<Symbol*, mtModule>(table_size, sizeof(PackageEntry))
|
||||
{
|
||||
}
|
||||
PackageEntryTable::PackageEntryTable() { }
|
||||
|
||||
PackageEntryTable::~PackageEntryTable() {
|
||||
// Walk through all buckets and all entries in each bucket,
|
||||
// freeing each entry.
|
||||
for (int i = 0; i < table_size(); ++i) {
|
||||
for (PackageEntry* p = bucket(i); p != NULL;) {
|
||||
PackageEntry* to_remove = p;
|
||||
// read next before freeing.
|
||||
p = p->next();
|
||||
|
||||
// Clean out the C heap allocated qualified exports list first before freeing the entry
|
||||
to_remove->delete_qualified_exports();
|
||||
to_remove->name()->decrement_refcount();
|
||||
|
||||
BasicHashtable<mtModule>::free_entry(to_remove);
|
||||
class PackageEntryTableDeleter : public StackObj {
|
||||
public:
|
||||
bool do_entry(const Symbol*& name, PackageEntry*& 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 package %s", str);
|
||||
log_debug(module)("PackageEntry: deleting package: %s", str);
|
||||
}
|
||||
delete entry;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
assert(number_of_entries() == 0, "should have removed all entries");
|
||||
};
|
||||
|
||||
PackageEntryTableDeleter deleter;
|
||||
_table.unlink(&deleter);
|
||||
assert(_table.number_of_entries() == 0, "should have removed all entries");
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
@ -225,21 +242,19 @@ PackageEntry* PackageEntry::get_archived_entry(PackageEntry* orig_entry) {
|
||||
}
|
||||
|
||||
void PackageEntry::iterate_symbols(MetaspaceClosure* closure) {
|
||||
closure->push(literal_addr()); // name
|
||||
closure->push(&_name);
|
||||
}
|
||||
|
||||
void PackageEntry::init_as_archived_entry() {
|
||||
Array<ModuleEntry*>* archived_qualified_exports = ModuleEntry::write_growable_array(_qualified_exports);
|
||||
|
||||
set_next(NULL);
|
||||
set_literal(ArchiveBuilder::get_relocated_symbol(literal()));
|
||||
set_hash(0x0); // re-init at runtime
|
||||
_name = ArchiveBuilder::get_relocated_symbol(_name);
|
||||
_module = ModuleEntry::get_archived_entry(_module);
|
||||
_qualified_exports = (GrowableArray<ModuleEntry*>*)archived_qualified_exports;
|
||||
_defined_by_cds_in_class_path = 0;
|
||||
JFR_ONLY(set_trace_id(0)); // re-init at runtime
|
||||
|
||||
ArchivePtrMarker::mark_pointer((address*)literal_addr());
|
||||
ArchivePtrMarker::mark_pointer((address*)&_name);
|
||||
ArchivePtrMarker::mark_pointer((address*)&_module);
|
||||
ArchivePtrMarker::mark_pointer((address*)&_qualified_exports);
|
||||
}
|
||||
@ -255,38 +270,38 @@ static int compare_package_by_name(PackageEntry* a, PackageEntry* b) {
|
||||
}
|
||||
|
||||
void PackageEntryTable::iterate_symbols(MetaspaceClosure* closure) {
|
||||
for (int i = 0; i < table_size(); ++i) {
|
||||
for (PackageEntry* p = bucket(i); p != NULL; p = p->next()) {
|
||||
auto syms = [&] (const Symbol*& key, PackageEntry*& p) {
|
||||
p->iterate_symbols(closure);
|
||||
}
|
||||
}
|
||||
};
|
||||
_table.iterate_all(syms);
|
||||
}
|
||||
|
||||
Array<PackageEntry*>* PackageEntryTable::allocate_archived_entries() {
|
||||
// First count the packages in named modules
|
||||
int n, i;
|
||||
for (n = 0, i = 0; i < table_size(); ++i) {
|
||||
for (PackageEntry* p = bucket(i); p != NULL; p = p->next()) {
|
||||
if (p->module()->name() != NULL) {
|
||||
n++;
|
||||
}
|
||||
int n = 0;
|
||||
auto count = [&] (const Symbol*& key, PackageEntry*& p) {
|
||||
if (p->module()->is_named()) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
};
|
||||
_table.iterate_all(count);
|
||||
|
||||
Array<PackageEntry*>* archived_packages = ArchiveBuilder::new_rw_array<PackageEntry*>(n);
|
||||
for (n = 0, i = 0; i < table_size(); ++i) {
|
||||
for (PackageEntry* p = bucket(i); p != NULL; p = p->next()) {
|
||||
if (p->module()->name() != NULL) {
|
||||
// We don't archive unnamed modules, or packages in unnamed modules. They will be
|
||||
// created on-demand at runtime as classes in such packages are loaded.
|
||||
archived_packages->at_put(n++, p);
|
||||
}
|
||||
// reset n
|
||||
n = 0;
|
||||
auto grab = [&] (const Symbol*& key, PackageEntry*& p) {
|
||||
if (p->module()->is_named()) {
|
||||
// We don't archive unnamed modules, or packages in unnamed modules. They will be
|
||||
// created on-demand at runtime as classes in such packages are loaded.
|
||||
archived_packages->at_put(n++, p);
|
||||
}
|
||||
}
|
||||
};
|
||||
_table.iterate_all(grab);
|
||||
|
||||
if (n > 1) {
|
||||
QuickSort::sort(archived_packages->data(), n, (_sort_Fn)compare_package_by_name, true);
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
archived_packages->at_put(i, archived_packages->at(i)->allocate_archived_entry());
|
||||
ArchivePtrMarker::mark_pointer((address*)archived_packages->adr_at(i));
|
||||
}
|
||||
@ -306,63 +321,41 @@ void PackageEntryTable::load_archived_entries(Array<PackageEntry*>* archived_pac
|
||||
for (int i = 0; i < archived_packages->length(); i++) {
|
||||
PackageEntry* archived_entry = archived_packages->at(i);
|
||||
archived_entry->load_from_archive();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // INCLUDE_CDS_JAVA_HEAP
|
||||
|
||||
PackageEntry* PackageEntryTable::new_entry(unsigned int hash, Symbol* name, ModuleEntry* module) {
|
||||
assert(Module_lock->owned_by_self(), "should have the Module_lock");
|
||||
PackageEntry* entry = (PackageEntry*)Hashtable<Symbol*, mtModule>::new_entry(hash, name);
|
||||
|
||||
JFR_ONLY(INIT_ID(entry);)
|
||||
|
||||
// Initialize fields specific to a PackageEntry
|
||||
entry->init();
|
||||
entry->name()->increment_refcount();
|
||||
entry->set_module(module);
|
||||
return entry;
|
||||
}
|
||||
|
||||
void PackageEntryTable::add_entry(int index, PackageEntry* 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 package entry in loader's package entry table. Assume Module lock
|
||||
// was taken by caller.
|
||||
void PackageEntryTable::locked_create_entry(Symbol* name, ModuleEntry* module) {
|
||||
assert(Module_lock->owned_by_self(), "should have the Module_lock");
|
||||
assert(locked_lookup_only(name) == NULL, "Package entry already exists");
|
||||
PackageEntry* entry = new_entry(compute_hash(name), name, module);
|
||||
add_entry(index_for(name), entry);
|
||||
PackageEntry* entry = new PackageEntry(name, module);
|
||||
bool created = _table.put(name, entry);
|
||||
assert(created, "must be");
|
||||
}
|
||||
|
||||
// Create package entry in loader's package entry table if it does not already
|
||||
// exist. Assume Module lock was taken by caller.
|
||||
void PackageEntryTable::locked_create_entry_if_not_exist(Symbol* name, ModuleEntry* module) {
|
||||
PackageEntry* PackageEntryTable::locked_create_entry_if_absent(Symbol* name, ModuleEntry* module) {
|
||||
assert(Module_lock->owned_by_self(), "should have the Module_lock");
|
||||
// Check if package entry already exists. If not, create it.
|
||||
if (locked_lookup_only(name) == NULL) {
|
||||
locked_create_entry(name, module);
|
||||
bool created;
|
||||
PackageEntry* entry = new PackageEntry(name, module);
|
||||
PackageEntry** old_entry = _table.put_if_absent(name, entry, &created);
|
||||
if (created) {
|
||||
return entry;
|
||||
} else {
|
||||
delete entry;
|
||||
return *old_entry;
|
||||
}
|
||||
}
|
||||
|
||||
PackageEntry* PackageEntryTable::lookup(Symbol* name, ModuleEntry* module) {
|
||||
PackageEntry* PackageEntryTable::create_entry_if_absent(Symbol* name, ModuleEntry* module) {
|
||||
MutexLocker ml(Module_lock);
|
||||
PackageEntry* p = locked_lookup_only(name);
|
||||
if (p != NULL) {
|
||||
return p;
|
||||
} else {
|
||||
assert(module != NULL, "module should never be null");
|
||||
PackageEntry* entry = new_entry(compute_hash(name), name, module);
|
||||
add_entry(index_for(name), entry);
|
||||
return entry;
|
||||
}
|
||||
return locked_create_entry_if_absent(name, module);
|
||||
}
|
||||
|
||||
PackageEntry* PackageEntryTable::lookup_only(Symbol* name) {
|
||||
@ -373,33 +366,26 @@ PackageEntry* PackageEntryTable::lookup_only(Symbol* name) {
|
||||
|
||||
PackageEntry* PackageEntryTable::locked_lookup_only(Symbol* name) {
|
||||
assert(Module_lock->owned_by_self(), "should have the Module_lock");
|
||||
int index = index_for(name);
|
||||
for (PackageEntry* p = bucket(index); p != NULL; p = p->next()) {
|
||||
if (p->name()->fast_compare(name) == 0) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
PackageEntry** entry = _table.get(name);
|
||||
return entry == nullptr ? nullptr : *entry;
|
||||
}
|
||||
|
||||
// Called when a define module for java.base is being processed.
|
||||
// Verify the packages loaded thus far are in java.base's package list.
|
||||
void PackageEntryTable::verify_javabase_packages(GrowableArray<Symbol*> *pkg_list) {
|
||||
assert_lock_strong(Module_lock);
|
||||
for (int i = 0; i < table_size(); i++) {
|
||||
for (PackageEntry* entry = bucket(i);
|
||||
entry != NULL;
|
||||
entry = entry->next()) {
|
||||
ModuleEntry* m = entry->module();
|
||||
Symbol* module_name = (m == NULL ? NULL : m->name());
|
||||
if (module_name != NULL &&
|
||||
(module_name->fast_compare(vmSymbols::java_base()) == 0) &&
|
||||
!pkg_list->contains(entry->name())) {
|
||||
ResourceMark rm;
|
||||
vm_exit_during_initialization("A non-" JAVA_BASE_NAME " package was loaded prior to module system initialization", entry->name()->as_C_string());
|
||||
}
|
||||
auto verifier = [&] (const Symbol*& name, PackageEntry*& entry) {
|
||||
ModuleEntry* m = entry->module();
|
||||
Symbol* module_name = (m == NULL ? NULL : m->name());
|
||||
if (module_name != NULL &&
|
||||
(module_name->fast_compare(vmSymbols::java_base()) == 0) &&
|
||||
!pkg_list->contains(entry->name())) {
|
||||
ResourceMark rm;
|
||||
vm_exit_during_initialization("A non-" JAVA_BASE_NAME " package was loaded prior to module system initialization",
|
||||
entry->name()->as_C_string());
|
||||
}
|
||||
}
|
||||
};
|
||||
_table.iterate_all(verifier);
|
||||
}
|
||||
|
||||
// iteration of qualified exports
|
||||
@ -424,31 +410,48 @@ bool PackageEntry::exported_pending_delete() const {
|
||||
// Remove dead entries from all packages' exported list
|
||||
void PackageEntryTable::purge_all_package_exports() {
|
||||
assert_locked_or_safepoint(Module_lock);
|
||||
for (int i = 0; i < table_size(); i++) {
|
||||
for (PackageEntry* entry = bucket(i);
|
||||
entry != NULL;
|
||||
entry = entry->next()) {
|
||||
if (entry->exported_pending_delete()) {
|
||||
// exported list is pending deletion due to a transition
|
||||
// from qualified to unqualified
|
||||
entry->delete_qualified_exports();
|
||||
} else if (entry->is_qual_exported()) {
|
||||
entry->purge_qualified_exports();
|
||||
}
|
||||
auto purge = [&] (const Symbol*& name, PackageEntry*& entry) {
|
||||
if (entry->exported_pending_delete()) {
|
||||
// exported list is pending deletion due to a transition
|
||||
// from qualified to unqualified
|
||||
entry->delete_qualified_exports();
|
||||
} else if (entry->is_qual_exported()) {
|
||||
entry->purge_qualified_exports();
|
||||
}
|
||||
}
|
||||
};
|
||||
_table.iterate_all(purge);
|
||||
}
|
||||
|
||||
void PackageEntryTable::packages_do(void f(PackageEntry*)) {
|
||||
auto doit = [&] (const Symbol*&name, PackageEntry*& entry) {
|
||||
f(entry);
|
||||
};
|
||||
assert_locked_or_safepoint(Module_lock);
|
||||
_table.iterate_all(doit);
|
||||
}
|
||||
|
||||
|
||||
GrowableArray<PackageEntry*>* PackageEntryTable::get_system_packages() {
|
||||
GrowableArray<PackageEntry*>* loaded_class_pkgs = new GrowableArray<PackageEntry*>(50);
|
||||
auto grab = [&] (const Symbol*&name, PackageEntry*& entry) {
|
||||
if (entry->has_loaded_class()) {
|
||||
loaded_class_pkgs->append(entry);
|
||||
}
|
||||
};
|
||||
|
||||
MutexLocker ml(Module_lock);
|
||||
_table.iterate_all(grab);
|
||||
// Returns a resource allocated object so caller must have ResourceMark
|
||||
return loaded_class_pkgs;
|
||||
}
|
||||
|
||||
void PackageEntryTable::print(outputStream* st) {
|
||||
auto printer = [&] (const Symbol*& name, PackageEntry*& entry) {
|
||||
entry->print(st);
|
||||
};
|
||||
st->print_cr("Package Entry Table (table_size=%d, entries=%d)",
|
||||
table_size(), number_of_entries());
|
||||
for (int i = 0; i < table_size(); i++) {
|
||||
for (PackageEntry* probe = bucket(i);
|
||||
probe != NULL;
|
||||
probe = probe->next()) {
|
||||
probe->print(st);
|
||||
}
|
||||
}
|
||||
_table.table_size(), _table.number_of_entries());
|
||||
_table.iterate_all(printer);
|
||||
}
|
||||
|
||||
// This function may be called from debuggers so access private fields directly
|
||||
@ -457,17 +460,9 @@ void PackageEntryTable::print(outputStream* st) {
|
||||
void PackageEntry::print(outputStream* st) {
|
||||
ResourceMark rm;
|
||||
st->print_cr("package entry " PTR_FORMAT " name %s module %s classpath_index "
|
||||
INT32_FORMAT " is_exported_unqualified %d is_exported_allUnnamed %d " "next " PTR_FORMAT,
|
||||
INT32_FORMAT " is_exported_unqualified %d is_exported_allUnnamed %d ",
|
||||
p2i(this), name()->as_C_string(),
|
||||
(module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE),
|
||||
_classpath_index, _export_flags == PKG_EXP_UNQUALIFIED,
|
||||
_export_flags == PKG_EXP_ALLUNNAMED, p2i(next()));
|
||||
}
|
||||
|
||||
void PackageEntryTable::verify() {
|
||||
verify_table<PackageEntry>("Package Entry Table");
|
||||
}
|
||||
|
||||
void PackageEntry::verify() {
|
||||
guarantee(name() != NULL, "A package entry must have a corresponding symbol name.");
|
||||
_export_flags == PKG_EXP_ALLUNNAMED);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2020, 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
|
||||
@ -29,7 +29,7 @@
|
||||
#include "oops/symbol.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/hashtable.hpp"
|
||||
#include "utilities/resourceHash.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
#if INCLUDE_JFR
|
||||
@ -38,6 +38,7 @@
|
||||
|
||||
template <class T> class Array;
|
||||
class MetaspaceClosure;
|
||||
class ModuleEntry;
|
||||
|
||||
// A PackageEntry basically represents a Java package. It contains:
|
||||
// - Symbol* containing the package's name.
|
||||
@ -97,8 +98,9 @@ class MetaspaceClosure;
|
||||
#define PKG_EXP_ALLUNNAMED 0x0002
|
||||
#define PKG_EXP_UNQUALIFIED_OR_ALL_UNAMED (PKG_EXP_UNQUALIFIED | PKG_EXP_ALLUNNAMED)
|
||||
|
||||
class PackageEntry : public HashtableEntry<Symbol*, mtModule> {
|
||||
class PackageEntry : public CHeapObj<mtModule> {
|
||||
private:
|
||||
Symbol* _name;
|
||||
ModuleEntry* _module;
|
||||
// Indicates if package is exported unqualifiedly or to all unnamed. Access to
|
||||
// this field is protected by the Module_lock.
|
||||
@ -120,17 +122,11 @@ private:
|
||||
// a bit map indicating which CDS classpath entries have defined classes in this package.
|
||||
volatile int _defined_by_cds_in_class_path;
|
||||
public:
|
||||
void init() {
|
||||
_module = NULL;
|
||||
_export_flags = 0;
|
||||
_classpath_index = -1;
|
||||
_must_walk_exports = false;
|
||||
_qualified_exports = NULL;
|
||||
_defined_by_cds_in_class_path = 0;
|
||||
}
|
||||
PackageEntry(Symbol* name, ModuleEntry* module);
|
||||
~PackageEntry();
|
||||
|
||||
// package name
|
||||
Symbol* name() const { return literal(); }
|
||||
Symbol* name() const { return _name; }
|
||||
|
||||
// the module containing the package definition
|
||||
ModuleEntry* module() const { return _module; }
|
||||
@ -199,14 +195,6 @@ public:
|
||||
void add_qexport(ModuleEntry* m);
|
||||
void set_export_walk_required(ClassLoaderData* m_loader_data);
|
||||
|
||||
PackageEntry* next() const {
|
||||
return (PackageEntry*)HashtableEntry<Symbol*, mtModule>::next();
|
||||
}
|
||||
|
||||
PackageEntry** next_addr() {
|
||||
return (PackageEntry**)HashtableEntry<Symbol*, mtModule>::next_addr();
|
||||
}
|
||||
|
||||
// iteration of qualified exports
|
||||
void package_exports_do(ModuleClosure* f);
|
||||
|
||||
@ -217,7 +205,6 @@ public:
|
||||
void delete_qualified_exports();
|
||||
|
||||
void print(outputStream* st = tty);
|
||||
void verify();
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
void iterate_symbols(MetaspaceClosure* closure);
|
||||
@ -248,47 +235,24 @@ public:
|
||||
|
||||
// The PackageEntryTable is a Hashtable containing a list of all packages defined
|
||||
// by a particular class loader. Each package is represented as a PackageEntry node.
|
||||
// The PackageEntryTable's lookup is lock free.
|
||||
//
|
||||
class PackageEntryTable : public Hashtable<Symbol*, mtModule> {
|
||||
friend class VMStructs;
|
||||
class PackageEntryTable : public CHeapObj<mtModule> {
|
||||
ResourceHashtable<const Symbol*, PackageEntry*, 109, ResourceObj::C_HEAP, mtModule,
|
||||
Symbol::compute_hash> _table;
|
||||
public:
|
||||
enum Constants {
|
||||
_packagetable_entry_size = 109 // number of entries in package entry table
|
||||
};
|
||||
|
||||
private:
|
||||
PackageEntry* new_entry(unsigned int hash, Symbol* name, ModuleEntry* module);
|
||||
void add_entry(int index, PackageEntry* new_entry);
|
||||
|
||||
int entry_size() const { return BasicHashtable<mtModule>::entry_size(); }
|
||||
|
||||
PackageEntry** bucket_addr(int i) {
|
||||
return (PackageEntry**)Hashtable<Symbol*, mtModule>::bucket_addr(i);
|
||||
}
|
||||
|
||||
static unsigned int compute_hash(Symbol* name) { return (unsigned int)(name->identity_hash()); }
|
||||
int index_for(Symbol* name) const { return hash_to_index(compute_hash(name)); }
|
||||
|
||||
public:
|
||||
PackageEntryTable(int table_size);
|
||||
PackageEntryTable();
|
||||
~PackageEntryTable();
|
||||
|
||||
PackageEntry* bucket(int i) {
|
||||
return (PackageEntry*)Hashtable<Symbol*, mtModule>::bucket(i);
|
||||
}
|
||||
|
||||
// Create package entry in loader's package entry table. Assume Module
|
||||
// lock was taken by caller.
|
||||
void locked_create_entry(Symbol* name, ModuleEntry* module);
|
||||
|
||||
// Create package entry in loader's package entry table if it does not
|
||||
// already exist. Assume Module lock was taken by caller.
|
||||
void locked_create_entry_if_not_exist(Symbol* name, ModuleEntry* module);
|
||||
PackageEntry* locked_create_entry_if_absent(Symbol* name, ModuleEntry* module);
|
||||
|
||||
// Lookup Package with loader's package entry table, add it if not found.
|
||||
// This will acquire the Module lock.
|
||||
PackageEntry* lookup(Symbol* name, ModuleEntry* module);
|
||||
PackageEntry* create_entry_if_absent(Symbol* name, ModuleEntry* module);
|
||||
|
||||
// Only lookup Package within loader's package entry table.
|
||||
// This will acquire the Module lock.
|
||||
@ -303,8 +267,11 @@ public:
|
||||
// purge dead weak references out of exported list
|
||||
void purge_all_package_exports();
|
||||
|
||||
GrowableArray<PackageEntry*>* get_system_packages();
|
||||
|
||||
void packages_do(void f(PackageEntry*));
|
||||
|
||||
void print(outputStream* st = tty);
|
||||
void verify();
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
void iterate_symbols(MetaspaceClosure* closure);
|
||||
|
@ -2879,11 +2879,10 @@ void InstanceKlass::set_package(ClassLoaderData* loader_data, PackageEntry* pkg_
|
||||
// in the java.base module it will be caught later when java.base
|
||||
// is defined by ModuleEntryTable::verify_javabase_packages check.
|
||||
assert(ModuleEntryTable::javabase_moduleEntry() != NULL, JAVA_BASE_NAME " module is NULL");
|
||||
_package_entry = loader_data->packages()->lookup(pkg_name, ModuleEntryTable::javabase_moduleEntry());
|
||||
_package_entry = loader_data->packages()->create_entry_if_absent(pkg_name, ModuleEntryTable::javabase_moduleEntry());
|
||||
} else {
|
||||
assert(loader_data->unnamed_module() != NULL, "unnamed module is NULL");
|
||||
_package_entry = loader_data->packages()->lookup(pkg_name,
|
||||
loader_data->unnamed_module());
|
||||
_package_entry = loader_data->packages()->create_entry_if_absent(pkg_name, loader_data->unnamed_module());
|
||||
}
|
||||
|
||||
// A package should have been successfully created
|
||||
|
@ -283,6 +283,5 @@ template class BasicHashtable<mtServiceability>;
|
||||
template class BasicHashtable<mtLogging>;
|
||||
|
||||
template void BasicHashtable<mtClass>::verify_table<DictionaryEntry>(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*);
|
||||
|
Loading…
Reference in New Issue
Block a user