1 /*
2 * Copyright (c) 1997, 2025, 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 "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/atomicAccess.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"
56 #include "runtime/trimNativeHeap.hpp"
57 #include "runtime/vmOperations.hpp"
58 #include "services/diagnosticCommand.hpp"
59 #include "utilities/concurrentHashTable.inline.hpp"
60 #include "utilities/concurrentHashTableTasks.inline.hpp"
61 #include "utilities/macros.hpp"
62 #include "utilities/resizableHashTable.hpp"
63 #include "utilities/utf8.hpp"
64 #if INCLUDE_G1GC
65 #include "gc/g1/g1CollectedHeap.hpp"
66 #endif
67
68 // We prefer short chains of avg 2
69 const double PREF_AVG_LIST_LEN = 2.0;
70 // 2^24 is max size
71 const size_t END_SIZE = 24;
72 // If a chain gets to 100 something might be wrong
73 const size_t REHASH_LEN = 100;
74 // If we have as many dead items as 50% of the number of bucket
75 const double CLEAN_DEAD_HIGH_WATER_MARK = 0.5;
76
77 #if INCLUDE_CDS_JAVA_HEAP
78 bool StringTable::_is_two_dimensional_shared_strings_array = false;
79 OopHandle StringTable::_shared_strings_array;
80 int StringTable::_shared_strings_array_root_index;
81
82 inline oop StringTable::read_string_from_compact_hashtable(address base_address, u4 index) {
83 assert(ArchiveHeapLoader::is_in_use(), "sanity");
84 objArrayOop array = (objArrayOop)(_shared_strings_array.resolve());
85 oop s;
86
87 if (!_is_two_dimensional_shared_strings_array) {
88 s = array->obj_at((int)index);
89 } else {
90 int primary_index = index >> _secondary_array_index_bits;
91 int secondary_index = index & _secondary_array_index_mask;
92 objArrayOop secondary = (objArrayOop)array->obj_at(primary_index);
93 s = secondary->obj_at(secondary_index);
94 }
95
96 assert(java_lang_String::is_instance(s), "must be");
97 return s;
98 }
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
140 StringWrapperInternal(const Handle oop_str, const size_t length) : oop_str(oop_str), type(StringType::OopStr), length(length) {}
141 StringWrapperInternal(const jchar* unicode_str, const size_t length) : unicode_str(unicode_str), type(StringType::UnicodeStr), length(length) {}
142 StringWrapperInternal(const Symbol* symbol_str, const size_t length) : symbol_str(symbol_str), type(StringType::SymbolStr), length(length) {}
143 StringWrapperInternal(const char* utf8_str, const size_t length) : utf8_str(utf8_str), type(StringType::UTF8Str), length(length) {}
144 };
145
146 static unsigned int hash_string(const jchar* s, int len, bool useAlt) {
147 return useAlt ?
148 AltHashing::halfsiphash_32(_alt_hash_seed, s, len) :
149 java_lang_String::hash_code(s, len);
150 }
151
152 const char* StringTable::get_symbol_utf8(const StringWrapper& symbol) {
153 return reinterpret_cast<const char*>(symbol.symbol_str->bytes());
154 }
155
156 unsigned int StringTable::hash_wrapped_string(const StringWrapper& wrapped_str) {
157 switch (wrapped_str.type) {
158 case StringType::OopStr:
159 return java_lang_String::hash_code(wrapped_str.oop_str());
160 case StringType::UnicodeStr:
161 return java_lang_String::hash_code(wrapped_str.unicode_str, static_cast<int>(wrapped_str.length));
162 case StringType::SymbolStr:
163 return java_lang_String::hash_code(get_symbol_utf8(wrapped_str), wrapped_str.length);
164 case StringType::UTF8Str:
165 return java_lang_String::hash_code(wrapped_str.utf8_str, wrapped_str.length);
166 default:
167 ShouldNotReachHere();
168 }
169 return 0;
170 }
171
172 // Unnamed int needed to fit CompactHashtable's equals type signature
173 bool StringTable::wrapped_string_equals(oop java_string, const StringWrapper& wrapped_str, int) {
174 switch (wrapped_str.type) {
175 case StringType::OopStr:
176 return java_lang_String::equals(java_string, wrapped_str.oop_str());
177 case StringType::UnicodeStr:
178 return java_lang_String::equals(java_string, wrapped_str.unicode_str, static_cast<int>(wrapped_str.length));
179 case StringType::SymbolStr:
180 return java_lang_String::equals(java_string, get_symbol_utf8(wrapped_str), wrapped_str.length);
181 case StringType::UTF8Str:
182 return java_lang_String::equals(java_string, wrapped_str.utf8_str, wrapped_str.length);
183 default:
184 ShouldNotReachHere();
185 }
186 return false;
187 }
188
189 class StringTableConfig : public StackObj {
190 private:
191 public:
192 typedef WeakHandle Value;
193
194 static uintx get_hash(Value const& value, bool* is_dead) {
195 oop val_oop = value.peek();
196 if (val_oop == nullptr) {
197 *is_dead = true;
198 return 0;
199 }
200 *is_dead = false;
201 ResourceMark rm;
202 // All String oops are hashed as unicode
203 int length;
204 jchar* chars = java_lang_String::as_unicode_string_or_null(val_oop, length);
205 if (chars != nullptr) {
206 return hash_string(chars, length, _alt_hash);
207 }
208 vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "get hash from oop");
209 return 0;
210 }
211 // We use default allocation/deallocation but counted
212 static void* allocate_node(void* context, size_t size, Value const& value) {
213 StringTable::item_added();
214 return AllocateHeap(size, mtSymbol);
215 }
216 static void free_node(void* context, void* memory, Value& value) {
217 value.release(StringTable::_oop_storage);
218 FreeHeap(memory);
219 StringTable::item_removed();
220 }
221 };
222
223 class StringTableLookup : StackObj {
224 uintx _hash;
225
226 protected:
227 Thread* _thread;
228 Handle _found;
229
230 public:
231 StringTableLookup(Thread* thread, uintx hash)
232 : _hash(hash), _thread(thread) {}
233 uintx get_hash() const { return _hash; }
234 bool is_dead(WeakHandle* value) {
235 oop val_oop = value->peek();
236 return val_oop == nullptr;
237 }
238 };
239
240 class StringTableLookupUnicode : public StringTableLookup {
241 private:
242 const jchar* _str;
243 int _len;
244
245 public:
246 StringTableLookupUnicode(Thread* thread, uintx hash, const jchar* key, int len)
247 : StringTableLookup(thread, hash), _str(key), _len(len) {}
248
249 bool equals(const WeakHandle* value) {
250 oop val_oop = value->peek();
251 if (val_oop == nullptr) {
252 return false;
253 }
254 bool equals = java_lang_String::equals(val_oop, _str, _len);
255 if (!equals) {
256 return false;
257 }
258 // Need to resolve weak handle and Handleize through possible safepoint.
259 _found = Handle(_thread, value->resolve());
260 return true;
261 }
262 };
263
264 class StringTableLookupUTF8 : public StringTableLookup {
265 private:
266 const char* _str;
267 size_t _utf8_len;
268
269 public:
270 StringTableLookupUTF8(Thread* thread, uintx hash, const char* key, size_t utf8_len)
271 : StringTableLookup(thread, hash), _str(key), _utf8_len(utf8_len) {}
272
273 bool equals(const WeakHandle* value) {
274 oop val_oop = value->peek();
275 if (val_oop == nullptr) {
276 return false;
277 }
278 bool equals = java_lang_String::equals(val_oop, _str, _utf8_len);
279 if (!equals) {
280 return false;
281 }
282 // Need to resolve weak handle and Handleize through possible safepoint.
283 _found = Handle(_thread, value->resolve());
284 return true;
285 }
286 };
287
288 class StringTableLookupOop : public StringTableLookup {
289 private:
290 Handle _find;
291
292 public:
293 StringTableLookupOop(Thread* thread, uintx hash, Handle handle)
294 : StringTableLookup(thread, hash), _find(handle) {}
295
296 bool equals(WeakHandle* value) {
297 oop val_oop = value->peek();
298 if (val_oop == nullptr) {
299 return false;
300 }
301 bool equals = java_lang_String::equals(_find(), val_oop);
302 if (!equals) {
303 return false;
304 }
305 // Need to resolve weak handle and Handleize through possible safepoint.
306 _found = Handle(_thread, value->resolve());
307 return true;
308 }
309 };
310
311 void StringTable::create_table() {
312 size_t start_size_log_2 = log2i_ceil(StringTableSize);
313 _current_size = ((size_t)1) << start_size_log_2;
314 log_trace(stringtable)("Start size: %zu (%zu)",
315 _current_size, start_size_log_2);
316 _local_table = new StringTableHash(start_size_log_2, END_SIZE, REHASH_LEN, true);
317 _oop_storage = OopStorageSet::create_weak("StringTable Weak", mtSymbol);
318 _oop_storage->register_num_dead_callback(&gc_notification);
319
320 #if INCLUDE_CDS_JAVA_HEAP
321 if (ArchiveHeapLoader::is_in_use()) {
322 _shared_strings_array = OopHandle(Universe::vm_global(), HeapShared::get_root(_shared_strings_array_root_index));
323 }
324 #endif
325 }
326
327 void StringTable::item_added() {
328 AtomicAccess::inc(&_items_count);
329 }
330
331 void StringTable::item_removed() {
332 AtomicAccess::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 AtomicAccess::load_acquire(&_has_work);
349 }
350
351 size_t StringTable::items_count_acquire() {
352 return AtomicAccess::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 AtomicAccess::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);
375 oop string = lookup_shared(wrapped_name, hash);
376 if (string != nullptr) {
377 return string;
378 }
379 if (_alt_hash) {
380 hash = hash_string(name, len, true);
381 }
382 return do_lookup(wrapped_name, hash);
383 }
384
385 class StringTableGet : public StackObj {
386 Thread* _thread;
387 Handle _return;
388 public:
389 StringTableGet(Thread* thread) : _thread(thread) {}
390 void operator()(WeakHandle* val) {
391 oop result = val->resolve();
392 assert(result != nullptr, "Result should be reachable");
393 _return = Handle(_thread, result);
394 }
395 oop get_res_oop() {
396 return _return();
397 }
398 };
399
400 void StringTable::update_needs_rehash(bool rehash) {
401 if (rehash) {
402 _needs_rehashing = true;
403 trigger_concurrent_work();
404 }
405 }
406
407 oop StringTable::do_lookup(const StringWrapper& name, uintx hash) {
408 Thread* thread = Thread::current();
409 StringTableGet stg(thread);
410 bool rehash_warning;
411
412 switch (name.type) {
413 case StringType::OopStr: {
414 StringTableLookupOop lookup(thread, hash, name.oop_str);
415 _local_table->get(thread, lookup, stg, &rehash_warning);
416 break;
417 }
418 case StringType::UnicodeStr: {
419 StringTableLookupUnicode lookup(thread, hash, name.unicode_str, static_cast<int>(name.length));
420 _local_table->get(thread, lookup, stg, &rehash_warning);
421 break;
422 }
423 case StringType::SymbolStr: {
424 StringTableLookupUTF8 lookup(thread, hash, get_symbol_utf8(name), name.length);
425 _local_table->get(thread, lookup, stg, &rehash_warning);
426 break;
427 }
428 case StringType::UTF8Str: {
429 StringTableLookupUTF8 lookup(thread, hash, name.utf8_str, name.length);
430 _local_table->get(thread, lookup, stg, &rehash_warning);
431 break;
432 }
433 default:
434 ShouldNotReachHere();
435 }
436
437 update_needs_rehash(rehash_warning);
438 return stg.get_res_oop();
439 }
440
441 // Converts and allocates to a unicode string and stores the unicode length in len
442 const jchar* StringTable::to_unicode(const StringWrapper& wrapped_str, int &len, TRAPS) {
443 switch (wrapped_str.type) {
444 case StringType::UnicodeStr:
445 len = static_cast<int>(wrapped_str.length);
446 return wrapped_str.unicode_str;
447 case StringType::OopStr:
448 return java_lang_String::as_unicode_string(wrapped_str.oop_str(), len, CHECK_NULL);
449 case StringType::SymbolStr: {
450 const char* utf8_str = get_symbol_utf8(wrapped_str);
451 int unicode_length = UTF8::unicode_length(utf8_str, wrapped_str.symbol_str->utf8_length());
452 jchar* chars = NEW_RESOURCE_ARRAY(jchar, unicode_length);
453 UTF8::convert_to_unicode(utf8_str, chars, unicode_length);
454 len = unicode_length;
455 return chars;
456 }
457 case StringType::UTF8Str: {
458 int unicode_length = UTF8::unicode_length(wrapped_str.utf8_str);
459 jchar* chars = NEW_RESOURCE_ARRAY(jchar, unicode_length);
460 UTF8::convert_to_unicode(wrapped_str.utf8_str, chars, unicode_length);
461 len = unicode_length;
462 return chars;
463 }
464 default:
465 ShouldNotReachHere();
466 }
467 return nullptr;
468 }
469
470 Handle StringTable::handle_from_wrapped_string(const StringWrapper& wrapped_str, TRAPS) {
471 switch (wrapped_str.type) {
472 case StringType::OopStr:
473 return wrapped_str.oop_str;
474 case StringType::UnicodeStr:
475 return java_lang_String::create_from_unicode(wrapped_str.unicode_str, static_cast<int>(wrapped_str.length), THREAD);
476 case StringType::SymbolStr:
477 return java_lang_String::create_from_symbol(wrapped_str.symbol_str, THREAD);
478 case StringType::UTF8Str:
479 return java_lang_String::create_from_str(wrapped_str.utf8_str, THREAD);
480 default:
481 ShouldNotReachHere();
482 }
483 return Handle();
484 }
485
486 // Interning
487 oop StringTable::intern(Symbol* symbol, TRAPS) {
488 if (symbol == nullptr) return nullptr;
489 int length = symbol->utf8_length();
490 StringWrapper name(symbol, length);
491 oop result = intern(name, CHECK_NULL);
492 return result;
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(!AtomicAccess::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);
536 }
537
538 oop StringTable::do_intern(const StringWrapper& name, uintx hash, TRAPS) {
539 HandleMark hm(THREAD); // cleanup strings created
540 Handle string_h = handle_from_wrapped_string(name, CHECK_NULL);
541
542 assert(StringTable::wrapped_string_equals(string_h(), name),
543 "string must be properly initialized");
544
545 // Notify deduplication support that the string is being interned. A string
546 // must never be deduplicated after it has been interned. Doing so interferes
547 // with compiler optimizations done on e.g. interned string literals.
548 if (StringDedup::is_enabled()) {
549 StringDedup::notify_intern(string_h());
550 }
551
552 StringTableLookupOop lookup(THREAD, hash, string_h);
553 StringTableGet stg(THREAD);
554
555 bool rehash_warning;
556 do {
557 // Callers have already looked up the String, so just go to add.
558 WeakHandle wh(_oop_storage, string_h);
559 // The hash table takes ownership of the WeakHandle, even if it's not inserted.
560 if (_local_table->insert(THREAD, lookup, wh, &rehash_warning)) {
561 update_needs_rehash(rehash_warning);
562 return wh.resolve();
563 }
564 // In case another thread did a concurrent add, return value already in the table.
565 // This could fail if the String got gc'ed concurrently, so loop back until success.
566 if (_local_table->get(THREAD, lookup, stg, &rehash_warning)) {
567 update_needs_rehash(rehash_warning);
568 return stg.get_res_oop();
569 }
570 } while(true);
571 }
572
573 // Concurrent work
574 void StringTable::grow(JavaThread* jt) {
575 StringTableHash::GrowTask gt(_local_table);
576 if (!gt.prepare(jt)) {
577 return;
578 }
579 log_trace(stringtable)("Started to grow");
580 {
581 TraceTime timer("Grow", TRACETIME_LOG(Debug, stringtable, perf));
582 while (gt.do_task(jt)) {
583 gt.pause(jt);
584 {
585 ThreadBlockInVM tbivm(jt);
586 }
587 gt.cont(jt);
588 }
589 }
590 gt.done(jt);
591 _current_size = table_size();
592 log_debug(stringtable)("Grown to size:%zu", _current_size);
593 }
594
595 struct StringTableDoDelete : StackObj {
596 void operator()(WeakHandle* val) {
597 /* do nothing */
598 }
599 };
600
601 struct StringTableDeleteCheck : StackObj {
602 long _count;
603 long _item;
604 StringTableDeleteCheck() : _count(0), _item(0) {}
605 bool operator()(WeakHandle* val) {
606 ++_item;
607 oop tmp = val->peek();
608 if (tmp == nullptr) {
609 ++_count;
610 return true;
611 } else {
612 return false;
613 }
614 }
615 };
616
617 void StringTable::clean_dead_entries(JavaThread* jt) {
618 StringTableHash::BulkDeleteTask bdt(_local_table);
619 if (!bdt.prepare(jt)) {
620 return;
621 }
622
623 StringTableDeleteCheck stdc;
624 StringTableDoDelete stdd;
625 NativeHeapTrimmer::SuspendMark sm("stringtable");
626 {
627 TraceTime timer("Clean", TRACETIME_LOG(Debug, stringtable, perf));
628 while(bdt.do_task(jt, stdc, stdd)) {
629 bdt.pause(jt);
630 {
631 ThreadBlockInVM tbivm(jt);
632 }
633 bdt.cont(jt);
634 }
635 bdt.done(jt);
636 }
637 log_debug(stringtable)("Cleaned %ld of %ld", stdc._count, stdc._item);
638 }
639
640 void StringTable::gc_notification(size_t num_dead) {
641 log_trace(stringtable)("Uncleaned items:%zu", num_dead);
642
643 if (has_work()) {
644 return;
645 }
646
647 double load_factor = StringTable::get_load_factor();
648 double dead_factor = StringTable::get_dead_factor(num_dead);
649 // We should clean/resize if we have more dead than alive,
650 // more items than preferred load factor or
651 // more dead items than water mark.
652 if ((dead_factor > load_factor) ||
653 (load_factor > PREF_AVG_LIST_LEN) ||
654 (dead_factor > CLEAN_DEAD_HIGH_WATER_MARK)) {
655 log_debug(stringtable)("Concurrent work triggered, live factor: %g dead factor: %g",
656 load_factor, dead_factor);
657 trigger_concurrent_work();
658 }
659 }
660
661 bool StringTable::should_grow() {
662 return get_load_factor() > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached();
663 }
664
665 void StringTable::do_concurrent_work(JavaThread* jt) {
666 // Rehash if needed. Rehashing goes to a safepoint but the rest of this
667 // work is concurrent.
668 if (needs_rehashing() && maybe_rehash_table()) {
669 AtomicAccess::release_store(&_has_work, false);
670 return; // done, else grow
671 }
672 log_debug(stringtable, perf)("Concurrent work, live factor: %g", get_load_factor());
673 // We prefer growing, since that also removes dead items
674 if (should_grow()) {
675 grow(jt);
676 } else {
677 clean_dead_entries(jt);
678 }
679 AtomicAccess::release_store(&_has_work, false);
680 }
681
682 // Called at VM_Operation safepoint
683 void StringTable::rehash_table() {
684 assert(SafepointSynchronize::is_at_safepoint(), "must be called at safepoint");
685 // The ServiceThread initiates the rehashing so it is not resizing.
686 assert (_local_table->is_safepoint_safe(), "Should not be resizing now");
687
688 _alt_hash_seed = AltHashing::compute_seed();
689
690 // We use current size, not max size.
691 size_t new_size = _local_table->get_size_log2(Thread::current());
692 StringTableHash* new_table = new StringTableHash(new_size, END_SIZE, REHASH_LEN, true);
693 // Use alt hash from now on
694 _alt_hash = true;
695 _local_table->rehash_nodes_to(Thread::current(), new_table);
696
697 // free old table
698 delete _local_table;
699 _local_table = new_table;
700
701 _rehashed = true;
702 _needs_rehashing = false;
703 }
704
705 bool StringTable::maybe_rehash_table() {
706 log_debug(stringtable)("Table imbalanced, rehashing called.");
707
708 // Grow instead of rehash.
709 if (should_grow()) {
710 log_debug(stringtable)("Choosing growing over rehashing.");
711 _needs_rehashing = false;
712 return false;
713 }
714 // Already rehashed.
715 if (_rehashed) {
716 log_warning(stringtable)("Rehashing already done, still long lists.");
717 _needs_rehashing = false;
718 return false;
719 }
720
721 VM_RehashStringTable op;
722 VMThread::execute(&op);
723 return true; // return true because we tried.
724 }
725
726 // Statistics
727 static size_t literal_size(oop obj) {
728 if (obj == nullptr) {
729 return 0;
730 }
731
732 size_t word_size = obj->size();
733
734 if (obj->klass() == vmClasses::String_klass()) {
735 // This may overcount if String.value arrays are shared.
736 word_size += java_lang_String::value(obj)->size();
737 }
738
739 return word_size * HeapWordSize;
740 }
741
742 struct SizeFunc : StackObj {
743 size_t operator()(WeakHandle* val) {
744 oop s = val->peek();
745 if (s == nullptr) {
746 // Dead
747 return 0;
748 }
749 return literal_size(s);
750 };
751 };
752
753 TableStatistics StringTable::get_table_statistics() {
754 static TableStatistics ts;
755 SizeFunc sz;
756
757 Thread* jt = Thread::current();
758 StringTableHash::StatisticsTask sts(_local_table);
759 if (!sts.prepare(jt)) {
760 return ts; // return old table statistics
761 }
762 {
763 TraceTime timer("GetStatistics", TRACETIME_LOG(Debug, stringtable, perf));
764 while (sts.do_task(jt, sz)) {
765 sts.pause(jt);
766 if (jt->is_Java_thread()) {
767 ThreadBlockInVM tbivm(JavaThread::cast(jt));
768 }
769 sts.cont(jt);
770 }
771 }
772 ts = sts.done(jt);
773 return ts;
774 }
775
776 void StringTable::print_table_statistics(outputStream* st) {
777 TableStatistics ts = get_table_statistics();
778 ts.print(st, "StringTable");
779 #if INCLUDE_CDS_JAVA_HEAP
780 if (!_shared_table.empty()) {
781 _shared_table.print_table_statistics(st, "Shared String Table");
782 }
783 #endif
784 }
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 ResizeableHashTable<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;
838 }
839
840 static void print_string(Thread* current, outputStream* st, oop s) {
841 typeArrayOop value = java_lang_String::value_no_keepalive(s);
842 int length = java_lang_String::length(s);
843 bool is_latin1 = java_lang_String::is_latin1(s);
844
845 if (length <= 0) {
846 st->print("%d: ", length);
847 } else {
848 ResourceMark rm(current);
849 size_t utf8_length = length;
850 char* utf8_string;
851
852 if (!is_latin1) {
853 jchar* chars = value->char_at_addr(0);
854 utf8_string = UNICODE::as_utf8(chars, utf8_length);
855 } else {
856 jbyte* bytes = value->byte_at_addr(0);
857 utf8_string = UNICODE::as_utf8(bytes, utf8_length);
858 }
859
860 st->print("%zu: ", utf8_length);
861 HashtableTextDump::put_utf8(st, utf8_string, utf8_length);
862 }
863 st->cr();
864 }
865
866 // Dumping
867 class PrintString : StackObj {
868 Thread* _thr;
869 outputStream* _st;
870 public:
871 PrintString(Thread* thr, outputStream* st) : _thr(thr), _st(st) {}
872 bool operator()(WeakHandle* val) {
873 oop s = val->peek();
874 if (s == nullptr) {
875 return true;
876 }
877 print_string(_thr, _st, s);
878 return true;
879 };
880 };
881
882 class PrintSharedString : StackObj {
883 Thread* _thr;
884 outputStream* _st;
885 public:
886 PrintSharedString(Thread* thr, outputStream* st) : _thr(thr), _st(st) {}
887 void do_value(oop s) {
888 if (s == nullptr) {
889 return;
890 }
891 print_string(_thr, _st, s);
892 };
893 };
894
895 void StringTable::dump(outputStream* st, bool verbose) {
896 if (!verbose) {
897 print_table_statistics(st);
898 } else {
899 Thread* thr = Thread::current();
900 ResourceMark rm(thr);
901 st->print_cr("VERSION: 1.1");
902 PrintString ps(thr, st);
903 if (!_local_table->try_scan(thr, ps)) {
904 st->print_cr("dump unavailable at this moment");
905 }
906 #if INCLUDE_CDS_JAVA_HEAP
907 if (!_shared_table.empty()) {
908 st->print_cr("#----------------");
909 st->print_cr("# Shared strings:");
910 st->print_cr("#----------------");
911 PrintSharedString pss(thr, st);
912 _shared_table.iterate(&pss);
913 }
914 #endif
915 }
916 }
917
918 // Utility for dumping strings
919 StringtableDCmd::StringtableDCmd(outputStream* output, bool heap) :
920 DCmdWithParser(output, heap),
921 _verbose("-verbose", "Dump the content of each string in the table",
922 "BOOLEAN", false, "false") {
923 _dcmdparser.add_dcmd_option(&_verbose);
924 }
925
926 void StringtableDCmd::execute(DCmdSource source, TRAPS) {
927 VM_DumpHashtable dumper(output(), VM_DumpHashtable::DumpStrings,
928 _verbose.value());
929 VMThread::execute(&dumper);
930 }
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(AtomicAccess::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 AOTMetaspace::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
1016 log_info(aot)("string table array (secondary)[%d] length = %d", i, len);
1017 assert(!ArchiveHeapWriter::is_too_large_to_archive(secondary), "sanity");
1018 }
1019
1020 assert(total == 0, "must be");
1021 _is_two_dimensional_shared_strings_array = true;
1022 }
1023 }
1024
1025 #ifndef PRODUCT
1026 void StringTable::verify_secondary_array_index_bits() {
1027 int max;
1028 for (max = 1; ; max++) {
1029 size_t next_size = objArrayOopDesc::object_size(1 << (max + 1));
1030 if (ArchiveHeapWriter::is_too_large_to_archive(next_size)) {
1031 break;
1032 }
1033 }
1034 // Currently max is 17 for +UseCompressedOops, 16 for -UseCompressedOops.
1035 // When we add support for Shenandoah (which has a smaller mininum region size than G1),
1036 // max will become 15/14.
1037 //
1038 // We use _secondary_array_index_bits==14 as that will be the eventual value, and will
1039 // make testing easier.
1040 assert(_secondary_array_index_bits <= max,
1041 "_secondary_array_index_bits (%d) must be smaller than max possible value (%d)",
1042 _secondary_array_index_bits, max);
1043 }
1044 #endif // PRODUCT
1045
1046 // This is called AFTER we enter the CDS safepoint.
1047 //
1048 // For each shared string:
1049 // [1] Store it into _shared_strings_array. Encode its position as a 32-bit index.
1050 // [2] Store the index and hashcode into _shared_table.
1051 oop StringTable::init_shared_strings_array() {
1052 assert(CDSConfig::is_dumping_heap(), "must be");
1053 objArrayOop array = (objArrayOop)(_shared_strings_array.resolve());
1054
1055 verify_secondary_array_index_bits();
1056
1057 int index = 0;
1058 auto copy_into_array = [&] (WeakHandle* val) {
1059 oop string = val->peek();
1060 if (string != nullptr && !ArchiveHeapWriter::is_string_too_large_to_archive(string)) {
1061 // If string is too large, don't put it into the string table.
1062 // - If there are no other refernences to it, it won't be stored into the archive,
1063 // so we are all good.
1064 // - If there's a referece to it, we will report an error inside HeapShared.cpp and
1065 // dumping will fail.
1066 HeapShared::add_to_dumped_interned_strings(string);
1067 if (!_is_two_dimensional_shared_strings_array) {
1068 assert(index < array->length(), "no strings should have been added");
1069 array->obj_at_put(index, string);
1070 } else {
1071 int primary_index = index >> _secondary_array_index_bits;
1072 int secondary_index = index & _secondary_array_index_mask;
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(AtomicAccess::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 _shared_table.serialize_header(soc);
1117
1118 if (soc->writing()) {
1119 // Sanity. Make sure we don't use the shared table at dump time
1120 _shared_table.reset();
1121 } else if (!ArchiveHeapLoader::is_in_use()) {
1122 _shared_table.reset();
1123 }
1124
1125 soc->do_bool(&_is_two_dimensional_shared_strings_array);
1126 soc->do_int(&_shared_strings_array_root_index);
1127 }
1128 #endif //INCLUDE_CDS_JAVA_HEAP