< prev index next >
src/hotspot/share/classfile/packageEntry.cpp
Print this page
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2020, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
@@ -24,17 +24,22 @@
#include "precompiled.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/packageEntry.hpp"
#include "logging/log.hpp"
+#include "memory/archiveUtils.hpp"
+#include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp"
+#include "oops/array.hpp"
#include "oops/symbol.hpp"
#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"
// 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");
assert(m != NULL, "No module to lookup in this package's qualified exports list");
@@ -186,10 +191,117 @@
}
assert(number_of_entries() == 0, "should have removed all entries");
assert(new_entry_free_list() == NULL, "entry present on PackageEntryTable's free list");
}
+#if INCLUDE_CDS_JAVA_HEAP
+typedef ResourceHashtable<
+ const PackageEntry*,
+ PackageEntry*,
+ primitive_hash<const PackageEntry*>,
+ primitive_equals<const PackageEntry*>,
+ 557, // prime number
+ ResourceObj::C_HEAP> ArchivedPackageEntries;
+static ArchivedPackageEntries* _archived_packages_entries = NULL;
+
+PackageEntry* PackageEntry::allocate_archived_entry() const {
+ assert(!in_unnamed_module(), "unnamed packages/modules are not archived");
+ PackageEntry* archived_entry = (PackageEntry*)MetaspaceShared::read_write_space_alloc(sizeof(PackageEntry));
+ memcpy((void*)archived_entry, (void*)this, sizeof(PackageEntry));
+
+ if (_archived_packages_entries == NULL) {
+ _archived_packages_entries = new (ResourceObj::C_HEAP, mtClass)ArchivedPackageEntries();
+ }
+ assert(_archived_packages_entries->get(this) == NULL, "Each PackageEntry must not be shared across PackageEntryTables");
+ _archived_packages_entries->put(this, archived_entry);
+
+ return archived_entry;
+}
+
+PackageEntry* PackageEntry::get_archived_entry(PackageEntry* orig_entry) {
+ PackageEntry** ptr = _archived_packages_entries->get(orig_entry);
+ assert(ptr != NULL && *ptr != NULL, "must have been allocated");
+ return *ptr;
+}
+
+void PackageEntry::init_as_archived_entry() {
+ Array<ModuleEntry*>* archived_qualified_exports = ModuleEntry::write_archived_entry_array(_qualified_exports);
+
+ set_next(NULL);
+ set_literal(MetaspaceShared::get_relocated_symbol(literal()));
+ set_hash(0x0); // re-init at runtime
+ _module = ModuleEntry::get_archived_entry(_module);
+ _qualified_exports = (GrowableArray<ModuleEntry*>*)archived_qualified_exports;
+ _defined_by_cds_in_class_path = 0;
+
+ ArchivePtrMarker::mark_pointer((address*)literal_addr());
+ ArchivePtrMarker::mark_pointer((address*)&_module);
+ ArchivePtrMarker::mark_pointer((address*)&_qualified_exports);
+}
+
+void PackageEntry::load_from_archive() {
+ _qualified_exports = ModuleEntry::read_archived_entry_array((Array<ModuleEntry*>*)_qualified_exports);
+ JFR_ONLY(INIT_ID(this);)
+}
+
+static int compare_package_by_name(PackageEntry* a, PackageEntry* b) {
+ return a->name()->fast_compare(b->name());
+}
+
+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++;
+ }
+ }
+ }
+
+ Array<PackageEntry*>* archived_packages = MetaspaceShared::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);
+ }
+ }
+ }
+ if (n > 1) {
+ QuickSort::sort(archived_packages->data(), n, (_sort_Fn)compare_package_by_name, true);
+ }
+ for (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));
+ }
+ return archived_packages;
+}
+
+void PackageEntryTable::init_archived_entries(Array<PackageEntry*>* archived_packages) {
+ for (int i = 0; i < archived_packages->length(); i++) {
+ PackageEntry* archived_entry = archived_packages->at(i);
+ archived_entry->init_as_archived_entry();
+ }
+}
+
+void PackageEntryTable::load_archived_entries(Array<PackageEntry*>* archived_packages) {
+ assert(UseSharedSpaces, "runtime only");
+
+ 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);
+ }
+}
+
+#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>::allocate_new_entry(hash, name);
JFR_ONLY(INIT_ID(entry);)
@@ -271,11 +383,10 @@
ResourceMark rm;
vm_exit_during_initialization("A non-" JAVA_BASE_NAME " package was loaded prior to module system initialization", entry->name()->as_C_string());
}
}
}
-
}
// iteration of qualified exports
void PackageEntry::package_exports_do(ModuleClosure* f) {
assert_locked_or_safepoint(Module_lock);
< prev index next >