Skip to content

Commit 85715e1

Browse files
committed
8317269: Store old classes in linked state in AOT cache
Reviewed-by: coleenp, matsaave
1 parent fdc11a1 commit 85715e1

35 files changed

+1482
-87
lines changed

src/hotspot/share/cds/aotMetaspace.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,8 @@ char* VM_PopulateDumpSharedSpace::dump_read_only_tables(AOTClassLocationConfig*&
652652
}
653653

654654
void VM_PopulateDumpSharedSpace::doit() {
655+
CDSConfig::set_is_at_aot_safepoint(true);
656+
655657
if (!CDSConfig::is_dumping_final_static_archive()) {
656658
guarantee(!CDSConfig::is_using_archive(), "We should not be using an archive when we dump");
657659
}
@@ -717,6 +719,8 @@ void VM_PopulateDumpSharedSpace::doit() {
717719
_map_info->set_serialized_data(serialized_data);
718720
_map_info->set_cloned_vtables(CppVtables::vtables_serialized_base());
719721
_map_info->header()->set_class_location_config(cl_config);
722+
723+
CDSConfig::set_is_at_aot_safepoint(false);
720724
}
721725

722726
class CollectClassesForLinking : public KlassClosure {
@@ -773,20 +777,17 @@ bool AOTMetaspace::may_be_eagerly_linked(InstanceKlass* ik) {
773777
return true;
774778
}
775779

776-
void AOTMetaspace::link_shared_classes(TRAPS) {
777-
AOTClassLinker::initialize();
778-
AOTClassInitializer::init_test_class(CHECK);
779-
780+
void AOTMetaspace::link_all_loaded_classes(JavaThread* current) {
780781
while (true) {
781-
ResourceMark rm(THREAD);
782+
ResourceMark rm(current);
782783
CollectClassesForLinking collect_classes;
783784
bool has_linked = false;
784785
const GrowableArray<OopHandle>* mirrors = collect_classes.mirrors();
785786
for (int i = 0; i < mirrors->length(); i++) {
786787
OopHandle mirror = mirrors->at(i);
787788
InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(mirror.resolve()));
788789
if (may_be_eagerly_linked(ik)) {
789-
has_linked |= try_link_class(THREAD, ik);
790+
has_linked |= try_link_class(current, ik);
790791
}
791792
}
792793

@@ -796,6 +797,13 @@ void AOTMetaspace::link_shared_classes(TRAPS) {
796797
// Class linking includes verification which may load more classes.
797798
// Keep scanning until we have linked no more classes.
798799
}
800+
}
801+
802+
void AOTMetaspace::link_shared_classes(TRAPS) {
803+
AOTClassLinker::initialize();
804+
AOTClassInitializer::init_test_class(CHECK);
805+
806+
link_all_loaded_classes(THREAD);
799807

800808
// Eargerly resolve all string constants in constant pools
801809
{

src/hotspot/share/cds/aotMetaspace.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ class AOTMetaspace : AllStatic {
135135
}
136136

137137
static bool try_link_class(JavaThread* current, InstanceKlass* ik);
138+
static void link_all_loaded_classes(JavaThread* current);
138139
static void link_shared_classes(TRAPS) NOT_CDS_RETURN;
139140
static bool may_be_eagerly_linked(InstanceKlass* ik) NOT_CDS_RETURN_(false);
140141

src/hotspot/share/cds/archiveBuilder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -937,7 +937,7 @@ void ArchiveBuilder::make_klasses_shareable() {
937937
ADD_COUNT(num_enum_klasses);
938938
}
939939

940-
if (!ik->can_be_verified_at_dumptime()) {
940+
if (CDSConfig::is_old_class_for_verifier(ik)) {
941941
ADD_COUNT(num_old_klasses);
942942
old = " old";
943943
}

src/hotspot/share/cds/cdsConfig.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ bool CDSConfig::_has_temp_aot_config_file = false;
5656
bool CDSConfig::_old_cds_flags_used = false;
5757
bool CDSConfig::_new_aot_flags_used = false;
5858
bool CDSConfig::_disable_heap_dumping = false;
59+
bool CDSConfig::_is_at_aot_safepoint = false;
5960

6061
const char* CDSConfig::_default_archive_path = nullptr;
6162
const char* CDSConfig::_input_static_archive_path = nullptr;
@@ -922,6 +923,35 @@ bool CDSConfig::is_dumping_lambdas_in_legacy_mode() {
922923
return !is_dumping_method_handles();
923924
}
924925

926+
bool CDSConfig::is_preserving_verification_constraints() {
927+
// Verification dependencies are classes used in assignability checks by the
928+
// bytecode verifier. In the following example, the verification dependencies
929+
// for X are A and B.
930+
//
931+
// class X {
932+
// A getA() { return new B(); }
933+
// }
934+
//
935+
// With the AOT cache, we can ensure that all the verification dependencies
936+
// (A and B in the above example) are unconditionally loaded during the bootstrap
937+
// of the production run. This means that if a class was successfully verified
938+
// in the assembly phase, all of the verifier's assignability checks will remain
939+
// valid in the production run, so we don't need to verify aot-linked classes again.
940+
941+
if (is_dumping_preimage_static_archive()) { // writing AOT config
942+
return AOTClassLinking;
943+
} else if (is_dumping_final_static_archive()) { // writing AOT cache
944+
return is_dumping_aot_linked_classes();
945+
} else {
946+
// For simplicity, we don't support this optimization with the old CDS workflow.
947+
return false;
948+
}
949+
}
950+
951+
bool CDSConfig::is_old_class_for_verifier(const InstanceKlass* ik) {
952+
return ik->major_version() < 50 /*JAVA_6_VERSION*/;
953+
}
954+
925955
#if INCLUDE_CDS_JAVA_HEAP
926956
bool CDSConfig::are_vm_options_incompatible_with_dumping_heap() {
927957
return check_options_incompatible_with_dumping_heap() != nullptr;

src/hotspot/share/cds/cdsConfig.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "utilities/macros.hpp"
3131

3232
class JavaThread;
33+
class InstanceKlass;
3334

3435
class CDSConfig : public AllStatic {
3536
#if INCLUDE_CDS
@@ -43,6 +44,7 @@ class CDSConfig : public AllStatic {
4344
static bool _has_aot_linked_classes;
4445
static bool _is_single_command_training;
4546
static bool _has_temp_aot_config_file;
47+
static bool _is_at_aot_safepoint;
4648

4749
const static char* _default_archive_path;
4850
const static char* _input_static_archive_path;
@@ -99,6 +101,9 @@ class CDSConfig : public AllStatic {
99101
static const char* type_of_archive_being_written();
100102
static void prepare_for_dumping();
101103

104+
static bool is_at_aot_safepoint() { return CDS_ONLY(_is_at_aot_safepoint) NOT_CDS(false); }
105+
static void set_is_at_aot_safepoint(bool value) { CDS_ONLY(_is_at_aot_safepoint = value); }
106+
102107
// --- Basic CDS features
103108

104109
// archive(s) in general
@@ -161,6 +166,10 @@ class CDSConfig : public AllStatic {
161166
static bool is_using_aot_linked_classes() NOT_CDS_JAVA_HEAP_RETURN_(false);
162167
static void set_has_aot_linked_classes(bool has_aot_linked_classes) NOT_CDS_JAVA_HEAP_RETURN;
163168

169+
// Bytecode verification
170+
static bool is_preserving_verification_constraints();
171+
static bool is_old_class_for_verifier(const InstanceKlass* ik);
172+
164173
// archive_path
165174

166175
// Points to the classes.jsa in $JAVA_HOME (could be input or output)

src/hotspot/share/cds/dumpTimeClassInfo.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ size_t DumpTimeClassInfo::runtime_info_bytesize() const {
4747
num_enum_klass_static_fields());
4848
}
4949

50-
void DumpTimeClassInfo::add_verification_constraint(InstanceKlass* k, Symbol* name,
50+
void DumpTimeClassInfo::add_verification_constraint(Symbol* name,
5151
Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object) {
5252
if (_verifier_constraints == nullptr) {
5353
_verifier_constraints = new (mtClass) GrowableArray<DTVerifierConstraint>(4, mtClass);
@@ -73,9 +73,14 @@ void DumpTimeClassInfo::add_verification_constraint(InstanceKlass* k, Symbol* na
7373

7474
if (log_is_enabled(Trace, aot, verification)) {
7575
ResourceMark rm;
76-
log_trace(aot, verification)("add_verification_constraint: %s: %s must be subclass of %s [0x%x] array len %d flags len %d",
77-
k->external_name(), from_name->as_klass_external_name(),
78-
name->as_klass_external_name(), c, vc_array->length(), vcflags_array->length());
76+
if (from_name != nullptr) {
77+
log_trace(aot, verification)("add verification constraint: %s: %s must be subclass of %s [0x%x]",
78+
_klass->external_name(), from_name->as_klass_external_name(),
79+
name->as_klass_external_name(), c);
80+
} else {
81+
log_trace(aot, verification)("added old verification constraint: %s: %s", _klass->external_name(),
82+
name->as_klass_external_name());
83+
}
7984
}
8085
}
8186

src/hotspot/share/cds/dumpTimeClassInfo.hpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class DumpTimeClassInfo: public CHeapObj<mtClass> {
8888
Symbol* _from_name;
8989
public:
9090
DTVerifierConstraint() : _name(nullptr), _from_name(nullptr) {}
91-
DTVerifierConstraint(Symbol* n, Symbol* fn) : _name(n), _from_name(fn) {
91+
DTVerifierConstraint(Symbol* n, Symbol* fn = nullptr) : _name(n), _from_name(fn) {
9292
Symbol::maybe_increment_refcount(_name);
9393
Symbol::maybe_increment_refcount(_from_name);
9494
}
@@ -152,8 +152,9 @@ class DumpTimeClassInfo: public CHeapObj<mtClass> {
152152
DumpTimeClassInfo& operator=(const DumpTimeClassInfo&) = delete;
153153
~DumpTimeClassInfo();
154154

155-
void add_verification_constraint(InstanceKlass* k, Symbol* name,
156-
Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object);
155+
// For old verifier: only name is saved; all other fields are null/false.
156+
void add_verification_constraint(Symbol* name,
157+
Symbol* from_name = nullptr, bool from_field_is_protected = false, bool from_is_array = false, bool from_is_object = false);
157158
void record_linking_constraint(Symbol* name, Handle loader1, Handle loader2);
158159
void add_enum_klass_static_field(int archived_heap_root_index);
159160
int enum_klass_static_field(int which_field);
@@ -175,6 +176,14 @@ class DumpTimeClassInfo: public CHeapObj<mtClass> {
175176
return array_length_or_zero(_verifier_constraint_flags);
176177
}
177178

179+
Symbol* verifier_constraint_name_at(int i) const {
180+
return _verifier_constraints->at(i).name();
181+
}
182+
183+
Symbol* verifier_constraint_from_name_at(int i) const {
184+
return _verifier_constraints->at(i).from_name();
185+
}
186+
178187
int num_loader_constraints() const {
179188
return array_length_or_zero(_loader_constraints);
180189
}

src/hotspot/share/cds/dynamicArchive.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ class DynamicArchiveBuilder : public ArchiveBuilder {
110110
}
111111

112112
void doit() {
113+
CDSConfig::set_is_at_aot_safepoint(true);
114+
doit_inner();
115+
CDSConfig::set_is_at_aot_safepoint(false);
116+
}
117+
118+
void doit_inner() {
113119
verify_universe("Before CDS dynamic dump");
114120
DEBUG_ONLY(SystemDictionaryShared::NoClassLoadingMark nclm);
115121

src/hotspot/share/cds/lambdaProxyClassDictionary.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -471,12 +471,12 @@ class LambdaProxyClassDictionary::CleanupDumpTimeLambdaProxyClassTable: StackObj
471471

472472
// If the caller class and/or nest_host are excluded, the associated lambda proxy
473473
// must also be excluded.
474-
bool always_exclude = SystemDictionaryShared::check_for_exclusion(caller_ik, nullptr) ||
475-
SystemDictionaryShared::check_for_exclusion(nest_host, nullptr);
474+
bool always_exclude = SystemDictionaryShared::should_be_excluded(caller_ik) ||
475+
SystemDictionaryShared::should_be_excluded(nest_host);
476476

477477
for (int i = info._proxy_klasses->length() - 1; i >= 0; i--) {
478478
InstanceKlass* ik = info._proxy_klasses->at(i);
479-
if (always_exclude || SystemDictionaryShared::check_for_exclusion(ik, nullptr)) {
479+
if (always_exclude || SystemDictionaryShared::should_be_excluded(ik)) {
480480
LambdaProxyClassDictionary::reset_registered_lambda_proxy_class(ik);
481481
info._proxy_klasses->remove_at(i);
482482
}

src/hotspot/share/cds/runTimeClassInfo.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,18 @@ void RunTimeClassInfo::init(DumpTimeClassInfo& info) {
4040
_num_verifier_constraints = info.num_verifier_constraints();
4141
_num_loader_constraints = info.num_loader_constraints();
4242
int i;
43+
44+
if (CDSConfig::is_preserving_verification_constraints() && CDSConfig::is_dumping_final_static_archive()) {
45+
// The production run doesn't need the verifier constraints, as we can guarantee that all classes checked by
46+
// the verifier during AOT training/assembly phases cannot be replaced in the production run.
47+
_num_verifier_constraints = 0;
48+
}
4349
if (_num_verifier_constraints > 0) {
4450
RTVerifierConstraint* vf_constraints = verifier_constraints();
4551
char* flags = verifier_constraint_flags();
4652
for (i = 0; i < _num_verifier_constraints; i++) {
47-
vf_constraints[i]._name = builder->any_to_offset_u4(info._verifier_constraints->at(i).name());
48-
vf_constraints[i]._from_name = builder->any_to_offset_u4(info._verifier_constraints->at(i).from_name());
53+
vf_constraints[i]._name = builder->any_to_offset_u4(info._verifier_constraints->at(i).name());
54+
vf_constraints[i]._from_name = builder->any_or_null_to_offset_u4(info._verifier_constraints->at(i).from_name());
4955
}
5056
for (i = 0; i < _num_verifier_constraints; i++) {
5157
flags[i] = info._verifier_constraint_flags->at(i);

0 commit comments

Comments
 (0)