Skip to content

Commit a71f621

Browse files
committed
8353694: Resolved Class/Field/Method CP entries missing from AOT Configuration
Reviewed-by: shade, vlivanov
1 parent 07aad68 commit a71f621

File tree

5 files changed

+120
-57
lines changed

5 files changed

+120
-57
lines changed

src/hotspot/share/cds/archiveUtils.inline.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ Array<T>* ArchiveUtils::archive_ptr_array(GrowableArray<T>* tmp_array) {
7878
Array<T>* archived_array = ArchiveBuilder::new_ro_array<T>(tmp_array->length());
7979
for (int i = 0; i < tmp_array->length(); i++) {
8080
T ptr = tmp_array->at(i);
81-
if (!builder->is_in_buffer_space(ptr)) {
81+
if (ptr != nullptr && !builder->is_in_buffer_space(ptr)) {
8282
if (is_dynamic_dump && MetaspaceShared::is_in_shared_metaspace(ptr)) {
8383
// We have a pointer that lives in the dynamic archive but points into
8484
// the static archive.

src/hotspot/share/cds/finalImageRecipes.cpp

Lines changed: 104 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -36,63 +36,134 @@
3636
#include "memory/resourceArea.hpp"
3737
#include "oops/constantPool.inline.hpp"
3838
#include "runtime/handles.inline.hpp"
39+
#include "runtime/mutexLocker.hpp"
3940

4041
static FinalImageRecipes* _final_image_recipes = nullptr;
4142

4243
void* FinalImageRecipes::operator new(size_t size) throw() {
4344
return ArchiveBuilder::current()->ro_region_alloc(size);
4445
}
4546

46-
void FinalImageRecipes::record_recipes_impl() {
47-
assert(CDSConfig::is_dumping_preimage_static_archive(), "must be");
47+
void FinalImageRecipes::record_all_classes() {
48+
_all_klasses = ArchiveUtils::archive_array(ArchiveBuilder::current()->klasses());
49+
ArchivePtrMarker::mark_pointer(&_all_klasses);
50+
}
51+
52+
void FinalImageRecipes::record_recipes_for_constantpool() {
4853
ResourceMark rm;
49-
GrowableArray<Klass*>* klasses = ArchiveBuilder::current()->klasses();
5054

51-
// Record the indys that have been resolved in the training run. These indys will be
52-
// resolved during the final image assembly.
55+
// The recipes are recorded regardless of CDSConfig::is_dumping_{invokedynamic,dynamic_proxies,reflection_data}().
56+
// If some of these options are not enabled, the corresponding recipes will be
57+
// ignored during the final image assembly.
58+
59+
GrowableArray<Array<int>*> tmp_cp_recipes;
60+
GrowableArray<int> tmp_cp_flags;
5361

54-
GrowableArray<InstanceKlass*> tmp_indy_klasses;
55-
GrowableArray<Array<int>*> tmp_indy_cp_indices;
56-
int total_indys_to_resolve = 0;
62+
GrowableArray<Klass*>* klasses = ArchiveBuilder::current()->klasses();
5763
for (int i = 0; i < klasses->length(); i++) {
64+
GrowableArray<int> cp_indices;
65+
int flags = 0;
66+
5867
Klass* k = klasses->at(i);
5968
if (k->is_instance_klass()) {
6069
InstanceKlass* ik = InstanceKlass::cast(k);
61-
GrowableArray<int> indices;
70+
ConstantPool* cp = ik->constants();
71+
ConstantPoolCache* cp_cache = cp->cache();
72+
73+
for (int cp_index = 1; cp_index < cp->length(); cp_index++) { // Index 0 is unused
74+
if (cp->tag_at(cp_index).value() == JVM_CONSTANT_Class) {
75+
Klass* k = cp->resolved_klass_at(cp_index);
76+
if (k->is_instance_klass()) {
77+
cp_indices.append(cp_index);
78+
flags |= HAS_CLASS;
79+
}
80+
}
81+
}
82+
83+
if (cp_cache != nullptr) {
84+
Array<ResolvedFieldEntry>* field_entries = cp_cache->resolved_field_entries();
85+
if (field_entries != nullptr) {
86+
for (int i = 0; i < field_entries->length(); i++) {
87+
ResolvedFieldEntry* rfe = field_entries->adr_at(i);
88+
if (rfe->is_resolved(Bytecodes::_getfield) ||
89+
rfe->is_resolved(Bytecodes::_putfield)) {
90+
cp_indices.append(rfe->constant_pool_index());
91+
flags |= HAS_FIELD_AND_METHOD;
92+
}
93+
}
94+
}
6295

63-
if (ik->constants()->cache() != nullptr) {
64-
Array<ResolvedIndyEntry>* tmp_indy_entries = ik->constants()->cache()->resolved_indy_entries();
65-
if (tmp_indy_entries != nullptr) {
66-
for (int i = 0; i < tmp_indy_entries->length(); i++) {
67-
ResolvedIndyEntry* rie = tmp_indy_entries->adr_at(i);
96+
Array<ResolvedMethodEntry>* method_entries = cp_cache->resolved_method_entries();
97+
if (method_entries != nullptr) {
98+
for (int i = 0; i < method_entries->length(); i++) {
99+
ResolvedMethodEntry* rme = method_entries->adr_at(i);
100+
if (rme->is_resolved(Bytecodes::_invokevirtual) ||
101+
rme->is_resolved(Bytecodes::_invokespecial) ||
102+
rme->is_resolved(Bytecodes::_invokeinterface) ||
103+
rme->is_resolved(Bytecodes::_invokestatic) ||
104+
rme->is_resolved(Bytecodes::_invokehandle)) {
105+
cp_indices.append(rme->constant_pool_index());
106+
flags |= HAS_FIELD_AND_METHOD;
107+
}
108+
}
109+
}
110+
111+
Array<ResolvedIndyEntry>* indy_entries = cp_cache->resolved_indy_entries();
112+
if (indy_entries != nullptr) {
113+
for (int i = 0; i < indy_entries->length(); i++) {
114+
ResolvedIndyEntry* rie = indy_entries->adr_at(i);
68115
int cp_index = rie->constant_pool_index();
69116
if (rie->is_resolved()) {
70-
indices.append(cp_index);
117+
cp_indices.append(cp_index);
118+
flags |= HAS_INDY;
71119
}
72120
}
73121
}
74122
}
123+
}
75124

76-
if (indices.length() > 0) {
77-
tmp_indy_klasses.append(ArchiveBuilder::current()->get_buffered_addr(ik));
78-
tmp_indy_cp_indices.append(ArchiveUtils::archive_array(&indices));
79-
total_indys_to_resolve += indices.length();
80-
}
125+
if (cp_indices.length() > 0) {
126+
tmp_cp_recipes.append(ArchiveUtils::archive_array(&cp_indices));
127+
} else {
128+
tmp_cp_recipes.append(nullptr);
81129
}
130+
tmp_cp_flags.append(flags);
82131
}
83132

84-
_all_klasses = ArchiveUtils::archive_array(klasses);
85-
ArchivePtrMarker::mark_pointer(&_all_klasses);
133+
_cp_recipes = ArchiveUtils::archive_array(&tmp_cp_recipes);
134+
ArchivePtrMarker::mark_pointer(&_cp_recipes);
135+
136+
_cp_flags = ArchiveUtils::archive_array(&tmp_cp_flags);
137+
ArchivePtrMarker::mark_pointer(&_cp_flags);
138+
}
86139

87-
assert(tmp_indy_klasses.length() == tmp_indy_cp_indices.length(), "must be");
88-
if (tmp_indy_klasses.length() > 0) {
89-
_indy_klasses = ArchiveUtils::archive_array(&tmp_indy_klasses);
90-
_indy_cp_indices = ArchiveUtils::archive_array(&tmp_indy_cp_indices);
140+
void FinalImageRecipes::apply_recipes_for_constantpool(JavaThread* current) {
141+
assert(CDSConfig::is_dumping_final_static_archive(), "must be");
91142

92-
ArchivePtrMarker::mark_pointer(&_indy_klasses);
93-
ArchivePtrMarker::mark_pointer(&_indy_cp_indices);
143+
for (int i = 0; i < _all_klasses->length(); i++) {
144+
Array<int>* cp_indices = _cp_recipes->at(i);
145+
int flags = _cp_flags->at(i);
146+
if (cp_indices != nullptr) {
147+
InstanceKlass* ik = InstanceKlass::cast(_all_klasses->at(i));
148+
if (ik->is_loaded()) {
149+
ResourceMark rm(current);
150+
ConstantPool* cp = ik->constants();
151+
GrowableArray<bool> preresolve_list(cp->length(), cp->length(), false);
152+
for (int j = 0; j < cp_indices->length(); j++) {
153+
preresolve_list.at_put(cp_indices->at(j), true);
154+
}
155+
if ((flags & HAS_CLASS) != 0) {
156+
AOTConstantPoolResolver::preresolve_class_cp_entries(current, ik, &preresolve_list);
157+
}
158+
if ((flags & HAS_FIELD_AND_METHOD) != 0) {
159+
AOTConstantPoolResolver::preresolve_field_and_method_cp_entries(current, ik, &preresolve_list);
160+
}
161+
if ((flags & HAS_INDY) != 0) {
162+
AOTConstantPoolResolver::preresolve_indy_cp_entries(current, ik, &preresolve_list);
163+
}
164+
}
165+
}
94166
}
95-
log_info(cds)("%d indies in %d classes will be resolved in final CDS image", total_indys_to_resolve, tmp_indy_klasses.length());
96167
}
97168

98169
void FinalImageRecipes::load_all_classes(TRAPS) {
@@ -122,27 +193,11 @@ void FinalImageRecipes::load_all_classes(TRAPS) {
122193
}
123194
}
124195

125-
void FinalImageRecipes::apply_recipes_for_invokedynamic(TRAPS) {
126-
assert(CDSConfig::is_dumping_final_static_archive(), "must be");
127-
128-
if (CDSConfig::is_dumping_invokedynamic() && _indy_klasses != nullptr) {
129-
assert(_indy_cp_indices != nullptr, "must be");
130-
for (int i = 0; i < _indy_klasses->length(); i++) {
131-
InstanceKlass* ik = _indy_klasses->at(i);
132-
ConstantPool* cp = ik->constants();
133-
Array<int>* cp_indices = _indy_cp_indices->at(i);
134-
GrowableArray<bool> preresolve_list(cp->length(), cp->length(), false);
135-
for (int j = 0; j < cp_indices->length(); j++) {
136-
preresolve_list.at_put(cp_indices->at(j), true);
137-
}
138-
AOTConstantPoolResolver::preresolve_indy_cp_entries(THREAD, ik, &preresolve_list);
139-
}
140-
}
141-
}
142-
143196
void FinalImageRecipes::record_recipes() {
197+
assert(CDSConfig::is_dumping_preimage_static_archive(), "must be");
144198
_final_image_recipes = new FinalImageRecipes();
145-
_final_image_recipes->record_recipes_impl();
199+
_final_image_recipes->record_all_classes();
200+
_final_image_recipes->record_recipes_for_constantpool();
146201
}
147202

148203
void FinalImageRecipes::apply_recipes(TRAPS) {
@@ -163,7 +218,7 @@ void FinalImageRecipes::apply_recipes(TRAPS) {
163218

164219
void FinalImageRecipes::apply_recipes_impl(TRAPS) {
165220
load_all_classes(CHECK);
166-
apply_recipes_for_invokedynamic(CHECK);
221+
apply_recipes_for_constantpool(THREAD);
167222
}
168223

169224
void FinalImageRecipes::serialize(SerializeClosure* soc) {

src/hotspot/share/cds/finalImageRecipes.hpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,26 +42,31 @@ template <typename T> class Array;
4242
// - The list of all classes that are stored in the AOTConfiguration file.
4343
// - The list of all classes that require AOT resolution of invokedynamic call sites.
4444
class FinalImageRecipes {
45+
static constexpr int HAS_CLASS = 0x1;
46+
static constexpr int HAS_FIELD_AND_METHOD = 0x2;
47+
static constexpr int HAS_INDY = 0x4;
48+
4549
// A list of all the archived classes from the preimage. We want to transfer all of these
4650
// into the final image.
4751
Array<Klass*>* _all_klasses;
4852

49-
// The classes who have resolved at least one indy CP entry during the training run.
50-
// _indy_cp_indices[i] is a list of all resolved CP entries for _indy_klasses[i].
51-
Array<InstanceKlass*>* _indy_klasses;
52-
Array<Array<int>*>* _indy_cp_indices;
53+
// For each klass k _all_klasses->at(i), _cp_recipes->at(i) lists all the {klass,field,method,indy}
54+
// cp indices that were resolved for k during the training run.
55+
Array<Array<int>*>* _cp_recipes;
56+
Array<int>* _cp_flags;
5357

54-
FinalImageRecipes() : _indy_klasses(nullptr), _indy_cp_indices(nullptr) {}
58+
FinalImageRecipes() : _all_klasses(nullptr), _cp_recipes(nullptr), _cp_flags(nullptr) {}
5559

5660
void* operator new(size_t size) throw();
5761

5862
// Called when dumping preimage
59-
void record_recipes_impl();
63+
void record_all_classes();
64+
void record_recipes_for_constantpool();
6065

6166
// Called when dumping final image
6267
void apply_recipes_impl(TRAPS);
6368
void load_all_classes(TRAPS);
64-
void apply_recipes_for_invokedynamic(TRAPS);
69+
void apply_recipes_for_constantpool(JavaThread* current);
6570

6671
public:
6772
static void serialize(SerializeClosure* soc);

src/hotspot/share/runtime/mutexLocker.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ Mutex* ClassListFile_lock = nullptr;
147147
Mutex* UnregisteredClassesTable_lock= nullptr;
148148
Mutex* LambdaFormInvokers_lock = nullptr;
149149
Mutex* ScratchObjects_lock = nullptr;
150+
Mutex* FinalImageRecipes_lock = nullptr;
150151
#endif // INCLUDE_CDS
151152
Mutex* Bootclasspath_lock = nullptr;
152153

@@ -299,6 +300,7 @@ void mutex_init() {
299300
MUTEX_DEFN(UnregisteredClassesTable_lock , PaddedMutex , nosafepoint-1);
300301
MUTEX_DEFN(LambdaFormInvokers_lock , PaddedMutex , safepoint);
301302
MUTEX_DEFN(ScratchObjects_lock , PaddedMutex , nosafepoint-1); // Holds DumpTimeTable_lock
303+
MUTEX_DEFN(FinalImageRecipes_lock , PaddedMutex , nosafepoint);
302304
#endif // INCLUDE_CDS
303305
MUTEX_DEFN(Bootclasspath_lock , PaddedMutex , nosafepoint);
304306

src/hotspot/share/runtime/mutexLocker.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ extern Mutex* ClassListFile_lock; // ClassListWriter()
129129
extern Mutex* UnregisteredClassesTable_lock; // UnregisteredClassesTableTable
130130
extern Mutex* LambdaFormInvokers_lock; // Protecting LambdaFormInvokers::_lambdaform_lines
131131
extern Mutex* ScratchObjects_lock; // Protecting _scratch_xxx_table in heapShared.cpp
132+
extern Mutex* FinalImageRecipes_lock; // Protecting the tables used by FinalImageRecipes.
132133
#endif // INCLUDE_CDS
133134
#if INCLUDE_JFR
134135
extern Mutex* JfrStacktrace_lock; // used to guard access to the JFR stacktrace table

0 commit comments

Comments
 (0)