8307567: Avoid relocating global roots to metaspaceObjs in CDS dump

Reviewed-by: matsaave, ccheung
This commit is contained in:
Ioi Lam 2023-05-16 01:40:07 +00:00
parent 316837226e
commit 05b51c75b9
15 changed files with 172 additions and 213 deletions

View File

@ -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);
}

View File

@ -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 <typename T>
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 <typename T>
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 <typename T> 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 <typename T> 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 <typename T> T get_source_addr(T buffered_addr) const {
return (T)get_source_addr((address)buffered_addr);

View File

@ -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);
}

View File

@ -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));

View File

@ -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));
}
}

View File

@ -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<u8>* 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);
}

View File

@ -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<u8>(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<u8>* array = MetadataFactory::new_array<u8>(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<SharedClassPathEntry*>(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<u8>(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<u8>* FileMapInfo::_saved_shared_path_table_array = nullptr;
bool FileMapInfo::_validating_shared_path_table = false;
bool FileMapInfo::_memory_mapping_failed = false;
GrowableArray<const char*>* FileMapInfo::_non_existent_class_paths = nullptr;

View File

@ -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<u1>* _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<u8>* _table;
int _size;
Array<SharedClassPathEntry*>* _entries;
public:
SharedPathTable() : _table(nullptr), _size(0) {}
SharedPathTable(Array<u8>* table, int size) : _table(table), _size(size) {}
SharedPathTable() : _entries(nullptr) {}
SharedPathTable(Array<SharedClassPathEntry*>* 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<u8>* table() {return _table;}
void set_table(Array<u8>* table) {_table = table;}
Array<SharedClassPathEntry*>* table() {return _entries;}
void set_table(Array<SharedClassPathEntry*>* 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<u8>*)from_mapped_offset(_shared_path_table_offset),
_shared_path_table_size);
return SharedPathTable((Array<SharedClassPathEntry*>*)
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<u8>* _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);

View File

@ -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));
}

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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");

View File

@ -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);
}
}
};

View File

@ -370,6 +370,7 @@ class MetaspaceObj {
f(ConstantPoolCache) \
f(Annotations) \
f(MethodCounters) \
f(SharedClassPathEntry) \
f(RecordComponent)
#define METASPACE_OBJ_TYPE_DECLARE(name) name ## Type,