Skip to content

Commit 567c688

Browse files
committed
8353597: Refactor handling VM options for AOT cache input and output
Reviewed-by: kvn, asmehra
1 parent 4dc9e58 commit 567c688

File tree

15 files changed

+254
-148
lines changed

15 files changed

+254
-148
lines changed

src/hotspot/share/cds/cdsConfig.cpp

Lines changed: 136 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,10 @@ bool CDSConfig::_old_cds_flags_used = false;
5151
bool CDSConfig::_new_aot_flags_used = false;
5252
bool CDSConfig::_disable_heap_dumping = false;
5353

54-
char* CDSConfig::_default_archive_path = nullptr;
55-
char* CDSConfig::_static_archive_path = nullptr;
56-
char* CDSConfig::_dynamic_archive_path = nullptr;
54+
const char* CDSConfig::_default_archive_path = nullptr;
55+
const char* CDSConfig::_input_static_archive_path = nullptr;
56+
const char* CDSConfig::_input_dynamic_archive_path = nullptr;
57+
const char* CDSConfig::_output_archive_path = nullptr;
5758

5859
JavaThread* CDSConfig::_dumper_thread = nullptr;
5960

@@ -66,7 +67,11 @@ int CDSConfig::get_status() {
6667
(is_using_archive() ? IS_USING_ARCHIVE : 0);
6768
}
6869

69-
void CDSConfig::initialize() {
70+
DEBUG_ONLY(static bool _cds_ergo_initialize_started = false);
71+
72+
void CDSConfig::ergo_initialize() {
73+
DEBUG_ONLY(_cds_ergo_initialize_started = true);
74+
7075
if (is_dumping_static_archive() && !is_dumping_final_static_archive()) {
7176
// Note: -Xshare and -XX:AOTMode flags are mutually exclusive.
7277
// - Classic workflow: -Xshare:on and -Xshare:dump cannot take effect at the same time.
@@ -83,18 +88,23 @@ void CDSConfig::initialize() {
8388

8489
// Initialize shared archive paths which could include both base and dynamic archive paths
8590
// This must be after set_ergonomics_flags() called so flag UseCompressedOops is set properly.
86-
//
87-
// UseSharedSpaces may be disabled if -XX:SharedArchiveFile is invalid.
8891
if (is_dumping_static_archive() || is_using_archive()) {
89-
init_shared_archive_paths();
92+
if (new_aot_flags_used()) {
93+
ergo_init_aot_paths();
94+
} else {
95+
ergo_init_classic_archive_paths();
96+
}
9097
}
9198

9299
if (!is_dumping_heap()) {
93100
_is_dumping_full_module_graph = false;
94101
}
95102
}
96103

97-
char* CDSConfig::default_archive_path() {
104+
const char* CDSConfig::default_archive_path() {
105+
// The path depends on UseCompressedOops, etc, which are set by GC ergonomics just
106+
// before CDSConfig::ergo_initialize() is called.
107+
assert(_cds_ergo_initialize_started, "sanity");
98108
if (_default_archive_path == nullptr) {
99109
stringStream tmp;
100110
const char* subdir = WINDOWS_ONLY("bin") NOT_WINDOWS("lib");
@@ -116,12 +126,12 @@ char* CDSConfig::default_archive_path() {
116126
return _default_archive_path;
117127
}
118128

119-
int CDSConfig::num_archives(const char* archive_path) {
120-
if (archive_path == nullptr) {
129+
int CDSConfig::num_archive_paths(const char* path_spec) {
130+
if (path_spec == nullptr) {
121131
return 0;
122132
}
123133
int npaths = 1;
124-
char* p = (char*)archive_path;
134+
char* p = (char*)path_spec;
125135
while (*p != '\0') {
126136
if (*p == os::path_separator()[0]) {
127137
npaths++;
@@ -131,9 +141,9 @@ int CDSConfig::num_archives(const char* archive_path) {
131141
return npaths;
132142
}
133143

134-
void CDSConfig::extract_shared_archive_paths(const char* archive_path,
135-
char** base_archive_path,
136-
char** top_archive_path) {
144+
void CDSConfig::extract_archive_paths(const char* archive_path,
145+
const char** base_archive_path,
146+
const char** top_archive_path) {
137147
char* begin_ptr = (char*)archive_path;
138148
char* end_ptr = strchr((char*)archive_path, os::path_separator()[0]);
139149
if (end_ptr == nullptr || end_ptr == begin_ptr) {
@@ -157,7 +167,8 @@ void CDSConfig::extract_shared_archive_paths(const char* archive_path,
157167
*top_archive_path = cur_path;
158168
}
159169

160-
void CDSConfig::init_shared_archive_paths() {
170+
void CDSConfig::ergo_init_classic_archive_paths() {
171+
assert(_cds_ergo_initialize_started, "sanity");
161172
if (ArchiveClassesAtExit != nullptr) {
162173
assert(!RecordDynamicDumpInfo, "already checked");
163174
if (is_dumping_static_archive()) {
@@ -172,21 +183,24 @@ void CDSConfig::init_shared_archive_paths() {
172183
}
173184

174185
if (SharedArchiveFile == nullptr) {
175-
_static_archive_path = default_archive_path();
186+
_input_static_archive_path = default_archive_path();
187+
if (is_dumping_static_archive()) {
188+
_output_archive_path = _input_static_archive_path;
189+
}
176190
} else {
177-
int archives = num_archives(SharedArchiveFile);
178-
assert(archives > 0, "must be");
191+
int num_archives = num_archive_paths(SharedArchiveFile);
192+
assert(num_archives > 0, "must be");
179193

180-
if (is_dumping_archive() && archives > 1) {
194+
if (is_dumping_archive() && num_archives > 1) {
181195
vm_exit_during_initialization(
182196
"Cannot have more than 1 archive file specified in -XX:SharedArchiveFile during CDS dumping");
183197
}
184198

185199
if (is_dumping_static_archive()) {
186-
assert(archives == 1, "must be");
200+
assert(num_archives == 1, "just checked above");
187201
// Static dump is simple: only one archive is allowed in SharedArchiveFile. This file
188-
// will be overwritten no matter regardless of its contents
189-
_static_archive_path = os::strdup_check_oom(SharedArchiveFile, mtArguments);
202+
// will be overwritten regardless of its contents
203+
_output_archive_path = SharedArchiveFile;
190204
} else {
191205
// SharedArchiveFile may specify one or two files. In case (c), the path for base.jsa
192206
// is read from top.jsa
@@ -197,48 +211,49 @@ void CDSConfig::init_shared_archive_paths() {
197211
// However, if either RecordDynamicDumpInfo or ArchiveClassesAtExit is used, we do not
198212
// allow cases (b) and (c). Case (b) is already checked above.
199213

200-
if (archives > 2) {
214+
if (num_archives > 2) {
201215
vm_exit_during_initialization(
202216
"Cannot have more than 2 archive files specified in the -XX:SharedArchiveFile option");
203217
}
204-
if (archives == 1) {
205-
char* base_archive_path = nullptr;
218+
219+
if (num_archives == 1) {
220+
const char* base_archive_path = nullptr;
206221
bool success =
207222
FileMapInfo::get_base_archive_name_from_header(SharedArchiveFile, &base_archive_path);
208223
if (!success) {
209224
// If +AutoCreateSharedArchive and the specified shared archive does not exist,
210225
// regenerate the dynamic archive base on default archive.
211226
if (AutoCreateSharedArchive && !os::file_exists(SharedArchiveFile)) {
212-
enable_dumping_dynamic_archive();
213-
ArchiveClassesAtExit = const_cast<char *>(SharedArchiveFile);
214-
_static_archive_path = default_archive_path();
215-
SharedArchiveFile = nullptr;
216-
} else {
227+
enable_dumping_dynamic_archive(SharedArchiveFile);
228+
FLAG_SET_ERGO(ArchiveClassesAtExit, SharedArchiveFile);
229+
_input_static_archive_path = default_archive_path();
230+
FLAG_SET_ERGO(SharedArchiveFile, nullptr);
231+
} else {
217232
if (AutoCreateSharedArchive) {
218233
warning("-XX:+AutoCreateSharedArchive is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info.");
219234
AutoCreateSharedArchive = false;
220235
}
221-
log_error(cds)("Not a valid %s (%s)", new_aot_flags_used() ? "AOT cache" : "archive", SharedArchiveFile);
236+
log_error(cds)("Not a valid archive (%s)", SharedArchiveFile);
222237
Arguments::no_shared_spaces("invalid archive");
223238
}
224239
} else if (base_archive_path == nullptr) {
225240
// User has specified a single archive, which is a static archive.
226-
_static_archive_path = const_cast<char *>(SharedArchiveFile);
241+
_input_static_archive_path = SharedArchiveFile;
227242
} else {
228243
// User has specified a single archive, which is a dynamic archive.
229-
_dynamic_archive_path = const_cast<char *>(SharedArchiveFile);
230-
_static_archive_path = base_archive_path; // has been c-heap allocated.
244+
_input_dynamic_archive_path = SharedArchiveFile;
245+
_input_static_archive_path = base_archive_path; // has been c-heap allocated.
231246
}
232247
} else {
233-
extract_shared_archive_paths((const char*)SharedArchiveFile,
234-
&_static_archive_path, &_dynamic_archive_path);
235-
if (_static_archive_path == nullptr) {
236-
assert(_dynamic_archive_path == nullptr, "must be");
248+
extract_archive_paths(SharedArchiveFile,
249+
&_input_static_archive_path, &_input_dynamic_archive_path);
250+
if (_input_static_archive_path == nullptr) {
251+
assert(_input_dynamic_archive_path == nullptr, "must be");
237252
Arguments::no_shared_spaces("invalid archive");
238253
}
239254
}
240255

241-
if (_dynamic_archive_path != nullptr) {
256+
if (_input_dynamic_archive_path != nullptr) {
242257
// Check for case (c)
243258
if (RecordDynamicDumpInfo) {
244259
vm_exit_during_initialization("-XX:+RecordDynamicDumpInfo is unsupported when a dynamic CDS archive is specified in -XX:SharedArchiveFile",
@@ -353,14 +368,22 @@ bool CDSConfig::has_unsupported_runtime_module_options() {
353368
return false;
354369
}
355370

356-
#define CHECK_ALIAS(f) check_flag_alias(FLAG_IS_DEFAULT(f), #f)
371+
#define CHECK_NEW_FLAG(f) check_new_flag(FLAG_IS_DEFAULT(f), #f)
357372

358-
void CDSConfig::check_flag_alias(bool alias_is_default, const char* alias_name) {
359-
if (old_cds_flags_used() && !alias_is_default) {
373+
void CDSConfig::check_new_flag(bool new_flag_is_default, const char* new_flag_name) {
374+
if (old_cds_flags_used() && !new_flag_is_default) {
360375
vm_exit_during_initialization(err_msg("Option %s cannot be used at the same time with "
361376
"-Xshare:on, -Xshare:auto, -Xshare:off, -Xshare:dump, "
362377
"DumpLoadedClassList, SharedClassListFile, or SharedArchiveFile",
363-
alias_name));
378+
new_flag_name));
379+
}
380+
}
381+
382+
#define CHECK_SINGLE_PATH(f) check_flag_single_path(#f, f)
383+
384+
void CDSConfig::check_flag_single_path(const char* flag_name, const char* value) {
385+
if (value != nullptr && num_archive_paths(value) != 1) {
386+
vm_exit_during_initialization(err_msg("Option %s must specify a single file name", flag_name));
364387
}
365388
}
366389

@@ -371,9 +394,13 @@ void CDSConfig::check_aot_flags() {
371394
_old_cds_flags_used = true;
372395
}
373396

374-
CHECK_ALIAS(AOTCache);
375-
CHECK_ALIAS(AOTConfiguration);
376-
CHECK_ALIAS(AOTMode);
397+
// "New" AOT flags must not be mixed with "classic" flags such as -Xshare:dump
398+
CHECK_NEW_FLAG(AOTCache);
399+
CHECK_NEW_FLAG(AOTConfiguration);
400+
CHECK_NEW_FLAG(AOTMode);
401+
402+
CHECK_SINGLE_PATH(AOTCache);
403+
CHECK_SINGLE_PATH(AOTConfiguration);
377404

378405
if (FLAG_IS_DEFAULT(AOTCache) && FLAG_IS_DEFAULT(AOTConfiguration) && FLAG_IS_DEFAULT(AOTMode)) {
379406
// AOTCache/AOTConfiguration/AOTMode not used.
@@ -411,11 +438,6 @@ void CDSConfig::check_aotmode_auto_or_on() {
411438
vm_exit_during_initialization("AOTConfiguration can only be used with -XX:AOTMode=record or -XX:AOTMode=create");
412439
}
413440

414-
if (!FLAG_IS_DEFAULT(AOTCache)) {
415-
assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked");
416-
FLAG_SET_ERGO(SharedArchiveFile, AOTCache);
417-
}
418-
419441
UseSharedSpaces = true;
420442
if (FLAG_IS_DEFAULT(AOTMode) || (strcmp(AOTMode, "auto") == 0)) {
421443
RequireSharedSpaces = false;
@@ -430,10 +452,6 @@ void CDSConfig::check_aotmode_record() {
430452
vm_exit_during_initialization("AOTCache must not be specified when using -XX:AOTMode=record");
431453
}
432454

433-
assert(FLAG_IS_DEFAULT(DumpLoadedClassList), "already checked");
434-
assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked");
435-
FLAG_SET_ERGO(SharedArchiveFile, AOTConfiguration);
436-
FLAG_SET_ERGO(DumpLoadedClassList, nullptr);
437455
UseSharedSpaces = false;
438456
RequireSharedSpaces = false;
439457
_is_dumping_static_archive = true;
@@ -449,10 +467,7 @@ void CDSConfig::check_aotmode_create() {
449467
vm_exit_during_initialization("AOTCache must be specified when using -XX:AOTMode=create");
450468
}
451469

452-
assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked");
453-
454470
_is_dumping_final_static_archive = true;
455-
FLAG_SET_ERGO(SharedArchiveFile, AOTConfiguration);
456471
UseSharedSpaces = true;
457472
RequireSharedSpaces = true;
458473

@@ -463,7 +478,29 @@ void CDSConfig::check_aotmode_create() {
463478
CDSConfig::enable_dumping_static_archive();
464479
}
465480

481+
void CDSConfig::ergo_init_aot_paths() {
482+
assert(_cds_ergo_initialize_started, "sanity");
483+
if (is_dumping_static_archive()) {
484+
if (is_dumping_preimage_static_archive()) {
485+
_output_archive_path = AOTConfiguration;
486+
} else {
487+
assert(is_dumping_final_static_archive(), "must be");
488+
_input_static_archive_path = AOTConfiguration;
489+
_output_archive_path = AOTCache;
490+
}
491+
} else if (is_using_archive()) {
492+
if (FLAG_IS_DEFAULT(AOTCache)) {
493+
// Only -XX:AOTMode={auto,on} is specified
494+
_input_static_archive_path = default_archive_path();
495+
} else {
496+
_input_static_archive_path = AOTCache;
497+
}
498+
}
499+
}
500+
466501
bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_flag_cmd_line) {
502+
assert(!_cds_ergo_initialize_started, "This is called earlier than CDSConfig::ergo_initialize()");
503+
467504
check_aot_flags();
468505

469506
if (!FLAG_IS_DEFAULT(AOTMode)) {
@@ -514,7 +551,7 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla
514551
if (ArchiveClassesAtExit == nullptr && !RecordDynamicDumpInfo) {
515552
disable_dumping_dynamic_archive();
516553
} else {
517-
enable_dumping_dynamic_archive();
554+
enable_dumping_dynamic_archive(ArchiveClassesAtExit);
518555
}
519556

520557
if (AutoCreateSharedArchive) {
@@ -546,6 +583,34 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla
546583
return true;
547584
}
548585

586+
void CDSConfig::prepare_for_dumping() {
587+
assert(CDSConfig::is_dumping_archive(), "sanity");
588+
589+
if (is_dumping_dynamic_archive() && !is_using_archive()) {
590+
assert(!is_dumping_static_archive(), "cannot be dumping both static and dynamic archives");
591+
592+
// This could happen if SharedArchiveFile has failed to load:
593+
// - -Xshare:off was specified
594+
// - SharedArchiveFile points to an non-existent file.
595+
// - SharedArchiveFile points to an archive that has failed CRC check
596+
// - SharedArchiveFile is not specified and the VM doesn't have a compatible default archive
597+
598+
#define __THEMSG " is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info."
599+
if (RecordDynamicDumpInfo) {
600+
log_error(cds)("-XX:+RecordDynamicDumpInfo%s", __THEMSG);
601+
MetaspaceShared::unrecoverable_loading_error();
602+
} else {
603+
assert(ArchiveClassesAtExit != nullptr, "sanity");
604+
log_warning(cds)("-XX:ArchiveClassesAtExit" __THEMSG);
605+
}
606+
#undef __THEMSG
607+
disable_dumping_dynamic_archive();
608+
return;
609+
}
610+
611+
check_unsupported_dumping_module_options();
612+
}
613+
549614
bool CDSConfig::is_dumping_classic_static_archive() {
550615
return _is_dumping_static_archive &&
551616
!is_dumping_preimage_static_archive() &&
@@ -560,6 +625,18 @@ bool CDSConfig::is_dumping_final_static_archive() {
560625
return _is_dumping_final_static_archive;
561626
}
562627

628+
void CDSConfig::enable_dumping_dynamic_archive(const char* output_path) {
629+
_is_dumping_dynamic_archive = true;
630+
if (output_path == nullptr) {
631+
// output_path can be null when the VM is started with -XX:+RecordDynamicDumpInfo
632+
// in anticipation of "jcmd VM.cds dynamic_dump", which will provide the actual
633+
// output path.
634+
_output_archive_path = nullptr;
635+
} else {
636+
_output_archive_path = os::strdup_check_oom(output_path, mtArguments);
637+
}
638+
}
639+
563640
bool CDSConfig::allow_only_single_java_thread() {
564641
// See comments in JVM_StartThread()
565642
return is_dumping_classic_static_archive() || is_dumping_final_static_archive();

0 commit comments

Comments
 (0)