Skip to content

Commit 4379e2d

Browse files
committed
8356125: Interned strings are omitted from AOT cache
Reviewed-by: shade, ccheung
1 parent b7b437d commit 4379e2d

File tree

12 files changed

+240
-120
lines changed

12 files changed

+240
-120
lines changed

src/hotspot/share/cds/aotClassLinker.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,6 @@ void AOTClassLinker::initialize() {
6464
}
6565

6666
assert(is_initialized(), "sanity");
67-
68-
AOTConstantPoolResolver::initialize();
6967
}
7068

7169
void AOTClassLinker::dispose() {
@@ -79,8 +77,6 @@ void AOTClassLinker::dispose() {
7977
_sorted_candidates = nullptr;
8078

8179
assert(!is_initialized(), "sanity");
82-
83-
AOTConstantPoolResolver::dispose();
8480
}
8581

8682
bool AOTClassLinker::is_vm_class(InstanceKlass* ik) {

src/hotspot/share/cds/aotConstantPoolResolver.cpp

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,6 @@
3737
#include "oops/klass.inline.hpp"
3838
#include "runtime/handles.inline.hpp"
3939

40-
AOTConstantPoolResolver::ClassesTable* AOTConstantPoolResolver::_processed_classes = nullptr;
41-
42-
void AOTConstantPoolResolver::initialize() {
43-
assert(_processed_classes == nullptr, "must be");
44-
_processed_classes = new (mtClass)ClassesTable();
45-
}
46-
47-
void AOTConstantPoolResolver::dispose() {
48-
assert(_processed_classes != nullptr, "must be");
49-
delete _processed_classes;
50-
_processed_classes = nullptr;
51-
}
52-
5340
// Returns true if we CAN PROVE that cp_index will always resolve to
5441
// the same information at both dump time and run time. This is a
5542
// necessary (but not sufficient) condition for pre-resolving cp_index
@@ -144,17 +131,11 @@ bool AOTConstantPoolResolver::is_class_resolution_deterministic(InstanceKlass* c
144131
}
145132
}
146133

147-
void AOTConstantPoolResolver::dumptime_resolve_constants(InstanceKlass* ik, TRAPS) {
134+
void AOTConstantPoolResolver::preresolve_string_cp_entries(InstanceKlass* ik, TRAPS) {
148135
if (!ik->is_linked()) {
136+
// The cp->resolved_referenced() array is not ready yet, so we can't call resolve_string().
149137
return;
150138
}
151-
bool first_time;
152-
_processed_classes->put_if_absent(ik, &first_time);
153-
if (!first_time) {
154-
// We have already resolved the constants in class, so no need to do it again.
155-
return;
156-
}
157-
158139
constantPoolHandle cp(THREAD, ik->constants());
159140
for (int cp_index = 1; cp_index < cp->length(); cp_index++) { // Index 0 is unused
160141
switch (cp->tag_at(cp_index).value()) {

src/hotspot/share/cds/aotConstantPoolResolver.hpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -80,17 +80,10 @@ class AOTConstantPoolResolver : AllStatic {
8080
static bool check_lambda_metafactory_methodhandle_arg(ConstantPool* cp, int bsms_attribute_index, int arg_i);
8181

8282
public:
83-
static void initialize();
84-
static void dispose();
85-
8683
static void preresolve_class_cp_entries(JavaThread* current, InstanceKlass* ik, GrowableArray<bool>* preresolve_list);
8784
static void preresolve_field_and_method_cp_entries(JavaThread* current, InstanceKlass* ik, GrowableArray<bool>* preresolve_list);
8885
static void preresolve_indy_cp_entries(JavaThread* current, InstanceKlass* ik, GrowableArray<bool>* preresolve_list);
89-
90-
91-
// Resolve all constant pool entries that are safe to be stored in the
92-
// CDS archive.
93-
static void dumptime_resolve_constants(InstanceKlass* ik, TRAPS);
86+
static void preresolve_string_cp_entries(InstanceKlass* ik, TRAPS);
9487

9588
static bool is_resolution_deterministic(ConstantPool* cp, int cp_index);
9689
};

src/hotspot/share/cds/heapShared.cpp

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -606,11 +606,8 @@ static objArrayOop get_archived_resolved_references(InstanceKlass* src_ik) {
606606
}
607607

608608
void HeapShared::archive_strings() {
609-
oop shared_strings_array = StringTable::init_shared_strings_array(_dumped_interned_strings);
609+
oop shared_strings_array = StringTable::init_shared_strings_array();
610610
bool success = archive_reachable_objects_from(1, _dump_time_special_subgraph, shared_strings_array);
611-
// We must succeed because:
612-
// - _dumped_interned_strings do not contain any large strings.
613-
// - StringTable::init_shared_table() doesn't create any large arrays.
614611
assert(success, "shared strings array must not point to arrays or strings that are too large to archive");
615612
StringTable::set_shared_strings_array_index(append_root(shared_strings_array));
616613
}
@@ -683,7 +680,7 @@ void HeapShared::write_heap(ArchiveHeapInfo *heap_info) {
683680
check_special_subgraph_classes();
684681
}
685682

686-
StringTable::write_shared_table(_dumped_interned_strings);
683+
StringTable::write_shared_table();
687684
ArchiveHeapWriter::write(_pending_roots, heap_info);
688685

689686
ArchiveBuilder::OtherROAllocMark mark;
@@ -710,8 +707,6 @@ void HeapShared::scan_java_class(Klass* orig_k) {
710707
bool success = HeapShared::archive_reachable_objects_from(1, _dump_time_special_subgraph, rr);
711708
assert(success, "must be");
712709
}
713-
714-
orig_ik->constants()->add_dumped_interned_strings();
715710
}
716711
}
717712

@@ -2067,11 +2062,8 @@ void HeapShared::archive_object_subgraphs(ArchivableStaticFieldInfo fields[],
20672062
#endif
20682063
}
20692064

2070-
// Not all the strings in the global StringTable are dumped into the archive, because
2071-
// some of those strings may be only referenced by classes that are excluded from
2072-
// the archive. We need to explicitly mark the strings that are:
2073-
// [1] used by classes that WILL be archived;
2074-
// [2] included in the SharedArchiveConfigFile.
2065+
// Keep track of the contents of the archived interned string table. This table
2066+
// is used only by CDSHeapVerifier.
20752067
void HeapShared::add_to_dumped_interned_strings(oop string) {
20762068
assert_at_safepoint(); // DumpedInternedStrings uses raw oops
20772069
assert(!ArchiveHeapWriter::is_string_too_large_to_archive(string), "must be");

src/hotspot/share/cds/metaspaceShared.cpp

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -646,15 +646,6 @@ void VM_PopulateDumpSharedSpace::doit() {
646646
// Block concurrent class unloading from changing the _dumptime_table
647647
MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
648648

649-
#if INCLUDE_CDS_JAVA_HEAP
650-
if (CDSConfig::is_dumping_heap() && _extra_interned_strings != nullptr) {
651-
for (int i = 0; i < _extra_interned_strings->length(); i ++) {
652-
OopHandle string = _extra_interned_strings->at(i);
653-
HeapShared::add_to_dumped_interned_strings(string.resolve());
654-
}
655-
}
656-
#endif
657-
658649
_builder.gather_source_objs();
659650
_builder.reserve_buffer();
660651

@@ -777,15 +768,15 @@ void MetaspaceShared::link_shared_classes(TRAPS) {
777768
// Keep scanning until we have linked no more classes.
778769
}
779770

780-
// Resolve constant pool entries -- we don't load any new classes during this stage
771+
// Eargerly resolve all string constants in constant pools
781772
{
782773
ResourceMark rm(THREAD);
783774
CollectClassesForLinking collect_classes;
784775
const GrowableArray<OopHandle>* mirrors = collect_classes.mirrors();
785776
for (int i = 0; i < mirrors->length(); i++) {
786777
OopHandle mirror = mirrors->at(i);
787778
InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(mirror.resolve()));
788-
AOTConstantPoolResolver::dumptime_resolve_constants(ik, CHECK);
779+
AOTConstantPoolResolver::preresolve_string_cp_entries(ik, CHECK);
789780
}
790781
}
791782

src/hotspot/share/classfile/stringTable.cpp

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,8 @@ void StringTable::allocate_shared_strings_array(TRAPS) {
946946
if (!CDSConfig::is_dumping_heap()) {
947947
return;
948948
}
949+
assert(CDSConfig::allow_only_single_java_thread(), "No more interned strings can be added");
950+
949951
if (_items_count > (size_t)max_jint) {
950952
fatal("Too many strings to be archived: %zu", _items_count);
951953
}
@@ -1026,48 +1028,61 @@ void StringTable::verify_secondary_array_index_bits() {
10261028
// For each shared string:
10271029
// [1] Store it into _shared_strings_array. Encode its position as a 32-bit index.
10281030
// [2] Store the index and hashcode into _shared_table.
1029-
oop StringTable::init_shared_strings_array(const DumpedInternedStrings* dumped_interned_strings) {
1031+
oop StringTable::init_shared_strings_array() {
10301032
assert(CDSConfig::is_dumping_heap(), "must be");
10311033
objArrayOop array = (objArrayOop)(_shared_strings_array.resolve());
10321034

10331035
verify_secondary_array_index_bits();
10341036

10351037
int index = 0;
1036-
auto copy_into_array = [&] (oop string, bool value_ignored) {
1037-
if (!_is_two_dimensional_shared_strings_array) {
1038-
assert(index < array->length(), "no strings should have been added");
1039-
array->obj_at_put(index, string);
1040-
} else {
1041-
int primary_index = index >> _secondary_array_index_bits;
1042-
int secondary_index = index & _secondary_array_index_mask;
1038+
auto copy_into_array = [&] (WeakHandle* val) {
1039+
oop string = val->peek();
1040+
if (string != nullptr && !ArchiveHeapWriter::is_string_too_large_to_archive(string)) {
1041+
// If string is too large, don't put it into the string table.
1042+
// - If there are no other refernences to it, it won't be stored into the archive,
1043+
// so we are all good.
1044+
// - If there's a referece to it, we will report an error inside HeapShared.cpp and
1045+
// dumping will fail.
1046+
HeapShared::add_to_dumped_interned_strings(string);
1047+
if (!_is_two_dimensional_shared_strings_array) {
1048+
assert(index < array->length(), "no strings should have been added");
1049+
array->obj_at_put(index, string);
1050+
} else {
1051+
int primary_index = index >> _secondary_array_index_bits;
1052+
int secondary_index = index & _secondary_array_index_mask;
10431053

1044-
assert(primary_index < array->length(), "no strings should have been added");
1045-
objArrayOop secondary = (objArrayOop)array->obj_at(primary_index);
1054+
assert(primary_index < array->length(), "no strings should have been added");
1055+
objArrayOop secondary = (objArrayOop)array->obj_at(primary_index);
10461056

1047-
assert(secondary != nullptr && secondary->is_objArray(), "must be");
1048-
assert(secondary_index < secondary->length(), "no strings should have been added");
1049-
secondary->obj_at_put(secondary_index, string);
1057+
assert(secondary != nullptr && secondary->is_objArray(), "must be");
1058+
assert(secondary_index < secondary->length(), "no strings should have been added");
1059+
secondary->obj_at_put(secondary_index, string);
1060+
}
1061+
index ++;
10501062
}
1051-
1052-
index ++;
1063+
return true;
10531064
};
1054-
dumped_interned_strings->iterate_all(copy_into_array);
10551065

1066+
_local_table->do_safepoint_scan(copy_into_array);
1067+
log_info(cds)("Archived %d interned strings", index);
10561068
return array;
1057-
}
1069+
};
10581070

1059-
void StringTable::write_shared_table(const DumpedInternedStrings* dumped_interned_strings) {
1071+
void StringTable::write_shared_table() {
10601072
_shared_table.reset();
10611073
CompactHashtableWriter writer((int)_items_count, ArchiveBuilder::string_stats());
10621074

10631075
int index = 0;
1064-
auto copy_into_shared_table = [&] (oop string, bool value_ignored) {
1065-
unsigned int hash = java_lang_String::hash_code(string);
1066-
writer.add(hash, index);
1067-
index ++;
1076+
auto copy_into_shared_table = [&] (WeakHandle* val) {
1077+
oop string = val->peek();
1078+
if (string != nullptr && !ArchiveHeapWriter::is_string_too_large_to_archive(string)) {
1079+
unsigned int hash = java_lang_String::hash_code(string);
1080+
writer.add(hash, index);
1081+
index ++;
1082+
}
1083+
return true;
10681084
};
1069-
dumped_interned_strings->iterate_all(copy_into_shared_table);
1070-
1085+
_local_table->do_safepoint_scan(copy_into_shared_table);
10711086
writer.dump(&_shared_table, "string");
10721087
}
10731088

src/hotspot/share/classfile/stringTable.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
#include "utilities/tableStatistics.hpp"
3434

3535
class CompactHashtableWriter;
36-
class DumpedInternedStrings;
3736
class JavaThread;
3837
class SerializeClosure;
3938

@@ -147,8 +146,8 @@ class StringTable : AllStatic {
147146
static oop lookup_shared(const jchar* name, int len) NOT_CDS_JAVA_HEAP_RETURN_(nullptr);
148147
static size_t shared_entry_count() NOT_CDS_JAVA_HEAP_RETURN_(0);
149148
static void allocate_shared_strings_array(TRAPS) NOT_CDS_JAVA_HEAP_RETURN;
150-
static oop init_shared_strings_array(const DumpedInternedStrings* dumped_interned_strings) NOT_CDS_JAVA_HEAP_RETURN_(nullptr);
151-
static void write_shared_table(const DumpedInternedStrings* dumped_interned_strings) NOT_CDS_JAVA_HEAP_RETURN;
149+
static oop init_shared_strings_array() NOT_CDS_JAVA_HEAP_RETURN_(nullptr);
150+
static void write_shared_table() NOT_CDS_JAVA_HEAP_RETURN;
152151
static void set_shared_strings_array_index(int root_index) NOT_CDS_JAVA_HEAP_RETURN;
153152
static void serialize_shared_table_header(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN;
154153

src/hotspot/share/oops/constantPool.cpp

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -374,40 +374,6 @@ objArrayOop ConstantPool::prepare_resolved_references_for_archiving() {
374374
}
375375
return rr;
376376
}
377-
378-
void ConstantPool::add_dumped_interned_strings() {
379-
InstanceKlass* ik = pool_holder();
380-
if (!ik->is_linked()) {
381-
// resolved_references() doesn't exist yet, so we have no resolved CONSTANT_String entries. However,
382-
// some static final fields may have default values that were initialized when the class was parsed.
383-
// We need to enter those into the CDS archive strings table.
384-
for (JavaFieldStream fs(ik); !fs.done(); fs.next()) {
385-
if (fs.access_flags().is_static()) {
386-
fieldDescriptor& fd = fs.field_descriptor();
387-
if (fd.field_type() == T_OBJECT) {
388-
int offset = fd.offset();
389-
check_and_add_dumped_interned_string(ik->java_mirror()->obj_field(offset));
390-
}
391-
}
392-
}
393-
} else {
394-
objArrayOop rr = resolved_references();
395-
if (rr != nullptr) {
396-
int rr_len = rr->length();
397-
for (int i = 0; i < rr_len; i++) {
398-
check_and_add_dumped_interned_string(rr->obj_at(i));
399-
}
400-
}
401-
}
402-
}
403-
404-
void ConstantPool::check_and_add_dumped_interned_string(oop obj) {
405-
if (obj != nullptr && java_lang_String::is_instance(obj) &&
406-
!ArchiveHeapWriter::is_string_too_large_to_archive(obj)) {
407-
HeapShared::add_to_dumped_interned_strings(obj);
408-
}
409-
}
410-
411377
#endif
412378

413379
#if INCLUDE_CDS

src/hotspot/share/oops/constantPool.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,6 @@ class ConstantPool : public Metadata {
162162
assert(is_within_bounds(cp_index), "index out of bounds");
163163
return (jdouble*) &base()[cp_index];
164164
}
165-
static void check_and_add_dumped_interned_string(oop obj);
166165

167166
ConstantPool(Array<u1>* tags);
168167
ConstantPool();
@@ -684,7 +683,6 @@ class ConstantPool : public Metadata {
684683
#if INCLUDE_CDS
685684
// CDS support
686685
objArrayOop prepare_resolved_references_for_archiving() NOT_CDS_JAVA_HEAP_RETURN_(nullptr);
687-
void add_dumped_interned_strings() NOT_CDS_JAVA_HEAP_RETURN;
688686
void remove_unshareable_info();
689687
void restore_unshareable_info(TRAPS);
690688
private:

0 commit comments

Comments
 (0)