< prev index next >

src/share/vm/classfile/symbolTable.cpp

Print this page


  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/resourceArea.hpp"
  36 #include "oops/oop.inline.hpp"
  37 #include "runtime/atomic.hpp"
  38 #include "runtime/mutexLocker.hpp"
  39 #include "utilities/hashtable.inline.hpp"
  40 
  41 // --------------------------------------------------------------------------
  42 // the number of buckets a thread claims
  43 const int ClaimChunkSize = 32;
  44 
  45 SymbolTable* SymbolTable::_the_table = NULL;
  46 // Static arena for symbols that are not deallocated
  47 Arena* SymbolTable::_arena = NULL;
  48 bool SymbolTable::_needs_rehashing = false;
  49 bool SymbolTable::_lookup_shared_first = false;
  50 
  51 CompactHashtable<Symbol*, char> SymbolTable::_shared_table;
  52 
  53 Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS) {
  54   assert (len <= Symbol::max_length(), "should be checked by caller");
  55 
  56   Symbol* sym;
  57 
  58   if (DumpSharedSpaces) {
  59     // Allocate all symbols to CLD shared metaspace
  60     sym = new (len, ClassLoaderData::the_null_class_loader_data(), THREAD) Symbol(name, len, PERM_REFCOUNT);
  61   } else if (c_heap) {
  62     // refcount starts as 1
  63     sym = new (len, THREAD) Symbol(name, len, 1);
  64     assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted");
  65   } else {
  66     // Allocate to global arena
  67     sym = new (len, arena(), THREAD) Symbol(name, len, PERM_REFCOUNT);
  68   }
  69   return sym;
  70 }
  71 
  72 void SymbolTable::initialize_symbols(int arena_alloc_size) {
  73   // Initialize the arena for global symbols, size passed in depends on CDS.
  74   if (arena_alloc_size == 0) {
  75     _arena = new (mtSymbol) Arena(mtSymbol);
  76   } else {
  77     _arena = new (mtSymbol) Arena(mtSymbol, arena_alloc_size);
  78   }
  79 }
  80 
  81 // Call function for all symbols in the symbol table.
  82 void SymbolTable::symbols_do(SymbolClosure *cl) {

  83   // all symbols from shared table
  84   _shared_table.symbols_do(cl);

  85 
  86   // all symbols from the dynamic table
  87   const int n = the_table()->table_size();
  88   for (int i = 0; i < n; i++) {
  89     for (HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
  90          p != NULL;
  91          p = p->next()) {
  92       cl->do_symbol(p->literal_addr());
  93     }
  94   }
  95 }
  96 












  97 int SymbolTable::_symbols_removed = 0;
  98 int SymbolTable::_symbols_counted = 0;
  99 volatile int SymbolTable::_parallel_claimed_idx = 0;
 100 
 101 void SymbolTable::buckets_unlink(int start_idx, int end_idx, BucketUnlinkContext* context) {
 102   for (int i = start_idx; i < end_idx; ++i) {
 103     HashtableEntry<Symbol*, mtSymbol>** p = the_table()->bucket_addr(i);
 104     HashtableEntry<Symbol*, mtSymbol>* entry = the_table()->bucket(i);
 105     while (entry != NULL) {
 106       // Shared entries are normally at the end of the bucket and if we run into
 107       // a shared entry, then there is nothing more to remove. However, if we
 108       // have rehashed the table, then the shared entries are no longer at the
 109       // end of the bucket.
 110       if (entry->is_shared() && !use_alternate_hashcode()) {
 111         break;
 112       }
 113       Symbol* s = entry->literal();
 114       context->_num_processed++;
 115       assert(s != NULL, "just checking");
 116       // If reference count is zero, remove.


 550 
 551 void SymbolTable::dump(outputStream* st, bool verbose) {
 552   if (!verbose) {
 553     the_table()->dump_table(st, "SymbolTable");
 554   } else {
 555     st->print_cr("VERSION: 1.0");
 556     for (int i = 0; i < the_table()->table_size(); ++i) {
 557       HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
 558       for ( ; p != NULL; p = p->next()) {
 559         Symbol* s = (Symbol*)(p->literal());
 560         const char* utf8_string = (const char*)s->bytes();
 561         int utf8_length = s->utf8_length();
 562         st->print("%d %d: ", utf8_length, s->refcount());
 563         HashtableTextDump::put_utf8(st, utf8_string, utf8_length);
 564         st->cr();
 565       }
 566     }
 567   }
 568 }
 569 
 570 void SymbolTable::serialize(SerializeClosure* soc) {
 571 #if INCLUDE_CDS
 572   _shared_table.reset();
 573   if (soc->writing()) {
 574     int num_buckets = the_table()->number_of_entries() /
 575                             SharedSymbolTableBucketSize;
 576     CompactSymbolTableWriter writer(num_buckets,
 577                                     &MetaspaceShared::stats()->symbol);
 578     for (int i = 0; i < the_table()->table_size(); ++i) {
 579       HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
 580       for ( ; p != NULL; p = p->next()) {
 581         Symbol* s = (Symbol*)(p->literal());
 582       unsigned int fixed_hash =  hash_shared_symbol((char*)s->bytes(), s->utf8_length());
 583         assert(fixed_hash == p->hash(), "must not rehash during dumping");
 584         writer.add(fixed_hash, s);
 585       }
 586     }
 587 
 588     writer.dump(&_shared_table);
 589   }
 590 
 591   _shared_table.set_type(CompactHashtable<Symbol*, char>::_symbol_table);
 592   _shared_table.serialize(soc);
 593 
 594   if (soc->writing()) {
 595     // Verify table is correct
 596     Symbol* sym = vmSymbols::java_lang_Object();
 597     const char* name = (const char*)sym->bytes();
 598     int len = sym->utf8_length();
 599     unsigned int hash = hash_symbol(name, len);
 600     assert(sym == _shared_table.lookup(name, hash, len), "sanity");


 601 






 602     // Sanity. Make sure we don't use the shared table at dump time
 603     _shared_table.reset();
 604   }
 605 #endif
 606 }
 607 
 608 //---------------------------------------------------------------------------
 609 // Non-product code
 610 
 611 #ifndef PRODUCT
 612 
 613 void SymbolTable::print_histogram() {
 614   MutexLocker ml(SymbolTable_lock);
 615   const int results_length = 100;
 616   int counts[results_length];
 617   int sizes[results_length];
 618   int i,j;
 619 
 620   // initialize results to zero
 621   for (j = 0; j < results_length; j++) {




  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 "utilities/hashtable.inline.hpp"
  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     c_heap = false;
  61   }
  62   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, PERM_REFCOUNT);
  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   if (!DumpSharedSpaces) {
  85     // all symbols from shared table
  86     _shared_table.symbols_do(cl);
  87   }
  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.


 565 
 566 void SymbolTable::dump(outputStream* st, bool verbose) {
 567   if (!verbose) {
 568     the_table()->dump_table(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++) {


< prev index next >