< prev index next >

src/hotspot/share/classfile/symbolTable.cpp

Print this page

        

@@ -56,33 +56,24 @@
 #define ON_STACK_BUFFER_LENGTH 128
 
 // --------------------------------------------------------------------------
 SymbolTable* SymbolTable::_the_table = NULL;
 CompactHashtable<Symbol*, char> SymbolTable::_shared_table;
-bool SymbolTable::_alt_hash = false;
+volatile bool SymbolTable::_alt_hash = false;
+volatile bool SymbolTable::_lookup_shared_first = false;
 // Static arena for symbols that are not deallocated
 Arena* SymbolTable::_arena = NULL;
-bool SymbolTable::_lookup_shared_first = false;
-int SymbolTable::_symbols_removed = 0;
-int SymbolTable::_symbols_counted = 0;
 
 static juint murmur_seed = 0;
 
 static inline void _log_trace_symboltable_helper(Symbol* sym, const char* msg) {
 #ifndef PRODUCT
   if (log_is_enabled(Trace, symboltable)) {
-    char *s;
-    {
-      ResourceMark rm;
-      s = sym->as_quoted_ascii();
-      s = os::strdup(s);
-    }
-    if (s == NULL) {
+    if (sym->as_quoted_ascii() == NULL) {
       log_trace(symboltable)("%s [%s]", msg, "NULL");
     } else {
-      log_trace(symboltable)("%s [%s]", msg, s);
-      os::free(s);
+      log_trace(symboltable)("%s [%s]", msg, sym->as_quoted_ascii());
     }
   }
 #endif // PRODUCT
 }
 

@@ -103,11 +94,11 @@
   static uintx get_hash(Symbol* const& value, bool* is_dead) {
     *is_dead = (value->refcount() == 0);
     if (*is_dead) {
       return 0;
     } else {
-      return hash_symbol((char*)value->bytes(), value->utf8_length(), SymbolTable::_alt_hash);
+      return hash_symbol((const char*)value->bytes(), value->utf8_length(), SymbolTable::_alt_hash);
     }
   }
   // We use default allocation/deallocation but counted
   static void* allocate_node(size_t size, Symbol* const& value) {
     SymbolTable::item_added();

@@ -126,20 +117,21 @@
     SymbolTableHash::BaseConfig::free_node(memory, value);
     SymbolTable::item_removed();
   }
 };
 
-static size_t ceil_pow_2(uintx value) {
+static size_t log2_ceil(uintx value) {
   size_t ret;
   for (ret = 1; ((size_t)1 << ret) < value; ++ret);
   return ret;
 }
 
 SymbolTable::SymbolTable() : _local_table(NULL), _current_size(0), _has_work(0),
-  _needs_rehashing(false), _items(0), _uncleaned_items(0) {
+  _needs_rehashing(false), _items_count(0), _uncleaned_items_count(0),
+  _symbols_removed(0), _symbols_counted(0) {
 
-  size_t start_size_log_2 = ceil_pow_2(SymbolTableSize);
+  size_t start_size_log_2 = log2_ceil(SymbolTableSize);
   _current_size = ((size_t)1) << start_size_log_2;
   log_trace(symboltable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")",
                          _current_size, start_size_log_2);
   _local_table = new SymbolTableHash(start_size_log_2, END_SIZE, REHASH_LEN);
 }

@@ -156,36 +148,36 @@
   } else {
     delete sym;
   }
 }
 
-size_t SymbolTable::item_added() {
-  return Atomic::add(1, &(SymbolTable::the_table()->_items));
+void SymbolTable::item_added() {
+  Atomic::inc(&(SymbolTable::the_table()->_items_count));
 }
 
 void SymbolTable::set_item_clean_count(size_t ncl) {
-  Atomic::store((int)ncl, &(SymbolTable::the_table()->_uncleaned_items));
-  log_trace(symboltable)("Set uncleaned items:" INT32_FORMAT, SymbolTable::the_table()->_uncleaned_items);
+  Atomic::store(ncl, &(SymbolTable::the_table()->_uncleaned_items_count));
+  log_trace(symboltable)("Set uncleaned items:" SIZE_FORMAT, SymbolTable::the_table()->_uncleaned_items_count);
 }
 
 void SymbolTable::mark_item_clean_count() {
-  if (Atomic::cmpxchg(1, &(SymbolTable::the_table()->_uncleaned_items), 0) == 0) { // only mark if unset
-    log_trace(symboltable)("Marked uncleaned items:" INT32_FORMAT, SymbolTable::the_table()->_uncleaned_items);
+  if (Atomic::cmpxchg((size_t)1, &(SymbolTable::the_table()->_uncleaned_items_count), (size_t)0) == 0) { // only mark if unset
+    log_trace(symboltable)("Marked uncleaned items:" SIZE_FORMAT, SymbolTable::the_table()->_uncleaned_items_count);
   }
 }
 
 void SymbolTable::item_removed() {
-  Atomic::add(1, &(SymbolTable::the_table()->_symbols_removed));
-  Atomic::sub(1, &(SymbolTable::the_table()->_items));
+  Atomic::inc(&(SymbolTable::the_table()->_symbols_removed));
+  Atomic::dec(&(SymbolTable::the_table()->_items_count));
 }
 
 double SymbolTable::get_load_factor() {
-  return (_items*1.0)/_current_size;
+  return (double)_items_count/_current_size;
 }
 
 double SymbolTable::get_dead_factor() {
-  return (_uncleaned_items*1.0)/_current_size;
+  return (double)_uncleaned_items_count/_current_size;
 }
 
 size_t SymbolTable::table_size(Thread* thread) {
   return ((size_t)(1)) << _local_table->get_size_log2(thread != NULL ? thread
                                                       : Thread::current());

@@ -195,25 +187,25 @@
   MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
   SymbolTable::the_table()->_has_work = true;
   Service_lock->notify_all();
 }
 
-Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS) {
+Symbol* SymbolTable::allocate_symbol(const char* name, int len, bool c_heap, TRAPS) {
   assert (len <= Symbol::max_length(), "should be checked by caller");
 
   Symbol* sym;
   if (DumpSharedSpaces) {
     c_heap = false;
   }
   if (c_heap) {
     // refcount starts as 1
-    sym = new (len, THREAD) Symbol(name, len, 1);
+    sym = new (len, THREAD) Symbol((const u1*)name, len, 1);
     assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted");
   } else {
     // Allocate to global arena
     MutexLocker ml(SymbolTable_lock); // Protect arena
-    sym = new (len, arena(), THREAD) Symbol(name, len, PERM_REFCOUNT);
+    sym = new (len, arena(), THREAD) Symbol((const u1*)name, len, PERM_REFCOUNT);
   }
   return sym;
 }
 
 void SymbolTable::initialize_symbols(int arena_alloc_size) {

@@ -267,11 +259,11 @@
   SymbolTable::the_table()->_local_table->do_scan(Thread::current(), mpd);
 }
 
 Symbol* SymbolTable::lookup_dynamic(const char* name,
                                     int len, unsigned int hash) {
-  Symbol* sym = SymbolTable::the_table()->do_lookup((char*)name, len, hash);
+  Symbol* sym = SymbolTable::the_table()->do_lookup(name, len, hash);
   assert((sym == NULL) || sym->refcount() != 0, "refcount must not be zero");
   return sym;
 }
 
 Symbol* SymbolTable::lookup_shared(const char* name,

@@ -311,58 +303,56 @@
 
 Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) {
   unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash);
   Symbol* sym = SymbolTable::the_table()->lookup_common(name, len, hash);
   if (sym == NULL) {
-    sym = SymbolTable::the_table()->do_add_if_needed((char*)name, len, hash, true, CHECK_NULL);
+    sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, true, CHECK_NULL);
   }
   assert(sym->refcount() != 0, "lookup should have incremented the count");
-  assert(sym->equals((char*)name, len), "symbol must be properly initialized");
+  assert(sym->equals(name, len), "symbol must be properly initialized");
   return sym;
 }
 
 Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) {
-  Symbol* found = NULL;
-  {
-    debug_only(NoSafepointVerifier nsv;)
-
-    char* name = (char*)sym->base() + begin;
-    int len = end - begin;
-    unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash);
+  assert(sym->refcount() != 0, "require a valid symbol");
+  const char* name = (const char*)sym->base() + begin;
+  int len = end - begin;
+  unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash);
+  Symbol* found = SymbolTable::the_table()->lookup_common(name, len, hash);
+  if (found == NULL) {
     found = SymbolTable::the_table()->do_add_if_needed(name, len, hash, true, THREAD);
   }
   return found;
 }
 
-class SymbolTableLookupChar : StackObj {
+class SymbolTableLookup : StackObj {
 private:
   Thread* _thread;
   uintx _hash;
   int _len;
   const char* _str;
-  Symbol* _found;
 public:
-  SymbolTableLookupChar(Thread* thread, const char* key, int len, uintx hash)
-  : _thread(thread), _hash(hash), _str(key), _len(len) , _found(NULL) {
-  }
+  SymbolTableLookup(Thread* thread, const char* key, int len, uintx hash)
+  : _thread(thread), _hash(hash), _str(key), _len(len) {}
   uintx get_hash() const {
     return _hash;
   }
   bool equals(Symbol** value, bool* is_dead) {
     assert(value != NULL, "expected valid value");
     assert(*value != NULL, "value should point to a symbol");
     Symbol *sym = *value;
     if (sym->equals(_str, _len)) {
       if (sym->try_increment_refcount()) {
         // something is referencing this symbol now.
-        _found = sym;
         return true;
       } else {
-        *is_dead = (sym->refcount() == 0);
+        assert(sym->refcount() == 0, "expected dead symbol");
+        *is_dead = true;
         return false;
       }
     } else {
+      *is_dead = (sym->refcount() == 0);
       return false;
     }
   }
 };
 

@@ -378,15 +368,15 @@
   Symbol* get_res_sym() {
     return _return;
   }
 };
 
-Symbol* SymbolTable::do_lookup(char* name, int len, uintx hash) {
+Symbol* SymbolTable::do_lookup(const char* name, int len, uintx hash) {
   Thread* thread = Thread::current();
-  SymbolTableLookupChar lookup(thread, name, len, hash);
+  SymbolTableLookup lookup(thread, name, len, hash);
   SymbolTableGet stg;
-  bool rehash_warning;
+  bool rehash_warning = false;
   _local_table->get(thread, lookup, stg, &rehash_warning);
   if (rehash_warning) {
     _needs_rehashing = true;
   }
   Symbol* sym = stg.get_res_sym();

@@ -435,19 +425,19 @@
 
 void SymbolTable::add(ClassLoaderData* loader_data, const constantPoolHandle& cp,
                       int names_count, const char** names, int* lengths,
                       int* cp_indices, unsigned int* hashValues, TRAPS) {
   bool c_heap = !loader_data->is_the_null_class_loader_data();
-  for (int i=0; i<names_count; i++) {
-    char *name = (char*)names[i];
+  for (int i = 0; i < names_count; i++) {
+    const char *name = names[i];
     int len = lengths[i];
     unsigned int hash = hashValues[i];
     Symbol* sym = SymbolTable::the_table()->lookup_common(name, len, hash);
     if (sym == NULL) {
       sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, c_heap, CHECK);
     }
-    assert(sym->refcount()!=0, "lookup should have incremented the count");
+    assert(sym->refcount() != 0, "lookup should have incremented the count");
     cp->symbol_at_put(cp_indices[i], sym);
   }
 }
 
 class SymbolTableCreateEntry : public StackObj {

@@ -457,32 +447,30 @@
   int         _len;
   bool        _heap;
   Symbol*     _return;
   Symbol*     _created;
 
+  void assert_for_name(Symbol* sym, const char* where) const {
 #ifdef ASSERT
-  void _assert_for_name(Symbol* sym, const char* where) const {
     assert(sym->utf8_length() == _len, "%s [%d,%d]", where, sym->utf8_length(), _len);
-    for (int i=0; i<_len; i++) {
+    for (int i = 0; i < _len; i++) {
       assert(sym->byte_at(i) == _name[i],
              "%s [%d,%d,%d]", where, i, sym->byte_at(i), _name[i]);
     }
-  }
 #endif
+  }
 
 public:
   SymbolTableCreateEntry(Thread* thread, const char* name, int len, bool heap)
   : _thread(thread), _name(name) , _len(len), _heap(heap), _return(NULL) , _created(NULL) {
     assert(_name != NULL, "expected valid name");
   }
   Symbol* operator()() {
-    _created = SymbolTable::the_table()->allocate_symbol((const u1*)_name, _len, _heap, _thread);
+    _created = SymbolTable::the_table()->allocate_symbol(_name, _len, _heap, _thread);
     assert(_created != NULL, "expected created symbol");
-#ifdef ASSERT
-    _assert_for_name(_created, "operator()()");
-#endif
-    assert(_created->equals((char*)_name, _len),
+    assert_for_name(_created, "operator()()");
+    assert(_created->equals(_name, _len),
            "symbol must be properly initialized [%p,%d,%d]", _name, _len, (int)_heap);
     return _created;
   }
   void operator()(bool inserted, Symbol** value) {
     assert(value != NULL, "expected valid value");

@@ -498,27 +486,23 @@
         _created->decrement_refcount();
         assert(_created->refcount() == 0, "expected dead symbol");
       }
     }
     _return = *value;
-#ifdef ASSERT
-    _assert_for_name(_return, "operator()");
-#endif
+    assert_for_name(_return, "operator()");
   }
   Symbol* get_new_sym() const {
-#ifdef ASSERT
-    _assert_for_name(_return, "get_new_sym");
-#endif
+    assert_for_name(_return, "get_new_sym");
     return _return;
   }
 };
 
-Symbol* SymbolTable::do_add_if_needed(char* name, int len, uintx hash, bool heap, TRAPS) {
-  SymbolTableLookupChar lookup(THREAD, name, len, hash);
+Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, bool heap, TRAPS) {
+  SymbolTableLookup lookup(THREAD, name, len, hash);
   SymbolTableCreateEntry stce(THREAD, name, len, heap);
-  bool rehash_warning;
-  bool clean_hint;
+  bool rehash_warning = false;
+  bool clean_hint = false;
   _local_table->get_insert_lazy(THREAD, lookup, stce, stce, &rehash_warning, &clean_hint);
   if (rehash_warning) {
     _needs_rehashing = true;
   }
   if (clean_hint) {

@@ -538,11 +522,11 @@
 Symbol* SymbolTable::new_permanent_symbol(const char* name, TRAPS) {
   unsigned int hash = 0;
   int len = (int)strlen(name);
   Symbol* sym = SymbolTable::lookup_only(name, len, hash);
   if (sym == NULL) {
-    sym = SymbolTable::the_table()->do_add_if_needed((char*)name, len, hash, false, CHECK_NULL);
+    sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, false, CHECK_NULL);
   }
   if (sym->refcount() != PERM_REFCOUNT) {
     sym->increment_refcount();
     _log_trace_symboltable_helper(sym, "Asked for a permanent symbol, but got a regular one");
   }

@@ -568,11 +552,11 @@
 public:
   bool operator()(Symbol** value) {
     guarantee(value != NULL, "expected valid value");
     guarantee(*value != NULL, "value should point to a symbol");
     Symbol* sym = *value;
-    guarantee(sym->equals((char*)sym->bytes(), sym->utf8_length()),
+    guarantee(sym->equals((const char*)sym->bytes(), sym->utf8_length()),
               "symbol must be internally consistent");
     return true;
   };
 };
 

@@ -623,15 +607,15 @@
   CopyToArchive(CompactSymbolTableWriter* writer) : _writer(writer) {}
   bool operator()(Symbol** value) {
     assert(value != NULL, "expected valid value");
     assert(*value != NULL, "value should point to a symbol");
     Symbol* sym = *value;
-    unsigned int fixed_hash =  hash_shared_symbol((char*)sym->bytes(), sym->utf8_length());
+    unsigned int fixed_hash = hash_shared_symbol((const char*)sym->bytes(), sym->utf8_length());
     if (fixed_hash == 0) {
       return true;
     }
-    assert(fixed_hash == hash_symbol((char*)sym->bytes(), sym->utf8_length(), false),
+    assert(fixed_hash == hash_symbol((const char*)sym->bytes(), sym->utf8_length(), false),
            "must not rehash during dumping");
 
     // add to the compact table
     _writer->add(fixed_hash, sym);
 

@@ -645,11 +629,11 @@
 }
 
 void SymbolTable::write_to_archive() {
   _shared_table.reset();
 
-  int num_buckets = (SymbolTable::the_table()->_items / SharedSymbolTableBucketSize);
+  int num_buckets = (SymbolTable::the_table()->_items_count / SharedSymbolTableBucketSize);
   // calculation of num_buckets can result in zero buckets, we need at least one
   CompactSymbolTableWriter writer(num_buckets > 1 ? num_buckets : 1,
                                   &MetaspaceShared::stats()->symbol);
   copy_shared_symbol_table(&writer);
   writer.dump(&_shared_table);

@@ -713,15 +697,11 @@
   bool operator()(Symbol** value) {
     assert(value != NULL, "expected valid value");
     assert(*value != NULL, "value should point to a symbol");
     _processed++;
     Symbol *sym = *value;
-    if (sym->refcount() == 0) {
-      return true;
-    } else {
-      return false;
-    }
+    return (sym->refcount() == 0);
   }
 };
 
 void SymbolTable::clean_dead_entries(JavaThread* jt) {
   SymbolTableHash::BulkDeleteTask bdt(_local_table);

@@ -742,11 +722,11 @@
     }
     SymbolTable::the_table()->set_item_clean_count(0);
     bdt.done(jt);
   }
 
-  Atomic::add(stdc._processed, &_symbols_counted);
+  Atomic::add((size_t)stdc._processed, &_symbols_counted);
 
   log_debug(symboltable)("Cleaned " INT32_FORMAT " of " INT32_FORMAT,
                          stdd._deleted, stdc._processed);
 }
 

@@ -876,33 +856,33 @@
 
 #ifndef PRODUCT
 
 class HistogramIterator : StackObj {
 public:
-  static const int results_length = 100;
-  int counts[results_length];
-  int sizes[results_length];
-  int total_size;
-  int total_count;
-  int total_length;
-  int max_length;
-  int out_of_range_count;
-  int out_of_range_size;
+  static const size_t results_length = 100;
+  size_t counts[results_length];
+  size_t sizes[results_length];
+  size_t total_size;
+  size_t total_count;
+  size_t total_length;
+  size_t max_length;
+  size_t out_of_range_count;
+  size_t out_of_range_size;
   HistogramIterator() : total_size(0), total_count(0), total_length(0),
                         max_length(0), out_of_range_count(0), out_of_range_size(0) {
     // initialize results to zero
-    for (int i = 0; i < results_length; i++) {
+    for (size_t i = 0; i < results_length; i++) {
       counts[i] = 0;
       sizes[i] = 0;
     }
   }
   bool operator()(Symbol** value) {
     assert(value != NULL, "expected valid value");
     assert(*value != NULL, "value should point to a symbol");
     Symbol* sym = *value;
-    int size = sym->size();
-    int len = sym->utf8_length();
+    size_t size = sym->size();
+    size_t len = sym->utf8_length();
     if (len < results_length) {
       counts[len]++;
       sizes[len] += size;
     } else {
       out_of_range_count++;

@@ -916,37 +896,39 @@
     return true;
   };
 };
 
 void SymbolTable::print_histogram() {
+  SymbolTable* st = SymbolTable::the_table();
   HistogramIterator hi;
-  SymbolTable::the_table()->_local_table->do_scan(Thread::current(), hi);
+  st->_local_table->do_scan(Thread::current(), hi);
   tty->print_cr("Symbol Table Histogram:");
-  tty->print_cr("  Total number of symbols  %7d", hi.total_count);
-  tty->print_cr("  Total size in memory     %7dK",
-          (hi.total_size*wordSize)/1024);
-  tty->print_cr("  Total counted            %7d", _symbols_counted);
-  tty->print_cr("  Total removed            %7d", _symbols_removed);
-  if (_symbols_counted > 0) {
+  tty->print_cr("  Total number of symbols  " SIZE_FORMAT_W(7), hi.total_count);
+  tty->print_cr("  Total size in memory     " SIZE_FORMAT_W(7) "K",
+          (hi.total_size * wordSize) / 1024);
+  tty->print_cr("  Total counted            " SIZE_FORMAT_W(7), st->_symbols_counted);
+  tty->print_cr("  Total removed            " SIZE_FORMAT_W(7), st->_symbols_removed);
+  if (SymbolTable::the_table()->_symbols_counted > 0) {
     tty->print_cr("  Percent removed          %3.2f",
-          ((float)_symbols_removed/(float)_symbols_counted)* 100);
+          ((float)st->_symbols_removed / st->_symbols_counted) * 100);
   }
-  tty->print_cr("  Reference counts         %7d", Symbol::_total_count);
-  tty->print_cr("  Symbol arena used        " SIZE_FORMAT_W(7) "K", arena()->used()/1024);
-  tty->print_cr("  Symbol arena size        " SIZE_FORMAT_W(7) "K", arena()->size_in_bytes()/1024);
-  tty->print_cr("  Total symbol length      %7d", hi.total_length);
-  tty->print_cr("  Maximum symbol length    %7d", hi.max_length);
-  tty->print_cr("  Average symbol length    %7.2f", ((float) hi.total_length / (float) hi.total_count));
+  tty->print_cr("  Reference counts         " SIZE_FORMAT_W(7), Symbol::_total_count);
+  tty->print_cr("  Symbol arena used        " SIZE_FORMAT_W(7) "K", arena()->used() / 1024);
+  tty->print_cr("  Symbol arena size        " SIZE_FORMAT_W(7) "K", arena()->size_in_bytes() / 1024);
+  tty->print_cr("  Total symbol length      " SIZE_FORMAT_W(7), hi.total_length);
+  tty->print_cr("  Maximum symbol length    " SIZE_FORMAT_W(7), hi.max_length);
+  tty->print_cr("  Average symbol length    %7.2f", ((float)hi.total_length / hi.total_count));
   tty->print_cr("  Symbol length histogram:");
   tty->print_cr("    %6s %10s %10s", "Length", "#Symbols", "Size");
-  for (int i = 0; i < hi.results_length; i++) {
+  for (size_t i = 0; i < hi.results_length; i++) {
     if (hi.counts[i] > 0) {
-      tty->print_cr("    %6d %10d %10dK", i, hi.counts[i], (hi.sizes[i]*wordSize)/1024);
+      tty->print_cr("    " SIZE_FORMAT_W(6) " " SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10) "K",
+                    i, hi.counts[i], (hi.sizes[i] * wordSize) / 1024);
     }
   }
-  tty->print_cr("  >=%6d %10d %10dK\n", hi.results_length,
-          hi.out_of_range_count, (hi.out_of_range_size*wordSize)/1024);
+  tty->print_cr("  >=" SIZE_FORMAT_W(6) " " SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10) "K\n",
+                hi.results_length, hi.out_of_range_count, (hi.out_of_range_size*wordSize) / 1024);
 }
 #endif // PRODUCT
 
 // Utility for dumping symbols
 SymboltableDCmd::SymboltableDCmd(outputStream* output, bool heap) :
< prev index next >