< prev index next >

src/hotspot/share/classfile/moduleEntry.cpp

Print this page

*** 27,47 **** --- 27,51 ---- #include "classfile/classLoader.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/moduleEntry.hpp" #include "logging/log.hpp" + #include "memory/archiveUtils.hpp" #include "memory/filemap.hpp" + #include "memory/heapShared.hpp" + #include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/oopHandle.inline.hpp" #include "oops/symbol.hpp" #include "runtime/handles.inline.hpp" #include "runtime/safepoint.hpp" #include "utilities/events.hpp" #include "utilities/growableArray.hpp" #include "utilities/hashtable.inline.hpp" #include "utilities/ostream.hpp" + #include "utilities/resourceHash.hpp" ModuleEntry* ModuleEntryTable::_javabase_module = NULL; oop ModuleEntry::module() const { return _module.resolve(); }
*** 106,124 **** } } // Returns the shared ProtectionDomain oop ModuleEntry::shared_protection_domain() { ! return _pd.resolve(); } // Set the shared ProtectionDomain atomically void ModuleEntry::set_shared_protection_domain(ClassLoaderData *loader_data, Handle pd_h) { // Create a handle for the shared ProtectionDomain and save it atomically. ! // init_handle_locked checks if someone beats us setting the _pd cache. ! loader_data->init_handle_locked(_pd, pd_h); } // Returns true if this module can read module m bool ModuleEntry::can_read(ModuleEntry* m) const { assert(m != NULL, "No module to lookup in this module's reads list"); --- 110,128 ---- } } // Returns the shared ProtectionDomain oop ModuleEntry::shared_protection_domain() { ! return _shared_pd.resolve(); } // Set the shared ProtectionDomain atomically void ModuleEntry::set_shared_protection_domain(ClassLoaderData *loader_data, Handle pd_h) { // Create a handle for the shared ProtectionDomain and save it atomically. ! // init_handle_locked checks if someone beats us setting the _shared_pd cache. ! loader_data->init_handle_locked(_shared_pd, pd_h); } // Returns true if this module can read module m bool ModuleEntry::can_read(ModuleEntry* m) const { assert(m != NULL, "No module to lookup in this module's reads list");
*** 360,369 **** --- 364,555 ---- } assert(number_of_entries() == 0, "should have removed all entries"); assert(new_entry_free_list() == NULL, "entry present on ModuleEntryTable's free list"); } + #if INCLUDE_CDS_JAVA_HEAP + typedef ResourceHashtable< + const ModuleEntry*, + ModuleEntry*, + primitive_hash<const ModuleEntry*>, + primitive_equals<const ModuleEntry*>, + 557, // prime number + ResourceObj::C_HEAP> ArchivedModuleEntries; + static ArchivedModuleEntries* _archive_modules_entries = NULL; + + ModuleEntry* ModuleEntry::allocate_archived_entry() const { + assert(is_named(), "unnamed packages/modules are not archived"); + ModuleEntry* archived_entry = (ModuleEntry*)MetaspaceShared::read_write_space_alloc(sizeof(ModuleEntry)); + memcpy((void*)archived_entry, (void*)this, sizeof(ModuleEntry)); + + if (_archive_modules_entries == NULL) { + _archive_modules_entries = new (ResourceObj::C_HEAP, mtClass)ArchivedModuleEntries(); + } + assert(_archive_modules_entries->get(this) == NULL, "Each ModuleEntry must not be shared across ModuleEntryTables"); + _archive_modules_entries->put(this, archived_entry); + + return archived_entry; + } + + ModuleEntry* ModuleEntry::get_archived_entry(ModuleEntry* orig_entry) { + ModuleEntry** ptr = _archive_modules_entries->get(orig_entry); + assert(ptr != NULL && *ptr != NULL, "must have been allocated"); + return *ptr; + } + + // GrowableArrays cannot be directly archived, as they need to be expandable at runtime. + // Write it out as an Array, and conver it back to GrowableArray at runtime. + Array<ModuleEntry*>* ModuleEntry::write_archived_entry_array(GrowableArray<ModuleEntry*>* array) { + Array<ModuleEntry*>* archived_array = NULL; + int length = (array == NULL) ? 0 : array->length(); + if (length > 0) { + archived_array = MetaspaceShared::new_ro_array<ModuleEntry*>(length); + for (int i = 0; i < length; i++) { + ModuleEntry* archived_entry = get_archived_entry(array->at(i)); + archived_array->at_put(i, archived_entry); + ArchivePtrMarker::mark_pointer((address*)archived_array->adr_at(i)); + } + } + + return archived_array; + } + + GrowableArray<ModuleEntry*>* ModuleEntry::read_archived_entry_array(Array<ModuleEntry*>* archived_array) { + GrowableArray<ModuleEntry*>* array = NULL; + int length = (archived_array == NULL) ? 0 : archived_array->length(); + if (length > 0) { + array = new (ResourceObj::C_HEAP, mtModule)GrowableArray<ModuleEntry*>(length, mtModule); + for (int i = 0; i < length; i++) { + ModuleEntry* archived_entry = archived_array->at(i); + array->append(archived_entry); + } + } + + return array; + } + + void ModuleEntry::init_as_archived_entry() { + Array<ModuleEntry*>* archived_reads = write_archived_entry_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(MetaspaceShared::get_relocated_symbol(literal())); + ArchivePtrMarker::mark_pointer((address*)literal_addr()); + } + _reads = (GrowableArray<ModuleEntry*>*)archived_reads; + if (_version != NULL) { + _version = MetaspaceShared::get_relocated_symbol(_version); + } + if (_location != NULL) { + _location = MetaspaceShared::get_relocated_symbol(_location); + } + + ArchivePtrMarker::mark_pointer((address*)&_reads); + ArchivePtrMarker::mark_pointer((address*)&_version); + ArchivePtrMarker::mark_pointer((address*)&_location); + } + + void ModuleEntry::init_archived_oops() { + assert(DumpSharedSpaces, "static dump only"); + oop module_obj = module(); + if (module_obj != NULL) { + oop m = HeapShared::find_archived_heap_object(module_obj); + assert(m != NULL, "sanity"); + _archived_module_narrow_oop = CompressedOops::encode(m); + } + assert(shared_protection_domain() == NULL, "never set during -Xshare:dump"); + // Clear handles and restore at run time. Handles cannot be archived. + OopHandle null_handle; + _module = null_handle; + } + + void ModuleEntry::load_from_archive(ClassLoaderData* loader_data) { + set_loader_data(loader_data); + _reads = read_archived_entry_array((Array<ModuleEntry*>*)_reads); + JFR_ONLY(INIT_ID(this);) + } + + void ModuleEntry::restore_archive_oops(ClassLoaderData* loader_data) { + Handle module_handle(Thread::current(), HeapShared::materialize_archived_object(_archived_module_narrow_oop)); + assert(module_handle.not_null(), "huh"); + set_module(loader_data->add_handle(module_handle)); + + // This was cleared to zero during dump time -- we didn't save the value + // because it may be affected by archive relocation. + java_lang_Module::set_module_entry(module_handle(), this); + + if (loader_data->class_loader() != NULL) { + java_lang_Module::set_loader(module_handle(), loader_data->class_loader()); + } + } + + static int compare_module_by_name(ModuleEntry** a, ModuleEntry** b) { + return a[0]->name()->fast_compare(b[0]->name()); + } + + Array<ModuleEntry*>* ModuleEntryTable::allocate_archived_entries() { + Array<ModuleEntry*>* archived_modules = MetaspaceShared::new_rw_array<ModuleEntry*>(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); + } + } + if (n > 0) { + // Always allocate in the same order to produce deterministic archive. + qsort(archived_modules->adr_at(0), n, sizeof(ModuleEntry*), (_sort_Fn)compare_module_by_name); + for (int i = 0; i < n; i++) { + archived_modules->at_put(i, archived_modules->at(i)->allocate_archived_entry()); + ArchivePtrMarker::mark_pointer((address*)archived_modules->adr_at(i)); + } + } + return archived_modules; + } + + void ModuleEntryTable::init_archived_entries(Array<ModuleEntry*>* archived_modules) { + assert(DumpSharedSpaces, "dump time only"); + for (int i = 0; i < archived_modules->length(); i++) { + ModuleEntry* archived_entry = archived_modules->at(i); + archived_entry->init_as_archived_entry(); + } + } + + void ModuleEntryTable::init_archived_oops(Array<ModuleEntry*>* archived_modules) { + assert(DumpSharedSpaces, "dump time only"); + for (int i = 0; i < archived_modules->length(); i++) { + ModuleEntry* archived_entry = archived_modules->at(i); + archived_entry->init_archived_oops(); + } + } + + void ModuleEntryTable::load_archived_entries(ClassLoaderData* loader_data, + Array<ModuleEntry*>* archived_modules) { + assert(UseSharedSpaces, "runtime only"); + + MutexLocker m1(Module_lock); + 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); + } + } + + void ModuleEntryTable::restore_archived_oops(ClassLoaderData* loader_data, Array<ModuleEntry*>* archived_modules) { + assert(UseSharedSpaces, "runtime only"); + for (int i = 0; i < archived_modules->length(); i++) { + ModuleEntry* archived_entry = archived_modules->at(i); + archived_entry->restore_archive_oops(loader_data); + } + } + #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");
< prev index next >