< prev index next >

src/hotspot/share/classfile/stringTable.cpp

Print this page
rev 50505 : imported patch 8204613-stringtable-unclean-fix


 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::items_to_clean(size_t ncl) {
 202   size_t total = Atomic::add((size_t)ncl, &(the_table()->_uncleaned_items));
 203   log_trace(stringtable)(
 204      "Uncleaned items:" SIZE_FORMAT " added: " SIZE_FORMAT " total:" SIZE_FORMAT,
 205      the_table()->_uncleaned_items, ncl, total);
 206   return total;
 207 }
 208 
 209 void StringTable::item_removed() {
 210   Atomic::add((size_t)-1, &(the_table()->_items));
 211   Atomic::add((size_t)-1, &(the_table()->_uncleaned_items));
 212 }
 213 
 214 double StringTable::get_load_factor() {
 215   return (_items*1.0)/_current_size;
 216 }
 217 
 218 double StringTable::get_dead_factor() {
 219   return (_uncleaned_items*1.0)/_current_size;
 220 }
 221 
 222 size_t StringTable::table_size(Thread* thread) {
 223   return ((size_t)(1)) << _local_table->get_size_log2(thread != NULL ? thread
 224                                                       : Thread::current());
 225 }
 226 
 227 void StringTable::trigger_concurrent_work() {
 228   MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
 229   the_table()->_has_work = true;
 230   Service_lock->notify_all();
 231 }


 388                                                       _count_total(0) {}
 389   bool do_object_b(oop obj) {
 390     bool ret = _real_boc->do_object_b(obj);
 391     if (!ret) {
 392       ++_count;
 393     }
 394     ++_count_total;
 395     return ret;
 396   }
 397 };
 398 
 399 void StringTable::unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f,
 400                                     int* processed, int* removed) {
 401   DoNothingClosure dnc;
 402   assert(is_alive != NULL, "No closure");
 403   StringTableIsAliveCounter stiac(is_alive);
 404   OopClosure* tmp = f != NULL ? f : &dnc;
 405 
 406   StringTable::the_table()->_weak_handles->weak_oops_do(&stiac, tmp);
 407 
 408   StringTable::the_table()->items_to_clean(stiac._count);


 409   StringTable::the_table()->check_concurrent_work();

 410   if (processed != NULL) {
 411     *processed = (int) stiac._count_total;
 412   }
 413   if (removed != NULL) {
 414     *removed = (int) stiac._count;
 415   }
 416 }
 417 
 418 void StringTable::oops_do(OopClosure* f) {
 419   assert(f != NULL, "No closure");
 420   StringTable::the_table()->_weak_handles->oops_do(f);
 421 }
 422 
 423 void StringTable::possibly_parallel_unlink(
 424    OopStorage::ParState<false, false>* _par_state_string, BoolObjectClosure* cl,
 425    int* processed, int* removed)
 426 {
 427   DoNothingClosure dnc;
 428   assert(cl != NULL, "No closure");
 429   StringTableIsAliveCounter stiac(cl);
 430 
 431   _par_state_string->weak_oops_do(&stiac, &dnc);
 432 
 433   StringTable::the_table()->items_to_clean(stiac._count);
 434   StringTable::the_table()->check_concurrent_work();

 435   *processed = (int) stiac._count_total;
 436   *removed = (int) stiac._count;
 437 }
 438 
 439 void StringTable::possibly_parallel_oops_do(
 440    OopStorage::ParState<false /* concurrent */, false /* const */>*
 441    _par_state_string, OopClosure* f)
 442 {
 443   assert(f != NULL, "No closure");
 444   _par_state_string->oops_do(f);
 445 }
 446 
 447 // Concurrent work
 448 void StringTable::grow(JavaThread* jt) {
 449   StringTableHash::GrowTask gt(_local_table);
 450   if (!gt.prepare(jt)) {
 451     return;
 452   }
 453   log_trace(stringtable)("Started to grow");
 454   {
 455     TraceTime timer("Grow", TRACETIME_LOG(Debug, stringtable, perf));
 456     while (gt.doTask(jt)) {
 457       gt.pause(jt);
 458       {
 459         ThreadBlockInVM tbivm(jt);
 460       }
 461       gt.cont(jt);
 462     }
 463   }
 464   gt.done(jt);
 465   _current_size = table_size(jt);
 466   log_debug(stringtable)("Grown to size:" SIZE_FORMAT, _current_size);
 467 }
 468 
 469 struct StringTableDoDelete : StackObj {
 470   long _count;
 471   StringTableDoDelete() : _count(0) {}
 472   void operator()(WeakHandle<vm_string_table_data>* val) {
 473     ++_count;
 474   }
 475 };
 476 
 477 struct StringTableDeleteCheck : StackObj {
 478   long _count;
 479   long _item;
 480   StringTableDeleteCheck() : _count(0), _item(0) {}
 481   bool operator()(WeakHandle<vm_string_table_data>* val) {
 482     ++_item;
 483     oop tmp = val->peek();
 484     if (tmp == NULL) {
 485       ++_count;
 486       return true;
 487     } else {
 488       return false;
 489     }
 490   }
 491 };
 492 
 493 void StringTable::clean_dead_entries(JavaThread* jt) {


 507         ThreadBlockInVM tbivm(jt);
 508       }
 509       if (!bdt.cont(jt)) {
 510         interrupted = true;
 511         break;
 512       }
 513     }
 514   }
 515   if (interrupted) {
 516     _has_work = true;
 517   } else {
 518     bdt.done(jt);
 519   }
 520   log_debug(stringtable)("Cleaned %ld of %ld", stdc._count, stdc._item);
 521 }
 522 
 523 void StringTable::check_concurrent_work() {
 524   if (_has_work) {
 525     return;
 526   }

 527   double load_factor = StringTable::get_load_factor();
 528   double dead_factor = StringTable::get_dead_factor();
 529   // We should clean/resize if we have more dead than alive,
 530   // more items than preferred load factor or
 531   // more dead items than water mark.
 532   if ((dead_factor > load_factor) ||
 533       (load_factor > PREF_AVG_LIST_LEN) ||
 534       (dead_factor > CLEAN_DEAD_HIGH_WATER_MARK)) {
 535     log_debug(stringtable)("Concurrent work triggered, live factor:%g dead factor:%g",
 536                            load_factor, dead_factor);
 537     trigger_concurrent_work();
 538   }
 539 }
 540 
 541 void StringTable::concurrent_work(JavaThread* jt) {
 542   _has_work = false;
 543   double load_factor = get_load_factor();
 544   log_debug(stringtable, perf)("Concurrent work, live factor: %g", load_factor);
 545   // We prefer growing, since that also removes dead items
 546   if (load_factor > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) {




 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 }


 387                                                       _count_total(0) {}
 388   bool do_object_b(oop obj) {
 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");
 457   {
 458     TraceTime timer("Grow", TRACETIME_LOG(Debug, stringtable, perf));
 459     while (gt.doTask(jt)) {
 460       gt.pause(jt);
 461       {
 462         ThreadBlockInVM tbivm(jt);
 463       }
 464       gt.cont(jt);
 465     }
 466   }
 467   gt.done(jt);
 468   _current_size = table_size(jt);
 469   log_debug(stringtable)("Grown to size:" SIZE_FORMAT, _current_size);
 470 }
 471 
 472 struct StringTableDoDelete : StackObj {


 473   void operator()(WeakHandle<vm_string_table_data>* val) {
 474     /* do nothing */
 475   }
 476 };
 477 
 478 struct StringTableDeleteCheck : StackObj {
 479   long _count;
 480   long _item;
 481   StringTableDeleteCheck() : _count(0), _item(0) {}
 482   bool operator()(WeakHandle<vm_string_table_data>* val) {
 483     ++_item;
 484     oop tmp = val->peek();
 485     if (tmp == NULL) {
 486       ++_count;
 487       return true;
 488     } else {
 489       return false;
 490     }
 491   }
 492 };
 493 
 494 void StringTable::clean_dead_entries(JavaThread* jt) {


 508         ThreadBlockInVM tbivm(jt);
 509       }
 510       if (!bdt.cont(jt)) {
 511         interrupted = true;
 512         break;
 513       }
 514     }
 515   }
 516   if (interrupted) {
 517     _has_work = true;
 518   } else {
 519     bdt.done(jt);
 520   }
 521   log_debug(stringtable)("Cleaned %ld of %ld", stdc._count, stdc._item);
 522 }
 523 
 524 void StringTable::check_concurrent_work() {
 525   if (_has_work) {
 526     return;
 527   }
 528 
 529   double load_factor = StringTable::get_load_factor();
 530   double dead_factor = StringTable::get_dead_factor();
 531   // We should clean/resize if we have more dead than alive,
 532   // more items than preferred load factor or
 533   // more dead items than water mark.
 534   if ((dead_factor > load_factor) ||
 535       (load_factor > PREF_AVG_LIST_LEN) ||
 536       (dead_factor > CLEAN_DEAD_HIGH_WATER_MARK)) {
 537     log_debug(stringtable)("Concurrent work triggered, live factor:%g dead factor:%g",
 538                            load_factor, dead_factor);
 539     trigger_concurrent_work();
 540   }
 541 }
 542 
 543 void StringTable::concurrent_work(JavaThread* jt) {
 544   _has_work = false;
 545   double load_factor = get_load_factor();
 546   log_debug(stringtable, perf)("Concurrent work, live factor: %g", load_factor);
 547   // We prefer growing, since that also removes dead items
 548   if (load_factor > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) {


< prev index next >