40
40
#include " logging/log.hpp"
41
41
#include " logging/logStream.hpp"
42
42
#include " memory/allocation.inline.hpp"
43
+ #include " memory/oopFactory.hpp"
43
44
#include " memory/resourceArea.hpp"
44
45
#include " oops/access.inline.hpp"
45
46
#include " oops/compressedOops.hpp"
@@ -72,26 +73,31 @@ const size_t REHASH_LEN = 100;
72
73
const double CLEAN_DEAD_HIGH_WATER_MARK = 0.5 ;
73
74
74
75
#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 );
81
87
} 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);
89
92
}
93
+
94
+ assert (java_lang_String::is_instance (s), " must be" );
95
+ return s;
90
96
}
91
97
92
98
typedef CompactHashtable<
93
99
const jchar*, oop,
94
- read_string_from_compact_hashtable,
100
+ StringTable:: read_string_from_compact_hashtable,
95
101
java_lang_String::equals> SharedStringTable;
96
102
97
103
static SharedStringTable _shared_table;
@@ -224,6 +230,12 @@ void StringTable::create_table() {
224
230
_local_table = new StringTableHash (start_size_log_2, END_SIZE, REHASH_LEN, true );
225
231
_oop_storage = OopStorageSet::create_weak (" StringTable Weak" , mtSymbol);
226
232
_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
227
239
}
228
240
229
241
size_t StringTable::item_added () {
@@ -755,49 +767,131 @@ oop StringTable::lookup_shared(const jchar* name, int len) {
755
767
return _shared_table.lookup (name, java_lang_String::hash_code (name, len), len);
756
768
}
757
769
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);
769
777
}
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 );
782
801
}
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 ;
784
826
}
785
- };
827
+ }
786
828
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) {
789
856
assert (HeapShared::can_write (), " must be" );
857
+ objArrayOop array = (objArrayOop)(_shared_strings_array.resolve ());
858
+
859
+ verify_secondary_array_index_bits ();
790
860
791
861
_shared_table.reset ();
792
862
CompactHashtableWriter writer (_items_count, ArchiveBuilder::string_stats ());
793
863
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);
799
887
800
888
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;
801
895
}
802
896
803
897
void StringTable::serialize_shared_table_header (SerializeClosure* soc) {
@@ -806,47 +900,11 @@ void StringTable::serialize_shared_table_header(SerializeClosure* soc) {
806
900
if (soc->writing ()) {
807
901
// Sanity. Make sure we don't use the shared table at dump time
808
902
_shared_table.reset ();
809
- } else if (!ArchiveHeapLoader::are_archived_strings_available ()) {
903
+ } else if (!ArchiveHeapLoader::is_in_use ()) {
810
904
_shared_table.reset ();
811
905
}
812
906
907
+ soc->do_bool (&_is_two_dimensional_shared_strings_array);
908
+ soc->do_u4 ((u4*)(&_shared_strings_array_root_index));
813
909
}
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
-
852
910
#endif // INCLUDE_CDS_JAVA_HEAP
0 commit comments