Skip to content

Commit 85789b6

Browse files
author
duke
committedMar 29, 2023
Automatic merge of jdk:master into master
2 parents 9fb8a1a + b524a74 commit 85789b6

13 files changed

+237
-145
lines changed
 

‎src/hotspot/share/cds/archiveHeapLoader.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ void ArchiveHeapLoader::fixup_regions() {
9191
} else if (_loading_failed) {
9292
fill_failed_loaded_heap();
9393
}
94-
if (is_fully_available()) {
94+
if (is_in_use()) {
9595
if (!MetaspaceShared::use_full_module_graph()) {
9696
// Need to remove all the archived java.lang.Module objects from HeapShared::roots().
9797
ClassLoaderDataShared::clear_archived_oops();
@@ -472,7 +472,7 @@ void ArchiveHeapLoader::finish_initialization() {
472472
verify_loaded_heap();
473473
}
474474
}
475-
if (is_fully_available()) {
475+
if (is_in_use()) {
476476
patch_native_pointers();
477477
}
478478
}

‎src/hotspot/share/cds/archiveHeapLoader.hpp

+1-7
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,7 @@ class ArchiveHeapLoader : AllStatic {
6565
NOT_CDS_JAVA_HEAP(return false;)
6666
}
6767

68-
static bool are_archived_strings_available() {
69-
return is_loaded() || closed_regions_mapped();
70-
}
71-
static bool are_archived_mirrors_available() {
72-
return is_fully_available();
73-
}
74-
static bool is_fully_available() {
68+
static bool is_in_use() {
7569
return is_loaded() || is_mapped();
7670
}
7771

‎src/hotspot/share/cds/archiveUtils.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -316,16 +316,16 @@ void ReadClosure::do_tag(int tag) {
316316
void ReadClosure::do_oop(oop *p) {
317317
if (UseCompressedOops) {
318318
narrowOop o = CompressedOops::narrow_oop_cast(nextPtr());
319-
if (CompressedOops::is_null(o) || !ArchiveHeapLoader::is_fully_available()) {
319+
if (CompressedOops::is_null(o) || !ArchiveHeapLoader::is_in_use()) {
320320
*p = nullptr;
321321
} else {
322322
assert(ArchiveHeapLoader::can_use(), "sanity");
323-
assert(ArchiveHeapLoader::is_fully_available(), "must be");
323+
assert(ArchiveHeapLoader::is_in_use(), "must be");
324324
*p = ArchiveHeapLoader::decode_from_archive(o);
325325
}
326326
} else {
327327
intptr_t dumptime_oop = nextPtr();
328-
if (dumptime_oop == 0 || !ArchiveHeapLoader::is_fully_available()) {
328+
if (dumptime_oop == 0 || !ArchiveHeapLoader::is_in_use()) {
329329
*p = nullptr;
330330
} else {
331331
assert(!ArchiveHeapLoader::is_loaded(), "ArchiveHeapLoader::can_load() is not supported for uncompessed oops");

‎src/hotspot/share/cds/heapShared.cpp

+31-19
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ oop HeapShared::get_root(int index, bool clear) {
261261
void HeapShared::clear_root(int index) {
262262
assert(index >= 0, "sanity");
263263
assert(UseSharedSpaces, "must be");
264-
if (ArchiveHeapLoader::is_fully_available()) {
264+
if (ArchiveHeapLoader::is_in_use()) {
265265
if (log_is_enabled(Debug, cds, heap)) {
266266
oop old = roots()->obj_at(index);
267267
log_debug(cds, heap)("Clearing root %d: was " PTR_FORMAT, index, p2i(old));
@@ -378,8 +378,6 @@ void HeapShared::remove_scratch_objects(Klass* k) {
378378
}
379379

380380
void HeapShared::archive_java_mirrors() {
381-
init_seen_objects_table();
382-
383381
for (int i = T_BOOLEAN; i < T_VOID+1; i++) {
384382
BasicType bt = (BasicType)i;
385383
if (!is_reference_type(bt)) {
@@ -404,7 +402,7 @@ void HeapShared::archive_java_mirrors() {
404402
if (m != nullptr) {
405403
Klass* buffered_k = ArchiveBuilder::get_buffered_klass(orig_k);
406404
bool success = archive_reachable_objects_from(1, _default_subgraph_info, m, /*is_closed_archive=*/ false);
407-
guarantee(success, "scratch mirrors should not point to any unachivable objects");
405+
guarantee(success, "scratch mirrors must point to only archivable objects");
408406
buffered_k->set_archived_java_mirror(append_root(m));
409407
ResourceMark rm;
410408
log_trace(cds, heap, mirror)(
@@ -425,8 +423,16 @@ void HeapShared::archive_java_mirrors() {
425423
}
426424
}
427425
}
426+
}
428427

429-
delete_seen_objects_table();
428+
void HeapShared::archive_strings() {
429+
oop shared_strings_array = StringTable::init_shared_table(_dumped_interned_strings);
430+
bool success = archive_reachable_objects_from(1, _default_subgraph_info, shared_strings_array, /*is_closed_archive=*/ false);
431+
// We must succeed because:
432+
// - _dumped_interned_strings do not contain any large strings.
433+
// - StringTable::init_shared_table() doesn't create any large arrays.
434+
assert(success, "shared strings array must not point to arrays or strings that are too large to archive");
435+
StringTable::set_shared_strings_array_index(append_root(shared_strings_array));
430436
}
431437

432438
void HeapShared::mark_native_pointers(oop orig_obj) {
@@ -501,7 +507,7 @@ void HeapShared::check_enum_obj(int level,
501507

502508
// See comments in HeapShared::check_enum_obj()
503509
bool HeapShared::initialize_enum_klass(InstanceKlass* k, TRAPS) {
504-
if (!ArchiveHeapLoader::is_fully_available()) {
510+
if (!ArchiveHeapLoader::is_in_use()) {
505511
return false;
506512
}
507513

@@ -556,22 +562,20 @@ void HeapShared::archive_objects(GrowableArray<MemRegion>* closed_regions,
556562
}
557563

558564
ArchiveHeapWriter::write(_pending_roots, closed_regions, open_regions, closed_bitmaps, open_bitmaps);
559-
StringTable::write_shared_table(_dumped_interned_strings);
560565
}
561566

562567
void HeapShared::copy_interned_strings() {
563568
init_seen_objects_table();
564569

565570
auto copier = [&] (oop s, bool value_ignored) {
566571
assert(s != nullptr, "sanity");
567-
if (!ArchiveHeapWriter::is_string_too_large_to_archive(s)) {
568-
bool success = archive_reachable_objects_from(1, _default_subgraph_info,
569-
s, /*is_closed_archive=*/true);
570-
assert(success, "must be");
571-
// Prevent string deduplication from changing the value field to
572-
// something not in the archive.
573-
java_lang_String::set_deduplication_forbidden(s);
574-
}
572+
assert(!ArchiveHeapWriter::is_string_too_large_to_archive(s), "large strings must have been filtered");
573+
bool success = archive_reachable_objects_from(1, _default_subgraph_info,
574+
s, /*is_closed_archive=*/true);
575+
assert(success, "string must be short enough to be archived");
576+
// Prevent string deduplication from changing the value field to
577+
// something not in the archive.
578+
java_lang_String::set_deduplication_forbidden(s);
575579
};
576580
_dumped_interned_strings->iterate_all(copier);
577581

@@ -589,10 +593,18 @@ void HeapShared::copy_closed_objects() {
589593
false /* is_full_module_graph */);
590594
}
591595

596+
void HeapShared::copy_special_open_objects() {
597+
// Archive special objects that do not belong to any subgraphs
598+
init_seen_objects_table();
599+
archive_java_mirrors();
600+
archive_strings();
601+
delete_seen_objects_table();
602+
}
603+
592604
void HeapShared::copy_open_objects() {
593605
assert(HeapShared::can_write(), "must be");
594606

595-
archive_java_mirrors();
607+
copy_special_open_objects();
596608

597609
archive_object_subgraphs(open_archive_subgraph_entry_fields,
598610
false /* is_closed_archive */,
@@ -861,7 +873,7 @@ void HeapShared::serialize_root(SerializeClosure* soc) {
861873
assert(oopDesc::is_oop_or_null(roots_oop), "is oop");
862874
// Create an OopHandle only if we have actually mapped or loaded the roots
863875
if (roots_oop != nullptr) {
864-
assert(ArchiveHeapLoader::is_fully_available(), "must be");
876+
assert(ArchiveHeapLoader::is_in_use(), "must be");
865877
_roots = OopHandle(Universe::vm_global(), roots_oop);
866878
}
867879
} else {
@@ -921,7 +933,7 @@ static void verify_the_heap(Klass* k, const char* which) {
921933
// this case, we will not load the ArchivedKlassSubGraphInfoRecord and will clear its roots.
922934
void HeapShared::resolve_classes(JavaThread* current) {
923935
assert(UseSharedSpaces, "runtime only!");
924-
if (!ArchiveHeapLoader::is_fully_available()) {
936+
if (!ArchiveHeapLoader::is_in_use()) {
925937
return; // nothing to do
926938
}
927939
resolve_classes_for_subgraphs(current, closed_archive_subgraph_entry_fields);
@@ -954,7 +966,7 @@ void HeapShared::resolve_classes_for_subgraph_of(JavaThread* current, Klass* k)
954966

955967
void HeapShared::initialize_from_archived_subgraph(JavaThread* current, Klass* k) {
956968
JavaThread* THREAD = current;
957-
if (!ArchiveHeapLoader::is_fully_available()) {
969+
if (!ArchiveHeapLoader::is_in_use()) {
958970
return; // nothing to do
959971
}
960972

‎src/hotspot/share/cds/heapShared.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ class HeapShared: AllStatic {
344344
static void mark_native_pointers(oop orig_obj);
345345
static bool has_been_archived(oop orig_obj);
346346
static void archive_java_mirrors();
347+
static void archive_strings();
347348
public:
348349
static void reset_archived_object_states(TRAPS);
349350
static void create_archived_object_cache() {
@@ -364,6 +365,7 @@ class HeapShared: AllStatic {
364365
GrowableArray<ArchiveHeapBitmapInfo>* open_bitmaps);
365366
static void copy_closed_objects();
366367
static void copy_open_objects();
368+
static void copy_special_open_objects();
367369

368370
static bool archive_reachable_objects_from(int level,
369371
KlassSubGraphInfo* subgraph_info,

‎src/hotspot/share/cds/metaspaceShared.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,7 @@ void MetaspaceShared::preload_and_dump_impl(TRAPS) {
801801
log_info(cds)("Rewriting and linking classes: done");
802802

803803
#if INCLUDE_CDS_JAVA_HEAP
804+
StringTable::allocate_shared_strings_array(CHECK);
804805
ArchiveHeapWriter::init();
805806
if (use_full_module_graph()) {
806807
HeapShared::reset_archived_object_states(CHECK);
@@ -1437,9 +1438,6 @@ void MetaspaceShared::initialize_shared_spaces() {
14371438
ReadClosure rc(&array);
14381439
serialize(&rc);
14391440

1440-
// Initialize the run-time symbol table.
1441-
SymbolTable::create_table();
1442-
14431441
// Finish up archived heap initialization. These must be
14441442
// done after ReadClosure.
14451443
static_mapinfo->patch_heap_embedded_pointers();

‎src/hotspot/share/classfile/javaClasses.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,7 @@ void java_lang_Class::fixup_mirror(Klass* k, TRAPS) {
889889
}
890890

891891
if (k->is_shared() && k->has_archived_mirror_index()) {
892-
if (ArchiveHeapLoader::are_archived_mirrors_available()) {
892+
if (ArchiveHeapLoader::is_in_use()) {
893893
bool present = restore_archived_mirror(k, Handle(), Handle(), Handle(), CHECK);
894894
assert(present, "Missing archived mirror for %s", k->external_name());
895895
return;

‎src/hotspot/share/classfile/stringTable.cpp

+143-85
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "logging/log.hpp"
4141
#include "logging/logStream.hpp"
4242
#include "memory/allocation.inline.hpp"
43+
#include "memory/oopFactory.hpp"
4344
#include "memory/resourceArea.hpp"
4445
#include "oops/access.inline.hpp"
4546
#include "oops/compressedOops.hpp"
@@ -72,26 +73,31 @@ const size_t REHASH_LEN = 100;
7273
const double CLEAN_DEAD_HIGH_WATER_MARK = 0.5;
7374

7475
#if INCLUDE_CDS_JAVA_HEAP
75-
inline oop read_string_from_compact_hashtable(address base_address, u4 offset) {
76-
assert(ArchiveHeapLoader::are_archived_strings_available(), "sanity");
77-
if (UseCompressedOops) {
78-
assert(sizeof(narrowOop) == sizeof(offset), "must be");
79-
narrowOop v = CompressedOops::narrow_oop_cast(offset);
80-
return ArchiveHeapLoader::decode_from_archive(v);
76+
bool StringTable::_is_two_dimensional_shared_strings_array = false;
77+
OopHandle StringTable::_shared_strings_array;
78+
int StringTable::_shared_strings_array_root_index;
79+
80+
inline oop StringTable::read_string_from_compact_hashtable(address base_address, u4 index) {
81+
assert(ArchiveHeapLoader::is_in_use(), "sanity");
82+
objArrayOop array = (objArrayOop)(_shared_strings_array.resolve());
83+
oop s;
84+
85+
if (!_is_two_dimensional_shared_strings_array) {
86+
s = array->obj_at((int)index);
8187
} else {
82-
assert(!ArchiveHeapLoader::is_loaded(), "Pointer relocation for uncompressed oops is unimplemented");
83-
intptr_t dumptime_oop = (uintptr_t)offset;
84-
assert(dumptime_oop != 0, "null strings cannot be interned");
85-
intptr_t runtime_oop = dumptime_oop +
86-
(intptr_t)FileMapInfo::current_info()->header()->heap_begin() +
87-
(intptr_t)ArchiveHeapLoader::mapped_heap_delta();
88-
return (oop)cast_to_oop(runtime_oop);
88+
int primary_index = index >> _secondary_array_index_bits;
89+
int secondary_index = index & _secondary_array_index_mask;
90+
objArrayOop secondary = (objArrayOop)array->obj_at(primary_index);
91+
s = secondary->obj_at(secondary_index);
8992
}
93+
94+
assert(java_lang_String::is_instance(s), "must be");
95+
return s;
9096
}
9197

9298
typedef CompactHashtable<
9399
const jchar*, oop,
94-
read_string_from_compact_hashtable,
100+
StringTable::read_string_from_compact_hashtable,
95101
java_lang_String::equals> SharedStringTable;
96102

97103
static SharedStringTable _shared_table;
@@ -224,6 +230,12 @@ void StringTable::create_table() {
224230
_local_table = new StringTableHash(start_size_log_2, END_SIZE, REHASH_LEN, true);
225231
_oop_storage = OopStorageSet::create_weak("StringTable Weak", mtSymbol);
226232
_oop_storage->register_num_dead_callback(&gc_notification);
233+
234+
#if INCLUDE_CDS_JAVA_HEAP
235+
if (ArchiveHeapLoader::is_in_use()) {
236+
_shared_strings_array = OopHandle(Universe::vm_global(), HeapShared::get_root(_shared_strings_array_root_index));
237+
}
238+
#endif
227239
}
228240

229241
size_t StringTable::item_added() {
@@ -755,49 +767,131 @@ oop StringTable::lookup_shared(const jchar* name, int len) {
755767
return _shared_table.lookup(name, java_lang_String::hash_code(name, len), len);
756768
}
757769

758-
class EncodeSharedStringsAsOffsets : StackObj {
759-
CompactHashtableWriter* _writer;
760-
private:
761-
u4 compute_delta(oop s) {
762-
HeapWord* start = G1CollectedHeap::heap()->reserved().start();
763-
intx offset = ((address)(void*)s) - ((address)(void*)start);
764-
assert(offset >= 0, "must be");
765-
if (offset > 0xffffffff) {
766-
fatal("too large");
767-
}
768-
return (u4)offset;
770+
// This is called BEFORE we enter the CDS safepoint. We can allocate heap objects.
771+
// This should be called when we know no more strings will be added (which will be easy
772+
// to guarantee because CDS runs with a single Java thread. See JDK-8253495.)
773+
void StringTable::allocate_shared_strings_array(TRAPS) {
774+
assert(DumpSharedSpaces, "must be");
775+
if (_items_count > (size_t)max_jint) {
776+
fatal("Too many strings to be archived: " SIZE_FORMAT, _items_count);
769777
}
770-
public:
771-
EncodeSharedStringsAsOffsets(CompactHashtableWriter* writer) : _writer(writer) {}
772-
bool do_entry(oop s, bool value_ignored) {
773-
assert(s != nullptr, "sanity");
774-
assert(!ArchiveHeapWriter::is_string_too_large_to_archive(s), "must be");
775-
oop req_s = ArchiveHeapWriter::source_obj_to_requested_obj(s);
776-
assert(req_s != nullptr, "must have been archived");
777-
unsigned int hash = java_lang_String::hash_code(s);
778-
if (UseCompressedOops) {
779-
_writer->add(hash, CompressedOops::narrow_oop_value(req_s));
780-
} else {
781-
_writer->add(hash, compute_delta(req_s));
778+
779+
int total = (int)_items_count;
780+
size_t single_array_size = objArrayOopDesc::object_size(total);
781+
782+
log_info(cds)("allocated string table for %d strings", total);
783+
784+
if (!ArchiveHeapWriter::is_too_large_to_archive(single_array_size)) {
785+
// The entire table can fit in a single array
786+
objArrayOop array = oopFactory::new_objArray(vmClasses::Object_klass(), total, CHECK);
787+
_shared_strings_array = OopHandle(Universe::vm_global(), array);
788+
log_info(cds)("string table array (single level) length = %d", total);
789+
} else {
790+
// Split the table in two levels of arrays.
791+
int primary_array_length = (total + _secondary_array_max_length - 1) / _secondary_array_max_length;
792+
size_t primary_array_size = objArrayOopDesc::object_size(primary_array_length);
793+
size_t secondary_array_size = objArrayOopDesc::object_size(_secondary_array_max_length);
794+
795+
if (ArchiveHeapWriter::is_too_large_to_archive(secondary_array_size)) {
796+
// This can only happen if you have an extremely large number of classes that
797+
// refer to more than 16384 * 16384 = 26M interned strings! Not a practical concern
798+
// but bail out for safety.
799+
log_error(cds)("Too many strings to be archived: " SIZE_FORMAT, _items_count);
800+
os::_exit(1);
782801
}
783-
return true; // keep iterating
802+
803+
objArrayOop primary = oopFactory::new_objArray(vmClasses::Object_klass(), primary_array_length, CHECK);
804+
objArrayHandle primaryHandle(THREAD, primary);
805+
_shared_strings_array = OopHandle(Universe::vm_global(), primary);
806+
807+
log_info(cds)("string table array (primary) length = %d", primary_array_length);
808+
for (int i = 0; i < primary_array_length; i++) {
809+
int len;
810+
if (total > _secondary_array_max_length) {
811+
len = _secondary_array_max_length;
812+
} else {
813+
len = total;
814+
}
815+
total -= len;
816+
817+
objArrayOop secondary = oopFactory::new_objArray(vmClasses::Object_klass(), len, CHECK);
818+
primaryHandle()->obj_at_put(i, secondary);
819+
820+
log_info(cds)("string table array (secondary)[%d] length = %d", i, len);
821+
assert(!ArchiveHeapWriter::is_too_large_to_archive(secondary), "sanity");
822+
}
823+
824+
assert(total == 0, "must be");
825+
_is_two_dimensional_shared_strings_array = true;
784826
}
785-
};
827+
}
786828

787-
// Write the _shared_table (a CompactHashtable) into the CDS archive file.
788-
void StringTable::write_shared_table(const DumpedInternedStrings* dumped_interned_strings) {
829+
#ifndef PRODUCT
830+
void StringTable::verify_secondary_array_index_bits() {
831+
int max;
832+
for (max = 1; ; max++) {
833+
size_t next_size = objArrayOopDesc::object_size(1 << (max + 1));
834+
if (ArchiveHeapWriter::is_too_large_to_archive(next_size)) {
835+
break;
836+
}
837+
}
838+
// Currently max is 17 for +UseCompressedOops, 16 for -UseCompressedOops.
839+
// When we add support for Shenandoah (which has a smaller mininum region size than G1),
840+
// max will become 15/14.
841+
//
842+
// We use _secondary_array_index_bits==14 as that will be the eventual value, and will
843+
// make testing easier.
844+
assert(_secondary_array_index_bits <= max,
845+
"_secondary_array_index_bits (%d) must be smaller than max possible value (%d)",
846+
_secondary_array_index_bits, max);
847+
}
848+
#endif // PRODUCT
849+
850+
// This is called AFTER we enter the CDS safepoint.
851+
//
852+
// For each shared string:
853+
// [1] Store it into _shared_strings_array. Encode its position as a 32-bit index.
854+
// [2] Store the index and hashcode into _shared_table.
855+
oop StringTable::init_shared_table(const DumpedInternedStrings* dumped_interned_strings) {
789856
assert(HeapShared::can_write(), "must be");
857+
objArrayOop array = (objArrayOop)(_shared_strings_array.resolve());
858+
859+
verify_secondary_array_index_bits();
790860

791861
_shared_table.reset();
792862
CompactHashtableWriter writer(_items_count, ArchiveBuilder::string_stats());
793863

794-
// Encode the strings in the CompactHashtable using offsets -- we know that the
795-
// strings will not move during runtime because they are inside the G1 closed
796-
// archive region.
797-
EncodeSharedStringsAsOffsets offset_finder(&writer);
798-
dumped_interned_strings->iterate(&offset_finder);
864+
int index = 0;
865+
auto copy_into_array = [&] (oop string, bool value_ignored) {
866+
unsigned int hash = java_lang_String::hash_code(string);
867+
writer.add(hash, index);
868+
869+
if (!_is_two_dimensional_shared_strings_array) {
870+
assert(index < array->length(), "no strings should have been added");
871+
array->obj_at_put(index, string);
872+
} else {
873+
int primary_index = index >> _secondary_array_index_bits;
874+
int secondary_index = index & _secondary_array_index_mask;
875+
876+
assert(primary_index < array->length(), "no strings should have been added");
877+
objArrayOop secondary = (objArrayOop)array->obj_at(primary_index);
878+
879+
assert(secondary != nullptr && secondary->is_objArray(), "must be");
880+
assert(secondary_index < secondary->length(), "no strings should have been added");
881+
secondary->obj_at_put(secondary_index, string);
882+
}
883+
884+
index ++;
885+
};
886+
dumped_interned_strings->iterate_all(copy_into_array);
799887

800888
writer.dump(&_shared_table, "string");
889+
890+
return array;
891+
}
892+
893+
void StringTable::set_shared_strings_array_index(int root_index) {
894+
_shared_strings_array_root_index = root_index;
801895
}
802896

803897
void StringTable::serialize_shared_table_header(SerializeClosure* soc) {
@@ -806,47 +900,11 @@ void StringTable::serialize_shared_table_header(SerializeClosure* soc) {
806900
if (soc->writing()) {
807901
// Sanity. Make sure we don't use the shared table at dump time
808902
_shared_table.reset();
809-
} else if (!ArchiveHeapLoader::are_archived_strings_available()) {
903+
} else if (!ArchiveHeapLoader::is_in_use()) {
810904
_shared_table.reset();
811905
}
812906

907+
soc->do_bool(&_is_two_dimensional_shared_strings_array);
908+
soc->do_u4((u4*)(&_shared_strings_array_root_index));
813909
}
814-
815-
class SharedStringTransfer {
816-
JavaThread* _current;
817-
public:
818-
SharedStringTransfer(JavaThread* current) : _current(current) {}
819-
820-
void do_value(oop string) {
821-
JavaThread* THREAD = _current;
822-
ExceptionMark rm(THREAD);
823-
HandleMark hm(THREAD);
824-
StringTable::intern(string, THREAD);
825-
if (HAS_PENDING_EXCEPTION) {
826-
// The archived constant pools contains strings that must be in the interned string table.
827-
// If we fail here, it means the VM runs out of memory during bootstrap, so there's no point
828-
// of trying to recover from here.
829-
vm_exit_during_initialization("Failed to transfer shared strings to interned string table");
830-
}
831-
}
832-
};
833-
834-
// If the CDS archive heap is loaded (not mapped) into the old generation,
835-
// it's possible for the shared strings to move due to full GC, making the
836-
// _shared_table invalid. Therefore, we proactively copy all the shared
837-
// strings into the _local_table, which can deal with oop relocation.
838-
void StringTable::transfer_shared_strings_to_local_table() {
839-
assert(ArchiveHeapLoader::is_loaded(), "must be");
840-
EXCEPTION_MARK;
841-
842-
// Reset _shared_table so that during the transfer, StringTable::intern()
843-
// will not look up from there. Instead, it will create a new entry in
844-
// _local_table for each element in shared_table_copy.
845-
SharedStringTable shared_table_copy = _shared_table;
846-
_shared_table.reset();
847-
848-
SharedStringTransfer transfer(THREAD);
849-
shared_table_copy.iterate(&transfer);
850-
}
851-
852910
#endif //INCLUDE_CDS_JAVA_HEAP

‎src/hotspot/share/classfile/stringTable.hpp

+35-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "memory/allocation.hpp"
2929
#include "memory/padded.hpp"
3030
#include "oops/oop.hpp"
31+
#include "oops/oopHandle.hpp"
3132
#include "oops/weakHandle.hpp"
3233
#include "utilities/tableStatistics.hpp"
3334

@@ -104,14 +105,46 @@ class StringTable : public CHeapObj<mtSymbol>{
104105
}
105106

106107
// Sharing
108+
#if INCLUDE_CDS_JAVA_HEAP
109+
static inline oop read_string_from_compact_hashtable(address base_address, u4 index);
110+
111+
private:
112+
static bool _is_two_dimensional_shared_strings_array;
113+
static OopHandle _shared_strings_array;
114+
static int _shared_strings_array_root_index;
115+
116+
// All the shared strings are referenced through _shared_strings_array to keep them alive.
117+
// Each shared string is stored as a 32-bit index in ::_shared_table. The index
118+
// is interpreted in two ways:
119+
//
120+
// [1] _is_two_dimensional_shared_strings_array = false: _shared_strings_array is an Object[].
121+
// Each shared string is stored as _shared_strings_array[index]
122+
//
123+
// [2] _is_two_dimensional_shared_strings_array = true: _shared_strings_array is an Object[][]
124+
// This happens when there are too many elements in the shared table. We store them
125+
// using two levels of objArrays, such that none of the arrays are too big for
126+
// ArchiveHeapWriter::is_too_large_to_archive(). In this case, the index is splited into two
127+
// parts. Each shared string is stored as _shared_strings_array[primary_index][secondary_index]:
128+
//
129+
// [bits 31 .. 14][ bits 13 .. 0 ]
130+
// primary_index secondary_index
131+
const static int _secondary_array_index_bits = 14;
132+
const static int _secondary_array_max_length = 1 << _secondary_array_index_bits;
133+
const static int _secondary_array_index_mask = _secondary_array_max_length - 1;
134+
135+
// make sure _secondary_array_index_bits is not too big
136+
static void verify_secondary_array_index_bits() PRODUCT_RETURN;
137+
#endif // INCLUDE_CDS_JAVA_HEAP
138+
107139
private:
108140
static oop lookup_shared(const jchar* name, int len, unsigned int hash) NOT_CDS_JAVA_HEAP_RETURN_(nullptr);
109141
public:
110142
static oop lookup_shared(const jchar* name, int len) NOT_CDS_JAVA_HEAP_RETURN_(nullptr);
111143
static size_t shared_entry_count() NOT_CDS_JAVA_HEAP_RETURN_(0);
112-
static void write_shared_table(const DumpedInternedStrings* dumped_interned_strings) NOT_CDS_JAVA_HEAP_RETURN;
144+
static void allocate_shared_strings_array(TRAPS) NOT_CDS_JAVA_HEAP_RETURN;
145+
static oop init_shared_table(const DumpedInternedStrings* dumped_interned_strings) NOT_CDS_JAVA_HEAP_RETURN_(NULL);
146+
static void set_shared_strings_array_index(int root_index) NOT_CDS_JAVA_HEAP_RETURN;
113147
static void serialize_shared_table_header(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN;
114-
static void transfer_shared_strings_to_local_table() NOT_CDS_JAVA_HEAP_RETURN;
115148

116149
// Jcmd
117150
static void dump(outputStream* st, bool verbose=false);

‎src/hotspot/share/memory/universe.cpp

+6-17
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ void Universe::set_archived_basic_type_mirror_index(BasicType t, int index) {
244244
}
245245

246246
void Universe::update_archived_basic_type_mirrors() {
247-
if (ArchiveHeapLoader::are_archived_mirrors_available()) {
247+
if (ArchiveHeapLoader::is_in_use()) {
248248
for (int i = T_BOOLEAN; i < T_VOID+1; i++) {
249249
int index = _archived_basic_type_mirror_indices[i];
250250
if (!is_reference_type((BasicType)i) && index >= 0) {
@@ -455,7 +455,7 @@ void Universe::genesis(TRAPS) {
455455
void Universe::initialize_basic_type_mirrors(TRAPS) {
456456
#if INCLUDE_CDS_JAVA_HEAP
457457
if (UseSharedSpaces &&
458-
ArchiveHeapLoader::are_archived_mirrors_available() &&
458+
ArchiveHeapLoader::is_in_use() &&
459459
_basic_type_mirrors[T_INT].resolve() != nullptr) {
460460
assert(ArchiveHeapLoader::can_use(), "Sanity");
461461

@@ -812,28 +812,17 @@ jint universe_init() {
812812
DynamicArchive::check_for_dynamic_dump();
813813
if (UseSharedSpaces) {
814814
// Read the data structures supporting the shared spaces (shared
815-
// system dictionary, symbol table, etc.). After that, access to
816-
// the file (other than the mapped regions) is no longer needed, and
817-
// the file is closed. Closing the file does not affect the
818-
// currently mapped regions.
815+
// system dictionary, symbol table, etc.)
819816
MetaspaceShared::initialize_shared_spaces();
820-
StringTable::create_table();
821-
if (ArchiveHeapLoader::is_loaded()) {
822-
StringTable::transfer_shared_strings_to_local_table();
823-
}
824-
} else
825-
#endif
826-
{
827-
SymbolTable::create_table();
828-
StringTable::create_table();
829817
}
830-
831-
#if INCLUDE_CDS
832818
if (Arguments::is_dumping_archive()) {
833819
MetaspaceShared::prepare_for_dumping();
834820
}
835821
#endif
836822

823+
SymbolTable::create_table();
824+
StringTable::create_table();
825+
837826
if (strlen(VerifySubSet) > 0) {
838827
Universe::initialize_verify_flags();
839828
}

‎src/hotspot/share/oops/constantPool.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ void ConstantPool::restore_unshareable_info(TRAPS) {
337337
if (vmClasses::Object_klass_loaded()) {
338338
ClassLoaderData* loader_data = pool_holder()->class_loader_data();
339339
#if INCLUDE_CDS_JAVA_HEAP
340-
if (ArchiveHeapLoader::is_fully_available() &&
340+
if (ArchiveHeapLoader::is_in_use() &&
341341
_cache->archived_references() != nullptr) {
342342
oop archived = _cache->archived_references();
343343
// Create handle for the archived resolved reference array object

‎src/hotspot/share/oops/klass.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protec
603603
if (this->has_archived_mirror_index()) {
604604
ResourceMark rm(THREAD);
605605
log_debug(cds, mirror)("%s has raw archived mirror", external_name());
606-
if (ArchiveHeapLoader::are_archived_mirrors_available()) {
606+
if (ArchiveHeapLoader::is_in_use()) {
607607
bool present = java_lang_Class::restore_archived_mirror(this, loader, module_handle,
608608
protection_domain,
609609
CHECK);

‎test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SharedStringsStress.java

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2023, 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
@@ -28,7 +28,7 @@
2828
* @requires vm.cds.write.archived.java.heap
2929
* @library /test/hotspot/jtreg/runtime/cds/appcds /test/lib
3030
* @build HelloString
31-
* @run driver/timeout=500 SharedStringsStress
31+
* @run driver/timeout=650 SharedStringsStress
3232
*/
3333
import java.io.File;
3434
import java.io.FileOutputStream;
@@ -52,7 +52,10 @@ public static void main(String[] args) throws Exception {
5252
out.println("VERSION: 1.0");
5353
out.println("@SECTION: String");
5454
out.println("31: shared_test_string_unique_14325");
55-
for (int i=0; i<200000; i++) {
55+
// Create enough entries to require the shared string
56+
// table to split into two levels of Object arrays. See
57+
// StringTable::allocate_shared_table() in HotSpot.
58+
for (int i=0; i<260000; i++) {
5659
String s = "generated_string " + i;
5760
out.println(s.length() + ": " + s);
5861
}
@@ -91,8 +94,11 @@ public static void test(String[] args) throws Exception {
9194
"-Xlog:gc+region+cds",
9295
"-Xlog:gc+region=trace"));
9396
TestCommon.checkDump(dumpOutput);
97+
dumpOutput.shouldContain("string table array (primary)");
98+
dumpOutput.shouldContain("string table array (secondary)");
99+
94100
OutputAnalyzer execOutput = TestCommon.exec(appJar,
95-
TestCommon.concat(vmOptionsPrefix, "HelloString"));
101+
TestCommon.concat(vmOptionsPrefix, "-Xlog:cds", "HelloString"));
96102
TestCommon.checkExec(execOutput);
97103
}
98104
}

0 commit comments

Comments
 (0)
Please sign in to comment.