Skip to content
Permalink
Browse files
8264735: Make dynamic dump repeatable
Reviewed-by: ccheung, iklam
  • Loading branch information
yminqi committed Jul 7, 2021
1 parent d1cecaa commit f741e4ca7499193d1d0d07fb27d11cbc0a6de6c1
Showing 14 changed files with 208 additions and 36 deletions.
@@ -190,6 +190,9 @@ ArchiveBuilder::~ArchiveBuilder() {
delete _klasses;
delete _symbols;
delete _special_refs;
if (_shared_rs.is_reserved()) {
_shared_rs.release();
}
}

bool ArchiveBuilder::is_dumping_full_module_graph() {
@@ -71,6 +71,11 @@ class ArchivePtrMarker : AllStatic {
static CHeapBitMap* ptrmap() {
return _ptrmap;
}

static void reset_map_and_vs() {
_ptrmap = nullptr;
_vs = nullptr;
}
};

// SharedDataRelocator is used to shift pointers in the CDS archive.
@@ -30,13 +30,47 @@
#include "classfile/systemDictionaryShared.hpp"
#include "memory/resourceArea.hpp"

DumpTimeClassInfo DumpTimeClassInfo::clone() {
DumpTimeClassInfo clone;
clone._klass = _klass;
clone._nest_host = _nest_host;
clone._failed_verification = _failed_verification;
clone._is_archived_lambda_proxy = _is_archived_lambda_proxy;
clone._has_checked_exclusion = _has_checked_exclusion;
clone._id = _id;
clone._clsfile_size = _clsfile_size;
clone._clsfile_crc32 = _clsfile_crc32;
clone._excluded = _excluded;
clone._is_early_klass = _is_early_klass;
clone._verifier_constraints = NULL;
clone._verifier_constraint_flags = NULL;
clone._loader_constraints = NULL;
int clone_num_verifier_constraints = num_verifier_constraints();
if (clone_num_verifier_constraints > 0) {
clone._verifier_constraints = new (ResourceObj::C_HEAP, mtClass) GrowableArray<DTVerifierConstraint>(clone_num_verifier_constraints, mtClass);
clone._verifier_constraint_flags = new (ResourceObj::C_HEAP, mtClass) GrowableArray<char>(clone_num_verifier_constraints, mtClass);
for (int i = 0; i < clone_num_verifier_constraints; i++) {
clone._verifier_constraints->append(_verifier_constraints->at(i));
clone._verifier_constraint_flags->append(_verifier_constraint_flags->at(i));
}
}
int clone_num_loader_constraints = num_loader_constraints();
if (clone_num_loader_constraints > 0) {
clone._loader_constraints = new (ResourceObj::C_HEAP, mtClass) GrowableArray<DTLoaderConstraint>(clone_num_loader_constraints, mtClass);
for (int i = 0; i < clone_num_loader_constraints; i++) {
clone._loader_constraints->append(_loader_constraints->at(i));
}
}
return clone;
}

void DumpTimeClassInfo::add_verification_constraint(InstanceKlass* k, Symbol* name,
Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object) {
if (_verifier_constraints == NULL) {
_verifier_constraints = new(ResourceObj::C_HEAP, mtClass) GrowableArray<DTVerifierConstraint>(4, mtClass);
_verifier_constraints = new (ResourceObj::C_HEAP, mtClass) GrowableArray<DTVerifierConstraint>(4, mtClass);
}
if (_verifier_constraint_flags == NULL) {
_verifier_constraint_flags = new(ResourceObj::C_HEAP, mtClass) GrowableArray<char>(4, mtClass);
_verifier_constraint_flags = new (ResourceObj::C_HEAP, mtClass) GrowableArray<char>(4, mtClass);
}
GrowableArray<DTVerifierConstraint>* vc_array = _verifier_constraints;
for (int i = 0; i < vc_array->length(); i++) {
@@ -152,6 +152,7 @@ class DumpTimeClassInfo: public CHeapObj<mtClass> {
void set_failed_verification() { _failed_verification = true; }
InstanceKlass* nest_host() const { return _nest_host; }
void set_nest_host(InstanceKlass* nest_host) { _nest_host = nest_host; }
DumpTimeClassInfo clone();
};


@@ -178,6 +179,10 @@ class DumpTimeSharedClassTable: public ResourceHashtable<
int _builtin_count;
int _unregistered_count;
public:
DumpTimeSharedClassTable() {
_builtin_count = 0;
_unregistered_count = 0;
}
DumpTimeClassInfo* find_or_allocate_info_for(InstanceKlass* k, bool dump_in_progress);
void inc_builtin_count() { _builtin_count++; }
void inc_unregistered_count() { _unregistered_count++; }
@@ -83,6 +83,7 @@ class DynamicArchiveBuilder : public ArchiveBuilder {

void init_header();
void release_header();
void post_dump();
void sort_methods();
void sort_methods(InstanceKlass* ik) const;
void remark_pointers_for_instance_klass(InstanceKlass* k, bool should_mark) const;
@@ -112,6 +113,9 @@ class DynamicArchiveBuilder : public ArchiveBuilder {
MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
SystemDictionaryShared::check_excluded_classes();

// save dumptime tables
SystemDictionaryShared::clone_dumptime_tables();

init_header();
gather_source_objs();
reserve_buffer();
@@ -158,6 +162,11 @@ class DynamicArchiveBuilder : public ArchiveBuilder {
write_archive(serialized_data);
release_header();

post_dump();

// Restore dumptime tables
SystemDictionaryShared::restore_dumptime_tables();

assert(_num_dump_regions_used == _total_dump_regions, "must be");
verify_universe("After CDS dynamic dump");
}
@@ -194,6 +203,10 @@ void DynamicArchiveBuilder::release_header() {
_header = NULL;
}

void DynamicArchiveBuilder::post_dump() {
ArchivePtrMarker::reset_map_and_vs();
}

void DynamicArchiveBuilder::sort_methods() {
InstanceKlass::disable_method_binary_search();
for (int i = 0; i < klasses()->length(); i++) {
@@ -347,42 +360,34 @@ void DynamicArchive::prepare_for_dynamic_dumping_at_exit() {
}
}

bool DynamicArchive::_has_been_dumped_once = false;

void DynamicArchive::dump(const char* archive_name, TRAPS) {
assert(UseSharedSpaces && RecordDynamicDumpInfo, "already checked in arguments.cpp?");
assert(ArchiveClassesAtExit == nullptr, "already checked in arguments.cpp?");
// During dynamic archive dumping, some of the data structures are overwritten so
// we cannot dump the dynamic archive again. TODO: this should be fixed.
if (has_been_dumped_once()) {
THROW_MSG(vmSymbols::java_lang_RuntimeException(),
"Dynamic dump has been done, and should only be done once");
ArchiveClassesAtExit = archive_name;
if (Arguments::init_shared_archive_paths()) {
dump(CHECK);
} else {
// prevent multiple dumps.
set_has_been_dumped_once();
ArchiveClassesAtExit = archive_name;
if (Arguments::init_shared_archive_paths()) {
dump();
} else {
ArchiveClassesAtExit = nullptr;
THROW_MSG(vmSymbols::java_lang_RuntimeException(),
"Could not setup SharedDynamicArchivePath");
}
// prevent do dynamic dump at exit.
ArchiveClassesAtExit = nullptr;
if (!Arguments::init_shared_archive_paths()) {
THROW_MSG(vmSymbols::java_lang_RuntimeException(),
"Could not restore SharedDynamicArchivePath");
}
THROW_MSG(vmSymbols::java_lang_RuntimeException(),
"Could not setup SharedDynamicArchivePath");
}
// prevent do dynamic dump at exit.
ArchiveClassesAtExit = nullptr;
if (!Arguments::init_shared_archive_paths()) {
THROW_MSG(vmSymbols::java_lang_RuntimeException(),
"Could not restore SharedDynamicArchivePath");
}
}

void DynamicArchive::dump() {
void DynamicArchive::dump(TRAPS) {
if (Arguments::GetSharedDynamicArchivePath() == NULL) {
log_warning(cds, dynamic)("SharedDynamicArchivePath is not specified");
return;
}

// copy shared path table to saved.
FileMapInfo::clone_shared_path_table(CHECK);

VM_PopulateDynamicDumpSharedSpace op;
VMThread::execute(&op);
}
@@ -58,13 +58,10 @@ class DynamicArchiveHeader : public FileMapHeader {
};

class DynamicArchive : AllStatic {
static bool _has_been_dumped_once;
public:
static void prepare_for_dynamic_dumping_at_exit();
static void dump(const char* archive_name, TRAPS);
static void dump();
static bool has_been_dumped_once() { return _has_been_dumped_once; }
static void set_has_been_dumped_once() { _has_been_dumped_once = true; }
static void dump(TRAPS);
static bool is_mapped() { return FileMapInfo::dynamic_info() != NULL; }
static bool validate(FileMapInfo* dynamic_info);
};
@@ -478,6 +478,24 @@ void FileMapInfo::copy_shared_path_table(ClassLoaderData* loader_data, TRAPS) {
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);
}
_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 != NULL,
"No modular java runtime image present when allocating the CDS classpath entry table");

if (_saved_shared_path_table_array != NULL) {
MetadataFactory::free_array<u8>(loader_data, _saved_shared_path_table_array);
_saved_shared_path_table_array = NULL;
}

copy_shared_path_table(loader_data, CHECK);
}

void FileMapInfo::allocate_shared_path_table(TRAPS) {
@@ -503,8 +521,7 @@ void FileMapInfo::allocate_shared_path_table(TRAPS) {
}

assert(i == _shared_path_table.size(), "number of shared path entry mismatch");

copy_shared_path_table(loader_data, CHECK);
clone_shared_path_table(CHECK);
}

int FileMapInfo::add_shared_classpaths(int i, const char* which, ClassPathEntry *cpe, TRAPS) {
@@ -2152,6 +2169,7 @@ FileMapInfo* FileMapInfo::_dynamic_archive_info = NULL;
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 = NULL;
bool FileMapInfo::_validating_shared_path_table = false;
bool FileMapInfo::_memory_mapping_failed = false;
GrowableArray<const char*>* FileMapInfo::_non_existent_class_paths = NULL;
@@ -346,6 +346,7 @@ class FileMapInfo : public CHeapObj<mtInternal> {
// 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
@@ -368,6 +369,7 @@ class FileMapInfo : public CHeapObj<mtInternal> {
return _shared_path_table;
}
static SharedPathTable saved_shared_path_table() {
assert(_saved_shared_path_table.size() >= 0, "Sanity check");
return _saved_shared_path_table;
}

@@ -497,6 +499,7 @@ class FileMapInfo : public CHeapObj<mtInternal> {

static void allocate_shared_path_table(TRAPS);
static void copy_shared_path_table(ClassLoaderData* loader_data, TRAPS);
static void clone_shared_path_table(TRAPS);
static int add_shared_classpaths(int i, const char* which, ClassPathEntry *cpe, TRAPS);
static void check_nonempty_dir_in_shared_path_table();
bool validate_shared_path_table();
@@ -27,6 +27,19 @@
#include "cds/lambdaProxyClassDictionary.hpp"
#include "classfile/systemDictionaryShared.hpp"

DumpTimeLambdaProxyClassInfo DumpTimeLambdaProxyClassInfo::clone() {
DumpTimeLambdaProxyClassInfo res;
res._proxy_klasses = NULL;
if (_proxy_klasses != NULL && _proxy_klasses->length() > 0) {
int num_proxy_klasses = _proxy_klasses->length();
res._proxy_klasses = new (ResourceObj::C_HEAP, mtClassShared) GrowableArray<InstanceKlass*>(num_proxy_klasses, mtClassShared);
for (int i = 0; i < num_proxy_klasses; i++) {
res._proxy_klasses->append(_proxy_klasses->at(i));
}
}
return res;
}

void LambdaProxyClassKey::mark_pointers() {
ArchivePtrMarker::mark_pointer(&_caller_ik);
ArchivePtrMarker::mark_pointer(&_instantiated_method_type);
@@ -110,7 +110,7 @@ class DumpTimeLambdaProxyClassInfo {
DumpTimeLambdaProxyClassInfo() : _proxy_klasses(NULL) {}
void add_proxy_klass(InstanceKlass* proxy_klass) {
if (_proxy_klasses == NULL) {
_proxy_klasses = new (ResourceObj::C_HEAP, mtClassShared)GrowableArray<InstanceKlass*>(5, mtClassShared);
_proxy_klasses = new (ResourceObj::C_HEAP, mtClassShared) GrowableArray<InstanceKlass*>(5, mtClassShared);
}
assert(_proxy_klasses != NULL, "sanity");
_proxy_klasses->append(proxy_klass);
@@ -121,6 +121,7 @@ class DumpTimeLambdaProxyClassInfo {
it->push(_proxy_klasses->adr_at(i));
}
}
DumpTimeLambdaProxyClassInfo clone(); // copy ctor will cause implicitly-declared
};

class RunTimeLambdaProxyClassInfo {
@@ -160,6 +161,7 @@ class DumpTimeLambdaProxyClassDictionary
137, // prime number
ResourceObj::C_HEAP> {
public:
DumpTimeLambdaProxyClassDictionary() : _count(0) {}
int _count;
};

1 comment on commit f741e4c

@openjdk-notifier
Copy link

@openjdk-notifier openjdk-notifier bot commented on f741e4c Jul 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.