172 _arena = new (mtSymbol) Arena(mtSymbol);
173 } else {
174 _arena = new (mtSymbol) Arena(mtSymbol, symbol_alloc_arena_size);
175 }
176 }
177
178 void SymbolTable::delete_symbol(Symbol* sym) {
179 if (sym->refcount() == PERM_REFCOUNT) {
180 MutexLocker ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena
181 // Deleting permanent symbol should not occur very often (insert race condition),
182 // so log it.
183 log_trace_symboltable_helper(sym, "Freeing permanent symbol");
184 if (!arena()->Afree(sym, sym->size())) {
185 log_trace_symboltable_helper(sym, "Leaked permanent symbol");
186 }
187 } else {
188 delete sym;
189 }
190 }
191
192 void SymbolTable::reset_has_items_to_clean() { Atomic::store(false, &_has_items_to_clean); }
193 void SymbolTable::mark_has_items_to_clean() { Atomic::store(true, &_has_items_to_clean); }
194 bool SymbolTable::has_items_to_clean() { return Atomic::load(&_has_items_to_clean); }
195
196 void SymbolTable::item_added() {
197 Atomic::inc(&_items_count);
198 }
199
200 void SymbolTable::item_removed() {
201 Atomic::inc(&(_symbols_removed));
202 Atomic::dec(&_items_count);
203 }
204
205 double SymbolTable::get_load_factor() {
206 return (double)_items_count/_current_size;
207 }
208
209 size_t SymbolTable::table_size() {
210 return ((size_t)1) << _local_table->get_size_log2(Thread::current());
211 }
212
213 void SymbolTable::trigger_cleanup() {
707 SymbolTableHash::BulkDeleteTask bdt(_local_table);
708 if (!bdt.prepare(jt)) {
709 return;
710 }
711
712 SymbolTableDeleteCheck stdc;
713 SymbolTableDoDelete stdd;
714 {
715 TraceTime timer("Clean", TRACETIME_LOG(Debug, symboltable, perf));
716 while (bdt.do_task(jt, stdc, stdd)) {
717 bdt.pause(jt);
718 {
719 ThreadBlockInVM tbivm(jt);
720 }
721 bdt.cont(jt);
722 }
723 reset_has_items_to_clean();
724 bdt.done(jt);
725 }
726
727 Atomic::add(stdc._processed, &_symbols_counted);
728
729 log_debug(symboltable)("Cleaned " SIZE_FORMAT " of " SIZE_FORMAT,
730 stdd._deleted, stdc._processed);
731 }
732
733 void SymbolTable::check_concurrent_work() {
734 if (_has_work) {
735 return;
736 }
737 // We should clean/resize if we have
738 // more items than preferred load factor or
739 // more dead items than water mark.
740 if (has_items_to_clean() || (get_load_factor() > PREF_AVG_LIST_LEN)) {
741 log_debug(symboltable)("Concurrent work triggered, load factor: %f, items to clean: %s",
742 get_load_factor(), has_items_to_clean() ? "true" : "false");
743 trigger_cleanup();
744 }
745 }
746
747 void SymbolTable::do_concurrent_work(JavaThread* jt) {
|
172 _arena = new (mtSymbol) Arena(mtSymbol);
173 } else {
174 _arena = new (mtSymbol) Arena(mtSymbol, symbol_alloc_arena_size);
175 }
176 }
177
178 void SymbolTable::delete_symbol(Symbol* sym) {
179 if (sym->refcount() == PERM_REFCOUNT) {
180 MutexLocker ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena
181 // Deleting permanent symbol should not occur very often (insert race condition),
182 // so log it.
183 log_trace_symboltable_helper(sym, "Freeing permanent symbol");
184 if (!arena()->Afree(sym, sym->size())) {
185 log_trace_symboltable_helper(sym, "Leaked permanent symbol");
186 }
187 } else {
188 delete sym;
189 }
190 }
191
192 void SymbolTable::reset_has_items_to_clean() { Atomic::store(&_has_items_to_clean, false); }
193 void SymbolTable::mark_has_items_to_clean() { Atomic::store(&_has_items_to_clean, true); }
194 bool SymbolTable::has_items_to_clean() { return Atomic::load(&_has_items_to_clean); }
195
196 void SymbolTable::item_added() {
197 Atomic::inc(&_items_count);
198 }
199
200 void SymbolTable::item_removed() {
201 Atomic::inc(&(_symbols_removed));
202 Atomic::dec(&_items_count);
203 }
204
205 double SymbolTable::get_load_factor() {
206 return (double)_items_count/_current_size;
207 }
208
209 size_t SymbolTable::table_size() {
210 return ((size_t)1) << _local_table->get_size_log2(Thread::current());
211 }
212
213 void SymbolTable::trigger_cleanup() {
707 SymbolTableHash::BulkDeleteTask bdt(_local_table);
708 if (!bdt.prepare(jt)) {
709 return;
710 }
711
712 SymbolTableDeleteCheck stdc;
713 SymbolTableDoDelete stdd;
714 {
715 TraceTime timer("Clean", TRACETIME_LOG(Debug, symboltable, perf));
716 while (bdt.do_task(jt, stdc, stdd)) {
717 bdt.pause(jt);
718 {
719 ThreadBlockInVM tbivm(jt);
720 }
721 bdt.cont(jt);
722 }
723 reset_has_items_to_clean();
724 bdt.done(jt);
725 }
726
727 Atomic::add(&_symbols_counted, stdc._processed);
728
729 log_debug(symboltable)("Cleaned " SIZE_FORMAT " of " SIZE_FORMAT,
730 stdd._deleted, stdc._processed);
731 }
732
733 void SymbolTable::check_concurrent_work() {
734 if (_has_work) {
735 return;
736 }
737 // We should clean/resize if we have
738 // more items than preferred load factor or
739 // more dead items than water mark.
740 if (has_items_to_clean() || (get_load_factor() > PREF_AVG_LIST_LEN)) {
741 log_debug(symboltable)("Concurrent work triggered, load factor: %f, items to clean: %s",
742 get_load_factor(), has_items_to_clean() ? "true" : "false");
743 trigger_cleanup();
744 }
745 }
746
747 void SymbolTable::do_concurrent_work(JavaThread* jt) {
|