1 /* 2 * Copyright (c) 1997, 2018, 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 "classfile/altHashing.hpp" 27 #include "classfile/compactHashtable.inline.hpp" 28 #include "classfile/javaClasses.hpp" 29 #include "classfile/symbolTable.hpp" 30 #include "memory/allocation.inline.hpp" 31 #include "memory/metaspaceClosure.hpp" 32 #include "memory/resourceArea.hpp" 33 #include "oops/oop.inline.hpp" 34 #include "runtime/atomic.hpp" 35 #include "runtime/interfaceSupport.inline.hpp" 36 #include "runtime/timerTrace.hpp" 37 #include "services/diagnosticCommand.hpp" 38 #include "utilities/concurrentHashTable.inline.hpp" 39 #include "utilities/concurrentHashTableTasks.inline.hpp" 40 41 // We used to not resize at all, so let's be conservative 42 // and not set it too short before we decide to resize, 43 // to match previous startup behavior 44 #define PREF_AVG_LIST_LEN 8 45 // 2^17 (131,072) is max size, which is about 6.5 times as large 46 // as the previous table size (used to be 20,011), 47 // which never resized 48 #define END_SIZE 17 49 // If a chain gets to 100 something might be wrong 50 #define REHASH_LEN 100 51 // We only get a chance to check whether we need 52 // to clean infrequently (on class unloading), 53 // so if we have even one dead entry then mark table for cleaning 54 #define CLEAN_DEAD_HIGH_WATER_MARK 0.0 55 56 #define ON_STACK_BUFFER_LENGTH 128 57 58 // -------------------------------------------------------------------------- 59 SymbolTable* SymbolTable::_the_table = NULL; 60 CompactHashtable<Symbol*, char> SymbolTable::_shared_table; 61 bool SymbolTable::_alt_hash = false; 62 // Static arena for symbols that are not deallocated 63 Arena* SymbolTable::_arena = NULL; 64 bool SymbolTable::_lookup_shared_first = false; 65 int SymbolTable::_symbols_removed = 0; 66 int SymbolTable::_symbols_counted = 0; 67 68 static juint murmur_seed = 0; 69 70 static inline void _log_trace_symboltable_helper(Symbol* sym, const char* msg) { 71 #ifndef PRODUCT 72 if (log_is_enabled(Trace, symboltable)) { 73 char *s; 74 { 75 ResourceMark rm; 76 s = sym->as_quoted_ascii(); 77 s = os::strdup(s); 78 } 79 if (s == NULL) { 80 log_trace(symboltable)("%s [%s]", msg, "NULL"); 81 } else { 82 log_trace(symboltable)("%s [%s]", msg, s); 83 os::free(s); 84 } 85 } 86 #endif // PRODUCT 87 } 88 89 // Pick hashing algorithm. 90 static uintx hash_symbol(const char* s, int len, bool useAlt) { 91 return useAlt ? 92 AltHashing::murmur3_32(murmur_seed, (const jbyte*)s, len) : 93 java_lang_String::hash_code((const jbyte*)s, len); 94 } 95 96 static uintx hash_shared_symbol(const char* s, int len) { 97 return java_lang_String::hash_code((const jbyte*)s, len); 98 } 99 100 class SymbolTableConfig : public SymbolTableHash::BaseConfig { 101 private: 102 public: 103 static uintx get_hash(Symbol* const& value, bool* is_dead) { 104 *is_dead = (value->refcount() == 0); 105 if (*is_dead) { 106 return 0; 107 } else { 108 return hash_symbol((char*)value->bytes(), value->utf8_length(), SymbolTable::_alt_hash); 109 } 110 } 111 // We use default allocation/deallocation but counted 112 static void* allocate_node(size_t size, Symbol* const& value) { 113 SymbolTable::item_added(); 114 return SymbolTableHash::BaseConfig::allocate_node(size, value); 115 } 116 static void free_node(void* memory, Symbol* const& value) { 117 // We get here either because #1 some threads lost a race 118 // to insert a newly created Symbol, or #2 we are freeing 119 // a symbol during normal cleanup deletion. 120 // If #1, then the symbol can be a permanent (refcount==PERM_REFCOUNT), 121 // or regular newly created one but with refcount==0 (see SymbolTableCreateEntry) 122 // If #2, then the symbol must have refcount==0 123 assert((value->refcount() == PERM_REFCOUNT) || (value->refcount() == 0), 124 "refcount %d", value->refcount()); 125 SymbolTable::delete_symbol(value); 126 SymbolTableHash::BaseConfig::free_node(memory, value); 127 SymbolTable::item_removed(); 128 } 129 }; 130 131 static size_t ceil_pow_2(uintx value) { 132 size_t ret; 133 for (ret = 1; ((size_t)1 << ret) < value; ++ret); 134 return ret; 135 } 136 137 SymbolTable::SymbolTable() : _local_table(NULL), _current_size(0), _has_work(0), 138 _needs_rehashing(false), _items(0), _uncleaned_items(0) { 139 140 size_t start_size_log_2 = ceil_pow_2(SymbolTableSize); 141 _current_size = ((size_t)1) << start_size_log_2; 142 log_trace(symboltable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")", 143 _current_size, start_size_log_2); 144 _local_table = new SymbolTableHash(start_size_log_2, END_SIZE, REHASH_LEN); 145 } 146 147 void SymbolTable::delete_symbol(Symbol* sym) { 148 if (sym->refcount() == PERM_REFCOUNT) { 149 MutexLocker ml(SymbolTable_lock); // Protect arena 150 // Deleting permanent symbol should not occur very often (insert race condition), 151 // so log it. 152 _log_trace_symboltable_helper(sym, "Freeing permanent symbol"); 153 if (!arena()->Afree(sym, sym->size())) { 154 _log_trace_symboltable_helper(sym, "Leaked permanent symbol"); 155 } 156 } else { 157 delete sym; 158 } 159 } 160 161 size_t SymbolTable::item_added() { 162 return Atomic::add(1, &(SymbolTable::the_table()->_items)); 163 } 164 165 void SymbolTable::set_item_clean_count(size_t ncl) { 166 Atomic::store((int)ncl, &(SymbolTable::the_table()->_uncleaned_items)); 167 log_trace(symboltable)("Set uncleaned items:" INT32_FORMAT, SymbolTable::the_table()->_uncleaned_items); 168 } 169 170 void SymbolTable::mark_item_clean_count() { 171 if (Atomic::cmpxchg(1, &(SymbolTable::the_table()->_uncleaned_items), 0) == 0) { // only mark if unset 172 log_trace(symboltable)("Marked uncleaned items:" INT32_FORMAT, SymbolTable::the_table()->_uncleaned_items); 173 } 174 } 175 176 void SymbolTable::item_removed() { 177 Atomic::add(1, &(SymbolTable::the_table()->_symbols_removed)); 178 Atomic::sub(1, &(SymbolTable::the_table()->_items)); 179 } 180 181 double SymbolTable::get_load_factor() { 182 return (_items*1.0)/_current_size; 183 } 184 185 double SymbolTable::get_dead_factor() { 186 return (_uncleaned_items*1.0)/_current_size; 187 } 188 189 size_t SymbolTable::table_size(Thread* thread) { 190 return ((size_t)(1)) << _local_table->get_size_log2(thread != NULL ? thread 191 : Thread::current()); 192 } 193 194 void SymbolTable::trigger_concurrent_work() { 195 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); 196 SymbolTable::the_table()->_has_work = true; 197 Service_lock->notify_all(); 198 } 199 200 Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS) { 201 assert (len <= Symbol::max_length(), "should be checked by caller"); 202 203 Symbol* sym; 204 if (DumpSharedSpaces) { 205 c_heap = false; 206 } 207 if (c_heap) { 208 // refcount starts as 1 209 sym = new (len, THREAD) Symbol(name, len, 1); 210 assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted"); 211 } else { 212 // Allocate to global arena 213 MutexLocker ml(SymbolTable_lock); // Protect arena 214 sym = new (len, arena(), THREAD) Symbol(name, len, PERM_REFCOUNT); 215 } 216 return sym; 217 } 218 219 void SymbolTable::initialize_symbols(int arena_alloc_size) { 220 // Initialize the arena for global symbols, size passed in depends on CDS. 221 if (arena_alloc_size == 0) { 222 _arena = new (mtSymbol) Arena(mtSymbol); 223 } else { 224 _arena = new (mtSymbol) Arena(mtSymbol, arena_alloc_size); 225 } 226 } 227 228 class SymbolsDo : StackObj { 229 SymbolClosure *_cl; 230 public: 231 SymbolsDo(SymbolClosure *cl) : _cl(cl) {} 232 bool operator()(Symbol** value) { 233 assert(value != NULL, "expected valid value"); 234 assert(*value != NULL, "value should point to a symbol"); 235 _cl->do_symbol(value); 236 return true; 237 }; 238 }; 239 240 // Call function for all symbols in the symbol table. 241 void SymbolTable::symbols_do(SymbolClosure *cl) { 242 // all symbols from shared table 243 _shared_table.symbols_do(cl); 244 245 // all symbols from the dynamic table 246 SymbolsDo sd(cl); 247 if (!SymbolTable::the_table()->_local_table->try_scan(Thread::current(), sd)) { 248 log_info(stringtable)("symbols_do unavailable at this moment"); 249 } 250 } 251 252 class MetaspacePointersDo : StackObj { 253 MetaspaceClosure *_it; 254 public: 255 MetaspacePointersDo(MetaspaceClosure *it) : _it(it) {} 256 bool operator()(Symbol** value) { 257 assert(value != NULL, "expected valid value"); 258 assert(*value != NULL, "value should point to a symbol"); 259 _it->push(value); 260 return true; 261 }; 262 }; 263 264 void SymbolTable::metaspace_pointers_do(MetaspaceClosure* it) { 265 assert(DumpSharedSpaces, "called only during dump time"); 266 MetaspacePointersDo mpd(it); 267 SymbolTable::the_table()->_local_table->do_scan(Thread::current(), mpd); 268 } 269 270 Symbol* SymbolTable::lookup_dynamic(const char* name, 271 int len, unsigned int hash) { 272 Symbol* sym = SymbolTable::the_table()->do_lookup((char*)name, len, hash); 273 assert((sym == NULL) || sym->refcount() != 0, "refcount must not be zero"); 274 return sym; 275 } 276 277 Symbol* SymbolTable::lookup_shared(const char* name, 278 int len, unsigned int hash) { 279 if (!_shared_table.empty()) { 280 if (SymbolTable::_alt_hash) { 281 // hash_code parameter may use alternate hashing algorithm but the shared table 282 // always uses the same original hash code. 283 hash = hash_shared_symbol(name, len); 284 } 285 return _shared_table.lookup(name, hash, len); 286 } else { 287 return NULL; 288 } 289 } 290 291 Symbol* SymbolTable::lookup_common(const char* name, 292 int len, unsigned int hash) { 293 Symbol* sym; 294 if (_lookup_shared_first) { 295 sym = lookup_shared(name, len, hash); 296 if (sym == NULL) { 297 _lookup_shared_first = false; 298 sym = lookup_dynamic(name, len, hash); 299 } 300 } else { 301 sym = lookup_dynamic(name, len, hash); 302 if (sym == NULL) { 303 sym = lookup_shared(name, len, hash); 304 if (sym != NULL) { 305 _lookup_shared_first = true; 306 } 307 } 308 } 309 return sym; 310 } 311 312 Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) { 313 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash); 314 Symbol* sym = SymbolTable::the_table()->lookup_common(name, len, hash); 315 if (sym == NULL) { 316 sym = SymbolTable::the_table()->do_add_if_needed((char*)name, len, hash, true, CHECK_NULL); 317 } 318 assert(sym->refcount() != 0, "lookup should have incremented the count"); 319 assert(sym->equals((char*)name, len), "symbol must be properly initialized"); 320 return sym; 321 } 322 323 Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) { 324 Symbol* found = NULL; 325 { 326 debug_only(NoSafepointVerifier nsv;) 327 328 char* name = (char*)sym->base() + begin; 329 int len = end - begin; 330 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash); 331 found = SymbolTable::the_table()->do_add_if_needed(name, len, hash, true, THREAD); 332 } 333 return found; 334 } 335 336 class SymbolTableLookupChar : StackObj { 337 private: 338 Thread* _thread; 339 uintx _hash; 340 int _len; 341 const char* _str; 342 Symbol* _found; 343 public: 344 SymbolTableLookupChar(Thread* thread, const char* key, int len, uintx hash) 345 : _thread(thread), _hash(hash), _str(key), _len(len) , _found(NULL) { 346 } 347 uintx get_hash() const { 348 return _hash; 349 } 350 bool equals(Symbol** value, bool* is_dead) { 351 assert(value != NULL, "expected valid value"); 352 assert(*value != NULL, "value should point to a symbol"); 353 Symbol *sym = *value; 354 if (sym->equals(_str, _len)) { 355 if (sym->try_increment_refcount()) { 356 // something is referencing this symbol now. 357 _found = sym; 358 return true; 359 } else { 360 *is_dead = (sym->refcount() == 0); 361 return false; 362 } 363 } else { 364 return false; 365 } 366 } 367 }; 368 369 class SymbolTableGet : public StackObj { 370 Symbol* _return; 371 public: 372 SymbolTableGet() : _return(NULL) { } 373 void operator()(Symbol** value) { 374 assert(value != NULL, "expected valid value"); 375 assert(*value != NULL, "value should point to a symbol"); 376 _return = *value; 377 } 378 Symbol* get_res_sym() { 379 return _return; 380 } 381 }; 382 383 Symbol* SymbolTable::do_lookup(char* name, int len, uintx hash) { 384 Thread* thread = Thread::current(); 385 SymbolTableLookupChar lookup(thread, name, len, hash); 386 SymbolTableGet stg; 387 bool rehash_warning; 388 _local_table->get(thread, lookup, stg, &rehash_warning); 389 if (rehash_warning) { 390 _needs_rehashing = true; 391 } 392 Symbol* sym = stg.get_res_sym(); 393 assert((sym == NULL) || sym->refcount() != 0, "found dead symbol"); 394 return sym; 395 } 396 397 Symbol* SymbolTable::lookup_only(const char* name, int len, unsigned int& hash) { 398 hash = hash_symbol(name, len, SymbolTable::_alt_hash); 399 return SymbolTable::the_table()->lookup_common(name, len, hash); 400 } 401 402 // Suggestion: Push unicode-based lookup all the way into the hashing 403 // and probing logic, so there is no need for convert_to_utf8 until 404 // an actual new Symbol* is created. 405 Symbol* SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) { 406 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); 407 char stack_buf[ON_STACK_BUFFER_LENGTH]; 408 if (utf8_length < (int) sizeof(stack_buf)) { 409 char* chars = stack_buf; 410 UNICODE::convert_to_utf8(name, utf16_length, chars); 411 return lookup(chars, utf8_length, THREAD); 412 } else { 413 ResourceMark rm(THREAD); 414 char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1); 415 UNICODE::convert_to_utf8(name, utf16_length, chars); 416 return lookup(chars, utf8_length, THREAD); 417 } 418 } 419 420 Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length, 421 unsigned int& hash) { 422 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); 423 char stack_buf[ON_STACK_BUFFER_LENGTH]; 424 if (utf8_length < (int) sizeof(stack_buf)) { 425 char* chars = stack_buf; 426 UNICODE::convert_to_utf8(name, utf16_length, chars); 427 return lookup_only(chars, utf8_length, hash); 428 } else { 429 ResourceMark rm; 430 char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1); 431 UNICODE::convert_to_utf8(name, utf16_length, chars); 432 return lookup_only(chars, utf8_length, hash); 433 } 434 } 435 436 void SymbolTable::add(ClassLoaderData* loader_data, const constantPoolHandle& cp, 437 int names_count, const char** names, int* lengths, 438 int* cp_indices, unsigned int* hashValues, TRAPS) { 439 bool c_heap = !loader_data->is_the_null_class_loader_data(); 440 for (int i=0; i<names_count; i++) { 441 char *name = (char*)names[i]; 442 int len = lengths[i]; 443 unsigned int hash = hashValues[i]; 444 Symbol* sym = SymbolTable::the_table()->lookup_common(name, len, hash); 445 if (sym == NULL) { 446 sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, c_heap, CHECK); 447 } 448 assert(sym->refcount()!=0, "lookup should have incremented the count"); 449 cp->symbol_at_put(cp_indices[i], sym); 450 } 451 } 452 453 class SymbolTableCreateEntry : public StackObj { 454 private: 455 Thread* _thread; 456 const char* _name; 457 int _len; 458 bool _heap; 459 Symbol* _return; 460 Symbol* _created; 461 462 #ifdef ASSERT 463 void _assert_for_name(Symbol* sym, const char* where) const { 464 assert(sym->utf8_length() == _len, "%s [%d,%d]", where, sym->utf8_length(), _len); 465 for (int i=0; i<_len; i++) { 466 assert(sym->byte_at(i) == _name[i], 467 "%s [%d,%d,%d]", where, i, sym->byte_at(i), _name[i]); 468 } 469 } 470 #endif 471 472 public: 473 SymbolTableCreateEntry(Thread* thread, const char* name, int len, bool heap) 474 : _thread(thread), _name(name) , _len(len), _heap(heap), _return(NULL) , _created(NULL) { 475 assert(_name != NULL, "expected valid name"); 476 } 477 Symbol* operator()() { 478 _created = SymbolTable::the_table()->allocate_symbol((const u1*)_name, _len, _heap, _thread); 479 assert(_created != NULL, "expected created symbol"); 480 #ifdef ASSERT 481 _assert_for_name(_created, "operator()()"); 482 #endif 483 assert(_created->equals((char*)_name, _len), 484 "symbol must be properly initialized [%p,%d,%d]", _name, _len, (int)_heap); 485 return _created; 486 } 487 void operator()(bool inserted, Symbol** value) { 488 assert(value != NULL, "expected valid value"); 489 assert(*value != NULL, "value should point to a symbol"); 490 if (!inserted && (_created != NULL)) { 491 // We created our symbol, but someone else inserted 492 // theirs first, so ours will be destroyed. 493 // Since symbols are created with refcount of 1, 494 // we must decrement it here to 0 to delete, 495 // unless it's a permanent one. 496 if (_created->refcount() != PERM_REFCOUNT) { 497 assert(_created->refcount() == 1, "expected newly created symbol"); 498 _created->decrement_refcount(); 499 assert(_created->refcount() == 0, "expected dead symbol"); 500 } 501 } 502 _return = *value; 503 #ifdef ASSERT 504 _assert_for_name(_return, "operator()"); 505 #endif 506 } 507 Symbol* get_new_sym() const { 508 #ifdef ASSERT 509 _assert_for_name(_return, "get_new_sym"); 510 #endif 511 return _return; 512 } 513 }; 514 515 Symbol* SymbolTable::do_add_if_needed(char* name, int len, uintx hash, bool heap, TRAPS) { 516 SymbolTableLookupChar lookup(THREAD, name, len, hash); 517 SymbolTableCreateEntry stce(THREAD, name, len, heap); 518 bool rehash_warning; 519 bool clean_hint; 520 _local_table->get_insert_lazy(THREAD, lookup, stce, stce, &rehash_warning, &clean_hint); 521 if (rehash_warning) { 522 _needs_rehashing = true; 523 } 524 if (clean_hint) { 525 // we just found out that there is a dead item, 526 // which we were unable to clean right now, 527 // but we have no way of telling whether it's 528 // been previously counted or not, so mark 529 // it only if no other items were found yet 530 mark_item_clean_count(); 531 check_concurrent_work(); 532 } 533 Symbol* sym = stce.get_new_sym(); 534 assert(sym->refcount() != 0, "zero is invalid"); 535 return sym; 536 } 537 538 Symbol* SymbolTable::new_permanent_symbol(const char* name, TRAPS) { 539 unsigned int hash = 0; 540 int len = (int)strlen(name); 541 Symbol* sym = SymbolTable::lookup_only(name, len, hash); 542 if (sym == NULL) { 543 sym = SymbolTable::the_table()->do_add_if_needed((char*)name, len, hash, false, CHECK_NULL); 544 } 545 if (sym->refcount() != PERM_REFCOUNT) { 546 sym->increment_refcount(); 547 _log_trace_symboltable_helper(sym, "Asked for a permanent symbol, but got a regular one"); 548 } 549 return sym; 550 } 551 552 struct SizeFunc : StackObj { 553 size_t operator()(Symbol** value) { 554 assert(value != NULL, "expected valid value"); 555 assert(*value != NULL, "value should point to a symbol"); 556 return (*value)->size() * HeapWordSize; 557 }; 558 }; 559 560 void SymbolTable::print_table_statistics(outputStream* st, 561 const char* table_name) { 562 SizeFunc sz; 563 _local_table->statistics_to(Thread::current(), sz, st, table_name); 564 } 565 566 // Verification 567 class VerifySymbols : StackObj { 568 public: 569 bool operator()(Symbol** value) { 570 guarantee(value != NULL, "expected valid value"); 571 guarantee(*value != NULL, "value should point to a symbol"); 572 Symbol* sym = *value; 573 guarantee(sym->equals((char*)sym->bytes(), sym->utf8_length()), 574 "symbol must be internally consistent"); 575 return true; 576 }; 577 }; 578 579 void SymbolTable::verify() { 580 Thread* thr = Thread::current(); 581 VerifySymbols vs; 582 if (!SymbolTable::the_table()->_local_table->try_scan(thr, vs)) { 583 log_info(stringtable)("verify unavailable at this moment"); 584 } 585 } 586 587 // Dumping 588 class DumpSymbol : StackObj { 589 Thread* _thr; 590 outputStream* _st; 591 public: 592 DumpSymbol(Thread* thr, outputStream* st) : _thr(thr), _st(st) {} 593 bool operator()(Symbol** value) { 594 assert(value != NULL, "expected valid value"); 595 assert(*value != NULL, "value should point to a symbol"); 596 Symbol* sym = *value; 597 const char* utf8_string = (const char*)sym->bytes(); 598 int utf8_length = sym->utf8_length(); 599 _st->print("%d %d: ", utf8_length, sym->refcount()); 600 HashtableTextDump::put_utf8(_st, utf8_string, utf8_length); 601 _st->cr(); 602 return true; 603 }; 604 }; 605 606 void SymbolTable::dump(outputStream* st, bool verbose) { 607 if (!verbose) { 608 SymbolTable::the_table()->print_table_statistics(st, "SymbolTable"); 609 } else { 610 Thread* thr = Thread::current(); 611 ResourceMark rm(thr); 612 st->print_cr("VERSION: 1.1"); 613 DumpSymbol ds(thr, st); 614 if (!SymbolTable::the_table()->_local_table->try_scan(thr, ds)) { 615 log_info(symboltable)("dump unavailable at this moment"); 616 } 617 } 618 } 619 620 #if INCLUDE_CDS 621 struct CopyToArchive : StackObj { 622 CompactSymbolTableWriter* _writer; 623 CopyToArchive(CompactSymbolTableWriter* writer) : _writer(writer) {} 624 bool operator()(Symbol** value) { 625 assert(value != NULL, "expected valid value"); 626 assert(*value != NULL, "value should point to a symbol"); 627 Symbol* sym = *value; 628 unsigned int fixed_hash = hash_shared_symbol((char*)sym->bytes(), sym->utf8_length()); 629 if (fixed_hash == 0) { 630 return true; 631 } 632 assert(fixed_hash == hash_symbol((char*)sym->bytes(), sym->utf8_length(), false), 633 "must not rehash during dumping"); 634 635 // add to the compact table 636 _writer->add(fixed_hash, sym); 637 638 return true; 639 } 640 }; 641 642 void SymbolTable::copy_shared_symbol_table(CompactSymbolTableWriter* writer) { 643 CopyToArchive copy(writer); 644 SymbolTable::the_table()->_local_table->do_scan(Thread::current(), copy); 645 } 646 647 void SymbolTable::write_to_archive() { 648 _shared_table.reset(); 649 650 int num_buckets = (SymbolTable::the_table()->_items / SharedSymbolTableBucketSize); 651 // calculation of num_buckets can result in zero buckets, we need at least one 652 CompactSymbolTableWriter writer(num_buckets > 1 ? num_buckets : 1, 653 &MetaspaceShared::stats()->symbol); 654 copy_shared_symbol_table(&writer); 655 writer.dump(&_shared_table); 656 657 // Verify table is correct 658 Symbol* sym = vmSymbols::java_lang_Object(); 659 const char* name = (const char*)sym->bytes(); 660 int len = sym->utf8_length(); 661 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash); 662 assert(sym == _shared_table.lookup(name, hash, len), "sanity"); 663 } 664 665 void SymbolTable::serialize(SerializeClosure* soc) { 666 _shared_table.set_type(CompactHashtable<Symbol*, char>::_symbol_table); 667 _shared_table.serialize(soc); 668 669 if (soc->writing()) { 670 // Sanity. Make sure we don't use the shared table at dump time 671 _shared_table.reset(); 672 } 673 } 674 #endif //INCLUDE_CDS 675 676 // Concurrent work 677 void SymbolTable::grow(JavaThread* jt) { 678 SymbolTableHash::GrowTask gt(_local_table); 679 if (!gt.prepare(jt)) { 680 return; 681 } 682 log_trace(symboltable)("Started to grow"); 683 { 684 TraceTime timer("Grow", TRACETIME_LOG(Debug, symboltable, perf)); 685 while (gt.do_task(jt)) { 686 gt.pause(jt); 687 { 688 ThreadBlockInVM tbivm(jt); 689 } 690 gt.cont(jt); 691 } 692 } 693 gt.done(jt); 694 _current_size = table_size(jt); 695 log_debug(symboltable)("Grown to size:" SIZE_FORMAT, _current_size); 696 } 697 698 struct SymbolTableDoDelete : StackObj { 699 int _deleted; 700 SymbolTableDoDelete() : _deleted(0) {} 701 void operator()(Symbol** value) { 702 assert(value != NULL, "expected valid value"); 703 assert(*value != NULL, "value should point to a symbol"); 704 Symbol *sym = *value; 705 assert(sym->refcount() == 0, "refcount"); 706 _deleted++; 707 } 708 }; 709 710 struct SymbolTableDeleteCheck : StackObj { 711 int _processed; 712 SymbolTableDeleteCheck() : _processed(0) {} 713 bool operator()(Symbol** value) { 714 assert(value != NULL, "expected valid value"); 715 assert(*value != NULL, "value should point to a symbol"); 716 _processed++; 717 Symbol *sym = *value; 718 if (sym->refcount() == 0) { 719 return true; 720 } else { 721 return false; 722 } 723 } 724 }; 725 726 void SymbolTable::clean_dead_entries(JavaThread* jt) { 727 SymbolTableHash::BulkDeleteTask bdt(_local_table); 728 if (!bdt.prepare(jt)) { 729 return; 730 } 731 732 SymbolTableDeleteCheck stdc; 733 SymbolTableDoDelete stdd; 734 { 735 TraceTime timer("Clean", TRACETIME_LOG(Debug, symboltable, perf)); 736 while (bdt.do_task(jt, stdc, stdd)) { 737 bdt.pause(jt); 738 { 739 ThreadBlockInVM tbivm(jt); 740 } 741 bdt.cont(jt); 742 } 743 SymbolTable::the_table()->set_item_clean_count(0); 744 bdt.done(jt); 745 } 746 747 Atomic::add(stdc._processed, &_symbols_counted); 748 749 log_debug(symboltable)("Cleaned " INT32_FORMAT " of " INT32_FORMAT, 750 stdd._deleted, stdc._processed); 751 } 752 753 void SymbolTable::check_concurrent_work() { 754 if (_has_work) { 755 return; 756 } 757 double load_factor = SymbolTable::get_load_factor(); 758 double dead_factor = SymbolTable::get_dead_factor(); 759 // We should clean/resize if we have more dead than alive, 760 // more items than preferred load factor or 761 // more dead items than water mark. 762 if ((dead_factor > load_factor) || 763 (load_factor > PREF_AVG_LIST_LEN) || 764 (dead_factor > CLEAN_DEAD_HIGH_WATER_MARK)) { 765 log_debug(symboltable)("Concurrent work triggered, live factor:%f dead factor:%f", 766 load_factor, dead_factor); 767 trigger_concurrent_work(); 768 } 769 } 770 771 void SymbolTable::concurrent_work(JavaThread* jt) { 772 double load_factor = get_load_factor(); 773 log_debug(symboltable, perf)("Concurrent work, live factor: %g", load_factor); 774 // We prefer growing, since that also removes dead items 775 if (load_factor > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) { 776 grow(jt); 777 } else { 778 clean_dead_entries(jt); 779 } 780 _has_work = false; 781 } 782 783 class CountDead : StackObj { 784 int _count; 785 public: 786 CountDead() : _count(0) {} 787 bool operator()(Symbol** value) { 788 assert(value != NULL, "expected valid value"); 789 assert(*value != NULL, "value should point to a symbol"); 790 Symbol* sym = *value; 791 if (sym->refcount() == 0) { 792 _count++; 793 } 794 return true; 795 }; 796 int get_dead_count() { 797 return _count; 798 } 799 }; 800 801 void SymbolTable::do_check_concurrent_work() { 802 CountDead counter; 803 if (!SymbolTable::the_table()->_local_table->try_scan(Thread::current(), counter)) { 804 log_info(symboltable)("count dead unavailable at this moment"); 805 } else { 806 SymbolTable::the_table()->set_item_clean_count(counter.get_dead_count()); 807 SymbolTable::the_table()->check_concurrent_work(); 808 } 809 } 810 811 void SymbolTable::do_concurrent_work(JavaThread* jt) { 812 SymbolTable::the_table()->concurrent_work(jt); 813 } 814 815 // Rehash 816 bool SymbolTable::do_rehash() { 817 if (!_local_table->is_safepoint_safe()) { 818 return false; 819 } 820 821 // We use max size 822 SymbolTableHash* new_table = new SymbolTableHash(END_SIZE, END_SIZE, REHASH_LEN); 823 // Use alt hash from now on 824 _alt_hash = true; 825 if (!_local_table->try_move_nodes_to(Thread::current(), new_table)) { 826 _alt_hash = false; 827 delete new_table; 828 return false; 829 } 830 831 // free old table 832 delete _local_table; 833 _local_table = new_table; 834 835 return true; 836 } 837 838 void SymbolTable::try_rehash_table() { 839 static bool rehashed = false; 840 log_debug(symboltable)("Table imbalanced, rehashing called."); 841 842 // Grow instead of rehash. 843 if (get_load_factor() > PREF_AVG_LIST_LEN && 844 !_local_table->is_max_size_reached()) { 845 log_debug(symboltable)("Choosing growing over rehashing."); 846 trigger_concurrent_work(); 847 _needs_rehashing = false; 848 return; 849 } 850 851 // Already rehashed. 852 if (rehashed) { 853 log_warning(symboltable)("Rehashing already done, still long lists."); 854 trigger_concurrent_work(); 855 _needs_rehashing = false; 856 return; 857 } 858 859 murmur_seed = AltHashing::compute_seed(); 860 861 if (do_rehash()) { 862 rehashed = true; 863 } else { 864 log_info(symboltable)("Resizes in progress rehashing skipped."); 865 } 866 867 _needs_rehashing = false; 868 } 869 870 void SymbolTable::rehash_table() { 871 SymbolTable::the_table()->try_rehash_table(); 872 } 873 874 //--------------------------------------------------------------------------- 875 // Non-product code 876 877 #ifndef PRODUCT 878 879 class HistogramIterator : StackObj { 880 public: 881 static const int results_length = 100; 882 int counts[results_length]; 883 int sizes[results_length]; 884 int total_size; 885 int total_count; 886 int total_length; 887 int max_length; 888 int out_of_range_count; 889 int out_of_range_size; 890 HistogramIterator() : total_size(0), total_count(0), total_length(0), 891 max_length(0), out_of_range_count(0), out_of_range_size(0) { 892 // initialize results to zero 893 for (int i = 0; i < results_length; i++) { 894 counts[i] = 0; 895 sizes[i] = 0; 896 } 897 } 898 bool operator()(Symbol** value) { 899 assert(value != NULL, "expected valid value"); 900 assert(*value != NULL, "value should point to a symbol"); 901 Symbol* sym = *value; 902 int size = sym->size(); 903 int len = sym->utf8_length(); 904 if (len < results_length) { 905 counts[len]++; 906 sizes[len] += size; 907 } else { 908 out_of_range_count++; 909 out_of_range_size += size; 910 } 911 total_count++; 912 total_size += size; 913 total_length += len; 914 max_length = MAX2(max_length, len); 915 916 return true; 917 }; 918 }; 919 920 void SymbolTable::print_histogram() { 921 HistogramIterator hi; 922 SymbolTable::the_table()->_local_table->do_scan(Thread::current(), hi); 923 tty->print_cr("Symbol Table Histogram:"); 924 tty->print_cr(" Total number of symbols %7d", hi.total_count); 925 tty->print_cr(" Total size in memory %7dK", 926 (hi.total_size*wordSize)/1024); 927 tty->print_cr(" Total counted %7d", _symbols_counted); 928 tty->print_cr(" Total removed %7d", _symbols_removed); 929 if (_symbols_counted > 0) { 930 tty->print_cr(" Percent removed %3.2f", 931 ((float)_symbols_removed/(float)_symbols_counted)* 100); 932 } 933 tty->print_cr(" Reference counts %7d", Symbol::_total_count); 934 tty->print_cr(" Symbol arena used " SIZE_FORMAT_W(7) "K", arena()->used()/1024); 935 tty->print_cr(" Symbol arena size " SIZE_FORMAT_W(7) "K", arena()->size_in_bytes()/1024); 936 tty->print_cr(" Total symbol length %7d", hi.total_length); 937 tty->print_cr(" Maximum symbol length %7d", hi.max_length); 938 tty->print_cr(" Average symbol length %7.2f", ((float) hi.total_length / (float) hi.total_count)); 939 tty->print_cr(" Symbol length histogram:"); 940 tty->print_cr(" %6s %10s %10s", "Length", "#Symbols", "Size"); 941 for (int i = 0; i < hi.results_length; i++) { 942 if (hi.counts[i] > 0) { 943 tty->print_cr(" %6d %10d %10dK", i, hi.counts[i], (hi.sizes[i]*wordSize)/1024); 944 } 945 } 946 tty->print_cr(" >=%6d %10d %10dK\n", hi.results_length, 947 hi.out_of_range_count, (hi.out_of_range_size*wordSize)/1024); 948 } 949 #endif // PRODUCT 950 951 // Utility for dumping symbols 952 SymboltableDCmd::SymboltableDCmd(outputStream* output, bool heap) : 953 DCmdWithParser(output, heap), 954 _verbose("-verbose", "Dump the content of each symbol in the table", 955 "BOOLEAN", false, "false") { 956 _dcmdparser.add_dcmd_option(&_verbose); 957 } 958 959 void SymboltableDCmd::execute(DCmdSource source, TRAPS) { 960 VM_DumpHashtable dumper(output(), VM_DumpHashtable::DumpSymbols, 961 _verbose.value()); 962 VMThread::execute(&dumper); 963 } 964 965 int SymboltableDCmd::num_arguments() { 966 ResourceMark rm; 967 SymboltableDCmd* dcmd = new SymboltableDCmd(NULL, false); 968 if (dcmd != NULL) { 969 DCmdMark mark(dcmd); 970 return dcmd->_dcmdparser.num_arguments(); 971 } else { 972 return 0; 973 } 974 }