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