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/cdsConfig.hpp" 27 #include "cds/dynamicArchive.hpp" 28 #include "classfile/altHashing.hpp" 29 #include "classfile/classLoaderData.hpp" 30 #include "classfile/compactHashtable.hpp" 31 #include "classfile/javaClasses.hpp" 32 #include "classfile/symbolTable.hpp" 33 #include "memory/allocation.inline.hpp" 34 #include "memory/metaspaceClosure.hpp" 35 #include "memory/resourceArea.hpp" 36 #include "oops/oop.inline.hpp" 37 #include "runtime/atomic.hpp" 38 #include "runtime/interfaceSupport.inline.hpp" 39 #include "runtime/timerTrace.hpp" 40 #include "runtime/trimNativeHeap.hpp" 41 #include "services/diagnosticCommand.hpp" 42 #include "utilities/concurrentHashTable.inline.hpp" 43 #include "utilities/concurrentHashTableTasks.inline.hpp" 44 #include "utilities/utf8.hpp" 45 46 // We used to not resize at all, so let's be conservative 47 // and not set it too short before we decide to resize, 48 // to match previous startup behavior 49 const double PREF_AVG_LIST_LEN = 8.0; 50 // 2^24 is max size, like StringTable. 51 const size_t END_SIZE = 24; 52 // If a chain gets to 100 something might be wrong 53 const size_t REHASH_LEN = 100; 54 55 const size_t ON_STACK_BUFFER_LENGTH = 128; 56 57 // -------------------------------------------------------------------------- 58 59 inline bool symbol_equals_compact_hashtable_entry(Symbol* value, const char* key, int len) { 60 if (value->equals(key, len)) { 61 return true; 62 } else { 63 return false; 64 } 65 } 66 67 static OffsetCompactHashtable< 68 const char*, Symbol*, 69 symbol_equals_compact_hashtable_entry 70 > _shared_table; 71 72 static OffsetCompactHashtable< 73 const char*, Symbol*, 74 symbol_equals_compact_hashtable_entry 75 > _dynamic_shared_table; 76 77 // -------------------------------------------------------------------------- 78 79 typedef ConcurrentHashTable<SymbolTableConfig, mtSymbol> SymbolTableHash; 80 static SymbolTableHash* _local_table = nullptr; 81 82 volatile bool SymbolTable::_has_work = 0; 83 volatile bool SymbolTable::_needs_rehashing = false; 84 85 // For statistics 86 static size_t _symbols_removed = 0; 87 static size_t _symbols_counted = 0; 88 static size_t _current_size = 0; 89 90 static volatile size_t _items_count = 0; 91 static volatile bool _has_items_to_clean = false; 92 93 94 static volatile bool _alt_hash = false; 95 96 #ifdef USE_LIBRARY_BASED_TLS_ONLY 97 static volatile bool _lookup_shared_first = false; 98 #else 99 // "_lookup_shared_first" can get highly contended with many cores if multiple threads 100 // are updating "lookup success history" in a global shared variable. If built-in TLS is available, use it. 101 static THREAD_LOCAL bool _lookup_shared_first = false; 102 #endif 103 104 // Static arena for symbols that are not deallocated 105 Arena* SymbolTable::_arena = nullptr; 106 107 static bool _rehashed = false; 108 static uint64_t _alt_hash_seed = 0; 109 110 static inline void log_trace_symboltable_helper(Symbol* sym, const char* msg) { 111 #ifndef PRODUCT 112 ResourceMark rm; 113 log_trace(symboltable)("%s [%s]", msg, sym->as_quoted_ascii()); 114 #endif // PRODUCT 115 } 116 117 // Pick hashing algorithm. 118 static unsigned int hash_symbol(const char* s, int len, bool useAlt) { 119 return useAlt ? 120 AltHashing::halfsiphash_32(_alt_hash_seed, (const uint8_t*)s, len) : 121 java_lang_String::hash_code((const jbyte*)s, len); 122 } 123 124 #if INCLUDE_CDS 125 static unsigned int hash_shared_symbol(const char* s, int len) { 126 return java_lang_String::hash_code((const jbyte*)s, len); 127 } 128 #endif 129 130 class SymbolTableConfig : public AllStatic { 131 132 public: 133 typedef Symbol Value; // value of the Node in the hashtable 134 135 static uintx get_hash(Value const& value, bool* is_dead) { 136 *is_dead = (value.refcount() == 0); 137 if (*is_dead) { 138 return 0; 139 } else { 140 return hash_symbol((const char*)value.bytes(), value.utf8_length(), _alt_hash); 141 } 142 } 143 // We use default allocation/deallocation but counted 144 static void* allocate_node(void* context, size_t size, Value const& value) { 145 SymbolTable::item_added(); 146 return allocate_node_impl(size, value); 147 } 148 static void free_node(void* context, void* memory, Value & value) { 149 // We get here because #1 some threads lost a race to insert a newly created Symbol 150 // or #2 we're cleaning up unused symbol. 151 // If #1, then the symbol can be either permanent, 152 // or regular newly created one (refcount==1) 153 // If #2, then the symbol is dead (refcount==0) 154 assert(value.is_permanent() || (value.refcount() == 1) || (value.refcount() == 0), 155 "refcount %d", value.refcount()); 156 #if INCLUDE_CDS 157 if (CDSConfig::is_dumping_static_archive()) { 158 // We have allocated with MetaspaceShared::symbol_space_alloc(). No deallocation is needed. 159 // Unreferenced Symbols will not be copied into the archive. 160 return; 161 } 162 #endif 163 if (value.refcount() == 1) { 164 value.decrement_refcount(); 165 assert(value.refcount() == 0, "expected dead symbol"); 166 } 167 if (value.refcount() != PERM_REFCOUNT) { 168 FreeHeap(memory); 169 } else { 170 MutexLocker ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena 171 // Deleting permanent symbol should not occur very often (insert race condition), 172 // so log it. 173 log_trace_symboltable_helper(&value, "Freeing permanent symbol"); 174 size_t alloc_size = SymbolTableHash::get_dynamic_node_size(value.byte_size()); 175 if (!SymbolTable::arena()->Afree(memory, alloc_size)) { 176 // Can't access the symbol after Afree, but we just printed it above. 177 NOT_PRODUCT(log_trace(symboltable)(" - Leaked permanent symbol");) 178 } 179 } 180 SymbolTable::item_removed(); 181 } 182 183 private: 184 static void* allocate_node_impl(size_t size, Value const& value) { 185 size_t alloc_size = SymbolTableHash::get_dynamic_node_size(value.byte_size()); 186 #if INCLUDE_CDS 187 if (CDSConfig::is_dumping_static_archive()) { 188 MutexLocker ml(DumpRegion_lock, Mutex::_no_safepoint_check_flag); 189 // To get deterministic output from -Xshare:dump, we ensure that Symbols are allocated in 190 // increasing addresses. When the symbols are copied into the archive, we preserve their 191 // relative address order (sorted, see ArchiveBuilder::gather_klasses_and_symbols). 192 // 193 // We cannot use arena because arena chunks are allocated by the OS. As a result, for example, 194 // the archived symbol of "java/lang/Object" may sometimes be lower than "java/lang/String", and 195 // sometimes be higher. This would cause non-deterministic contents in the archive. 196 DEBUG_ONLY(static void* last = nullptr); 197 void* p = (void*)MetaspaceShared::symbol_space_alloc(alloc_size); 198 assert(p > last, "must increase monotonically"); 199 DEBUG_ONLY(last = p); 200 return p; 201 } 202 #endif 203 if (value.refcount() != PERM_REFCOUNT) { 204 return AllocateHeap(alloc_size, mtSymbol); 205 } else { 206 // Allocate to global arena 207 MutexLocker ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena 208 return SymbolTable::arena()->Amalloc(alloc_size); 209 } 210 } 211 }; 212 213 void SymbolTable::create_table () { 214 size_t start_size_log_2 = log2i_ceil(SymbolTableSize); 215 _current_size = ((size_t)1) << start_size_log_2; 216 log_trace(symboltable)("Start size: %zu (%zu)", 217 _current_size, start_size_log_2); 218 _local_table = new SymbolTableHash(start_size_log_2, END_SIZE, REHASH_LEN, true); 219 220 // Initialize the arena for global symbols, size passed in depends on CDS. 221 if (symbol_alloc_arena_size == 0) { 222 _arena = new (mtSymbol) Arena(mtSymbol); 223 } else { 224 _arena = new (mtSymbol) Arena(mtSymbol, Arena::Tag::tag_other, symbol_alloc_arena_size); 225 } 226 } 227 228 void SymbolTable::reset_has_items_to_clean() { Atomic::store(&_has_items_to_clean, false); } 229 void SymbolTable::mark_has_items_to_clean() { Atomic::store(&_has_items_to_clean, true); } 230 bool SymbolTable::has_items_to_clean() { return Atomic::load(&_has_items_to_clean); } 231 232 void SymbolTable::item_added() { 233 Atomic::inc(&_items_count); 234 } 235 236 void SymbolTable::item_removed() { 237 Atomic::inc(&(_symbols_removed)); 238 Atomic::dec(&_items_count); 239 } 240 241 double SymbolTable::get_load_factor() { 242 return (double)_items_count/(double)_current_size; 243 } 244 245 size_t SymbolTable::table_size() { 246 return ((size_t)1) << _local_table->get_size_log2(Thread::current()); 247 } 248 249 bool SymbolTable::has_work() { return Atomic::load_acquire(&_has_work); } 250 251 void SymbolTable::trigger_cleanup() { 252 // Avoid churn on ServiceThread 253 if (!has_work()) { 254 MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag); 255 _has_work = true; 256 Service_lock->notify_all(); 257 } 258 } 259 260 class SymbolsDo : StackObj { 261 SymbolClosure *_cl; 262 public: 263 SymbolsDo(SymbolClosure *cl) : _cl(cl) {} 264 bool operator()(Symbol* value) { 265 assert(value != nullptr, "expected valid value"); 266 _cl->do_symbol(&value); 267 return true; 268 }; 269 }; 270 271 class SharedSymbolIterator { 272 SymbolClosure* _symbol_closure; 273 public: 274 SharedSymbolIterator(SymbolClosure* f) : _symbol_closure(f) {} 275 void do_value(Symbol* symbol) { 276 _symbol_closure->do_symbol(&symbol); 277 } 278 }; 279 280 // Call function for all symbols in the symbol table. 281 void SymbolTable::symbols_do(SymbolClosure *cl) { 282 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint"); 283 // all symbols from shared table 284 SharedSymbolIterator iter(cl); 285 _shared_table.iterate(&iter); 286 _dynamic_shared_table.iterate(&iter); 287 288 // all symbols from the dynamic table 289 SymbolsDo sd(cl); 290 _local_table->do_safepoint_scan(sd); 291 } 292 293 // Call function for all symbols in shared table. Used by -XX:+PrintSharedArchiveAndExit 294 void SymbolTable::shared_symbols_do(SymbolClosure *cl) { 295 SharedSymbolIterator iter(cl); 296 _shared_table.iterate(&iter); 297 _dynamic_shared_table.iterate(&iter); 298 } 299 300 Symbol* SymbolTable::lookup_dynamic(const char* name, 301 int len, unsigned int hash) { 302 Symbol* sym = do_lookup(name, len, hash); 303 assert((sym == nullptr) || sym->refcount() != 0, "refcount must not be zero"); 304 return sym; 305 } 306 307 #if INCLUDE_CDS 308 Symbol* SymbolTable::lookup_shared(const char* name, 309 int len, unsigned int hash) { 310 Symbol* sym = nullptr; 311 if (!_shared_table.empty()) { 312 if (_alt_hash) { 313 // hash_code parameter may use alternate hashing algorithm but the shared table 314 // always uses the same original hash code. 315 hash = hash_shared_symbol(name, len); 316 } 317 sym = _shared_table.lookup(name, hash, len); 318 if (sym == nullptr && DynamicArchive::is_mapped()) { 319 sym = _dynamic_shared_table.lookup(name, hash, len); 320 } 321 } 322 return sym; 323 } 324 #endif 325 326 Symbol* SymbolTable::lookup_common(const char* name, 327 int len, unsigned int hash) { 328 Symbol* sym; 329 if (_lookup_shared_first) { 330 sym = lookup_shared(name, len, hash); 331 if (sym == nullptr) { 332 _lookup_shared_first = false; 333 sym = lookup_dynamic(name, len, hash); 334 } 335 } else { 336 sym = lookup_dynamic(name, len, hash); 337 if (sym == nullptr) { 338 sym = lookup_shared(name, len, hash); 339 if (sym != nullptr) { 340 _lookup_shared_first = true; 341 } 342 } 343 } 344 return sym; 345 } 346 347 // Symbols should represent entities from the constant pool that are 348 // limited to <64K in length, but usage errors creep in allowing Symbols 349 // to be used for arbitrary strings. For debug builds we will assert if 350 // a string is too long, whereas product builds will truncate it. 351 static int check_length(const char* name, int len) { 352 assert(len >= 0, "negative length %d suggests integer overflow in the caller", len); 353 assert(len <= Symbol::max_length(), 354 "String length %d exceeds the maximum Symbol length of %d", len, Symbol::max_length()); 355 if (len > Symbol::max_length()) { 356 warning("A string \"%.80s ... %.80s\" exceeds the maximum Symbol " 357 "length of %d and has been truncated", name, (name + len - 80), Symbol::max_length()); 358 len = Symbol::max_length(); 359 } 360 return len; 361 } 362 363 Symbol* SymbolTable::new_symbol(const char* name, int len) { 364 len = check_length(name, len); 365 unsigned int hash = hash_symbol(name, len, _alt_hash); 366 Symbol* sym = lookup_common(name, len, hash); 367 if (sym == nullptr) { 368 sym = do_add_if_needed(name, len, hash, /* is_permanent */ false); 369 } 370 assert(sym->refcount() != 0, "lookup should have incremented the count"); 371 assert(sym->equals(name, len), "symbol must be properly initialized"); 372 return sym; 373 } 374 375 Symbol* SymbolTable::new_symbol(const Symbol* sym, int begin, int end) { 376 assert(begin <= end && end <= sym->utf8_length(), "just checking"); 377 assert(sym->refcount() != 0, "require a valid symbol"); 378 const char* name = (const char*)sym->base() + begin; 379 int len = end - begin; 380 assert(len <= Symbol::max_length(), "sanity"); 381 unsigned int hash = hash_symbol(name, len, _alt_hash); 382 Symbol* found = lookup_common(name, len, hash); 383 if (found == nullptr) { 384 found = do_add_if_needed(name, len, hash, /* is_permanent */ false); 385 } 386 return found; 387 } 388 389 class SymbolTableLookup : StackObj { 390 private: 391 uintx _hash; 392 int _len; 393 const char* _str; 394 public: 395 SymbolTableLookup(const char* key, int len, uintx hash) 396 : _hash(hash), _len(len), _str(key) {} 397 uintx get_hash() const { 398 return _hash; 399 } 400 // Note: When equals() returns "true", the symbol's refcount is incremented. This is 401 // needed to ensure that the symbol is kept alive before equals() returns to the caller, 402 // so that another thread cannot clean the symbol up concurrently. The caller is 403 // responsible for decrementing the refcount, when the symbol is no longer needed. 404 bool equals(Symbol* value) { 405 assert(value != nullptr, "expected valid value"); 406 Symbol *sym = value; 407 if (sym->equals(_str, _len)) { 408 if (sym->try_increment_refcount()) { 409 // something is referencing this symbol now. 410 return true; 411 } else { 412 assert(sym->refcount() == 0, "expected dead symbol"); 413 return false; 414 } 415 } else { 416 return false; 417 } 418 } 419 bool is_dead(Symbol* value) { 420 return value->refcount() == 0; 421 } 422 }; 423 424 class SymbolTableGet : public StackObj { 425 Symbol* _return; 426 public: 427 SymbolTableGet() : _return(nullptr) {} 428 void operator()(Symbol* value) { 429 assert(value != nullptr, "expected valid value"); 430 _return = value; 431 } 432 Symbol* get_res_sym() const { 433 return _return; 434 } 435 }; 436 437 void SymbolTable::update_needs_rehash(bool rehash) { 438 if (rehash) { 439 _needs_rehashing = true; 440 trigger_cleanup(); 441 } 442 } 443 444 Symbol* SymbolTable::do_lookup(const char* name, int len, uintx hash) { 445 Thread* thread = Thread::current(); 446 SymbolTableLookup lookup(name, len, hash); 447 SymbolTableGet stg; 448 bool rehash_warning = false; 449 _local_table->get(thread, lookup, stg, &rehash_warning); 450 update_needs_rehash(rehash_warning); 451 Symbol* sym = stg.get_res_sym(); 452 assert((sym == nullptr) || sym->refcount() != 0, "found dead symbol"); 453 return sym; 454 } 455 456 Symbol* SymbolTable::lookup_only(const char* name, int len, unsigned int& hash) { 457 hash = hash_symbol(name, len, _alt_hash); 458 return lookup_common(name, len, hash); 459 } 460 461 // Suggestion: Push unicode-based lookup all the way into the hashing 462 // and probing logic, so there is no need for convert_to_utf8 until 463 // an actual new Symbol* is created. 464 Symbol* SymbolTable::new_symbol(const jchar* name, int utf16_length) { 465 size_t utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); 466 char stack_buf[ON_STACK_BUFFER_LENGTH]; 467 if (utf8_length < sizeof(stack_buf)) { 468 char* chars = stack_buf; 469 UNICODE::convert_to_utf8(name, utf16_length, chars); 470 return new_symbol(chars, checked_cast<int>(utf8_length)); 471 } else { 472 ResourceMark rm; 473 char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1); 474 UNICODE::convert_to_utf8(name, utf16_length, chars); 475 return new_symbol(chars, checked_cast<int>(utf8_length)); 476 } 477 } 478 479 Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length, 480 unsigned int& hash) { 481 size_t utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); 482 char stack_buf[ON_STACK_BUFFER_LENGTH]; 483 if (utf8_length < sizeof(stack_buf)) { 484 char* chars = stack_buf; 485 UNICODE::convert_to_utf8(name, utf16_length, chars); 486 return lookup_only(chars, checked_cast<int>(utf8_length), hash); 487 } else { 488 ResourceMark rm; 489 char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1); 490 UNICODE::convert_to_utf8(name, utf16_length, chars); 491 return lookup_only(chars, checked_cast<int>(utf8_length), hash); 492 } 493 } 494 495 void SymbolTable::new_symbols(ClassLoaderData* loader_data, const constantPoolHandle& cp, 496 int names_count, const char** names, int* lengths, 497 int* cp_indices, unsigned int* hashValues) { 498 // Note that is_permanent will be false for non-strong hidden classes. 499 // even if their loader is the boot loader because they will have a different cld. 500 bool is_permanent = loader_data->is_the_null_class_loader_data(); 501 for (int i = 0; i < names_count; i++) { 502 const char *name = names[i]; 503 int len = lengths[i]; 504 assert(len <= Symbol::max_length(), "must be - these come from the constant pool"); 505 unsigned int hash = hashValues[i]; 506 assert(lookup_shared(name, len, hash) == nullptr, "must have checked already"); 507 Symbol* sym = do_add_if_needed(name, len, hash, is_permanent); 508 assert(sym->refcount() != 0, "lookup should have incremented the count"); 509 cp->symbol_at_put(cp_indices[i], sym); 510 } 511 } 512 513 Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, bool is_permanent) { 514 assert(len <= Symbol::max_length(), "caller should have ensured this"); 515 SymbolTableLookup lookup(name, len, hash); 516 SymbolTableGet stg; 517 bool clean_hint = false; 518 bool rehash_warning = false; 519 Thread* current = Thread::current(); 520 Symbol* sym; 521 522 ResourceMark rm(current); 523 const int alloc_size = Symbol::byte_size(len); 524 u1* u1_buf = NEW_RESOURCE_ARRAY_IN_THREAD(current, u1, alloc_size); 525 Symbol* tmp = ::new ((void*)u1_buf) Symbol((const u1*)name, len, 526 (is_permanent || CDSConfig::is_dumping_static_archive()) ? PERM_REFCOUNT : 1); 527 528 do { 529 if (_local_table->insert(current, lookup, *tmp, &rehash_warning, &clean_hint)) { 530 if (_local_table->get(current, lookup, stg, &rehash_warning)) { 531 sym = stg.get_res_sym(); 532 // The get adds one to ref count, but we inserted with our ref already included. 533 // Therefore decrement with one. 534 if (sym->refcount() != PERM_REFCOUNT) { 535 sym->decrement_refcount(); 536 } 537 break; 538 } 539 } 540 541 // In case another thread did a concurrent add, return value already in the table. 542 // This could fail if the symbol got deleted concurrently, so loop back until success. 543 if (_local_table->get(current, lookup, stg, &rehash_warning)) { 544 // The lookup added a refcount, which is ours. 545 sym = stg.get_res_sym(); 546 break; 547 } 548 } while(true); 549 550 update_needs_rehash(rehash_warning); 551 552 if (clean_hint) { 553 mark_has_items_to_clean(); 554 check_concurrent_work(); 555 } 556 557 assert((sym == nullptr) || sym->refcount() != 0, "found dead symbol"); 558 return sym; 559 } 560 561 Symbol* SymbolTable::new_permanent_symbol(const char* name) { 562 unsigned int hash = 0; 563 int len = check_length(name, (int)strlen(name)); 564 Symbol* sym = SymbolTable::lookup_only(name, len, hash); 565 if (sym == nullptr) { 566 sym = do_add_if_needed(name, len, hash, /* is_permanent */ true); 567 } 568 if (!sym->is_permanent()) { 569 sym->make_permanent(); 570 log_trace_symboltable_helper(sym, "Asked for a permanent symbol, but got a regular one"); 571 } 572 return sym; 573 } 574 575 struct SizeFunc : StackObj { 576 size_t operator()(Symbol* value) { 577 assert(value != nullptr, "expected valid value"); 578 return (value)->size() * HeapWordSize; 579 }; 580 }; 581 582 TableStatistics SymbolTable::get_table_statistics() { 583 static TableStatistics ts; 584 SizeFunc sz; 585 ts = _local_table->statistics_get(Thread::current(), sz, ts); 586 return ts; 587 } 588 589 void SymbolTable::print_table_statistics(outputStream* st) { 590 SizeFunc sz; 591 _local_table->statistics_to(Thread::current(), sz, st, "SymbolTable"); 592 593 if (!_shared_table.empty()) { 594 _shared_table.print_table_statistics(st, "Shared Symbol Table"); 595 } 596 597 if (!_dynamic_shared_table.empty()) { 598 _dynamic_shared_table.print_table_statistics(st, "Dynamic Shared Symbol Table"); 599 } 600 } 601 602 // Verification 603 class VerifySymbols : StackObj { 604 public: 605 bool operator()(Symbol* value) { 606 guarantee(value != nullptr, "expected valid value"); 607 Symbol* sym = value; 608 guarantee(sym->equals((const char*)sym->bytes(), sym->utf8_length()), 609 "symbol must be internally consistent"); 610 return true; 611 }; 612 }; 613 614 void SymbolTable::verify() { 615 Thread* thr = Thread::current(); 616 VerifySymbols vs; 617 if (!_local_table->try_scan(thr, vs)) { 618 log_info(symboltable)("verify unavailable at this moment"); 619 } 620 } 621 622 static void print_symbol(outputStream* st, Symbol* sym) { 623 const char* utf8_string = (const char*)sym->bytes(); 624 int utf8_length = sym->utf8_length(); 625 st->print("%d %d: ", utf8_length, sym->refcount()); 626 HashtableTextDump::put_utf8(st, utf8_string, utf8_length); 627 st->cr(); 628 } 629 630 // Dumping 631 class DumpSymbol : StackObj { 632 Thread* _thr; 633 outputStream* _st; 634 public: 635 DumpSymbol(Thread* thr, outputStream* st) : _thr(thr), _st(st) {} 636 bool operator()(Symbol* value) { 637 assert(value != nullptr, "expected valid value"); 638 print_symbol(_st, value); 639 return true; 640 }; 641 }; 642 643 class DumpSharedSymbol : StackObj { 644 outputStream* _st; 645 public: 646 DumpSharedSymbol(outputStream* st) : _st(st) {} 647 void do_value(Symbol* value) { 648 assert(value != nullptr, "value should point to a symbol"); 649 print_symbol(_st, value); 650 }; 651 }; 652 653 void SymbolTable::dump(outputStream* st, bool verbose) { 654 if (!verbose) { 655 print_table_statistics(st); 656 } else { 657 Thread* thr = Thread::current(); 658 ResourceMark rm(thr); 659 st->print_cr("VERSION: 1.1"); 660 DumpSymbol ds(thr, st); 661 if (!_local_table->try_scan(thr, ds)) { 662 log_info(symboltable)("dump unavailable at this moment"); 663 } 664 if (!_shared_table.empty()) { 665 st->print_cr("#----------------"); 666 st->print_cr("# Shared symbols:"); 667 st->print_cr("#----------------"); 668 DumpSharedSymbol dss(st); 669 _shared_table.iterate(&dss); 670 } 671 if (!_dynamic_shared_table.empty()) { 672 st->print_cr("#------------------------"); 673 st->print_cr("# Dynamic shared symbols:"); 674 st->print_cr("#------------------------"); 675 DumpSharedSymbol dss(st); 676 _dynamic_shared_table.iterate(&dss); 677 } 678 } 679 } 680 681 #if INCLUDE_CDS 682 void SymbolTable::copy_shared_symbol_table(GrowableArray<Symbol*>* symbols, 683 CompactHashtableWriter* writer) { 684 ArchiveBuilder* builder = ArchiveBuilder::current(); 685 int len = symbols->length(); 686 for (int i = 0; i < len; i++) { 687 Symbol* sym = ArchiveBuilder::get_buffered_symbol(symbols->at(i)); 688 unsigned int fixed_hash = hash_shared_symbol((const char*)sym->bytes(), sym->utf8_length()); 689 assert(fixed_hash == hash_symbol((const char*)sym->bytes(), sym->utf8_length(), false), 690 "must not rehash during dumping"); 691 sym->set_permanent(); 692 writer->add(fixed_hash, builder->buffer_to_offset_u4((address)sym)); 693 } 694 } 695 696 size_t SymbolTable::estimate_size_for_archive() { 697 if (_items_count > (size_t)max_jint) { 698 fatal("Too many symbols to be archived: %zu", _items_count); 699 } 700 return CompactHashtableWriter::estimate_size(int(_items_count)); 701 } 702 703 void SymbolTable::write_to_archive(GrowableArray<Symbol*>* symbols) { 704 CompactHashtableWriter writer(int(_items_count), ArchiveBuilder::symbol_stats()); 705 copy_shared_symbol_table(symbols, &writer); 706 if (CDSConfig::is_dumping_static_archive()) { 707 _shared_table.reset(); 708 writer.dump(&_shared_table, "symbol"); 709 } else { 710 assert(CDSConfig::is_dumping_dynamic_archive(), "must be"); 711 _dynamic_shared_table.reset(); 712 writer.dump(&_dynamic_shared_table, "symbol"); 713 } 714 } 715 716 void SymbolTable::serialize_shared_table_header(SerializeClosure* soc, 717 bool is_static_archive) { 718 OffsetCompactHashtable<const char*, Symbol*, symbol_equals_compact_hashtable_entry> * table; 719 if (is_static_archive) { 720 table = &_shared_table; 721 } else { 722 table = &_dynamic_shared_table; 723 } 724 table->serialize_header(soc); 725 if (soc->writing()) { 726 // Sanity. Make sure we don't use the shared table at dump time 727 table->reset(); 728 } 729 } 730 #endif //INCLUDE_CDS 731 732 // Concurrent work 733 void SymbolTable::grow(JavaThread* jt) { 734 SymbolTableHash::GrowTask gt(_local_table); 735 if (!gt.prepare(jt)) { 736 return; 737 } 738 log_trace(symboltable)("Started to grow"); 739 { 740 TraceTime timer("Grow", TRACETIME_LOG(Debug, symboltable, perf)); 741 while (gt.do_task(jt)) { 742 gt.pause(jt); 743 { 744 ThreadBlockInVM tbivm(jt); 745 } 746 gt.cont(jt); 747 } 748 } 749 gt.done(jt); 750 _current_size = table_size(); 751 log_debug(symboltable)("Grown to size:%zu", _current_size); 752 } 753 754 struct SymbolTableDoDelete : StackObj { 755 size_t _deleted; 756 SymbolTableDoDelete() : _deleted(0) {} 757 void operator()(Symbol* value) { 758 assert(value != nullptr, "expected valid value"); 759 Symbol *sym = value; 760 assert(sym->refcount() == 0, "refcount"); 761 _deleted++; 762 } 763 }; 764 765 struct SymbolTableDeleteCheck : StackObj { 766 size_t _processed; 767 SymbolTableDeleteCheck() : _processed(0) {} 768 bool operator()(Symbol* value) { 769 assert(value != nullptr, "expected valid value"); 770 _processed++; 771 Symbol *sym = value; 772 return (sym->refcount() == 0); 773 } 774 }; 775 776 void SymbolTable::clean_dead_entries(JavaThread* jt) { 777 SymbolTableHash::BulkDeleteTask bdt(_local_table); 778 if (!bdt.prepare(jt)) { 779 return; 780 } 781 782 SymbolTableDeleteCheck stdc; 783 SymbolTableDoDelete stdd; 784 NativeHeapTrimmer::SuspendMark sm("symboltable"); 785 { 786 TraceTime timer("Clean", TRACETIME_LOG(Debug, symboltable, perf)); 787 while (bdt.do_task(jt, stdc, stdd)) { 788 bdt.pause(jt); 789 { 790 ThreadBlockInVM tbivm(jt); 791 } 792 bdt.cont(jt); 793 } 794 reset_has_items_to_clean(); 795 bdt.done(jt); 796 } 797 798 Atomic::add(&_symbols_counted, stdc._processed); 799 800 log_debug(symboltable)("Cleaned %zu of %zu", 801 stdd._deleted, stdc._processed); 802 } 803 804 void SymbolTable::check_concurrent_work() { 805 if (has_work()) { 806 return; 807 } 808 // We should clean/resize if we have 809 // more items than preferred load factor or 810 // more dead items than water mark. 811 if (has_items_to_clean() || (get_load_factor() > PREF_AVG_LIST_LEN)) { 812 log_debug(symboltable)("Concurrent work triggered, load factor: %f, items to clean: %s", 813 get_load_factor(), has_items_to_clean() ? "true" : "false"); 814 trigger_cleanup(); 815 } 816 } 817 818 bool SymbolTable::should_grow() { 819 return get_load_factor() > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached(); 820 } 821 822 void SymbolTable::do_concurrent_work(JavaThread* jt) { 823 // Rehash if needed. Rehashing goes to a safepoint but the rest of this 824 // work is concurrent. 825 if (needs_rehashing() && maybe_rehash_table()) { 826 Atomic::release_store(&_has_work, false); 827 return; // done, else grow 828 } 829 log_debug(symboltable, perf)("Concurrent work, live factor: %g", get_load_factor()); 830 // We prefer growing, since that also removes dead items 831 if (should_grow()) { 832 grow(jt); 833 } else { 834 clean_dead_entries(jt); 835 } 836 Atomic::release_store(&_has_work, false); 837 } 838 839 // Called at VM_Operation safepoint 840 void SymbolTable::rehash_table() { 841 assert(SafepointSynchronize::is_at_safepoint(), "must be called at safepoint"); 842 // The ServiceThread initiates the rehashing so it is not resizing. 843 assert (_local_table->is_safepoint_safe(), "Should not be resizing now"); 844 845 _alt_hash_seed = AltHashing::compute_seed(); 846 847 // We use current size 848 size_t new_size = _local_table->get_size_log2(Thread::current()); 849 SymbolTableHash* new_table = new SymbolTableHash(new_size, END_SIZE, REHASH_LEN, true); 850 // Use alt hash from now on 851 _alt_hash = true; 852 _local_table->rehash_nodes_to(Thread::current(), new_table); 853 854 // free old table 855 delete _local_table; 856 _local_table = new_table; 857 858 _rehashed = true; 859 _needs_rehashing = false; 860 } 861 862 bool SymbolTable::maybe_rehash_table() { 863 log_debug(symboltable)("Table imbalanced, rehashing called."); 864 865 // Grow instead of rehash. 866 if (should_grow()) { 867 log_debug(symboltable)("Choosing growing over rehashing."); 868 _needs_rehashing = false; 869 return false; 870 } 871 872 // Already rehashed. 873 if (_rehashed) { 874 log_warning(symboltable)("Rehashing already done, still long lists."); 875 _needs_rehashing = false; 876 return false; 877 } 878 879 VM_RehashSymbolTable op; 880 VMThread::execute(&op); 881 return true; 882 } 883 884 //--------------------------------------------------------------------------- 885 // Non-product code 886 887 #ifndef PRODUCT 888 889 class HistogramIterator : StackObj { 890 public: 891 static const size_t results_length = 100; 892 size_t counts[results_length]; 893 size_t sizes[results_length]; 894 size_t total_size; 895 size_t total_count; 896 size_t total_length; 897 size_t max_length; 898 size_t out_of_range_count; 899 size_t out_of_range_size; 900 HistogramIterator() : total_size(0), total_count(0), total_length(0), 901 max_length(0), out_of_range_count(0), out_of_range_size(0) { 902 // initialize results to zero 903 for (size_t i = 0; i < results_length; i++) { 904 counts[i] = 0; 905 sizes[i] = 0; 906 } 907 } 908 bool operator()(Symbol* value) { 909 assert(value != nullptr, "expected valid value"); 910 Symbol* sym = value; 911 size_t size = sym->size(); 912 size_t len = sym->utf8_length(); 913 if (len < results_length) { 914 counts[len]++; 915 sizes[len] += size; 916 } else { 917 out_of_range_count++; 918 out_of_range_size += size; 919 } 920 total_count++; 921 total_size += size; 922 total_length += len; 923 max_length = MAX2(max_length, len); 924 925 return true; 926 }; 927 }; 928 929 void SymbolTable::print_histogram() { 930 HistogramIterator hi; 931 _local_table->do_scan(Thread::current(), hi); 932 tty->print_cr("Symbol Table Histogram:"); 933 tty->print_cr(" Total number of symbols %7zu", hi.total_count); 934 tty->print_cr(" Total size in memory %7zuK", (hi.total_size * wordSize) / K); 935 tty->print_cr(" Total counted %7zu", _symbols_counted); 936 tty->print_cr(" Total removed %7zu", _symbols_removed); 937 if (_symbols_counted > 0) { 938 tty->print_cr(" Percent removed %3.2f", 939 ((double)_symbols_removed / (double)_symbols_counted) * 100); 940 } 941 tty->print_cr(" Reference counts %7zu", Symbol::_total_count); 942 tty->print_cr(" Symbol arena used %7zuK", arena()->used() / K); 943 tty->print_cr(" Symbol arena size %7zuK", arena()->size_in_bytes() / K); 944 tty->print_cr(" Total symbol length %7zu", hi.total_length); 945 tty->print_cr(" Maximum symbol length %7zu", hi.max_length); 946 tty->print_cr(" Average symbol length %7.2f", ((double)hi.total_length / (double)hi.total_count)); 947 tty->print_cr(" Symbol length histogram:"); 948 tty->print_cr(" %6s %10s %10s", "Length", "#Symbols", "Size"); 949 for (size_t i = 0; i < hi.results_length; i++) { 950 if (hi.counts[i] > 0) { 951 tty->print_cr(" %6zu %10zu %10zuK", 952 i, hi.counts[i], (hi.sizes[i] * wordSize) / K); 953 } 954 } 955 tty->print_cr(" >= %6zu %10zu %10zuK\n", 956 hi.results_length, hi.out_of_range_count, (hi.out_of_range_size*wordSize) / K); 957 } 958 #endif // PRODUCT 959 960 // Utility for dumping symbols 961 SymboltableDCmd::SymboltableDCmd(outputStream* output, bool heap) : 962 DCmdWithParser(output, heap), 963 _verbose("-verbose", "Dump the content of each symbol in the table", 964 "BOOLEAN", false, "false") { 965 _dcmdparser.add_dcmd_option(&_verbose); 966 } 967 968 void SymboltableDCmd::execute(DCmdSource source, TRAPS) { 969 VM_DumpHashtable dumper(output(), VM_DumpHashtable::DumpSymbols, 970 _verbose.value()); 971 VMThread::execute(&dumper); 972 }