< prev index next >

src/hotspot/share/classfile/stringTable.cpp

Print this page




  47 #include "runtime/mutexLocker.hpp"
  48 #include "runtime/safepointVerifiers.hpp"
  49 #include "runtime/timerTrace.hpp"
  50 #include "runtime/interfaceSupport.inline.hpp"
  51 #include "services/diagnosticCommand.hpp"
  52 #include "utilities/concurrentHashTable.inline.hpp"
  53 #include "utilities/concurrentHashTableTasks.inline.hpp"
  54 #include "utilities/macros.hpp"
  55 
  56 // We prefer short chains of avg 2
  57 #define PREF_AVG_LIST_LEN   2
  58 // 2^24 is max size
  59 #define END_SIZE           24
  60 // If a chain gets to 32 something might be wrong
  61 #define REHASH_LEN         32
  62 // If we have as many dead items as 50% of the number of bucket
  63 #define CLEAN_DEAD_HIGH_WATER_MARK 0.5
  64 
  65 // --------------------------------------------------------------------------
  66 StringTable* StringTable::_the_table = NULL;
  67 bool StringTable::_shared_string_mapped = false;
  68 CompactHashtable<oop, char> StringTable::_shared_table;
  69 bool StringTable::_alt_hash = false;

  70 
  71 static juint murmur_seed = 0;
  72 
  73 uintx hash_string(const jchar* s, int len, bool useAlt) {
  74   return  useAlt ?
  75     AltHashing::murmur3_32(murmur_seed, s, len) :
  76     java_lang_String::hash_code(s, len);
  77 }
  78 
  79 class StringTableConfig : public StringTableHash::BaseConfig {
  80  private:
  81  public:
  82   static uintx get_hash(WeakHandle<vm_string_table_data> const& value,
  83                         bool* is_dead) {
  84     EXCEPTION_MARK;
  85     oop val_oop = value.peek();
  86     if (val_oop == NULL) {
  87       *is_dead = true;
  88       return 0;
  89     }


 159     return _hash;
 160   }
 161 
 162   bool equals(WeakHandle<vm_string_table_data>* value, bool* is_dead) {
 163     oop val_oop = value->peek();
 164     if (val_oop == NULL) {
 165       // dead oop, mark this hash dead for cleaning
 166       *is_dead = true;
 167       return false;
 168     }
 169     bool equals = java_lang_String::equals(_find(), val_oop);
 170     if (!equals) {
 171       return false;
 172     }
 173     // Need to resolve weak handle and Handleize through possible safepoint.
 174     _found = Handle(_thread, value->resolve());
 175     return true;
 176   }
 177 };
 178 
 179 static size_t ceil_pow_2(uintx val) {
 180   size_t ret;
 181   for (ret = 1; ((size_t)1 << ret) < val; ++ret);
 182   return ret;
 183 }
 184 
 185 StringTable::StringTable() : _local_table(NULL), _current_size(0), _has_work(0),
 186   _needs_rehashing(false), _weak_handles(NULL), _items(0), _uncleaned_items(0) {
 187   _weak_handles = new OopStorage("StringTable weak",
 188                                  StringTableWeakAlloc_lock,
 189                                  StringTableWeakActive_lock);
 190   size_t start_size_log_2 = ceil_pow_2(StringTableSize);
 191   _current_size = ((size_t)1) << start_size_log_2;
 192   log_trace(stringtable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")",
 193                          _current_size, start_size_log_2);
 194   _local_table = new StringTableHash(start_size_log_2, END_SIZE, REHASH_LEN);
 195 }
 196 
 197 size_t StringTable::item_added() {
 198   return Atomic::add((size_t)1, &(the_table()->_items));
 199 }
 200 
 201 size_t StringTable::add_items_to_clean(size_t ndead) {
 202   size_t total = Atomic::add((size_t)ndead, &(the_table()->_uncleaned_items));
 203   log_trace(stringtable)(
 204      "Uncleaned items:" SIZE_FORMAT " added: " SIZE_FORMAT " total:" SIZE_FORMAT,
 205      the_table()->_uncleaned_items, ndead, total);
 206   return total;
 207 }
 208 
 209 void StringTable::item_removed() {
 210   Atomic::add((size_t)-1, &(the_table()->_items));
 211 }
 212 
 213 double StringTable::get_load_factor() {
 214   return (_items*1.0)/_current_size;
 215 }
 216 
 217 double StringTable::get_dead_factor() {
 218   return (_uncleaned_items*1.0)/_current_size;
 219 }
 220 
 221 size_t StringTable::table_size(Thread* thread) {
 222   return ((size_t)(1)) << _local_table->get_size_log2(thread != NULL ? thread
 223                                                       : Thread::current());
 224 }
 225 
 226 void StringTable::trigger_concurrent_work() {
 227   MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
 228   the_table()->_has_work = true;
 229   Service_lock->notify_all();
 230 }
 231 
 232 // Probing
 233 oop StringTable::lookup(Symbol* symbol) {
 234   ResourceMark rm;
 235   int length;
 236   jchar* chars = symbol->as_unicode(length);
 237   return lookup(chars, length);
 238 }


 389     bool ret = _real_boc->do_object_b(obj);
 390     if (!ret) {
 391       ++_count;
 392     }
 393     ++_count_total;
 394     return ret;
 395   }
 396 };
 397 
 398 void StringTable::unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f,
 399                                     int* processed, int* removed) {
 400   DoNothingClosure dnc;
 401   assert(is_alive != NULL, "No closure");
 402   StringTableIsAliveCounter stiac(is_alive);
 403   OopClosure* tmp = f != NULL ? f : &dnc;
 404 
 405   StringTable::the_table()->_weak_handles->weak_oops_do(&stiac, tmp);
 406 
 407   // This is the serial case without ParState.
 408   // Just set the correct number and check for a cleaning phase.
 409   the_table()->_uncleaned_items = stiac._count;
 410   StringTable::the_table()->check_concurrent_work();
 411 
 412   if (processed != NULL) {
 413     *processed = (int) stiac._count_total;
 414   }
 415   if (removed != NULL) {
 416     *removed = (int) stiac._count;
 417   }
 418 }
 419 
 420 void StringTable::oops_do(OopClosure* f) {
 421   assert(f != NULL, "No closure");
 422   StringTable::the_table()->_weak_handles->oops_do(f);
 423 }
 424 
 425 void StringTable::possibly_parallel_unlink(
 426    OopStorage::ParState<false, false>* _par_state_string, BoolObjectClosure* cl,
 427    int* processed, int* removed)
 428 {
 429   DoNothingClosure dnc;
 430   assert(cl != NULL, "No closure");
 431   StringTableIsAliveCounter stiac(cl);
 432 
 433   _par_state_string->weak_oops_do(&stiac, &dnc);
 434 
 435   // Accumulate the dead strings.
 436   the_table()->add_items_to_clean(stiac._count);
 437 
 438   *processed = (int) stiac._count_total;
 439   *removed = (int) stiac._count;
 440 }
 441 
 442 void StringTable::possibly_parallel_oops_do(
 443    OopStorage::ParState<false /* concurrent */, false /* const */>*
 444    _par_state_string, OopClosure* f)
 445 {
 446   assert(f != NULL, "No closure");
 447   _par_state_string->oops_do(f);
 448 }
 449 
 450 // Concurrent work
 451 void StringTable::grow(JavaThread* jt) {
 452   StringTableHash::GrowTask gt(_local_table);
 453   if (!gt.prepare(jt)) {
 454     return;
 455   }
 456   log_trace(stringtable)("Started to grow");


 826     }
 827 
 828     val->replace(new_s);
 829     // add to the compact table
 830     _writer->add(hash, new_s);
 831     return true;
 832   }
 833 };
 834 
 835 void StringTable::copy_shared_string_table(CompactStringTableWriter* writer) {
 836   assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
 837 
 838   CopyToArchive copy(writer);
 839   StringTable::the_table()->_local_table->do_scan(Thread::current(), copy);
 840 }
 841 
 842 void StringTable::write_to_archive() {
 843   assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
 844 
 845   _shared_table.reset();
 846   int num_buckets = the_table()->_items / SharedSymbolTableBucketSize;
 847   // calculation of num_buckets can result in zero buckets, we need at least one
 848   CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1,
 849                                   &MetaspaceShared::stats()->string);
 850 
 851   // Copy the interned strings into the "string space" within the java heap
 852   copy_shared_string_table(&writer);
 853   writer.dump(&_shared_table);
 854 }
 855 
 856 void StringTable::serialize(SerializeClosure* soc) {
 857   _shared_table.set_type(CompactHashtable<oop, char>::_string_table);
 858   _shared_table.serialize(soc);
 859 
 860   if (soc->writing()) {
 861     // Sanity. Make sure we don't use the shared table at dump time
 862     _shared_table.reset();
 863   } else if (!_shared_string_mapped) {
 864     _shared_table.reset();
 865   }
 866 }


  47 #include "runtime/mutexLocker.hpp"
  48 #include "runtime/safepointVerifiers.hpp"
  49 #include "runtime/timerTrace.hpp"
  50 #include "runtime/interfaceSupport.inline.hpp"
  51 #include "services/diagnosticCommand.hpp"
  52 #include "utilities/concurrentHashTable.inline.hpp"
  53 #include "utilities/concurrentHashTableTasks.inline.hpp"
  54 #include "utilities/macros.hpp"
  55 
  56 // We prefer short chains of avg 2
  57 #define PREF_AVG_LIST_LEN   2
  58 // 2^24 is max size
  59 #define END_SIZE           24
  60 // If a chain gets to 32 something might be wrong
  61 #define REHASH_LEN         32
  62 // If we have as many dead items as 50% of the number of bucket
  63 #define CLEAN_DEAD_HIGH_WATER_MARK 0.5
  64 
  65 // --------------------------------------------------------------------------
  66 StringTable* StringTable::_the_table = NULL;

  67 CompactHashtable<oop, char> StringTable::_shared_table;
  68 volatile bool StringTable::_shared_string_mapped = false;
  69 volatile bool StringTable::_alt_hash = false;
  70 
  71 static juint murmur_seed = 0;
  72 
  73 uintx hash_string(const jchar* s, int len, bool useAlt) {
  74   return  useAlt ?
  75     AltHashing::murmur3_32(murmur_seed, s, len) :
  76     java_lang_String::hash_code(s, len);
  77 }
  78 
  79 class StringTableConfig : public StringTableHash::BaseConfig {
  80  private:
  81  public:
  82   static uintx get_hash(WeakHandle<vm_string_table_data> const& value,
  83                         bool* is_dead) {
  84     EXCEPTION_MARK;
  85     oop val_oop = value.peek();
  86     if (val_oop == NULL) {
  87       *is_dead = true;
  88       return 0;
  89     }


 159     return _hash;
 160   }
 161 
 162   bool equals(WeakHandle<vm_string_table_data>* value, bool* is_dead) {
 163     oop val_oop = value->peek();
 164     if (val_oop == NULL) {
 165       // dead oop, mark this hash dead for cleaning
 166       *is_dead = true;
 167       return false;
 168     }
 169     bool equals = java_lang_String::equals(_find(), val_oop);
 170     if (!equals) {
 171       return false;
 172     }
 173     // Need to resolve weak handle and Handleize through possible safepoint.
 174     _found = Handle(_thread, value->resolve());
 175     return true;
 176   }
 177 };
 178 
 179 static size_t log2_ceil(uintx val) {
 180   size_t ret;
 181   for (ret = 1; ((size_t)1 << ret) < val; ++ret);
 182   return ret;
 183 }
 184 
 185 StringTable::StringTable() : _local_table(NULL), _current_size(0), _has_work(0),
 186   _needs_rehashing(false), _weak_handles(NULL), _items_count(0), _uncleaned_items_count(0) {
 187   _weak_handles = new OopStorage("StringTable weak",
 188                                  StringTableWeakAlloc_lock,
 189                                  StringTableWeakActive_lock);
 190   size_t start_size_log_2 = log2_ceil(StringTableSize);
 191   _current_size = ((size_t)1) << start_size_log_2;
 192   log_trace(stringtable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")",
 193                          _current_size, start_size_log_2);
 194   _local_table = new StringTableHash(start_size_log_2, END_SIZE, REHASH_LEN);
 195 }
 196 
 197 size_t StringTable::item_added() {
 198   return Atomic::add((size_t)1, &(the_table()->_items_count));
 199 }
 200 
 201 size_t StringTable::add_items_count_to_clean(size_t ndead) {
 202   size_t total = Atomic::add((size_t)ndead, &(the_table()->_uncleaned_items_count));
 203   log_trace(stringtable)(
 204      "Uncleaned items:" SIZE_FORMAT " added: " SIZE_FORMAT " total:" SIZE_FORMAT,
 205      the_table()->_uncleaned_items_count, ndead, total);
 206   return total;
 207 }
 208 
 209 void StringTable::item_removed() {
 210   Atomic::add((size_t)-1, &(the_table()->_items_count));
 211 }
 212 
 213 double StringTable::get_load_factor() {
 214   return (double)_items_count/_current_size;
 215 }
 216 
 217 double StringTable::get_dead_factor() {
 218   return (double)_uncleaned_items_count/_current_size;
 219 }
 220 
 221 size_t StringTable::table_size(Thread* thread) {
 222   return ((size_t)(1)) << _local_table->get_size_log2(thread != NULL ? thread
 223                                                       : Thread::current());
 224 }
 225 
 226 void StringTable::trigger_concurrent_work() {
 227   MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
 228   the_table()->_has_work = true;
 229   Service_lock->notify_all();
 230 }
 231 
 232 // Probing
 233 oop StringTable::lookup(Symbol* symbol) {
 234   ResourceMark rm;
 235   int length;
 236   jchar* chars = symbol->as_unicode(length);
 237   return lookup(chars, length);
 238 }


 389     bool ret = _real_boc->do_object_b(obj);
 390     if (!ret) {
 391       ++_count;
 392     }
 393     ++_count_total;
 394     return ret;
 395   }
 396 };
 397 
 398 void StringTable::unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f,
 399                                     int* processed, int* removed) {
 400   DoNothingClosure dnc;
 401   assert(is_alive != NULL, "No closure");
 402   StringTableIsAliveCounter stiac(is_alive);
 403   OopClosure* tmp = f != NULL ? f : &dnc;
 404 
 405   StringTable::the_table()->_weak_handles->weak_oops_do(&stiac, tmp);
 406 
 407   // This is the serial case without ParState.
 408   // Just set the correct number and check for a cleaning phase.
 409   the_table()->_uncleaned_items_count = stiac._count;
 410   StringTable::the_table()->check_concurrent_work();
 411 
 412   if (processed != NULL) {
 413     *processed = (int) stiac._count_total;
 414   }
 415   if (removed != NULL) {
 416     *removed = (int) stiac._count;
 417   }
 418 }
 419 
 420 void StringTable::oops_do(OopClosure* f) {
 421   assert(f != NULL, "No closure");
 422   StringTable::the_table()->_weak_handles->oops_do(f);
 423 }
 424 
 425 void StringTable::possibly_parallel_unlink(
 426    OopStorage::ParState<false, false>* _par_state_string, BoolObjectClosure* cl,
 427    int* processed, int* removed)
 428 {
 429   DoNothingClosure dnc;
 430   assert(cl != NULL, "No closure");
 431   StringTableIsAliveCounter stiac(cl);
 432 
 433   _par_state_string->weak_oops_do(&stiac, &dnc);
 434 
 435   // Accumulate the dead strings.
 436   the_table()->add_items_count_to_clean(stiac._count);
 437 
 438   *processed = (int) stiac._count_total;
 439   *removed = (int) stiac._count;
 440 }
 441 
 442 void StringTable::possibly_parallel_oops_do(
 443    OopStorage::ParState<false /* concurrent */, false /* const */>*
 444    _par_state_string, OopClosure* f)
 445 {
 446   assert(f != NULL, "No closure");
 447   _par_state_string->oops_do(f);
 448 }
 449 
 450 // Concurrent work
 451 void StringTable::grow(JavaThread* jt) {
 452   StringTableHash::GrowTask gt(_local_table);
 453   if (!gt.prepare(jt)) {
 454     return;
 455   }
 456   log_trace(stringtable)("Started to grow");


 826     }
 827 
 828     val->replace(new_s);
 829     // add to the compact table
 830     _writer->add(hash, new_s);
 831     return true;
 832   }
 833 };
 834 
 835 void StringTable::copy_shared_string_table(CompactStringTableWriter* writer) {
 836   assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
 837 
 838   CopyToArchive copy(writer);
 839   StringTable::the_table()->_local_table->do_scan(Thread::current(), copy);
 840 }
 841 
 842 void StringTable::write_to_archive() {
 843   assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
 844 
 845   _shared_table.reset();
 846   int num_buckets = the_table()->_items_count / SharedSymbolTableBucketSize;
 847   // calculation of num_buckets can result in zero buckets, we need at least one
 848   CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1,
 849                                   &MetaspaceShared::stats()->string);
 850 
 851   // Copy the interned strings into the "string space" within the java heap
 852   copy_shared_string_table(&writer);
 853   writer.dump(&_shared_table);
 854 }
 855 
 856 void StringTable::serialize(SerializeClosure* soc) {
 857   _shared_table.set_type(CompactHashtable<oop, char>::_string_table);
 858   _shared_table.serialize(soc);
 859 
 860   if (soc->writing()) {
 861     // Sanity. Make sure we don't use the shared table at dump time
 862     _shared_table.reset();
 863   } else if (!_shared_string_mapped) {
 864     _shared_table.reset();
 865   }
 866 }
< prev index next >