1 /*
  2  * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 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 "precompiled.hpp"
 26 #include "cds/archiveBuilder.hpp"
 27 #include "cds/archiveHeapLoader.inline.hpp"
 28 #include "cds/archiveHeapWriter.hpp"
 29 #include "cds/cdsConfig.hpp"
 30 #include "cds/filemap.hpp"
 31 #include "cds/heapShared.hpp"
 32 #include "classfile/altHashing.hpp"
 33 #include "classfile/compactHashtable.hpp"
 34 #include "classfile/javaClasses.inline.hpp"
 35 #include "classfile/stringTable.hpp"
 36 #include "classfile/vmClasses.hpp"
 37 #include "gc/shared/collectedHeap.hpp"
 38 #include "gc/shared/oopStorage.inline.hpp"
 39 #include "gc/shared/oopStorageSet.hpp"
 40 #include "gc/shared/stringdedup/stringDedup.hpp"
 41 #include "logging/log.hpp"
 42 #include "logging/logStream.hpp"
 43 #include "memory/allocation.inline.hpp"
 44 #include "memory/oopFactory.hpp"
 45 #include "memory/resourceArea.hpp"
 46 #include "oops/access.inline.hpp"
 47 #include "oops/compressedOops.hpp"
 48 #include "oops/oop.inline.hpp"
 49 #include "oops/typeArrayOop.inline.hpp"
 50 #include "oops/weakHandle.inline.hpp"
 51 #include "runtime/atomic.hpp"
 52 #include "runtime/handles.inline.hpp"
 53 #include "runtime/interfaceSupport.inline.hpp"
 54 #include "runtime/mutexLocker.hpp"
 55 #include "runtime/safepointVerifiers.hpp"
 56 #include "runtime/timerTrace.hpp"
 57 #include "runtime/trimNativeHeap.hpp"
 58 #include "runtime/vmOperations.hpp"
 59 #include "services/diagnosticCommand.hpp"
 60 #include "utilities/concurrentHashTable.inline.hpp"
 61 #include "utilities/concurrentHashTableTasks.inline.hpp"
 62 #include "utilities/macros.hpp"
 63 #include "utilities/resizeableResourceHash.hpp"
 64 #include "utilities/utf8.hpp"
 65 #if INCLUDE_G1GC
 66 #include "gc/g1/g1CollectedHeap.hpp"
 67 #endif
 68 
 69 // We prefer short chains of avg 2
 70 const double PREF_AVG_LIST_LEN = 2.0;
 71 // 2^24 is max size
 72 const size_t END_SIZE = 24;
 73 // If a chain gets to 100 something might be wrong
 74 const size_t REHASH_LEN = 100;
 75 // If we have as many dead items as 50% of the number of bucket
 76 const double CLEAN_DEAD_HIGH_WATER_MARK = 0.5;
 77 
 78 #if INCLUDE_CDS_JAVA_HEAP
 79 bool StringTable::_is_two_dimensional_shared_strings_array = false;
 80 OopHandle StringTable::_shared_strings_array;
 81 int StringTable::_shared_strings_array_root_index;
 82 
 83 inline oop StringTable::read_string_from_compact_hashtable(address base_address, u4 index) {
 84   assert(ArchiveHeapLoader::is_in_use(), "sanity");
 85   objArrayOop array = (objArrayOop)(_shared_strings_array.resolve());
 86   oop s;
 87 
 88   if (!_is_two_dimensional_shared_strings_array) {
 89     s = array->obj_at((int)index);
 90   } else {
 91     int primary_index = index >> _secondary_array_index_bits;
 92     int secondary_index = index & _secondary_array_index_mask;
 93     objArrayOop secondary = (objArrayOop)array->obj_at(primary_index);
 94     s = secondary->obj_at(secondary_index);
 95   }
 96 
 97   assert(java_lang_String::is_instance(s), "must be");
 98   return s;
 99 }
100 
101 typedef CompactHashtable<
102   const jchar*, oop,
103   StringTable::read_string_from_compact_hashtable,
104   java_lang_String::equals> SharedStringTable;
105 
106 static SharedStringTable _shared_table;
107 #endif
108 
109 // --------------------------------------------------------------------------
110 
111 typedef ConcurrentHashTable<StringTableConfig, mtSymbol> StringTableHash;
112 static StringTableHash* _local_table = nullptr;
113 
114 volatile bool StringTable::_has_work = false;
115 volatile bool StringTable::_needs_rehashing = false;
116 OopStorage*   StringTable::_oop_storage;
117 
118 static size_t _current_size = 0;
119 static volatile size_t _items_count = 0;
120 
121 volatile bool _alt_hash = false;
122 
123 static bool _rehashed = false;
124 static uint64_t _alt_hash_seed = 0;
125 
126 static unsigned int hash_string(const jchar* s, int len, bool useAlt) {
127   return  useAlt ?
128     AltHashing::halfsiphash_32(_alt_hash_seed, s, len) :
129     java_lang_String::hash_code(s, len);
130 }
131 
132 class StringTableConfig : public StackObj {
133  private:
134  public:
135   typedef WeakHandle Value;
136 
137   static uintx get_hash(Value const& value, bool* is_dead) {
138     oop val_oop = value.peek();
139     if (val_oop == nullptr) {
140       *is_dead = true;
141       return 0;
142     }
143     *is_dead = false;
144     ResourceMark rm;
145     // All String oops are hashed as unicode
146     int length;
147     jchar* chars = java_lang_String::as_unicode_string_or_null(val_oop, length);
148     if (chars != nullptr) {
149       return hash_string(chars, length, _alt_hash);
150     }
151     vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "get hash from oop");
152     return 0;
153   }
154   // We use default allocation/deallocation but counted
155   static void* allocate_node(void* context, size_t size, Value const& value) {
156     StringTable::item_added();
157     return AllocateHeap(size, mtSymbol);
158   }
159   static void free_node(void* context, void* memory, Value& value) {
160     value.release(StringTable::_oop_storage);
161     FreeHeap(memory);
162     StringTable::item_removed();
163   }
164 };
165 
166 class StringTableLookupJchar : StackObj {
167  private:
168   Thread* _thread;
169   uintx _hash;
170   int _len;
171   const jchar* _str;
172   Handle _found;
173 
174  public:
175   StringTableLookupJchar(Thread* thread, uintx hash, const jchar* key, int len)
176     : _thread(thread), _hash(hash), _len(len), _str(key) {
177   }
178   uintx get_hash() const {
179     return _hash;
180   }
181   bool equals(WeakHandle* value) {
182     oop val_oop = value->peek();
183     if (val_oop == nullptr) {
184       return false;
185     }
186     bool equals = java_lang_String::equals(val_oop, _str, _len);
187     if (!equals) {
188       return false;
189     }
190     // Need to resolve weak handle and Handleize through possible safepoint.
191      _found = Handle(_thread, value->resolve());
192     return true;
193   }
194   bool is_dead(WeakHandle* value) {
195     oop val_oop = value->peek();
196     return val_oop == nullptr;
197   }
198 };
199 
200 class StringTableLookupOop : public StackObj {
201  private:
202   Thread* _thread;
203   uintx _hash;
204   Handle _find;
205   Handle _found;  // Might be a different oop with the same value that's already
206                   // in the table, which is the point.
207  public:
208   StringTableLookupOop(Thread* thread, uintx hash, Handle handle)
209     : _thread(thread), _hash(hash), _find(handle) { }
210 
211   uintx get_hash() const {
212     return _hash;
213   }
214 
215   bool equals(WeakHandle* value) {
216     oop val_oop = value->peek();
217     if (val_oop == nullptr) {
218       return false;
219     }
220     bool equals = java_lang_String::equals(_find(), val_oop);
221     if (!equals) {
222       return false;
223     }
224     // Need to resolve weak handle and Handleize through possible safepoint.
225     _found = Handle(_thread, value->resolve());
226     return true;
227   }
228 
229   bool is_dead(WeakHandle* value) {
230     oop val_oop = value->peek();
231     return val_oop == nullptr;
232   }
233 };
234 
235 void StringTable::create_table() {
236   size_t start_size_log_2 = ceil_log2(StringTableSize);
237   _current_size = ((size_t)1) << start_size_log_2;
238   log_trace(stringtable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")",
239                          _current_size, start_size_log_2);
240   _local_table = new StringTableHash(start_size_log_2, END_SIZE, REHASH_LEN, true);
241   _oop_storage = OopStorageSet::create_weak("StringTable Weak", mtSymbol);
242   _oop_storage->register_num_dead_callback(&gc_notification);
243 
244 #if INCLUDE_CDS_JAVA_HEAP
245   if (ArchiveHeapLoader::is_in_use()) {
246     _shared_strings_array = OopHandle(Universe::vm_global(), HeapShared::get_root(_shared_strings_array_root_index));
247   }
248 #endif
249 }
250 
251 void StringTable::item_added() {
252   Atomic::inc(&_items_count);
253 }
254 
255 void StringTable::item_removed() {
256   Atomic::dec(&_items_count);
257 }
258 
259 double StringTable::get_load_factor() {
260   return double(_items_count)/double(_current_size);
261 }
262 
263 double StringTable::get_dead_factor(size_t num_dead) {
264   return double(num_dead)/double(_current_size);
265 }
266 
267 size_t StringTable::table_size() {
268   return ((size_t)1) << _local_table->get_size_log2(Thread::current());
269 }
270 
271 bool StringTable::has_work() {
272   return Atomic::load_acquire(&_has_work);
273 }
274 
275 void StringTable::trigger_concurrent_work() {
276   // Avoid churn on ServiceThread
277   if (!has_work()) {
278     MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
279     Atomic::store(&_has_work, true);
280     Service_lock->notify_all();
281   }
282 }
283 
284 // Probing
285 oop StringTable::lookup(Symbol* symbol) {
286   ResourceMark rm;
287   int length;
288   jchar* chars = symbol->as_unicode(length);
289   return lookup(chars, length);
290 }
291 
292 oop StringTable::lookup(const jchar* name, int len) {
293   unsigned int hash = java_lang_String::hash_code(name, len);
294   oop string = lookup_shared(name, len, hash);
295   if (string != nullptr) {
296     return string;
297   }
298   if (_alt_hash) {
299     hash = hash_string(name, len, true);
300   }
301   return do_lookup(name, len, hash);
302 }
303 
304 class StringTableGet : public StackObj {
305   Thread* _thread;
306   Handle  _return;
307  public:
308   StringTableGet(Thread* thread) : _thread(thread) {}
309   void operator()(WeakHandle* val) {
310     oop result = val->resolve();
311     assert(result != nullptr, "Result should be reachable");
312     _return = Handle(_thread, result);
313   }
314   oop get_res_oop() {
315     return _return();
316   }
317 };
318 
319 void StringTable::update_needs_rehash(bool rehash) {
320   if (rehash) {
321     _needs_rehashing = true;
322     trigger_concurrent_work();
323   }
324 }
325 
326 oop StringTable::do_lookup(const jchar* name, int len, uintx hash) {
327   Thread* thread = Thread::current();
328   StringTableLookupJchar lookup(thread, hash, name, len);
329   StringTableGet stg(thread);
330   bool rehash_warning;
331   _local_table->get(thread, lookup, stg, &rehash_warning);
332   update_needs_rehash(rehash_warning);
333   return stg.get_res_oop();
334 }
335 
336 // Interning
337 oop StringTable::intern(Symbol* symbol, TRAPS) {
338   if (symbol == nullptr) return nullptr;
339   ResourceMark rm(THREAD);
340   int length;
341   jchar* chars = symbol->as_unicode(length);
342   Handle string;
343   oop result = intern(string, chars, length, CHECK_NULL);
344   return result;
345 }
346 
347 oop StringTable::intern(oop string, TRAPS) {
348   if (string == nullptr) return nullptr;
349   ResourceMark rm(THREAD);
350   int length;
351   Handle h_string (THREAD, string);
352   jchar* chars = java_lang_String::as_unicode_string(string, length,
353                                                      CHECK_NULL);
354   oop result = intern(h_string, chars, length, CHECK_NULL);
355   return result;
356 }
357 
358 oop StringTable::intern(const char* utf8_string, TRAPS) {
359   if (utf8_string == nullptr) return nullptr;
360   ResourceMark rm(THREAD);
361   int length = UTF8::unicode_length(utf8_string);
362   jchar* chars = NEW_RESOURCE_ARRAY(jchar, length);
363   UTF8::convert_to_unicode(utf8_string, chars, length);
364   Handle string;
365   oop result = intern(string, chars, length, CHECK_NULL);
366   return result;
367 }
368 
369 oop StringTable::intern(Handle string_or_null_h, const jchar* name, int len, TRAPS) {
370   // shared table always uses java_lang_String::hash_code
371   unsigned int hash = java_lang_String::hash_code(name, len);
372   oop found_string = lookup_shared(name, len, hash);
373   if (found_string != nullptr) {
374     return found_string;
375   }
376   if (_alt_hash) {
377     hash = hash_string(name, len, true);
378   }
379   found_string = do_lookup(name, len, hash);
380   if (found_string != nullptr) {
381     return found_string;
382   }
383   return do_intern(string_or_null_h, name, len, hash, THREAD);
384 }
385 
386 oop StringTable::do_intern(Handle string_or_null_h, const jchar* name,
387                            int len, uintx hash, TRAPS) {
388   HandleMark hm(THREAD);  // cleanup strings created
389   Handle string_h;
390 
391   if (!string_or_null_h.is_null()) {
392     string_h = string_or_null_h;
393   } else {
394     string_h = java_lang_String::create_from_unicode(name, len, CHECK_NULL);
395   }
396 
397   assert(java_lang_String::equals(string_h(), name, len),
398          "string must be properly initialized");
399   assert(len == java_lang_String::length(string_h()), "Must be same length");
400 
401   // Notify deduplication support that the string is being interned.  A string
402   // must never be deduplicated after it has been interned.  Doing so interferes
403   // with compiler optimizations done on e.g. interned string literals.
404   if (StringDedup::is_enabled()) {
405     StringDedup::notify_intern(string_h());
406   }
407 
408   StringTableLookupOop lookup(THREAD, hash, string_h);
409   StringTableGet stg(THREAD);
410 
411   bool rehash_warning;
412   do {
413     // Callers have already looked up the String using the jchar* name, so just go to add.
414     WeakHandle wh(_oop_storage, string_h);
415     // The hash table takes ownership of the WeakHandle, even if it's not inserted.
416     if (_local_table->insert(THREAD, lookup, wh, &rehash_warning)) {
417       update_needs_rehash(rehash_warning);
418       return wh.resolve();
419     }
420     // In case another thread did a concurrent add, return value already in the table.
421     // This could fail if the String got gc'ed concurrently, so loop back until success.
422     if (_local_table->get(THREAD, lookup, stg, &rehash_warning)) {
423       update_needs_rehash(rehash_warning);
424       return stg.get_res_oop();
425     }
426   } while(true);
427 }
428 
429 // Concurrent work
430 void StringTable::grow(JavaThread* jt) {
431   StringTableHash::GrowTask gt(_local_table);
432   if (!gt.prepare(jt)) {
433     return;
434   }
435   log_trace(stringtable)("Started to grow");
436   {
437     TraceTime timer("Grow", TRACETIME_LOG(Debug, stringtable, perf));
438     while (gt.do_task(jt)) {
439       gt.pause(jt);
440       {
441         ThreadBlockInVM tbivm(jt);
442       }
443       gt.cont(jt);
444     }
445   }
446   gt.done(jt);
447   _current_size = table_size();
448   log_debug(stringtable)("Grown to size:" SIZE_FORMAT, _current_size);
449 }
450 
451 struct StringTableDoDelete : StackObj {
452   void operator()(WeakHandle* val) {
453     /* do nothing */
454   }
455 };
456 
457 struct StringTableDeleteCheck : StackObj {
458   long _count;
459   long _item;
460   StringTableDeleteCheck() : _count(0), _item(0) {}
461   bool operator()(WeakHandle* val) {
462     ++_item;
463     oop tmp = val->peek();
464     if (tmp == nullptr) {
465       ++_count;
466       return true;
467     } else {
468       return false;
469     }
470   }
471 };
472 
473 void StringTable::clean_dead_entries(JavaThread* jt) {
474   StringTableHash::BulkDeleteTask bdt(_local_table);
475   if (!bdt.prepare(jt)) {
476     return;
477   }
478 
479   StringTableDeleteCheck stdc;
480   StringTableDoDelete stdd;
481   NativeHeapTrimmer::SuspendMark sm("stringtable");
482   {
483     TraceTime timer("Clean", TRACETIME_LOG(Debug, stringtable, perf));
484     while(bdt.do_task(jt, stdc, stdd)) {
485       bdt.pause(jt);
486       {
487         ThreadBlockInVM tbivm(jt);
488       }
489       bdt.cont(jt);
490     }
491     bdt.done(jt);
492   }
493   log_debug(stringtable)("Cleaned %ld of %ld", stdc._count, stdc._item);
494 }
495 
496 void StringTable::gc_notification(size_t num_dead) {
497   log_trace(stringtable)("Uncleaned items:" SIZE_FORMAT, num_dead);
498 
499   if (has_work()) {
500     return;
501   }
502 
503   double load_factor = StringTable::get_load_factor();
504   double dead_factor = StringTable::get_dead_factor(num_dead);
505   // We should clean/resize if we have more dead than alive,
506   // more items than preferred load factor or
507   // more dead items than water mark.
508   if ((dead_factor > load_factor) ||
509       (load_factor > PREF_AVG_LIST_LEN) ||
510       (dead_factor > CLEAN_DEAD_HIGH_WATER_MARK)) {
511     log_debug(stringtable)("Concurrent work triggered, live factor: %g dead factor: %g",
512                            load_factor, dead_factor);
513     trigger_concurrent_work();
514   }
515 }
516 
517 bool StringTable::should_grow() {
518   return get_load_factor() > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached();
519 }
520 
521 void StringTable::do_concurrent_work(JavaThread* jt) {
522   // Rehash if needed.  Rehashing goes to a safepoint but the rest of this
523   // work is concurrent.
524   if (needs_rehashing() && maybe_rehash_table()) {
525     Atomic::release_store(&_has_work, false);
526     return; // done, else grow
527   }
528   log_debug(stringtable, perf)("Concurrent work, live factor: %g", get_load_factor());
529   // We prefer growing, since that also removes dead items
530   if (should_grow()) {
531     grow(jt);
532   } else {
533     clean_dead_entries(jt);
534   }
535   Atomic::release_store(&_has_work, false);
536 }
537 
538 // Called at VM_Operation safepoint
539 void StringTable::rehash_table() {
540   assert(SafepointSynchronize::is_at_safepoint(), "must be called at safepoint");
541   // The ServiceThread initiates the rehashing so it is not resizing.
542   assert (_local_table->is_safepoint_safe(), "Should not be resizing now");
543 
544   _alt_hash_seed = AltHashing::compute_seed();
545 
546   // We use current size, not max size.
547   size_t new_size = _local_table->get_size_log2(Thread::current());
548   StringTableHash* new_table = new StringTableHash(new_size, END_SIZE, REHASH_LEN, true);
549   // Use alt hash from now on
550   _alt_hash = true;
551   _local_table->rehash_nodes_to(Thread::current(), new_table);
552 
553   // free old table
554   delete _local_table;
555   _local_table = new_table;
556 
557   _rehashed = true;
558   _needs_rehashing = false;
559 }
560 
561 bool StringTable::maybe_rehash_table() {
562   log_debug(stringtable)("Table imbalanced, rehashing called.");
563 
564   // Grow instead of rehash.
565   if (should_grow()) {
566     log_debug(stringtable)("Choosing growing over rehashing.");
567     _needs_rehashing = false;
568     return false;
569   }
570   // Already rehashed.
571   if (_rehashed) {
572     log_warning(stringtable)("Rehashing already done, still long lists.");
573     _needs_rehashing = false;
574     return false;
575   }
576 
577   VM_RehashStringTable op;
578   VMThread::execute(&op);
579   return true;  // return true because we tried.
580 }
581 
582 // Statistics
583 static size_t literal_size(oop obj) {
584   if (obj == nullptr) {
585     return 0;
586   }
587 
588   size_t word_size = obj->size();
589 
590   if (obj->klass() == vmClasses::String_klass()) {
591     // This may overcount if String.value arrays are shared.
592     word_size += java_lang_String::value(obj)->size();
593   }
594 
595   return word_size * HeapWordSize;
596 }
597 
598 struct SizeFunc : StackObj {
599   size_t operator()(WeakHandle* val) {
600     oop s = val->peek();
601     if (s == nullptr) {
602       // Dead
603       return 0;
604     }
605     return literal_size(s);
606   };
607 };
608 
609 TableStatistics StringTable::get_table_statistics() {
610   static TableStatistics ts;
611   SizeFunc sz;
612   ts = _local_table->statistics_get(Thread::current(), sz, ts);
613   return ts;
614 }
615 
616 void StringTable::print_table_statistics(outputStream* st) {
617   SizeFunc sz;
618   _local_table->statistics_to(Thread::current(), sz, st, "StringTable");
619 #if INCLUDE_CDS_JAVA_HEAP
620   if (!_shared_table.empty()) {
621     _shared_table.print_table_statistics(st, "Shared String Table");
622   }
623 #endif
624 }
625 
626 // Verification
627 class VerifyStrings : StackObj {
628  public:
629   bool operator()(WeakHandle* val) {
630     oop s = val->peek();
631     if (s != nullptr) {
632       assert(java_lang_String::length(s) >= 0, "Length on string must work.");
633     }
634     return true;
635   };
636 };
637 
638 // This verification is part of Universe::verify() and needs to be quick.
639 void StringTable::verify() {
640   VerifyStrings vs;
641   _local_table->do_safepoint_scan(vs);
642 }
643 
644 // Verification and comp
645 class VerifyCompStrings : StackObj {
646   static unsigned string_hash(oop const& str) {
647     return java_lang_String::hash_code_noupdate(str);
648   }
649   static bool string_equals(oop const& a, oop const& b) {
650     return java_lang_String::equals(a, b);
651   }
652 
653   ResizeableResourceHashtable<oop, bool, AnyObj::C_HEAP, mtInternal,
654                               string_hash, string_equals> _table;
655  public:
656   size_t _errors;
657   VerifyCompStrings() : _table(unsigned(_items_count / 8) + 1, 0 /* do not resize */), _errors(0) {}
658   bool operator()(WeakHandle* val) {
659     oop s = val->resolve();
660     if (s == nullptr) {
661       return true;
662     }
663     bool created;
664     _table.put_if_absent(s, true, &created);
665     assert(created, "Duplicate strings");
666     if (!created) {
667       _errors++;
668     }
669     return true;
670   };
671 };
672 
673 size_t StringTable::verify_and_compare_entries() {
674   Thread* thr = Thread::current();
675   VerifyCompStrings vcs;
676   _local_table->do_scan(thr, vcs);
677   return vcs._errors;
678 }
679 
680 static void print_string(Thread* current, outputStream* st, oop s) {
681   typeArrayOop value     = java_lang_String::value_no_keepalive(s);
682   int          length    = java_lang_String::length(s);
683   bool         is_latin1 = java_lang_String::is_latin1(s);
684 
685   if (length <= 0) {
686     st->print("%d: ", length);
687   } else {
688     ResourceMark rm(current);
689     size_t utf8_length = length;
690     char* utf8_string;
691 
692     if (!is_latin1) {
693       jchar* chars = value->char_at_addr(0);
694       utf8_string = UNICODE::as_utf8(chars, utf8_length);
695     } else {
696       jbyte* bytes = value->byte_at_addr(0);
697       utf8_string = UNICODE::as_utf8(bytes, utf8_length);
698     }
699 
700     st->print("%zu: ", utf8_length);
701     HashtableTextDump::put_utf8(st, utf8_string, utf8_length);
702   }
703   st->cr();
704 }
705 
706 // Dumping
707 class PrintString : StackObj {
708   Thread* _thr;
709   outputStream* _st;
710  public:
711   PrintString(Thread* thr, outputStream* st) : _thr(thr), _st(st) {}
712   bool operator()(WeakHandle* val) {
713     oop s = val->peek();
714     if (s == nullptr) {
715       return true;
716     }
717     print_string(_thr, _st, s);
718     return true;
719   };
720 };
721 
722 class PrintSharedString : StackObj {
723   Thread* _thr;
724   outputStream* _st;
725 public:
726   PrintSharedString(Thread* thr, outputStream* st) : _thr(thr), _st(st) {}
727   void do_value(oop s) {
728     if (s == nullptr) {
729       return;
730     }
731     print_string(_thr, _st, s);
732   };
733 };
734 
735 void StringTable::dump(outputStream* st, bool verbose) {
736   if (!verbose) {
737     print_table_statistics(st);
738   } else {
739     Thread* thr = Thread::current();
740     ResourceMark rm(thr);
741     st->print_cr("VERSION: 1.1");
742     PrintString ps(thr, st);
743     if (!_local_table->try_scan(thr, ps)) {
744       st->print_cr("dump unavailable at this moment");
745     }
746 #if INCLUDE_CDS_JAVA_HEAP
747     if (!_shared_table.empty()) {
748       st->print_cr("#----------------");
749       st->print_cr("# Shared strings:");
750       st->print_cr("#----------------");
751       PrintSharedString pss(thr, st);
752       _shared_table.iterate(&pss);
753     }
754 #endif
755   }
756 }
757 
758 // Utility for dumping strings
759 StringtableDCmd::StringtableDCmd(outputStream* output, bool heap) :
760                                  DCmdWithParser(output, heap),
761   _verbose("-verbose", "Dump the content of each string in the table",
762            "BOOLEAN", false, "false") {
763   _dcmdparser.add_dcmd_option(&_verbose);
764 }
765 
766 void StringtableDCmd::execute(DCmdSource source, TRAPS) {
767   VM_DumpHashtable dumper(output(), VM_DumpHashtable::DumpStrings,
768                          _verbose.value());
769   VMThread::execute(&dumper);
770 }
771 
772 // Sharing
773 #if INCLUDE_CDS_JAVA_HEAP
774 size_t StringTable::shared_entry_count() {
775   return _shared_table.entry_count();
776 }
777 
778 oop StringTable::lookup_shared(const jchar* name, int len, unsigned int hash) {
779   assert(hash == java_lang_String::hash_code(name, len),
780          "hash must be computed using java_lang_String::hash_code");
781   return _shared_table.lookup(name, hash, len);
782 }
783 
784 oop StringTable::lookup_shared(const jchar* name, int len) {
785   return _shared_table.lookup(name, java_lang_String::hash_code(name, len), len);
786 }
787 
788 // This is called BEFORE we enter the CDS safepoint. We can allocate heap objects.
789 // This should be called when we know no more strings will be added (which will be easy
790 // to guarantee because CDS runs with a single Java thread. See JDK-8253495.)
791 void StringTable::allocate_shared_strings_array(TRAPS) {
792   if (!CDSConfig::is_dumping_heap()) {
793     return;
794   }
795   if (_items_count > (size_t)max_jint) {
796     fatal("Too many strings to be archived: %zu", _items_count);
797   }
798 
799   int total = (int)_items_count;
800   size_t single_array_size = objArrayOopDesc::object_size(total);
801 
802   log_info(cds)("allocated string table for %d strings", total);
803 
804   if (!ArchiveHeapWriter::is_too_large_to_archive(single_array_size)) {
805     // The entire table can fit in a single array
806     objArrayOop array = oopFactory::new_objArray(vmClasses::Object_klass(), total, CHECK);
807     _shared_strings_array = OopHandle(Universe::vm_global(), array);
808     log_info(cds)("string table array (single level) length = %d", total);
809   } else {
810     // Split the table in two levels of arrays.
811     int primary_array_length = (total + _secondary_array_max_length - 1) / _secondary_array_max_length;
812     size_t primary_array_size = objArrayOopDesc::object_size(primary_array_length);
813     size_t secondary_array_size = objArrayOopDesc::object_size(_secondary_array_max_length);
814 
815     if (ArchiveHeapWriter::is_too_large_to_archive(secondary_array_size)) {
816       // This can only happen if you have an extremely large number of classes that
817       // refer to more than 16384 * 16384 = 26M interned strings! Not a practical concern
818       // but bail out for safety.
819       log_error(cds)("Too many strings to be archived: %zu", _items_count);
820       MetaspaceShared::unrecoverable_writing_error();
821     }
822 
823     objArrayOop primary = oopFactory::new_objArray(vmClasses::Object_klass(), primary_array_length, CHECK);
824     objArrayHandle primaryHandle(THREAD, primary);
825     _shared_strings_array = OopHandle(Universe::vm_global(), primary);
826 
827     log_info(cds)("string table array (primary) length = %d", primary_array_length);
828     for (int i = 0; i < primary_array_length; i++) {
829       int len;
830       if (total > _secondary_array_max_length) {
831         len = _secondary_array_max_length;
832       } else {
833         len = total;
834       }
835       total -= len;
836 
837       objArrayOop secondary = oopFactory::new_objArray(vmClasses::Object_klass(), len, CHECK);
838       primaryHandle()->obj_at_put(i, secondary);
839 
840       log_info(cds)("string table array (secondary)[%d] length = %d", i, len);
841       assert(!ArchiveHeapWriter::is_too_large_to_archive(secondary), "sanity");
842     }
843 
844     assert(total == 0, "must be");
845     _is_two_dimensional_shared_strings_array = true;
846   }
847 }
848 
849 #ifndef PRODUCT
850 void StringTable::verify_secondary_array_index_bits() {
851   int max;
852   for (max = 1; ; max++) {
853     size_t next_size = objArrayOopDesc::object_size(1 << (max + 1));
854     if (ArchiveHeapWriter::is_too_large_to_archive(next_size)) {
855       break;
856     }
857   }
858   // Currently max is 17 for +UseCompressedOops, 16 for -UseCompressedOops.
859   // When we add support for Shenandoah (which has a smaller mininum region size than G1),
860   // max will become 15/14.
861   //
862   // We use _secondary_array_index_bits==14 as that will be the eventual value, and will
863   // make testing easier.
864   assert(_secondary_array_index_bits <= max,
865          "_secondary_array_index_bits (%d) must be smaller than max possible value (%d)",
866          _secondary_array_index_bits, max);
867 }
868 #endif // PRODUCT
869 
870 // This is called AFTER we enter the CDS safepoint.
871 //
872 // For each shared string:
873 // [1] Store it into _shared_strings_array. Encode its position as a 32-bit index.
874 // [2] Store the index and hashcode into _shared_table.
875 oop StringTable::init_shared_table(const DumpedInternedStrings* dumped_interned_strings) {
876   assert(HeapShared::can_write(), "must be");
877   objArrayOop array = (objArrayOop)(_shared_strings_array.resolve());
878 
879   verify_secondary_array_index_bits();
880 
881   _shared_table.reset();
882   CompactHashtableWriter writer((int)_items_count, ArchiveBuilder::string_stats());
883 
884   int index = 0;
885   auto copy_into_array = [&] (oop string, bool value_ignored) {
886     unsigned int hash = java_lang_String::hash_code(string);
887     writer.add(hash, index);
888 
889     if (!_is_two_dimensional_shared_strings_array) {
890       assert(index < array->length(), "no strings should have been added");
891       array->obj_at_put(index, string);
892     } else {
893       int primary_index = index >> _secondary_array_index_bits;
894       int secondary_index = index & _secondary_array_index_mask;
895 
896       assert(primary_index < array->length(), "no strings should have been added");
897       objArrayOop secondary = (objArrayOop)array->obj_at(primary_index);
898 
899       assert(secondary != nullptr && secondary->is_objArray(), "must be");
900       assert(secondary_index < secondary->length(), "no strings should have been added");
901       secondary->obj_at_put(secondary_index, string);
902     }
903 
904     index ++;
905   };
906   dumped_interned_strings->iterate_all(copy_into_array);
907 
908   writer.dump(&_shared_table, "string");
909 
910   return array;
911 }
912 
913 void StringTable::set_shared_strings_array_index(int root_index) {
914   _shared_strings_array_root_index = root_index;
915 }
916 
917 void StringTable::serialize_shared_table_header(SerializeClosure* soc) {
918   _shared_table.serialize_header(soc);
919 
920   if (soc->writing()) {
921     // Sanity. Make sure we don't use the shared table at dump time
922     _shared_table.reset();
923   } else if (!ArchiveHeapLoader::is_in_use()) {
924     _shared_table.reset();
925   }
926 
927   soc->do_bool(&_is_two_dimensional_shared_strings_array);
928   soc->do_int(&_shared_strings_array_root_index);
929 }
930 #endif //INCLUDE_CDS_JAVA_HEAP