symbolTable.cpp revision 8413:92457dfb91bd
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/shared/collectedHeap.inline.hpp"
32#include "gc/shared/gcLocker.inline.hpp"
33#include "memory/allocation.inline.hpp"
34#include "memory/filemap.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
40PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
41
42// --------------------------------------------------------------------------
43// the number of buckets a thread claims
44const int ClaimChunkSize = 32;
45
46SymbolTable* SymbolTable::_the_table = NULL;
47// Static arena for symbols that are not deallocated
48Arena* SymbolTable::_arena = NULL;
49bool SymbolTable::_needs_rehashing = false;
50bool SymbolTable::_lookup_shared_first = false;
51
52CompactHashtable<Symbol*, char> SymbolTable::_shared_table;
53
54Symbol* 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
73void 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.
83void 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
98int SymbolTable::_symbols_removed = 0;
99int SymbolTable::_symbols_counted = 0;
100volatile int SymbolTable::_parallel_claimed_idx = 0;
101
102void 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.
136void 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
149void 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.
177void 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
196Symbol* 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
217Symbol* SymbolTable::lookup_shared(const char* name,
218                                   int len, unsigned int hash) {
219  return _shared_table.lookup(name, hash, len);
220}
221
222Symbol* 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.
246unsigned 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
260Symbol* 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
276Symbol* 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
315Symbol* 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
327Symbol** 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.
345Symbol* 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
360Symbol* 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
376void 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
397Symbol* 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
411Symbol* 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.
457bool 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
507void 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
521void 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
540bool 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
567const 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
577void 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
641void 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
661SymboltableDCmd::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
668void SymboltableDCmd::execute(DCmdSource source, TRAPS) {
669  VM_DumpHashtable dumper(output(), VM_DumpHashtable::DumpSymbols,
670                         _verbose.value());
671  VMThread::execute(&dumper);
672}
673
674int 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}
684