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