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