1 /* 2 * Copyright (c) 1997, 2017, 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 "classfile/systemDictionary.hpp" 31 #include "gc/shared/collectedHeap.inline.hpp" 32 #include "gc/shared/gcLocker.hpp" 33 #include "memory/allocation.inline.hpp" 34 #include "memory/filemap.hpp" 35 #include "memory/metaspaceClosure.hpp" 36 #include "memory/resourceArea.hpp" 37 #include "oops/oop.inline.hpp" 38 #include "runtime/atomic.hpp" 39 #include "runtime/mutexLocker.hpp" 40 #include "runtime/safepointVerifiers.hpp" 41 #include "services/diagnosticCommand.hpp" 42 #include "utilities/hashtable.inline.hpp" 43 44 // -------------------------------------------------------------------------- 45 // the number of buckets a thread claims 46 const int ClaimChunkSize = 32; 47 48 SymbolTable* SymbolTable::_the_table = NULL; 49 // Static arena for symbols that are not deallocated 50 Arena* SymbolTable::_arena = NULL; 51 bool SymbolTable::_needs_rehashing = false; 52 bool SymbolTable::_lookup_shared_first = false; 53 54 CompactHashtable<Symbol*, char> SymbolTable::_shared_table; 55 56 Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS) { 57 assert (len <= Symbol::max_length(), "should be checked by caller"); 58 59 Symbol* sym; 60 61 if (DumpSharedSpaces) { 62 c_heap = false; 63 } 64 if (c_heap) { 65 // refcount starts as 1 66 sym = new (len, THREAD) Symbol(name, len, 1); 67 assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted"); 68 } else { 69 // Allocate to global arena 70 sym = new (len, arena(), THREAD) Symbol(name, len, PERM_REFCOUNT); 71 } 72 return sym; 73 } 74 75 void SymbolTable::initialize_symbols(int arena_alloc_size) { 76 // Initialize the arena for global symbols, size passed in depends on CDS. 77 if (arena_alloc_size == 0) { 78 _arena = new (mtSymbol) Arena(mtSymbol); 79 } else { 80 _arena = new (mtSymbol) Arena(mtSymbol, arena_alloc_size); 81 } 82 } 83 84 // Call function for all symbols in the symbol table. 85 void SymbolTable::symbols_do(SymbolClosure *cl) { 86 // all symbols from shared table 87 _shared_table.symbols_do(cl); 88 89 // all symbols from the dynamic table 90 const int n = the_table()->table_size(); 91 for (int i = 0; i < n; i++) { 92 for (HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); 93 p != NULL; 94 p = p->next()) { 95 cl->do_symbol(p->literal_addr()); 96 } 97 } 98 } 99 100 void SymbolTable::metaspace_pointers_do(MetaspaceClosure* it) { 101 assert(DumpSharedSpaces, "called only during dump time"); 102 const int n = the_table()->table_size(); 103 for (int i = 0; i < n; i++) { 104 for (HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); 105 p != NULL; 106 p = p->next()) { 107 it->push(p->literal_addr()); 108 } 109 } 110 } 111 112 int SymbolTable::_symbols_removed = 0; 113 int SymbolTable::_symbols_counted = 0; 114 volatile int SymbolTable::_parallel_claimed_idx = 0; 115 116 void SymbolTable::buckets_unlink(int start_idx, int end_idx, BucketUnlinkContext* context) { 117 for (int i = start_idx; i < end_idx; ++i) { 118 HashtableEntry<Symbol*, mtSymbol>** p = the_table()->bucket_addr(i); 119 HashtableEntry<Symbol*, mtSymbol>* entry = the_table()->bucket(i); 120 while (entry != NULL) { 121 // Shared entries are normally at the end of the bucket and if we run into 122 // a shared entry, then there is nothing more to remove. However, if we 123 // have rehashed the table, then the shared entries are no longer at the 124 // end of the bucket. 125 if (entry->is_shared() && !use_alternate_hashcode()) { 126 break; 127 } 128 Symbol* s = entry->literal(); 129 context->_num_processed++; 130 assert(s != NULL, "just checking"); 131 // If reference count is zero, remove. 132 if (s->refcount() == 0) { 133 assert(!entry->is_shared(), "shared entries should be kept live"); 134 delete s; 135 *p = entry->next(); 136 context->free_entry(entry); 137 } else { 138 p = entry->next_addr(); 139 } 140 // get next entry 141 entry = (HashtableEntry<Symbol*, mtSymbol>*)HashtableEntry<Symbol*, mtSymbol>::make_ptr(*p); 142 } 143 } 144 } 145 146 // Remove unreferenced symbols from the symbol table 147 // This is done late during GC. 148 void SymbolTable::unlink(int* processed, int* removed) { 149 BucketUnlinkContext context; 150 buckets_unlink(0, the_table()->table_size(), &context); 151 _the_table->bulk_free_entries(&context); 152 *processed = context._num_processed; 153 *removed = context._num_removed; 154 155 _symbols_removed = context._num_removed; 156 _symbols_counted = context._num_processed; 157 } 158 159 void SymbolTable::possibly_parallel_unlink(int* processed, int* removed) { 160 const int limit = the_table()->table_size(); 161 162 BucketUnlinkContext context; 163 for (;;) { 164 // Grab next set of buckets to scan 165 int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize; 166 if (start_idx >= limit) { 167 // End of table 168 break; 169 } 170 171 int end_idx = MIN2(limit, start_idx + ClaimChunkSize); 172 buckets_unlink(start_idx, end_idx, &context); 173 } 174 175 _the_table->bulk_free_entries(&context); 176 *processed = context._num_processed; 177 *removed = context._num_removed; 178 179 Atomic::add(context._num_processed, &_symbols_counted); 180 Atomic::add(context._num_removed, &_symbols_removed); 181 } 182 183 // Create a new table and using alternate hash code, populate the new table 184 // with the existing strings. Set flag to use the alternate hash code afterwards. 185 void SymbolTable::rehash_table() { 186 if (DumpSharedSpaces) { 187 tty->print_cr("Warning: rehash_table should not be called while dumping archive"); 188 return; 189 } 190 191 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); 192 // This should never happen with -Xshare:dump but it might in testing mode. 193 if (DumpSharedSpaces) return; 194 // Create a new symbol table 195 SymbolTable* new_table = new SymbolTable(); 196 197 the_table()->move_to(new_table); 198 199 // Delete the table and buckets (entries are reused in new table). 200 delete _the_table; 201 // Don't check if we need rehashing until the table gets unbalanced again. 202 // Then rehash with a new global seed. 203 _needs_rehashing = false; 204 _the_table = new_table; 205 } 206 207 // Lookup a symbol in a bucket. 208 209 Symbol* SymbolTable::lookup_dynamic(int index, const char* name, 210 int len, unsigned int hash) { 211 int count = 0; 212 for (HashtableEntry<Symbol*, mtSymbol>* e = bucket(index); e != NULL; e = e->next()) { 213 count++; // count all entries in this bucket, not just ones with same hash 214 if (e->hash() == hash) { 215 Symbol* sym = e->literal(); 216 if (sym->equals(name, len)) { 217 // something is referencing this symbol now. 218 sym->increment_refcount(); 219 return sym; 220 } 221 } 222 } 223 // If the bucket size is too deep check if this hash code is insufficient. 224 if (count >= rehash_count && !needs_rehashing()) { 225 _needs_rehashing = check_rehash_table(count); 226 } 227 return NULL; 228 } 229 230 Symbol* SymbolTable::lookup_shared(const char* name, 231 int len, unsigned int hash) { 232 if (use_alternate_hashcode()) { 233 // hash_code parameter may use alternate hashing algorithm but the shared table 234 // always uses the same original hash code. 235 hash = hash_shared_symbol(name, len); 236 } 237 return _shared_table.lookup(name, hash, len); 238 } 239 240 Symbol* SymbolTable::lookup(int index, const char* name, 241 int len, unsigned int hash) { 242 Symbol* sym; 243 if (_lookup_shared_first) { 244 sym = lookup_shared(name, len, hash); 245 if (sym != NULL) { 246 return sym; 247 } 248 _lookup_shared_first = false; 249 return lookup_dynamic(index, name, len, hash); 250 } else { 251 sym = lookup_dynamic(index, name, len, hash); 252 if (sym != NULL) { 253 return sym; 254 } 255 sym = lookup_shared(name, len, hash); 256 if (sym != NULL) { 257 _lookup_shared_first = true; 258 } 259 return sym; 260 } 261 } 262 263 u4 SymbolTable::encode_shared(Symbol* sym) { 264 assert(DumpSharedSpaces, "called only during dump time"); 265 uintx base_address = uintx(MetaspaceShared::shared_rs()->base()); 266 uintx offset = uintx(sym) - base_address; 267 assert(offset < 0x7fffffff, "sanity"); 268 return u4(offset); 269 } 270 271 Symbol* SymbolTable::decode_shared(u4 offset) { 272 assert(!DumpSharedSpaces, "called only during runtime"); 273 uintx base_address = _shared_table.base_address(); 274 Symbol* sym = (Symbol*)(base_address + offset); 275 276 #ifndef PRODUCT 277 const char* s = (const char*)sym->bytes(); 278 int len = sym->utf8_length(); 279 unsigned int hash = hash_symbol(s, len); 280 assert(sym == lookup_shared(s, len, hash), "must be shared symbol"); 281 #endif 282 283 return sym; 284 } 285 286 // Pick hashing algorithm. 287 unsigned int SymbolTable::hash_symbol(const char* s, int len) { 288 return use_alternate_hashcode() ? 289 AltHashing::murmur3_32(seed(), (const jbyte*)s, len) : 290 java_lang_String::hash_code((const jbyte*)s, len); 291 } 292 293 unsigned int SymbolTable::hash_shared_symbol(const char* s, int len) { 294 return java_lang_String::hash_code((const jbyte*)s, len); 295 } 296 297 298 // We take care not to be blocking while holding the 299 // SymbolTable_lock. Otherwise, the system might deadlock, since the 300 // symboltable is used during compilation (VM_thread) The lock free 301 // synchronization is simplified by the fact that we do not delete 302 // entries in the symbol table during normal execution (only during 303 // safepoints). 304 305 Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) { 306 unsigned int hashValue = hash_symbol(name, len); 307 int index = the_table()->hash_to_index(hashValue); 308 309 Symbol* s = the_table()->lookup(index, name, len, hashValue); 310 311 // Found 312 if (s != NULL) return s; 313 314 // Grab SymbolTable_lock first. 315 MutexLocker ml(SymbolTable_lock, THREAD); 316 317 // Otherwise, add to symbol to table 318 return the_table()->basic_add(index, (u1*)name, len, hashValue, true, THREAD); 319 } 320 321 Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) { 322 char* buffer; 323 int index, len; 324 unsigned int hashValue; 325 char* name; 326 { 327 debug_only(NoSafepointVerifier nsv;) 328 329 name = (char*)sym->base() + begin; 330 len = end - begin; 331 hashValue = hash_symbol(name, len); 332 index = the_table()->hash_to_index(hashValue); 333 Symbol* s = the_table()->lookup(index, name, len, hashValue); 334 335 // Found 336 if (s != NULL) return s; 337 } 338 339 // Otherwise, add to symbol to table. Copy to a C string first. 340 char stack_buf[128]; 341 ResourceMark rm(THREAD); 342 if (len <= 128) { 343 buffer = stack_buf; 344 } else { 345 buffer = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len); 346 } 347 for (int i=0; i<len; i++) { 348 buffer[i] = name[i]; 349 } 350 // Make sure there is no safepoint in the code above since name can't move. 351 // We can't include the code in NoSafepointVerifier because of the 352 // ResourceMark. 353 354 // Grab SymbolTable_lock first. 355 MutexLocker ml(SymbolTable_lock, THREAD); 356 357 return the_table()->basic_add(index, (u1*)buffer, len, hashValue, true, THREAD); 358 } 359 360 Symbol* SymbolTable::lookup_only(const char* name, int len, 361 unsigned int& hash) { 362 hash = hash_symbol(name, len); 363 int index = the_table()->hash_to_index(hash); 364 365 Symbol* s = the_table()->lookup(index, name, len, hash); 366 return s; 367 } 368 369 // Look up the address of the literal in the SymbolTable for this Symbol* 370 // Do not create any new symbols 371 // Do not increment the reference count to keep this alive 372 Symbol** SymbolTable::lookup_symbol_addr(Symbol* sym){ 373 unsigned int hash = hash_symbol((char*)sym->bytes(), sym->utf8_length()); 374 int index = the_table()->hash_to_index(hash); 375 376 for (HashtableEntry<Symbol*, mtSymbol>* e = the_table()->bucket(index); e != NULL; e = e->next()) { 377 if (e->hash() == hash) { 378 Symbol* literal_sym = e->literal(); 379 if (sym == literal_sym) { 380 return e->literal_addr(); 381 } 382 } 383 } 384 return NULL; 385 } 386 387 // Suggestion: Push unicode-based lookup all the way into the hashing 388 // and probing logic, so there is no need for convert_to_utf8 until 389 // an actual new Symbol* is created. 390 Symbol* SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) { 391 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); 392 char stack_buf[128]; 393 if (utf8_length < (int) sizeof(stack_buf)) { 394 char* chars = stack_buf; 395 UNICODE::convert_to_utf8(name, utf16_length, chars); 396 return lookup(chars, utf8_length, THREAD); 397 } else { 398 ResourceMark rm(THREAD); 399 char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);; 400 UNICODE::convert_to_utf8(name, utf16_length, chars); 401 return lookup(chars, utf8_length, THREAD); 402 } 403 } 404 405 Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length, 406 unsigned int& hash) { 407 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); 408 char stack_buf[128]; 409 if (utf8_length < (int) sizeof(stack_buf)) { 410 char* chars = stack_buf; 411 UNICODE::convert_to_utf8(name, utf16_length, chars); 412 return lookup_only(chars, utf8_length, hash); 413 } else { 414 ResourceMark rm; 415 char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);; 416 UNICODE::convert_to_utf8(name, utf16_length, chars); 417 return lookup_only(chars, utf8_length, hash); 418 } 419 } 420 421 void SymbolTable::add(ClassLoaderData* loader_data, const constantPoolHandle& cp, 422 int names_count, 423 const char** names, int* lengths, int* cp_indices, 424 unsigned int* hashValues, TRAPS) { 425 // Grab SymbolTable_lock first. 426 MutexLocker ml(SymbolTable_lock, THREAD); 427 428 SymbolTable* table = the_table(); 429 bool added = table->basic_add(loader_data, cp, names_count, names, lengths, 430 cp_indices, hashValues, CHECK); 431 if (!added) { 432 // do it the hard way 433 for (int i=0; i<names_count; i++) { 434 int index = table->hash_to_index(hashValues[i]); 435 bool c_heap = !loader_data->is_the_null_class_loader_data(); 436 Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], hashValues[i], c_heap, CHECK); 437 cp->symbol_at_put(cp_indices[i], sym); 438 } 439 } 440 } 441 442 Symbol* SymbolTable::new_permanent_symbol(const char* name, TRAPS) { 443 unsigned int hash; 444 Symbol* result = SymbolTable::lookup_only((char*)name, (int)strlen(name), hash); 445 if (result != NULL) { 446 return result; 447 } 448 // Grab SymbolTable_lock first. 449 MutexLocker ml(SymbolTable_lock, THREAD); 450 451 SymbolTable* table = the_table(); 452 int index = table->hash_to_index(hash); 453 return table->basic_add(index, (u1*)name, (int)strlen(name), hash, false, THREAD); 454 } 455 456 Symbol* SymbolTable::basic_add(int index_arg, u1 *name, int len, 457 unsigned int hashValue_arg, bool c_heap, TRAPS) { 458 assert(!Universe::heap()->is_in_reserved(name), 459 "proposed name of symbol must be stable"); 460 461 // Don't allow symbols to be created which cannot fit in a Symbol*. 462 if (len > Symbol::max_length()) { 463 THROW_MSG_0(vmSymbols::java_lang_InternalError(), 464 "name is too long to represent"); 465 } 466 467 // Cannot hit a safepoint in this function because the "this" pointer can move. 468 NoSafepointVerifier nsv; 469 470 // Check if the symbol table has been rehashed, if so, need to recalculate 471 // the hash value and index. 472 unsigned int hashValue; 473 int index; 474 if (use_alternate_hashcode()) { 475 hashValue = hash_symbol((const char*)name, len); 476 index = hash_to_index(hashValue); 477 } else { 478 hashValue = hashValue_arg; 479 index = index_arg; 480 } 481 482 // Since look-up was done lock-free, we need to check if another 483 // thread beat us in the race to insert the symbol. 484 Symbol* test = lookup(index, (char*)name, len, hashValue); 485 if (test != NULL) { 486 // A race occurred and another thread introduced the symbol. 487 assert(test->refcount() != 0, "lookup should have incremented the count"); 488 return test; 489 } 490 491 // Create a new symbol. 492 Symbol* sym = allocate_symbol(name, len, c_heap, CHECK_NULL); 493 assert(sym->equals((char*)name, len), "symbol must be properly initialized"); 494 495 HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym); 496 add_entry(index, entry); 497 return sym; 498 } 499 500 // This version of basic_add adds symbols in batch from the constant pool 501 // parsing. 502 bool SymbolTable::basic_add(ClassLoaderData* loader_data, const constantPoolHandle& cp, 503 int names_count, 504 const char** names, int* lengths, 505 int* cp_indices, unsigned int* hashValues, 506 TRAPS) { 507 508 // Check symbol names are not too long. If any are too long, don't add any. 509 for (int i = 0; i< names_count; i++) { 510 if (lengths[i] > Symbol::max_length()) { 511 THROW_MSG_0(vmSymbols::java_lang_InternalError(), 512 "name is too long to represent"); 513 } 514 } 515 516 // Cannot hit a safepoint in this function because the "this" pointer can move. 517 NoSafepointVerifier nsv; 518 519 for (int i=0; i<names_count; i++) { 520 // Check if the symbol table has been rehashed, if so, need to recalculate 521 // the hash value. 522 unsigned int hashValue; 523 if (use_alternate_hashcode()) { 524 hashValue = hash_symbol(names[i], lengths[i]); 525 } else { 526 hashValue = hashValues[i]; 527 } 528 // Since look-up was done lock-free, we need to check if another 529 // thread beat us in the race to insert the symbol. 530 int index = hash_to_index(hashValue); 531 Symbol* test = lookup(index, names[i], lengths[i], hashValue); 532 if (test != NULL) { 533 // A race occurred and another thread introduced the symbol, this one 534 // will be dropped and collected. Use test instead. 535 cp->symbol_at_put(cp_indices[i], test); 536 assert(test->refcount() != 0, "lookup should have incremented the count"); 537 } else { 538 // Create a new symbol. The null class loader is never unloaded so these 539 // are allocated specially in a permanent arena. 540 bool c_heap = !loader_data->is_the_null_class_loader_data(); 541 Symbol* sym = allocate_symbol((const u1*)names[i], lengths[i], c_heap, CHECK_(false)); 542 assert(sym->equals(names[i], lengths[i]), "symbol must be properly initialized"); // why wouldn't it be??? 543 HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym); 544 add_entry(index, entry); 545 cp->symbol_at_put(cp_indices[i], sym); 546 } 547 } 548 return true; 549 } 550 551 552 void SymbolTable::verify() { 553 for (int i = 0; i < the_table()->table_size(); ++i) { 554 HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); 555 for ( ; p != NULL; p = p->next()) { 556 Symbol* s = (Symbol*)(p->literal()); 557 guarantee(s != NULL, "symbol is NULL"); 558 unsigned int h = hash_symbol((char*)s->bytes(), s->utf8_length()); 559 guarantee(p->hash() == h, "broken hash in symbol table entry"); 560 guarantee(the_table()->hash_to_index(h) == i, 561 "wrong index in symbol table"); 562 } 563 } 564 } 565 566 void SymbolTable::dump(outputStream* st, bool verbose) { 567 if (!verbose) { 568 the_table()->print_table_statistics(st, "SymbolTable"); 569 } else { 570 st->print_cr("VERSION: 1.0"); 571 for (int i = 0; i < the_table()->table_size(); ++i) { 572 HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); 573 for ( ; p != NULL; p = p->next()) { 574 Symbol* s = (Symbol*)(p->literal()); 575 const char* utf8_string = (const char*)s->bytes(); 576 int utf8_length = s->utf8_length(); 577 st->print("%d %d: ", utf8_length, s->refcount()); 578 HashtableTextDump::put_utf8(st, utf8_string, utf8_length); 579 st->cr(); 580 } 581 } 582 } 583 } 584 585 void SymbolTable::write_to_archive() { 586 #if INCLUDE_CDS 587 _shared_table.reset(); 588 589 int num_buckets = the_table()->number_of_entries() / 590 SharedSymbolTableBucketSize; 591 CompactSymbolTableWriter writer(num_buckets, 592 &MetaspaceShared::stats()->symbol); 593 for (int i = 0; i < the_table()->table_size(); ++i) { 594 HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); 595 for ( ; p != NULL; p = p->next()) { 596 Symbol* s = (Symbol*)(p->literal()); 597 unsigned int fixed_hash = hash_shared_symbol((char*)s->bytes(), s->utf8_length()); 598 assert(fixed_hash == p->hash(), "must not rehash during dumping"); 599 writer.add(fixed_hash, s); 600 } 601 } 602 603 writer.dump(&_shared_table); 604 605 // Verify table is correct 606 Symbol* sym = vmSymbols::java_lang_Object(); 607 const char* name = (const char*)sym->bytes(); 608 int len = sym->utf8_length(); 609 unsigned int hash = hash_symbol(name, len); 610 assert(sym == _shared_table.lookup(name, hash, len), "sanity"); 611 #endif 612 } 613 614 void SymbolTable::serialize(SerializeClosure* soc) { 615 #if INCLUDE_CDS 616 _shared_table.set_type(CompactHashtable<Symbol*, char>::_symbol_table); 617 _shared_table.serialize(soc); 618 619 if (soc->writing()) { 620 // Sanity. Make sure we don't use the shared table at dump time 621 _shared_table.reset(); 622 } 623 #endif 624 } 625 626 //--------------------------------------------------------------------------- 627 // Non-product code 628 629 #ifndef PRODUCT 630 631 void SymbolTable::print_histogram() { 632 MutexLocker ml(SymbolTable_lock); 633 const int results_length = 100; 634 int counts[results_length]; 635 int sizes[results_length]; 636 int i,j; 637 638 // initialize results to zero 639 for (j = 0; j < results_length; j++) { 640 counts[j] = 0; 641 sizes[j] = 0; 642 } 643 644 int total_size = 0; 645 int total_count = 0; 646 int total_length = 0; 647 int max_length = 0; 648 int out_of_range_count = 0; 649 int out_of_range_size = 0; 650 for (i = 0; i < the_table()->table_size(); i++) { 651 HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); 652 for ( ; p != NULL; p = p->next()) { 653 int size = p->literal()->size(); 654 int len = p->literal()->utf8_length(); 655 if (len < results_length) { 656 counts[len]++; 657 sizes[len] += size; 658 } else { 659 out_of_range_count++; 660 out_of_range_size += size; 661 } 662 total_count++; 663 total_size += size; 664 total_length += len; 665 max_length = MAX2(max_length, len); 666 } 667 } 668 tty->print_cr("Symbol Table Histogram:"); 669 tty->print_cr(" Total number of symbols %7d", total_count); 670 tty->print_cr(" Total size in memory %7dK", 671 (total_size*wordSize)/1024); 672 tty->print_cr(" Total counted %7d", _symbols_counted); 673 tty->print_cr(" Total removed %7d", _symbols_removed); 674 if (_symbols_counted > 0) { 675 tty->print_cr(" Percent removed %3.2f", 676 ((float)_symbols_removed/(float)_symbols_counted)* 100); 677 } 678 tty->print_cr(" Reference counts %7d", Symbol::_total_count); 679 tty->print_cr(" Symbol arena used " SIZE_FORMAT_W(7) "K", arena()->used()/1024); 680 tty->print_cr(" Symbol arena size " SIZE_FORMAT_W(7) "K", arena()->size_in_bytes()/1024); 681 tty->print_cr(" Total symbol length %7d", total_length); 682 tty->print_cr(" Maximum symbol length %7d", max_length); 683 tty->print_cr(" Average symbol length %7.2f", ((float) total_length / (float) total_count)); 684 tty->print_cr(" Symbol length histogram:"); 685 tty->print_cr(" %6s %10s %10s", "Length", "#Symbols", "Size"); 686 for (i = 0; i < results_length; i++) { 687 if (counts[i] > 0) { 688 tty->print_cr(" %6d %10d %10dK", i, counts[i], (sizes[i]*wordSize)/1024); 689 } 690 } 691 tty->print_cr(" >=%6d %10d %10dK\n", results_length, 692 out_of_range_count, (out_of_range_size*wordSize)/1024); 693 } 694 695 void SymbolTable::print() { 696 for (int i = 0; i < the_table()->table_size(); ++i) { 697 HashtableEntry<Symbol*, mtSymbol>** p = the_table()->bucket_addr(i); 698 HashtableEntry<Symbol*, mtSymbol>* entry = the_table()->bucket(i); 699 if (entry != NULL) { 700 while (entry != NULL) { 701 tty->print(PTR_FORMAT " ", p2i(entry->literal())); 702 entry->literal()->print(); 703 tty->print(" %d", entry->literal()->refcount()); 704 p = entry->next_addr(); 705 entry = (HashtableEntry<Symbol*, mtSymbol>*)HashtableEntry<Symbol*, mtSymbol>::make_ptr(*p); 706 } 707 tty->cr(); 708 } 709 } 710 } 711 #endif // PRODUCT 712 713 714 // Utility for dumping symbols 715 SymboltableDCmd::SymboltableDCmd(outputStream* output, bool heap) : 716 DCmdWithParser(output, heap), 717 _verbose("-verbose", "Dump the content of each symbol in the table", 718 "BOOLEAN", false, "false") { 719 _dcmdparser.add_dcmd_option(&_verbose); 720 } 721 722 void SymboltableDCmd::execute(DCmdSource source, TRAPS) { 723 VM_DumpHashtable dumper(output(), VM_DumpHashtable::DumpSymbols, 724 _verbose.value()); 725 VMThread::execute(&dumper); 726 } 727 728 int SymboltableDCmd::num_arguments() { 729 ResourceMark rm; 730 SymboltableDCmd* dcmd = new SymboltableDCmd(NULL, false); 731 if (dcmd != NULL) { 732 DCmdMark mark(dcmd); 733 return dcmd->_dcmdparser.num_arguments(); 734 } else { 735 return 0; 736 } 737 }