src/hotspot/share/classfile/symbolTable.cpp
changeset 52931 3b0fe3d6c3d7
parent 52516 d5eebe1e03fe
child 52951 722eaae2a785
equal deleted inserted replaced
52930:df629b081ff6 52931:3b0fe3d6c3d7
    40 #include "utilities/concurrentHashTableTasks.inline.hpp"
    40 #include "utilities/concurrentHashTableTasks.inline.hpp"
    41 
    41 
    42 // We used to not resize at all, so let's be conservative
    42 // We used to not resize at all, so let's be conservative
    43 // and not set it too short before we decide to resize,
    43 // and not set it too short before we decide to resize,
    44 // to match previous startup behavior
    44 // to match previous startup behavior
    45 #define PREF_AVG_LIST_LEN           8
    45 const double PREF_AVG_LIST_LEN = 8.0;
    46 // 2^17 (131,072) is max size, which is about 6.5 times as large
    46 // 2^17 (131,072) is max size, which is about 6.5 times as large
    47 // as the previous table size (used to be 20,011),
    47 // as the previous table size (used to be 20,011),
    48 // which never resized
    48 // which never resized
    49 #define END_SIZE                    17
    49 const size_t END_SIZE = 17;
    50 // If a chain gets to 100 something might be wrong
    50 // If a chain gets to 100 something might be wrong
    51 #define REHASH_LEN                  100
    51 const size_t REHASH_LEN = 100;
    52 // We only get a chance to check whether we need
    52 // We only get a chance to check whether we need
    53 // to clean infrequently (on class unloading),
    53 // to clean infrequently (on class unloading),
    54 // so if we have even one dead entry then mark table for cleaning
    54 // so if we have even one dead entry then mark table for cleaning
    55 #define CLEAN_DEAD_HIGH_WATER_MARK  0.0
    55 const double CLEAN_DEAD_HIGH_WATER_MARK = 0.0;
    56 
    56 
    57 #define ON_STACK_BUFFER_LENGTH 128
    57 const size_t ON_STACK_BUFFER_LENGTH = 128;
    58 
    58 
    59 // --------------------------------------------------------------------------
    59 // --------------------------------------------------------------------------
    60 
    60 
    61 inline bool symbol_equals_compact_hashtable_entry(Symbol* value, const char* key, int len) {
    61 inline bool symbol_equals_compact_hashtable_entry(Symbol* value, const char* key, int len) {
    62   if (value->equals(key, len)) {
    62   if (value->equals(key, len)) {
   169 void SymbolTable::set_item_clean_count(size_t ncl) {
   169 void SymbolTable::set_item_clean_count(size_t ncl) {
   170   Atomic::store(ncl, &(SymbolTable::the_table()->_uncleaned_items_count));
   170   Atomic::store(ncl, &(SymbolTable::the_table()->_uncleaned_items_count));
   171   log_trace(symboltable)("Set uncleaned items:" SIZE_FORMAT, SymbolTable::the_table()->_uncleaned_items_count);
   171   log_trace(symboltable)("Set uncleaned items:" SIZE_FORMAT, SymbolTable::the_table()->_uncleaned_items_count);
   172 }
   172 }
   173 
   173 
       
   174 // Mark one item as needing to be cleaned, but only if no other items are marked yet
   174 void SymbolTable::mark_item_clean_count() {
   175 void SymbolTable::mark_item_clean_count() {
   175   if (Atomic::cmpxchg((size_t)1, &(SymbolTable::the_table()->_uncleaned_items_count), (size_t)0) == 0) { // only mark if unset
   176   if (Atomic::cmpxchg((size_t)1, &(SymbolTable::the_table()->_uncleaned_items_count), (size_t)0) == 0) {
   176     log_trace(symboltable)("Marked uncleaned items:" SIZE_FORMAT, SymbolTable::the_table()->_uncleaned_items_count);
   177     log_trace(symboltable)("Marked uncleaned items:" SIZE_FORMAT, SymbolTable::the_table()->_uncleaned_items_count);
   177   }
   178   }
   178 }
   179 }
   179 
   180 
   180 void SymbolTable::item_removed() {
   181 void SymbolTable::item_removed() {
   181   Atomic::inc(&(SymbolTable::the_table()->_symbols_removed));
   182   Atomic::inc(&(SymbolTable::the_table()->_symbols_removed));
   182   Atomic::dec(&(SymbolTable::the_table()->_items_count));
   183   Atomic::dec(&(SymbolTable::the_table()->_items_count));
   183 }
   184 }
   184 
   185 
   185 double SymbolTable::get_load_factor() {
   186 double SymbolTable::get_load_factor() const {
   186   return (double)_items_count/_current_size;
   187   return (double)_items_count/_current_size;
   187 }
   188 }
   188 
   189 
   189 double SymbolTable::get_dead_factor() {
   190 double SymbolTable::get_dead_factor() const {
   190   return (double)_uncleaned_items_count/_current_size;
   191   return (double)_uncleaned_items_count/_current_size;
   191 }
   192 }
   192 
   193 
   193 size_t SymbolTable::table_size() {
   194 size_t SymbolTable::table_size() {
   194   return ((size_t)1) << _local_table->get_size_log2(Thread::current());
   195   return ((size_t)1) << _local_table->get_size_log2(Thread::current());
   384   void operator()(Symbol** value) {
   385   void operator()(Symbol** value) {
   385     assert(value != NULL, "expected valid value");
   386     assert(value != NULL, "expected valid value");
   386     assert(*value != NULL, "value should point to a symbol");
   387     assert(*value != NULL, "value should point to a symbol");
   387     _return = *value;
   388     _return = *value;
   388   }
   389   }
   389   Symbol* get_res_sym() {
   390   Symbol* get_res_sym() const {
   390     return _return;
   391     return _return;
   391   }
   392   }
   392 };
   393 };
   393 
   394 
   394 Symbol* SymbolTable::do_lookup(const char* name, int len, uintx hash) {
   395 Symbol* SymbolTable::do_lookup(const char* name, int len, uintx hash) {
   692   _current_size = table_size();
   693   _current_size = table_size();
   693   log_debug(symboltable)("Grown to size:" SIZE_FORMAT, _current_size);
   694   log_debug(symboltable)("Grown to size:" SIZE_FORMAT, _current_size);
   694 }
   695 }
   695 
   696 
   696 struct SymbolTableDoDelete : StackObj {
   697 struct SymbolTableDoDelete : StackObj {
   697   int _deleted;
   698   size_t _deleted;
   698   SymbolTableDoDelete() : _deleted(0) {}
   699   SymbolTableDoDelete() : _deleted(0) {}
   699   void operator()(Symbol** value) {
   700   void operator()(Symbol** value) {
   700     assert(value != NULL, "expected valid value");
   701     assert(value != NULL, "expected valid value");
   701     assert(*value != NULL, "value should point to a symbol");
   702     assert(*value != NULL, "value should point to a symbol");
   702     Symbol *sym = *value;
   703     Symbol *sym = *value;
   704     _deleted++;
   705     _deleted++;
   705   }
   706   }
   706 };
   707 };
   707 
   708 
   708 struct SymbolTableDeleteCheck : StackObj {
   709 struct SymbolTableDeleteCheck : StackObj {
   709   int _processed;
   710   size_t _processed;
   710   SymbolTableDeleteCheck() : _processed(0) {}
   711   SymbolTableDeleteCheck() : _processed(0) {}
   711   bool operator()(Symbol** value) {
   712   bool operator()(Symbol** value) {
   712     assert(value != NULL, "expected valid value");
   713     assert(value != NULL, "expected valid value");
   713     assert(*value != NULL, "value should point to a symbol");
   714     assert(*value != NULL, "value should point to a symbol");
   714     _processed++;
   715     _processed++;
   736     }
   737     }
   737     SymbolTable::the_table()->set_item_clean_count(0);
   738     SymbolTable::the_table()->set_item_clean_count(0);
   738     bdt.done(jt);
   739     bdt.done(jt);
   739   }
   740   }
   740 
   741 
   741   Atomic::add((size_t)stdc._processed, &_symbols_counted);
   742   Atomic::add(stdc._processed, &_symbols_counted);
   742 
   743 
   743   log_debug(symboltable)("Cleaned " INT32_FORMAT " of " INT32_FORMAT,
   744   log_debug(symboltable)("Cleaned " SIZE_FORMAT " of " SIZE_FORMAT,
   744                          stdd._deleted, stdc._processed);
   745                          stdd._deleted, stdc._processed);
   745 }
   746 }
   746 
   747 
   747 void SymbolTable::check_concurrent_work() {
   748 void SymbolTable::check_concurrent_work() {
   748   if (_has_work) {
   749   if (_has_work) {
   773   }
   774   }
   774   _has_work = false;
   775   _has_work = false;
   775 }
   776 }
   776 
   777 
   777 class CountDead : StackObj {
   778 class CountDead : StackObj {
   778   int _count;
   779   size_t _count;
   779 public:
   780 public:
   780   CountDead() : _count(0) {}
   781   CountDead() : _count(0) {}
   781   bool operator()(Symbol** value) {
   782   bool operator()(Symbol** value) {
   782     assert(value != NULL, "expected valid value");
   783     assert(value != NULL, "expected valid value");
   783     assert(*value != NULL, "value should point to a symbol");
   784     assert(*value != NULL, "value should point to a symbol");
   785     if (sym->refcount() == 0) {
   786     if (sym->refcount() == 0) {
   786       _count++;
   787       _count++;
   787     }
   788     }
   788     return true;
   789     return true;
   789   };
   790   };
   790   int get_dead_count() {
   791   size_t get_dead_count() const {
   791     return _count;
   792     return _count;
   792   }
   793   }
   793 };
   794 };
   794 
   795 
   795 void SymbolTable::do_check_concurrent_work() {
   796 void SymbolTable::do_check_concurrent_work() {