< prev index next >

src/hotspot/share/classfile/stringTable.cpp

Print this page

  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "cds/archiveBuilder.hpp"
  26 #include "cds/archiveHeapLoader.inline.hpp"
  27 #include "cds/archiveHeapWriter.hpp"
  28 #include "cds/cdsConfig.hpp"
  29 #include "cds/heapShared.hpp"
  30 #include "classfile/altHashing.hpp"
  31 #include "classfile/compactHashtable.hpp"
  32 #include "classfile/javaClasses.inline.hpp"
  33 #include "classfile/stringTable.hpp"
  34 #include "classfile/vmClasses.hpp"

  35 #include "gc/shared/collectedHeap.hpp"
  36 #include "gc/shared/oopStorage.inline.hpp"
  37 #include "gc/shared/oopStorageSet.hpp"
  38 #include "gc/shared/stringdedup/stringDedup.hpp"
  39 #include "logging/log.hpp"
  40 #include "logging/logStream.hpp"
  41 #include "memory/allocation.inline.hpp"
  42 #include "memory/oopFactory.hpp"
  43 #include "memory/resourceArea.hpp"
  44 #include "oops/access.inline.hpp"
  45 #include "oops/compressedOops.hpp"
  46 #include "oops/oop.inline.hpp"
  47 #include "oops/typeArrayOop.inline.hpp"
  48 #include "oops/weakHandle.inline.hpp"
  49 #include "runtime/atomic.hpp"
  50 #include "runtime/handles.inline.hpp"
  51 #include "runtime/interfaceSupport.inline.hpp"
  52 #include "runtime/mutexLocker.hpp"
  53 #include "runtime/safepointVerifiers.hpp"
  54 #include "runtime/timerTrace.hpp"

  98 
  99 typedef CompactHashtable<
 100   const StringTable::StringWrapper&, oop,
 101   StringTable::read_string_from_compact_hashtable,
 102   StringTable::wrapped_string_equals> SharedStringTable;
 103 
 104 static SharedStringTable _shared_table;
 105 #endif
 106 
 107 // --------------------------------------------------------------------------
 108 
 109 typedef ConcurrentHashTable<StringTableConfig, mtSymbol> StringTableHash;
 110 static StringTableHash* _local_table = nullptr;
 111 
 112 volatile bool StringTable::_has_work = false;
 113 volatile bool StringTable::_needs_rehashing = false;
 114 OopStorage*   StringTable::_oop_storage;
 115 
 116 static size_t _current_size = 0;
 117 static volatile size_t _items_count = 0;

 118 
 119 volatile bool _alt_hash = false;
 120 
 121 static bool _rehashed = false;
 122 static uint64_t _alt_hash_seed = 0;
 123 
 124 enum class StringType {
 125   OopStr, UnicodeStr, SymbolStr, UTF8Str
 126 };
 127 
 128 struct StringWrapperInternal {
 129   union {
 130     const Handle oop_str;
 131     const jchar* unicode_str;
 132     const Symbol* symbol_str;
 133     const char* utf8_str;
 134   };
 135   const StringType type;
 136   const size_t length;
 137 

 329 void StringTable::item_removed() {
 330   Atomic::dec(&_items_count);
 331 }
 332 
 333 double StringTable::get_load_factor() {
 334   return double(_items_count)/double(_current_size);
 335 }
 336 
 337 double StringTable::get_dead_factor(size_t num_dead) {
 338   return double(num_dead)/double(_current_size);
 339 }
 340 
 341 size_t StringTable::table_size() {
 342   return ((size_t)1) << _local_table->get_size_log2(Thread::current());
 343 }
 344 
 345 bool StringTable::has_work() {
 346   return Atomic::load_acquire(&_has_work);
 347 }
 348 




 349 void StringTable::trigger_concurrent_work() {
 350   // Avoid churn on ServiceThread
 351   if (!has_work()) {
 352     MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
 353     Atomic::store(&_has_work, true);
 354     Service_lock->notify_all();
 355   }
 356 }
 357 
 358 // Probing
 359 oop StringTable::lookup(Symbol* symbol) {
 360   ResourceMark rm;
 361   int length;
 362   jchar* chars = symbol->as_unicode(length);
 363   return lookup(chars, length);
 364 }
 365 
 366 oop StringTable::lookup(const jchar* name, int len) {
 367   unsigned int hash = java_lang_String::hash_code(name, len);
 368   StringWrapper wrapped_name(name, len);

 487 }
 488 
 489 oop StringTable::intern(oop string, TRAPS) {
 490   if (string == nullptr) return nullptr;
 491   int length = java_lang_String::length(string);
 492   Handle h_string (THREAD, string);
 493   StringWrapper name(h_string, length);
 494   oop result = intern(name, CHECK_NULL);
 495   return result;
 496 }
 497 
 498 oop StringTable::intern(const char* utf8_string, TRAPS) {
 499   if (utf8_string == nullptr) return nullptr;
 500   size_t length = strlen(utf8_string);
 501   StringWrapper name(utf8_string, length);
 502   oop result = intern(name, CHECK_NULL);
 503   return result;
 504 }
 505 
 506 oop StringTable::intern(const StringWrapper& name, TRAPS) {



 507   // shared table always uses java_lang_String::hash_code
 508   unsigned int hash = hash_wrapped_string(name);
 509   oop found_string = lookup_shared(name, hash);
 510   if (found_string != nullptr) {
 511     return found_string;
 512   }
 513 
 514   if (_alt_hash) {
 515     ResourceMark rm(THREAD);
 516     // Convert to unicode for alt hashing
 517     int unicode_length;
 518     const jchar* chars = to_unicode(name, unicode_length, CHECK_NULL);
 519     hash = hash_string(chars, unicode_length, true);
 520   }
 521 
 522   found_string = do_lookup(name, hash);
 523   if (found_string != nullptr) {
 524     return found_string;
 525   }
 526   return do_intern(name, hash, THREAD);

 776 
 777 // Verification
 778 class VerifyStrings : StackObj {
 779  public:
 780   bool operator()(WeakHandle* val) {
 781     oop s = val->peek();
 782     if (s != nullptr) {
 783       assert(java_lang_String::length(s) >= 0, "Length on string must work.");
 784     }
 785     return true;
 786   };
 787 };
 788 
 789 // This verification is part of Universe::verify() and needs to be quick.
 790 void StringTable::verify() {
 791   VerifyStrings vs;
 792   _local_table->do_safepoint_scan(vs);
 793 }
 794 
 795 // Verification and comp
 796 class VerifyCompStrings : StackObj {
 797   static unsigned string_hash(oop const& str) {
 798     return java_lang_String::hash_code_noupdate(str);
 799   }
 800   static bool string_equals(oop const& a, oop const& b) {
 801     return java_lang_String::equals(a, b);
 802   }
 803 
 804   ResizeableResourceHashtable<oop, bool, AnyObj::C_HEAP, mtInternal,
 805                               string_hash, string_equals> _table;
 806  public:
 807   size_t _errors;
 808   VerifyCompStrings() : _table(unsigned(_items_count / 8) + 1, 0 /* do not resize */), _errors(0) {}
 809   bool operator()(WeakHandle* val) {
 810     oop s = val->resolve();
 811     if (s == nullptr) {
 812       return true;
 813     }
 814     bool created;
 815     _table.put_if_absent(s, true, &created);
 816     assert(created, "Duplicate strings");
 817     if (!created) {
 818       _errors++;
 819     }
 820     return true;
 821   };
 822 };
 823 
 824 size_t StringTable::verify_and_compare_entries() {
 825   Thread* thr = Thread::current();
 826   VerifyCompStrings vcs;
 827   _local_table->do_scan(thr, vcs);
 828   return vcs._errors;

 922 
 923 // Sharing
 924 #if INCLUDE_CDS_JAVA_HEAP
 925 size_t StringTable::shared_entry_count() {
 926   return _shared_table.entry_count();
 927 }
 928 
 929 oop StringTable::lookup_shared(const StringWrapper& name, unsigned int hash) {
 930   assert(hash == hash_wrapped_string(name),
 931          "hash must be computed using java_lang_String::hash_code");
 932   // len is required but is already part of StringWrapper, so 0 is used
 933   return _shared_table.lookup(name, hash, 0);
 934 }
 935 
 936 oop StringTable::lookup_shared(const jchar* name, int len) {
 937   StringWrapper wrapped_name(name, len);
 938   // len is required but is already part of StringWrapper, so 0 is used
 939   return _shared_table.lookup(wrapped_name, java_lang_String::hash_code(name, len), 0);
 940 }
 941 
 942 // This is called BEFORE we enter the CDS safepoint. We can allocate heap objects.
 943 // This should be called when we know no more strings will be added (which will be easy
 944 // to guarantee because CDS runs with a single Java thread. See JDK-8253495.)
 945 void StringTable::allocate_shared_strings_array(TRAPS) {
 946   if (!CDSConfig::is_dumping_heap()) {
 947     return;
 948   }
 949   assert(CDSConfig::allow_only_single_java_thread(), "No more interned strings can be added");
 950 
 951   if (_items_count > (size_t)max_jint) {
 952     fatal("Too many strings to be archived: %zu", _items_count);













 953   }
 954 
 955   int total = (int)_items_count;
 956   size_t single_array_size = objArrayOopDesc::object_size(total);
 957 
 958   log_info(aot)("allocated string table for %d strings", total);
 959 
 960   if (!ArchiveHeapWriter::is_too_large_to_archive(single_array_size)) {
 961     // The entire table can fit in a single array
 962     objArrayOop array = oopFactory::new_objArray(vmClasses::Object_klass(), total, CHECK);
 963     _shared_strings_array = OopHandle(Universe::vm_global(), array);
 964     log_info(aot)("string table array (single level) length = %d", total);
 965   } else {
 966     // Split the table in two levels of arrays.
 967     int primary_array_length = (total + _secondary_array_max_length - 1) / _secondary_array_max_length;
 968     size_t primary_array_size = objArrayOopDesc::object_size(primary_array_length);
 969     size_t secondary_array_size = objArrayOopDesc::object_size(_secondary_array_max_length);
 970 
 971     if (ArchiveHeapWriter::is_too_large_to_archive(secondary_array_size)) {
 972       // This can only happen if you have an extremely large number of classes that
 973       // refer to more than 16384 * 16384 = 26M interned strings! Not a practical concern
 974       // but bail out for safety.
 975       log_error(aot)("Too many strings to be archived: %zu", _items_count);
 976       MetaspaceShared::unrecoverable_writing_error();
 977     }
 978 
 979     objArrayOop primary = oopFactory::new_objArray(vmClasses::Object_klass(), primary_array_length, CHECK);
 980     objArrayHandle primaryHandle(THREAD, primary);
 981     _shared_strings_array = OopHandle(Universe::vm_global(), primary);
 982 
 983     log_info(aot)("string table array (primary) length = %d", primary_array_length);
 984     for (int i = 0; i < primary_array_length; i++) {
 985       int len;
 986       if (total > _secondary_array_max_length) {
 987         len = _secondary_array_max_length;
 988       } else {
 989         len = total;
 990       }
 991       total -= len;
 992 
 993       objArrayOop secondary = oopFactory::new_objArray(vmClasses::Object_klass(), len, CHECK);
 994       primaryHandle()->obj_at_put(i, secondary);
 995 

1053 
1054         assert(primary_index < array->length(), "no strings should have been added");
1055         objArrayOop secondary = (objArrayOop)array->obj_at(primary_index);
1056 
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 ++;
1062     }
1063     return true;
1064   };
1065 
1066   _local_table->do_safepoint_scan(copy_into_array);
1067   log_info(aot)("Archived %d interned strings", index);
1068   return array;
1069 };
1070 
1071 void StringTable::write_shared_table() {
1072   _shared_table.reset();
1073   CompactHashtableWriter writer((int)_items_count, ArchiveBuilder::string_stats());
1074 
1075   int index = 0;
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;
1084   };
1085   _local_table->do_safepoint_scan(copy_into_shared_table);
1086   writer.dump(&_shared_table, "string");


1087 }
1088 
1089 void StringTable::set_shared_strings_array_index(int root_index) {
1090   _shared_strings_array_root_index = root_index;
1091 }
1092 
1093 void StringTable::serialize_shared_table_header(SerializeClosure* soc) {






1094   _shared_table.serialize_header(soc);
1095 
1096   if (soc->writing()) {
1097     // Sanity. Make sure we don't use the shared table at dump time
1098     _shared_table.reset();
1099   } else if (!ArchiveHeapLoader::is_in_use()) {
1100     _shared_table.reset();
1101   }
1102 
1103   soc->do_bool(&_is_two_dimensional_shared_strings_array);
1104   soc->do_int(&_shared_strings_array_root_index);
1105 }
1106 #endif //INCLUDE_CDS_JAVA_HEAP

  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "cds/archiveBuilder.hpp"
  26 #include "cds/archiveHeapLoader.inline.hpp"
  27 #include "cds/archiveHeapWriter.hpp"
  28 #include "cds/cdsConfig.hpp"
  29 #include "cds/heapShared.hpp"
  30 #include "classfile/altHashing.hpp"
  31 #include "classfile/compactHashtable.hpp"
  32 #include "classfile/javaClasses.inline.hpp"
  33 #include "classfile/stringTable.hpp"
  34 #include "classfile/vmClasses.hpp"
  35 #include "compiler/compileBroker.hpp"
  36 #include "gc/shared/collectedHeap.hpp"
  37 #include "gc/shared/oopStorage.inline.hpp"
  38 #include "gc/shared/oopStorageSet.hpp"
  39 #include "gc/shared/stringdedup/stringDedup.hpp"
  40 #include "logging/log.hpp"
  41 #include "logging/logStream.hpp"
  42 #include "memory/allocation.inline.hpp"
  43 #include "memory/oopFactory.hpp"
  44 #include "memory/resourceArea.hpp"
  45 #include "oops/access.inline.hpp"
  46 #include "oops/compressedOops.hpp"
  47 #include "oops/oop.inline.hpp"
  48 #include "oops/typeArrayOop.inline.hpp"
  49 #include "oops/weakHandle.inline.hpp"
  50 #include "runtime/atomic.hpp"
  51 #include "runtime/handles.inline.hpp"
  52 #include "runtime/interfaceSupport.inline.hpp"
  53 #include "runtime/mutexLocker.hpp"
  54 #include "runtime/safepointVerifiers.hpp"
  55 #include "runtime/timerTrace.hpp"

  99 
 100 typedef CompactHashtable<
 101   const StringTable::StringWrapper&, oop,
 102   StringTable::read_string_from_compact_hashtable,
 103   StringTable::wrapped_string_equals> SharedStringTable;
 104 
 105 static SharedStringTable _shared_table;
 106 #endif
 107 
 108 // --------------------------------------------------------------------------
 109 
 110 typedef ConcurrentHashTable<StringTableConfig, mtSymbol> StringTableHash;
 111 static StringTableHash* _local_table = nullptr;
 112 
 113 volatile bool StringTable::_has_work = false;
 114 volatile bool StringTable::_needs_rehashing = false;
 115 OopStorage*   StringTable::_oop_storage;
 116 
 117 static size_t _current_size = 0;
 118 static volatile size_t _items_count = 0;
 119 DEBUG_ONLY(static bool _disable_interning_during_cds_dump = false);
 120 
 121 volatile bool _alt_hash = false;
 122 
 123 static bool _rehashed = false;
 124 static uint64_t _alt_hash_seed = 0;
 125 
 126 enum class StringType {
 127   OopStr, UnicodeStr, SymbolStr, UTF8Str
 128 };
 129 
 130 struct StringWrapperInternal {
 131   union {
 132     const Handle oop_str;
 133     const jchar* unicode_str;
 134     const Symbol* symbol_str;
 135     const char* utf8_str;
 136   };
 137   const StringType type;
 138   const size_t length;
 139 

 331 void StringTable::item_removed() {
 332   Atomic::dec(&_items_count);
 333 }
 334 
 335 double StringTable::get_load_factor() {
 336   return double(_items_count)/double(_current_size);
 337 }
 338 
 339 double StringTable::get_dead_factor(size_t num_dead) {
 340   return double(num_dead)/double(_current_size);
 341 }
 342 
 343 size_t StringTable::table_size() {
 344   return ((size_t)1) << _local_table->get_size_log2(Thread::current());
 345 }
 346 
 347 bool StringTable::has_work() {
 348   return Atomic::load_acquire(&_has_work);
 349 }
 350 
 351 size_t StringTable::items_count_acquire() {
 352   return Atomic::load_acquire(&_items_count);
 353 }
 354 
 355 void StringTable::trigger_concurrent_work() {
 356   // Avoid churn on ServiceThread
 357   if (!has_work()) {
 358     MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
 359     Atomic::store(&_has_work, true);
 360     Service_lock->notify_all();
 361   }
 362 }
 363 
 364 // Probing
 365 oop StringTable::lookup(Symbol* symbol) {
 366   ResourceMark rm;
 367   int length;
 368   jchar* chars = symbol->as_unicode(length);
 369   return lookup(chars, length);
 370 }
 371 
 372 oop StringTable::lookup(const jchar* name, int len) {
 373   unsigned int hash = java_lang_String::hash_code(name, len);
 374   StringWrapper wrapped_name(name, len);

 493 }
 494 
 495 oop StringTable::intern(oop string, TRAPS) {
 496   if (string == nullptr) return nullptr;
 497   int length = java_lang_String::length(string);
 498   Handle h_string (THREAD, string);
 499   StringWrapper name(h_string, length);
 500   oop result = intern(name, CHECK_NULL);
 501   return result;
 502 }
 503 
 504 oop StringTable::intern(const char* utf8_string, TRAPS) {
 505   if (utf8_string == nullptr) return nullptr;
 506   size_t length = strlen(utf8_string);
 507   StringWrapper name(utf8_string, length);
 508   oop result = intern(name, CHECK_NULL);
 509   return result;
 510 }
 511 
 512 oop StringTable::intern(const StringWrapper& name, TRAPS) {
 513   assert(!Atomic::load_acquire(&_disable_interning_during_cds_dump),
 514          "All threads that may intern strings should have been stopped before CDS starts copying the interned string table");
 515 
 516   // shared table always uses java_lang_String::hash_code
 517   unsigned int hash = hash_wrapped_string(name);
 518   oop found_string = lookup_shared(name, hash);
 519   if (found_string != nullptr) {
 520     return found_string;
 521   }
 522 
 523   if (_alt_hash) {
 524     ResourceMark rm(THREAD);
 525     // Convert to unicode for alt hashing
 526     int unicode_length;
 527     const jchar* chars = to_unicode(name, unicode_length, CHECK_NULL);
 528     hash = hash_string(chars, unicode_length, true);
 529   }
 530 
 531   found_string = do_lookup(name, hash);
 532   if (found_string != nullptr) {
 533     return found_string;
 534   }
 535   return do_intern(name, hash, THREAD);

 785 
 786 // Verification
 787 class VerifyStrings : StackObj {
 788  public:
 789   bool operator()(WeakHandle* val) {
 790     oop s = val->peek();
 791     if (s != nullptr) {
 792       assert(java_lang_String::length(s) >= 0, "Length on string must work.");
 793     }
 794     return true;
 795   };
 796 };
 797 
 798 // This verification is part of Universe::verify() and needs to be quick.
 799 void StringTable::verify() {
 800   VerifyStrings vs;
 801   _local_table->do_safepoint_scan(vs);
 802 }
 803 
 804 // Verification and comp
 805 class StringTable::VerifyCompStrings : StackObj {
 806   static unsigned string_hash(oop const& str) {
 807     return java_lang_String::hash_code_noupdate(str);
 808   }
 809   static bool string_equals(oop const& a, oop const& b) {
 810     return java_lang_String::equals(a, b);
 811   }
 812 
 813   ResizeableResourceHashtable<oop, bool, AnyObj::C_HEAP, mtInternal,
 814                               string_hash, string_equals> _table;
 815  public:
 816   size_t _errors;
 817   VerifyCompStrings() : _table(unsigned(items_count_acquire() / 8) + 1, 0 /* do not resize */), _errors(0) {}
 818   bool operator()(WeakHandle* val) {
 819     oop s = val->resolve();
 820     if (s == nullptr) {
 821       return true;
 822     }
 823     bool created;
 824     _table.put_if_absent(s, true, &created);
 825     assert(created, "Duplicate strings");
 826     if (!created) {
 827       _errors++;
 828     }
 829     return true;
 830   };
 831 };
 832 
 833 size_t StringTable::verify_and_compare_entries() {
 834   Thread* thr = Thread::current();
 835   VerifyCompStrings vcs;
 836   _local_table->do_scan(thr, vcs);
 837   return vcs._errors;

 931 
 932 // Sharing
 933 #if INCLUDE_CDS_JAVA_HEAP
 934 size_t StringTable::shared_entry_count() {
 935   return _shared_table.entry_count();
 936 }
 937 
 938 oop StringTable::lookup_shared(const StringWrapper& name, unsigned int hash) {
 939   assert(hash == hash_wrapped_string(name),
 940          "hash must be computed using java_lang_String::hash_code");
 941   // len is required but is already part of StringWrapper, so 0 is used
 942   return _shared_table.lookup(name, hash, 0);
 943 }
 944 
 945 oop StringTable::lookup_shared(const jchar* name, int len) {
 946   StringWrapper wrapped_name(name, len);
 947   // len is required but is already part of StringWrapper, so 0 is used
 948   return _shared_table.lookup(wrapped_name, java_lang_String::hash_code(name, len), 0);
 949 }
 950 
 951 // This is called BEFORE we enter the CDS safepoint. We can still allocate Java object arrays to
 952 // be used by the shared strings table.

 953 void StringTable::allocate_shared_strings_array(TRAPS) {
 954   if (!CDSConfig::is_dumping_heap()) {
 955     return;
 956   }

 957 
 958   CompileBroker::wait_for_no_active_tasks();
 959 
 960   precond(CDSConfig::allow_only_single_java_thread());
 961 
 962   // At this point, no more strings will be added:
 963   // - There's only a single Java thread (this thread). It no longer executes Java bytecodes
 964   //   so JIT compilation will eventually stop.
 965   // - CompileBroker has no more active tasks, so all JIT requests have been processed.
 966 
 967   // This flag will be cleared after intern table dumping has completed, so we can run the
 968   // compiler again (for future AOT method compilation, etc).
 969   DEBUG_ONLY(Atomic::release_store(&_disable_interning_during_cds_dump, true));
 970 
 971   if (items_count_acquire() > (size_t)max_jint) {
 972     fatal("Too many strings to be archived: %zu", items_count_acquire());
 973   }
 974 
 975   int total = (int)items_count_acquire();
 976   size_t single_array_size = objArrayOopDesc::object_size(total);
 977 
 978   log_info(aot)("allocated string table for %d strings", total);
 979 
 980   if (!ArchiveHeapWriter::is_too_large_to_archive(single_array_size)) {
 981     // The entire table can fit in a single array
 982     objArrayOop array = oopFactory::new_objArray(vmClasses::Object_klass(), total, CHECK);
 983     _shared_strings_array = OopHandle(Universe::vm_global(), array);
 984     log_info(aot)("string table array (single level) length = %d", total);
 985   } else {
 986     // Split the table in two levels of arrays.
 987     int primary_array_length = (total + _secondary_array_max_length - 1) / _secondary_array_max_length;
 988     size_t primary_array_size = objArrayOopDesc::object_size(primary_array_length);
 989     size_t secondary_array_size = objArrayOopDesc::object_size(_secondary_array_max_length);
 990 
 991     if (ArchiveHeapWriter::is_too_large_to_archive(secondary_array_size)) {
 992       // This can only happen if you have an extremely large number of classes that
 993       // refer to more than 16384 * 16384 = 26M interned strings! Not a practical concern
 994       // but bail out for safety.
 995       log_error(aot)("Too many strings to be archived: %zu", items_count_acquire());
 996       MetaspaceShared::unrecoverable_writing_error();
 997     }
 998 
 999     objArrayOop primary = oopFactory::new_objArray(vmClasses::Object_klass(), primary_array_length, CHECK);
1000     objArrayHandle primaryHandle(THREAD, primary);
1001     _shared_strings_array = OopHandle(Universe::vm_global(), primary);
1002 
1003     log_info(aot)("string table array (primary) length = %d", primary_array_length);
1004     for (int i = 0; i < primary_array_length; i++) {
1005       int len;
1006       if (total > _secondary_array_max_length) {
1007         len = _secondary_array_max_length;
1008       } else {
1009         len = total;
1010       }
1011       total -= len;
1012 
1013       objArrayOop secondary = oopFactory::new_objArray(vmClasses::Object_klass(), len, CHECK);
1014       primaryHandle()->obj_at_put(i, secondary);
1015 

1073 
1074         assert(primary_index < array->length(), "no strings should have been added");
1075         objArrayOop secondary = (objArrayOop)array->obj_at(primary_index);
1076 
1077         assert(secondary != nullptr && secondary->is_objArray(), "must be");
1078         assert(secondary_index < secondary->length(), "no strings should have been added");
1079         secondary->obj_at_put(secondary_index, string);
1080       }
1081       index ++;
1082     }
1083     return true;
1084   };
1085 
1086   _local_table->do_safepoint_scan(copy_into_array);
1087   log_info(aot)("Archived %d interned strings", index);
1088   return array;
1089 };
1090 
1091 void StringTable::write_shared_table() {
1092   _shared_table.reset();
1093   CompactHashtableWriter writer((int)items_count_acquire(), ArchiveBuilder::string_stats());
1094 
1095   int index = 0;
1096   auto copy_into_shared_table = [&] (WeakHandle* val) {
1097     oop string = val->peek();
1098     if (string != nullptr && !ArchiveHeapWriter::is_string_too_large_to_archive(string)) {
1099       unsigned int hash = java_lang_String::hash_code(string);
1100       writer.add(hash, index);
1101       index ++;
1102     }
1103     return true;
1104   };
1105   _local_table->do_safepoint_scan(copy_into_shared_table);
1106   writer.dump(&_shared_table, "string");
1107 
1108   DEBUG_ONLY(Atomic::release_store(&_disable_interning_during_cds_dump, false));
1109 }
1110 
1111 void StringTable::set_shared_strings_array_index(int root_index) {
1112   _shared_strings_array_root_index = root_index;
1113 }
1114 
1115 void StringTable::serialize_shared_table_header(SerializeClosure* soc) {
1116   if (soc->writing() && !CDSConfig::is_dumping_heap()) {
1117     _shared_table.reset();
1118     _is_two_dimensional_shared_strings_array = false;
1119     _shared_strings_array_root_index = -1;
1120   }
1121 
1122   _shared_table.serialize_header(soc);
1123 
1124   if (soc->writing()) {
1125     // Sanity. Make sure we don't use the shared table at dump time
1126     _shared_table.reset();
1127   } else if (!ArchiveHeapLoader::is_in_use()) {
1128     _shared_table.reset();
1129   }
1130 
1131   soc->do_bool(&_is_two_dimensional_shared_strings_array);
1132   soc->do_int(&_shared_strings_array_root_index);
1133 }
1134 #endif //INCLUDE_CDS_JAVA_HEAP
< prev index next >