diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp index a6076956546..f8a6bc293b5 100644 --- a/src/hotspot/share/cds/archiveBuilder.cpp +++ b/src/hotspot/share/cds/archiveBuilder.cpp @@ -236,7 +236,7 @@ void ArchiveBuilder::gather_klasses_and_symbols() { ResourceMark rm; log_info(cds)("Gathering classes and symbols ... "); GatherKlassesAndSymbols doit(this); - iterate_roots(&doit, /*is_relocating_pointers=*/false); + iterate_roots(&doit); #if INCLUDE_CDS_JAVA_HEAP if (is_dumping_full_module_graph()) { ClassLoaderDataShared::iterate_symbols(&doit); @@ -390,24 +390,18 @@ address ArchiveBuilder::reserve_buffer() { return buffer_bottom; } -void ArchiveBuilder::iterate_sorted_roots(MetaspaceClosure* it, bool is_relocating_pointers) { - int i; - - if (!is_relocating_pointers) { - // Don't relocate _symbol, so we can safely call decrement_refcount on the - // original symbols. - int num_symbols = _symbols->length(); - for (i = 0; i < num_symbols; i++) { - it->push(_symbols->adr_at(i)); - } +void ArchiveBuilder::iterate_sorted_roots(MetaspaceClosure* it) { + int num_symbols = _symbols->length(); + for (int i = 0; i < num_symbols; i++) { + it->push(_symbols->adr_at(i)); } int num_klasses = _klasses->length(); - for (i = 0; i < num_klasses; i++) { + for (int i = 0; i < num_klasses; i++) { it->push(_klasses->adr_at(i)); } - iterate_roots(it, is_relocating_pointers); + iterate_roots(it); } class GatherSortedSourceObjs : public MetaspaceClosure { @@ -422,7 +416,7 @@ public: virtual void do_pending_ref(Ref* ref) { if (ref->obj() != nullptr) { - _builder->remember_embedded_pointer_in_copied_obj(enclosing_ref(), ref); + _builder->remember_embedded_pointer_in_gathered_obj(enclosing_ref(), ref); } } }; @@ -434,7 +428,7 @@ bool ArchiveBuilder::gather_one_source_obj(MetaspaceClosure::Ref* enclosing_ref, return false; } ref->set_keep_after_pushing(); - remember_embedded_pointer_in_copied_obj(enclosing_ref, ref); + remember_embedded_pointer_in_gathered_obj(enclosing_ref, ref); FollowMode follow_mode = get_follow_mode(ref); SourceObjInfo src_info(ref, read_only, follow_mode); @@ -461,8 +455,8 @@ bool ArchiveBuilder::gather_one_source_obj(MetaspaceClosure::Ref* enclosing_ref, } } -void ArchiveBuilder::remember_embedded_pointer_in_copied_obj(MetaspaceClosure::Ref* enclosing_ref, - MetaspaceClosure::Ref* ref) { +void ArchiveBuilder::remember_embedded_pointer_in_gathered_obj(MetaspaceClosure::Ref* enclosing_ref, + MetaspaceClosure::Ref* ref) { assert(ref->obj() != nullptr, "should have checked"); if (enclosing_ref != nullptr) { @@ -485,7 +479,7 @@ void ArchiveBuilder::gather_source_objs() { log_info(cds)("Gathering all archivable objects ... "); gather_klasses_and_symbols(); GatherSortedSourceObjs doit(this); - iterate_sorted_roots(&doit, /*is_relocating_pointers=*/false); + iterate_sorted_roots(&doit); doit.finish(); } @@ -639,6 +633,19 @@ void ArchiveBuilder::make_shallow_copy(DumpRegion *dump_region, SourceObjInfo* s _alloc_stats.record(ref->msotype(), int(newtop - oldtop), src_info->read_only()); } +// This is used by code that hand-assemble data structures, such as the LambdaProxyClassKey, that are +// not handled by MetaspaceClosure. +void ArchiveBuilder::write_pointer_in_buffer(address* ptr_location, address src_addr) { + assert(is_in_buffer_space(ptr_location), "must be"); + if (src_addr == nullptr) { + *ptr_location = nullptr; + ArchivePtrMarker::clear_pointer(ptr_location); + } else { + *ptr_location = get_buffered_addr(src_addr); + ArchivePtrMarker::mark_pointer(ptr_location); + } +} + address ArchiveBuilder::get_buffered_addr(address src_addr) const { SourceObjInfo* p = _src_obj_table.get(src_addr); assert(p != nullptr, "must be"); @@ -659,46 +666,12 @@ void ArchiveBuilder::relocate_embedded_pointers(ArchiveBuilder::SourceObjList* s } } -class RefRelocator: public MetaspaceClosure { - ArchiveBuilder* _builder; - -public: - RefRelocator(ArchiveBuilder* builder) : _builder(builder) {} - - virtual bool do_ref(Ref* ref, bool read_only) { - if (ref->not_null()) { - ref->update(_builder->get_buffered_addr(ref->obj())); - ArchivePtrMarker::mark_pointer(ref->addr()); - } - return false; // Do not recurse. - } -}; - -void ArchiveBuilder::relocate_roots() { - log_info(cds)("Relocating external roots ... "); - ResourceMark rm; - RefRelocator doit(this); - iterate_sorted_roots(&doit, /*is_relocating_pointers=*/true); - doit.finish(); - log_info(cds)("done"); -} - void ArchiveBuilder::relocate_metaspaceobj_embedded_pointers() { log_info(cds)("Relocating embedded pointers in core regions ... "); relocate_embedded_pointers(&_rw_src_objs); relocate_embedded_pointers(&_ro_src_objs); } -// We must relocate vmClasses::_klasses[] only after we have copied the -// java objects in during dump_java_heap_objects(): during the object copy, we operate on -// old objects which assert that their klass is the original klass. -void ArchiveBuilder::relocate_vm_classes() { - log_info(cds)("Relocating vmClasses::_klasses[] ... "); - ResourceMark rm; - RefRelocator doit(this); - vmClasses::metaspace_pointers_do(&doit); -} - void ArchiveBuilder::make_klasses_shareable() { int num_instance_klasses = 0; int num_boot_klasses = 0; @@ -715,7 +688,7 @@ void ArchiveBuilder::make_klasses_shareable() { const char* unlinked = ""; const char* hidden = ""; const char* generated = ""; - Klass* k = klasses()->at(i); + Klass* k = get_buffered_addr(klasses()->at(i)); k->remove_java_mirror(); if (k->is_objArray_klass()) { // InstanceKlass and TypeArrayKlass will in turn call remove_unshareable_info @@ -798,6 +771,10 @@ uintx ArchiveBuilder::any_to_offset(address p) const { assert(DynamicDumpSharedSpaces, "must be"); return p - _mapped_static_archive_bottom; } + if (!is_in_buffer_space(p)) { + // p must be a "source" address + p = get_buffered_addr(p); + } return buffer_to_offset(p); } diff --git a/src/hotspot/share/cds/archiveBuilder.hpp b/src/hotspot/share/cds/archiveBuilder.hpp index a022fd6a0b0..ca174e6fea8 100644 --- a/src/hotspot/share/cds/archiveBuilder.hpp +++ b/src/hotspot/share/cds/archiveBuilder.hpp @@ -241,7 +241,7 @@ private: bool is_dumping_full_module_graph(); FollowMode get_follow_mode(MetaspaceClosure::Ref *ref); - void iterate_sorted_roots(MetaspaceClosure* it, bool is_relocating_pointers); + void iterate_sorted_roots(MetaspaceClosure* it); void sort_symbols_and_fix_hash(); void sort_klasses(); static int compare_symbols_by_address(Symbol** a, Symbol** b); @@ -256,7 +256,7 @@ private: void clean_up_src_obj_table(); protected: - virtual void iterate_roots(MetaspaceClosure* it, bool is_relocating_pointers) = 0; + virtual void iterate_roots(MetaspaceClosure* it) = 0; // Conservative estimate for number of bytes needed for: size_t _estimated_metaspaceobj_bytes; // all archived MetaspaceObj's. @@ -303,6 +303,11 @@ public: return current()->buffer_to_requested_delta(); } + inline static u4 to_offset_u4(uintx offset) { + guarantee(offset <= MAX_SHARED_DELTA, "must be 32-bit offset " INTPTR_FORMAT, offset); + return (u4)offset; + } + public: static const uintx MAX_SHARED_DELTA = 0x7FFFFFFF; @@ -317,15 +322,13 @@ public: template u4 buffer_to_offset_u4(T p) const { uintx offset = buffer_to_offset((address)p); - guarantee(offset <= MAX_SHARED_DELTA, "must be 32-bit offset " INTPTR_FORMAT, offset); - return (u4)offset; + return to_offset_u4(offset); } template u4 any_to_offset_u4(T p) const { uintx offset = any_to_offset((address)p); - guarantee(offset <= MAX_SHARED_DELTA, "must be 32-bit offset " INTPTR_FORMAT, offset); - return (u4)offset; + return to_offset_u4(offset); } static void assert_is_vm_thread() PRODUCT_RETURN; @@ -338,7 +341,7 @@ public: void gather_source_objs(); bool gather_klass_and_symbol(MetaspaceClosure::Ref* ref, bool read_only); bool gather_one_source_obj(MetaspaceClosure::Ref* enclosing_ref, MetaspaceClosure::Ref* ref, bool read_only); - void remember_embedded_pointer_in_copied_obj(MetaspaceClosure::Ref* enclosing_ref, MetaspaceClosure::Ref* ref); + void remember_embedded_pointer_in_gathered_obj(MetaspaceClosure::Ref* enclosing_ref, MetaspaceClosure::Ref* ref); DumpRegion* rw_region() { return &_rw_region; } DumpRegion* ro_region() { return &_ro_region; } @@ -375,15 +378,22 @@ public: void dump_rw_metadata(); void dump_ro_metadata(); void relocate_metaspaceobj_embedded_pointers(); - void relocate_roots(); - void relocate_vm_classes(); void make_klasses_shareable(); void relocate_to_requested(); void write_archive(FileMapInfo* mapinfo, ArchiveHeapInfo* heap_info); void write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region, bool read_only, bool allow_exec); + void write_pointer_in_buffer(address* ptr_location, address src_addr); + template void write_pointer_in_buffer(T* ptr_location, T src_addr) { + write_pointer_in_buffer((address*)ptr_location, (address)src_addr); + } + address get_buffered_addr(address src_addr) const; + template T get_buffered_addr(T src_addr) const { + return (T)get_buffered_addr((address)src_addr); + } + address get_source_addr(address buffered_addr) const; template T get_source_addr(T buffered_addr) const { return (T)get_source_addr((address)buffered_addr); diff --git a/src/hotspot/share/cds/archiveUtils.cpp b/src/hotspot/share/cds/archiveUtils.cpp index bda205055eb..91e18b6f316 100644 --- a/src/hotspot/share/cds/archiveUtils.cpp +++ b/src/hotspot/share/cds/archiveUtils.cpp @@ -262,6 +262,21 @@ void DumpRegion::pack(DumpRegion* next) { } } +void WriteClosure::do_ptr(void** p) { + // Write ptr into the archive; ptr can be: + // (a) null -> written as 0 + // (b) a "buffered" address -> written as is + // (c) a "source" address -> convert to "buffered" and write + // The common case is (c). E.g., when writing the vmClasses into the archive. + // We have (b) only when we don't have a corresponding source object. E.g., + // the archived c++ vtable entries. + address ptr = *(address*)p; + if (ptr != nullptr && !ArchiveBuilder::current()->is_in_buffer_space(ptr)) { + ptr = ArchiveBuilder::current()->get_buffered_addr(ptr); + } + _dump_region->append_intptr_t((intptr_t)ptr, true); +} + void WriteClosure::do_oop(oop* o) { if (*o == nullptr) { _dump_region->append_intptr_t(0); @@ -282,7 +297,7 @@ void WriteClosure::do_region(u_char* start, size_t size) { assert(size % sizeof(intptr_t) == 0, "bad size"); do_tag((int)size); while (size > 0) { - _dump_region->append_intptr_t(*(intptr_t*)start, true); + do_ptr((void**)start); start += sizeof(intptr_t); size -= sizeof(intptr_t); } diff --git a/src/hotspot/share/cds/archiveUtils.hpp b/src/hotspot/share/cds/archiveUtils.hpp index 27f5344677e..7fcd20c816a 100644 --- a/src/hotspot/share/cds/archiveUtils.hpp +++ b/src/hotspot/share/cds/archiveUtils.hpp @@ -184,9 +184,7 @@ public: _dump_region = r; } - void do_ptr(void** p) { - _dump_region->append_intptr_t((intptr_t)*p, true); - } + void do_ptr(void** p); void do_u4(u4* p) { _dump_region->append_intptr_t((intptr_t)(*p)); diff --git a/src/hotspot/share/cds/cppVtables.cpp b/src/hotspot/share/cds/cppVtables.cpp index 05144f474c2..94ec7cd9f19 100644 --- a/src/hotspot/share/cds/cppVtables.cpp +++ b/src/hotspot/share/cds/cppVtables.cpp @@ -253,6 +253,7 @@ intptr_t* CppVtables::get_archived_vtable(MetaspaceObj::Type msotype, address ob case MetaspaceObj::ConstantPoolCacheType: case MetaspaceObj::AnnotationsType: case MetaspaceObj::MethodCountersType: + case MetaspaceObj::SharedClassPathEntryType: case MetaspaceObj::RecordComponentType: // These have no vtables. break; @@ -268,7 +269,7 @@ intptr_t* CppVtables::get_archived_vtable(MetaspaceObj::Type msotype, address ob } if (kind >= _num_cloned_vtable_kinds) { fatal("Cannot find C++ vtable for " INTPTR_FORMAT " -- you probably added" - " a new subtype of Klass or MetaData without updating CPP_VTABLE_TYPES_DO", + " a new subtype of Klass or MetaData without updating CPP_VTABLE_TYPES_DO or the cases in this 'switch' statement", p2i(obj)); } } diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp index 43e425c11c5..34ba3e69afc 100644 --- a/src/hotspot/share/cds/dynamicArchive.cpp +++ b/src/hotspot/share/cds/dynamicArchive.cpp @@ -129,7 +129,6 @@ public: dump_rw_metadata(); dump_ro_metadata(); relocate_metaspaceobj_embedded_pointers(); - relocate_roots(); verify_estimate_size(_estimated_metaspaceobj_bytes, "MetaspaceObjs"); @@ -175,7 +174,7 @@ public: verify_universe("After CDS dynamic dump"); } - virtual void iterate_roots(MetaspaceClosure* it, bool is_relocating_pointers) { + virtual void iterate_roots(MetaspaceClosure* it) { FileMapInfo::metaspace_pointers_do(it); SystemDictionaryShared::dumptime_classes_do(it); } @@ -216,7 +215,7 @@ void DynamicArchiveBuilder::post_dump() { void DynamicArchiveBuilder::sort_methods() { InstanceKlass::disable_method_binary_search(); for (int i = 0; i < klasses()->length(); i++) { - Klass* k = klasses()->at(i); + Klass* k = get_buffered_addr(klasses()->at(i)); if (k->is_instance_klass()) { sort_methods(InstanceKlass::cast(k)); } @@ -231,7 +230,7 @@ void DynamicArchiveBuilder::sort_methods(InstanceKlass* ik) const { // We have reached a supertype that's already in the base archive return; } - + assert(is_in_buffer_space(ik), "method sorting must be done on buffered class, not original class"); if (ik->java_mirror() == nullptr) { // null mirror means this class has already been visited and methods are already sorted return; @@ -315,9 +314,7 @@ void DynamicArchiveBuilder::remark_pointers_for_instance_klass(InstanceKlass* k, } void DynamicArchiveBuilder::write_archive(char* serialized_data) { - Array* table = FileMapInfo::saved_shared_path_table().table(); - SharedPathTable runtime_table(table, FileMapInfo::shared_path_table().size()); - _header->set_shared_path_table(runtime_table); + _header->set_shared_path_table(FileMapInfo::shared_path_table().table()); _header->set_serialized_data(serialized_data); FileMapInfo* dynamic_info = FileMapInfo::dynamic_info(); @@ -394,7 +391,6 @@ void DynamicArchive::dump_at_exit(JavaThread* current, const char* archive_name) MetaspaceShared::link_shared_classes(false/*not from jcmd*/, THREAD); if (!HAS_PENDING_EXCEPTION) { // copy shared path table to saved. - FileMapInfo::clone_shared_path_table(current); if (!HAS_PENDING_EXCEPTION) { VM_PopulateDynamicDumpSharedSpace op(archive_name); VMThread::execute(&op); @@ -418,7 +414,6 @@ void DynamicArchive::dump_for_jcmd(const char* archive_name, TRAPS) { assert(DynamicDumpSharedSpaces, "already checked by check_for_dynamic_dump() during VM startup"); MetaspaceShared::link_shared_classes(true/*from jcmd*/, CHECK); // copy shared path table to saved. - FileMapInfo::clone_shared_path_table(CHECK); VM_PopulateDynamicDumpSharedSpace op(archive_name); VMThread::execute(&op); } diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 999b18d70f8..f29814efed6 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -292,7 +292,6 @@ void FileMapHeader::print(outputStream* st) { st->print_cr("- heap_end: " INTPTR_FORMAT, p2i(_heap_end)); st->print_cr("- jvm_ident: %s", _jvm_ident); st->print_cr("- shared_path_table_offset: " SIZE_FORMAT_X, _shared_path_table_offset); - st->print_cr("- shared_path_table_size: %d", _shared_path_table_size); st->print_cr("- app_class_paths_start_index: %d", _app_class_paths_start_index); st->print_cr("- app_module_paths_start_index: %d", _app_module_paths_start_index); st->print_cr("- num_module_paths: %d", _num_module_paths); @@ -453,64 +452,27 @@ bool SharedClassPathEntry::check_non_existent() const { } } - void SharedClassPathEntry::metaspace_pointers_do(MetaspaceClosure* it) { it->push(&_name); it->push(&_manifest); } void SharedPathTable::metaspace_pointers_do(MetaspaceClosure* it) { - it->push(&_table); - for (int i=0; i<_size; i++) { - path_at(i)->metaspace_pointers_do(it); - } + it->push(&_entries); } void SharedPathTable::dumptime_init(ClassLoaderData* loader_data, TRAPS) { - size_t entry_size = sizeof(SharedClassPathEntry); - int num_entries = 0; - num_entries += ClassLoader::num_boot_classpath_entries(); - num_entries += ClassLoader::num_app_classpath_entries(); - num_entries += ClassLoader::num_module_path_entries(); - num_entries += FileMapInfo::num_non_existent_class_paths(); - size_t bytes = entry_size * num_entries; - - _table = MetadataFactory::new_array(loader_data, (int)bytes, CHECK); - _size = num_entries; -} - -// Make a copy of the _shared_path_table for use during dynamic CDS dump. -// It is needed because some Java code continues to execute after dynamic dump has finished. -// However, during dynamic dump, we have modified FileMapInfo::_shared_path_table so -// FileMapInfo::shared_path(i) returns incorrect information in ClassLoader::record_result(). -void FileMapInfo::copy_shared_path_table(ClassLoaderData* loader_data, TRAPS) { - size_t entry_size = sizeof(SharedClassPathEntry); - size_t bytes = entry_size * _shared_path_table.size(); - - Array* array = MetadataFactory::new_array(loader_data, (int)bytes, CHECK); - _saved_shared_path_table = SharedPathTable(array, _shared_path_table.size()); - - for (int i = 0; i < _shared_path_table.size(); i++) { - _saved_shared_path_table.path_at(i)->copy_from(shared_path(i), loader_data, CHECK); + const int num_entries = + ClassLoader::num_boot_classpath_entries() + + ClassLoader::num_app_classpath_entries() + + ClassLoader::num_module_path_entries() + + FileMapInfo::num_non_existent_class_paths(); + _entries = MetadataFactory::new_array(loader_data, num_entries, CHECK); + for (int i = 0; i < num_entries; i++) { + SharedClassPathEntry* ent = + new (loader_data, SharedClassPathEntry::size(), MetaspaceObj::SharedClassPathEntryType, THREAD) SharedClassPathEntry; + _entries->at_put(i, ent); } - _saved_shared_path_table_array = array; -} - -void FileMapInfo::clone_shared_path_table(TRAPS) { - Arguments::assert_is_dumping_archive(); - - ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); - ClassPathEntry* jrt = ClassLoader::get_jrt_entry(); - - assert(jrt != nullptr, - "No modular java runtime image present when allocating the CDS classpath entry table"); - - if (_saved_shared_path_table_array != nullptr) { - MetadataFactory::free_array(loader_data, _saved_shared_path_table_array); - _saved_shared_path_table_array = nullptr; - } - - copy_shared_path_table(loader_data, CHECK); } void FileMapInfo::allocate_shared_path_table(TRAPS) { @@ -536,7 +498,6 @@ void FileMapInfo::allocate_shared_path_table(TRAPS) { } assert(i == _shared_path_table.size(), "number of shared path entry mismatch"); - clone_shared_path_table(CHECK); } int FileMapInfo::add_shared_classpaths(int i, const char* which, ClassPathEntry *cpe, TRAPS) { @@ -2328,20 +2289,10 @@ void FileMapInfo::assert_mark(bool check) { } } -void FileMapInfo::metaspace_pointers_do(MetaspaceClosure* it, bool use_copy) { - if (use_copy) { - _saved_shared_path_table.metaspace_pointers_do(it); - } else { - _shared_path_table.metaspace_pointers_do(it); - } -} - FileMapInfo* FileMapInfo::_current_info = nullptr; FileMapInfo* FileMapInfo::_dynamic_archive_info = nullptr; bool FileMapInfo::_heap_pointers_need_patching = false; SharedPathTable FileMapInfo::_shared_path_table; -SharedPathTable FileMapInfo::_saved_shared_path_table; -Array* FileMapInfo::_saved_shared_path_table_array = nullptr; bool FileMapInfo::_validating_shared_path_table = false; bool FileMapInfo::_memory_mapping_failed = false; GrowableArray* FileMapInfo::_non_existent_class_paths = nullptr; diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index 70ccb10e8a6..3428c465b4d 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -28,6 +28,7 @@ #include "cds/metaspaceShared.hpp" #include "include/cds.h" #include "logging/logLevel.hpp" +#include "memory/allocation.hpp" #include "oops/array.hpp" #include "oops/compressedOops.hpp" #include "utilities/align.hpp" @@ -48,7 +49,7 @@ class ClassLoaderData; class ClassPathEntry; class outputStream; -class SharedClassPathEntry { +class SharedClassPathEntry : public MetaspaceObj { enum { modules_image_entry, jar_entry, @@ -69,9 +70,17 @@ class SharedClassPathEntry { Array* _manifest; public: + SharedClassPathEntry() : _type(0), _is_module_path(false), + _from_class_path_attr(false), _timestamp(0), + _filesize(0), _name(nullptr), _manifest(nullptr) {} + static int size() { + static_assert(is_aligned(sizeof(SharedClassPathEntry), wordSize), "must be"); + return (int)(sizeof(SharedClassPathEntry) / wordSize); + } void init(bool is_modules_image, bool is_module_path, ClassPathEntry* cpe, TRAPS); void init_as_non_existent(const char* path, TRAPS); void metaspace_pointers_do(MetaspaceClosure* it); + MetaspaceObj::Type type() const { return SharedClassPathEntryType; } bool validate(bool is_class_path = true) const; // The _timestamp only gets set for jar files. @@ -106,29 +115,22 @@ public: }; class SharedPathTable { - Array* _table; - int _size; + Array* _entries; public: - SharedPathTable() : _table(nullptr), _size(0) {} - SharedPathTable(Array* table, int size) : _table(table), _size(size) {} + SharedPathTable() : _entries(nullptr) {} + SharedPathTable(Array* entries) : _entries(entries) {} void dumptime_init(ClassLoaderData* loader_data, TRAPS); void metaspace_pointers_do(MetaspaceClosure* it); int size() { - return _size; + return _entries == nullptr ? 0 : _entries->length(); } SharedClassPathEntry* path_at(int index) { - if (index < 0) { - return nullptr; - } - assert(index < _size, "sanity"); - char* p = (char*)_table->data(); - p += sizeof(SharedClassPathEntry) * index; - return (SharedClassPathEntry*)p; + return _entries->at(index); } - Array* table() {return _table;} - void set_table(Array* table) {_table = table;} + Array* table() {return _entries;} + void set_table(Array* table) {_entries = table;} }; @@ -215,7 +217,6 @@ private: // validate_shared_path_table() // validate_non_existent_class_paths() size_t _shared_path_table_offset; - int _shared_path_table_size; jshort _app_class_paths_start_index; // Index of first app classpath entry jshort _app_module_paths_start_index; // Index of first module path entry @@ -290,7 +291,6 @@ public: void set_shared_path_table(SharedPathTable table) { set_as_offset((char*)table.table(), &_shared_path_table_offset); - _shared_path_table_size = table.size(); } void set_requested_base(char* b) { @@ -299,8 +299,8 @@ public: } SharedPathTable shared_path_table() const { - return SharedPathTable((Array*)from_mapped_offset(_shared_path_table_offset), - _shared_path_table_size); + return SharedPathTable((Array*) + from_mapped_offset(_shared_path_table_offset)); } bool validate(); @@ -338,10 +338,7 @@ private: const char* _base_archive_name; FileMapHeader* _header; - // TODO: Probably change the following to be non-static static SharedPathTable _shared_path_table; - static SharedPathTable _saved_shared_path_table; - static Array* _saved_shared_path_table_array; // remember the table array for cleanup static bool _validating_shared_path_table; // FileMapHeader describes the shared space data in the file to be @@ -361,13 +358,11 @@ public: static SharedPathTable shared_path_table() { return _shared_path_table; } - static SharedPathTable saved_shared_path_table() { - assert(_saved_shared_path_table.size() >= 0, "Sanity check"); - return _saved_shared_path_table; - } bool init_from_file(int fd); - static void metaspace_pointers_do(MetaspaceClosure* it, bool use_copy = true); + static void metaspace_pointers_do(MetaspaceClosure* it) { + _shared_path_table.metaspace_pointers_do(it); + } void log_paths(const char* msg, int start_idx, int end_idx); diff --git a/src/hotspot/share/cds/lambdaProxyClassDictionary.cpp b/src/hotspot/share/cds/lambdaProxyClassDictionary.cpp index f3defd6bf39..0f0bcb1b9b9 100644 --- a/src/hotspot/share/cds/lambdaProxyClassDictionary.cpp +++ b/src/hotspot/share/cds/lambdaProxyClassDictionary.cpp @@ -26,6 +26,7 @@ #include "cds/archiveBuilder.hpp" #include "cds/lambdaProxyClassDictionary.hpp" #include "classfile/systemDictionaryShared.hpp" +#include "memory/resourceArea.hpp" // This constructor is used only by SystemDictionaryShared::clone_dumptime_tables(). // See comments there about the need for making a deep copy. @@ -46,13 +47,15 @@ DumpTimeLambdaProxyClassInfo::~DumpTimeLambdaProxyClassInfo() { } } -void LambdaProxyClassKey::mark_pointers() { - ArchivePtrMarker::mark_pointer(&_caller_ik); - ArchivePtrMarker::mark_pointer(&_instantiated_method_type); - ArchivePtrMarker::mark_pointer(&_invoked_name); - ArchivePtrMarker::mark_pointer(&_invoked_type); - ArchivePtrMarker::mark_pointer(&_member_method); - ArchivePtrMarker::mark_pointer(&_method_type); +void LambdaProxyClassKey::init_for_archive(LambdaProxyClassKey& dumptime_key) { + ArchiveBuilder* b = ArchiveBuilder::current(); + + b->write_pointer_in_buffer(&_caller_ik, dumptime_key._caller_ik); + b->write_pointer_in_buffer(&_instantiated_method_type, dumptime_key._instantiated_method_type); + b->write_pointer_in_buffer(&_invoked_name, dumptime_key._invoked_name); + b->write_pointer_in_buffer(&_invoked_type, dumptime_key._invoked_type); + b->write_pointer_in_buffer(&_member_method, dumptime_key._member_method); + b->write_pointer_in_buffer(&_method_type, dumptime_key._method_type); } unsigned int LambdaProxyClassKey::hash() const { @@ -62,3 +65,26 @@ unsigned int LambdaProxyClassKey::hash() const { SystemDictionaryShared::hash_for_shared_dictionary((address)_method_type) + SystemDictionaryShared::hash_for_shared_dictionary((address)_instantiated_method_type); } + +#ifndef PRODUCT +void LambdaProxyClassKey::print_on(outputStream* st) const { + ResourceMark rm; + st->print_cr("LambdaProxyClassKey : " INTPTR_FORMAT " hash: %0x08x", p2i(this), hash()); + st->print_cr("_caller_ik : %s", _caller_ik->external_name()); + st->print_cr("_instantiated_method_type : %s", _instantiated_method_type->as_C_string()); + st->print_cr("_invoked_name : %s", _invoked_name->as_C_string()); + st->print_cr("_invoked_type : %s", _invoked_type->as_C_string()); + st->print_cr("_member_method : %s", _member_method->name()->as_C_string()); + st->print_cr("_method_type : %s", _method_type->as_C_string()); +} + +void RunTimeLambdaProxyClassInfo::print_on(outputStream* st) const { + _key.print_on(st); +} +#endif + +void RunTimeLambdaProxyClassInfo::init(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info) { + _key.init_for_archive(key); + ArchiveBuilder::current()->write_pointer_in_buffer(&_proxy_klass_head, + info._proxy_klasses->at(0)); +} diff --git a/src/hotspot/share/cds/lambdaProxyClassDictionary.hpp b/src/hotspot/share/cds/lambdaProxyClassDictionary.hpp index 0f1e855aeea..c3ad88b8632 100644 --- a/src/hotspot/share/cds/lambdaProxyClassDictionary.hpp +++ b/src/hotspot/share/cds/lambdaProxyClassDictionary.hpp @@ -32,6 +32,7 @@ class InstanceKlass; class Method; class Symbol; +class outputStream; class LambdaProxyClassKey { InstanceKlass* _caller_ik; @@ -73,7 +74,6 @@ public: _instantiated_method_type == other._instantiated_method_type; } - void mark_pointers(); unsigned int hash() const; static unsigned int dumptime_hash(Symbol* sym) { @@ -102,6 +102,12 @@ public: } InstanceKlass* caller_ik() const { return _caller_ik; } + + void init_for_archive(LambdaProxyClassKey& dumptime_key); + +#ifndef PRODUCT + void print_on(outputStream* st) const; +#endif }; class DumpTimeLambdaProxyClassInfo { @@ -141,12 +147,7 @@ public: const RunTimeLambdaProxyClassInfo* value, LambdaProxyClassKey* key, int len_unused) { return (value->_key.equals(*key)); } - void init(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info) { - _key = key; - _key.mark_pointers(); - _proxy_klass_head = info._proxy_klasses->at(0); - ArchivePtrMarker::mark_pointer(&_proxy_klass_head); - } + void init(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info); unsigned int hash() const { return _key.hash(); @@ -154,6 +155,9 @@ public: LambdaProxyClassKey key() const { return _key; } +#ifndef PRODUCT + void print_on(outputStream* st) const; +#endif }; class DumpTimeLambdaProxyClassDictionary diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index cfcbc6cc666..86be63c7b71 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -451,8 +451,8 @@ class StaticArchiveBuilder : public ArchiveBuilder { public: StaticArchiveBuilder() : ArchiveBuilder() {} - virtual void iterate_roots(MetaspaceClosure* it, bool is_relocating_pointers) { - FileMapInfo::metaspace_pointers_do(it, false); + virtual void iterate_roots(MetaspaceClosure* it) { + FileMapInfo::metaspace_pointers_do(it); SystemDictionaryShared::dumptime_classes_do(it); Universe::metaspace_pointers_do(it); vmSymbols::metaspace_pointers_do(it); @@ -507,14 +507,9 @@ void VM_PopulateDumpSharedSpace::doit() { builder.dump_ro_metadata(); builder.relocate_metaspaceobj_embedded_pointers(); - // Dump supported java heap objects dump_java_heap_objects(builder.klasses()); - - builder.relocate_roots(); dump_shared_symbol_table(builder.symbols()); - builder.relocate_vm_classes(); - log_info(cds)("Make classes shareable"); builder.make_klasses_shareable(); @@ -588,8 +583,7 @@ bool MetaspaceShared::may_be_eagerly_linked(InstanceKlass* ik) { // that may not be expected by custom class loaders. // // It's OK to do this for the built-in loaders as we know they can - // tolerate this. (Note that unregistered classes are loaded by the null - // loader during DumpSharedSpaces). + // tolerate this. return false; } return true; diff --git a/src/hotspot/share/cds/runTimeClassInfo.cpp b/src/hotspot/share/cds/runTimeClassInfo.cpp index 8c17659f242..2536b533086 100644 --- a/src/hotspot/share/cds/runTimeClassInfo.cpp +++ b/src/hotspot/share/cds/runTimeClassInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2023, 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 @@ -30,8 +30,8 @@ void RunTimeClassInfo::init(DumpTimeClassInfo& info) { ArchiveBuilder* builder = ArchiveBuilder::current(); - assert(builder->is_in_buffer_space(info._klass), "must be"); - _klass = info._klass; + builder->write_pointer_in_buffer(&_klass, info._klass); + if (!SystemDictionaryShared::is_builtin(_klass)) { CrcInfo* c = crc(); c->_clsfile_size = info._clsfile_size; @@ -62,8 +62,7 @@ void RunTimeClassInfo::init(DumpTimeClassInfo& info) { } if (_klass->is_hidden()) { - InstanceKlass* n_h = info.nest_host(); - set_nest_host(n_h); + builder->write_pointer_in_buffer(nest_host_addr(), info.nest_host()); } if (_klass->has_archived_enum_objs()) { int num = info.num_enum_klass_static_fields(); @@ -73,8 +72,6 @@ void RunTimeClassInfo::init(DumpTimeClassInfo& info) { set_enum_klass_static_field_root_index_at(i, root_index); } } - - ArchivePtrMarker::mark_pointer(&_klass); } size_t RunTimeClassInfo::crc_size(InstanceKlass* klass) { diff --git a/src/hotspot/share/cds/runTimeClassInfo.hpp b/src/hotspot/share/cds/runTimeClassInfo.hpp index 1360c46883c..b5ffe0028e3 100644 --- a/src/hotspot/share/cds/runTimeClassInfo.hpp +++ b/src/hotspot/share/cds/runTimeClassInfo.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2023, 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 @@ -180,10 +180,6 @@ public: InstanceKlass* nest_host() { return *nest_host_addr(); } - void set_nest_host(InstanceKlass* k) { - *nest_host_addr() = k; - ArchivePtrMarker::mark_pointer((address*)nest_host_addr()); - } RTLoaderConstraint* loader_constraints() { assert(_num_loader_constraints > 0, "sanity"); diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index e3561b39fd0..4b182b80d96 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -1166,22 +1166,19 @@ public: AdjustLambdaProxyClassInfo() {} bool do_entry(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info) { int len = info._proxy_klasses->length(); - if (len > 1) { - for (int i = 0; i < len-1; i++) { - InstanceKlass* ok0 = info._proxy_klasses->at(i+0); // this is original klass - InstanceKlass* ok1 = info._proxy_klasses->at(i+1); // this is original klass - assert(ArchiveBuilder::current()->is_in_buffer_space(ok0), "must be"); - assert(ArchiveBuilder::current()->is_in_buffer_space(ok1), "must be"); - InstanceKlass* bk0 = ok0; - InstanceKlass* bk1 = ok1; - assert(bk0->next_link() == 0, "must be called after Klass::remove_unshareable_info()"); - assert(bk1->next_link() == 0, "must be called after Klass::remove_unshareable_info()"); - bk0->set_next_link(bk1); - bk1->set_lambda_proxy_is_available(); - ArchivePtrMarker::mark_pointer(bk0->next_link_addr()); + InstanceKlass* last_buff_k = nullptr; + + for (int i = len - 1; i >= 0; i--) { + InstanceKlass* orig_k = info._proxy_klasses->at(i); + InstanceKlass* buff_k = ArchiveBuilder::current()->get_buffered_addr(orig_k); + assert(ArchiveBuilder::current()->is_in_buffer_space(buff_k), "must be"); + buff_k->set_lambda_proxy_is_available(); + buff_k->set_next_link(last_buff_k); + if (last_buff_k != nullptr) { + ArchivePtrMarker::mark_pointer(buff_k->next_link_addr()); } + last_buff_k = buff_k; } - info._proxy_klasses->at(0)->set_lambda_proxy_is_available(); return true; } @@ -1205,6 +1202,7 @@ public: unsigned int hash; Symbol* name = info._klass->name(); + name = ArchiveBuilder::current()->get_buffered_addr(name); hash = SystemDictionaryShared::hash_for_shared_dictionary((address)name); u4 delta = _builder->buffer_to_offset_u4((address)record); if (_is_builtin && info._klass->is_hidden()) { @@ -1218,7 +1216,8 @@ public: } // Save this for quick runtime lookup of InstanceKlass* -> RunTimeClassInfo* - RunTimeClassInfo::set_for(info._klass, record); + InstanceKlass* buffered_klass = ArchiveBuilder::current()->get_buffered_addr(info._klass); + RunTimeClassInfo::set_for(buffered_klass, record); } } }; diff --git a/src/hotspot/share/memory/allocation.hpp b/src/hotspot/share/memory/allocation.hpp index bd3bd27f01d..0bb1840fd34 100644 --- a/src/hotspot/share/memory/allocation.hpp +++ b/src/hotspot/share/memory/allocation.hpp @@ -370,6 +370,7 @@ class MetaspaceObj { f(ConstantPoolCache) \ f(Annotations) \ f(MethodCounters) \ + f(SharedClassPathEntry) \ f(RecordComponent) #define METASPACE_OBJ_TYPE_DECLARE(name) name ## Type,