68 const char*, Symbol*, |
68 const char*, Symbol*, |
69 symbol_equals_compact_hashtable_entry |
69 symbol_equals_compact_hashtable_entry |
70 > _shared_table; |
70 > _shared_table; |
71 |
71 |
72 // -------------------------------------------------------------------------- |
72 // -------------------------------------------------------------------------- |
73 SymbolTable* SymbolTable::_the_table = NULL; |
73 |
74 volatile bool SymbolTable::_alt_hash = false; |
74 typedef ConcurrentHashTable<Symbol*, |
75 volatile bool SymbolTable::_lookup_shared_first = false; |
75 SymbolTableConfig, mtSymbol> SymbolTableHash; |
|
76 static SymbolTableHash* _local_table = NULL; |
|
77 |
|
78 volatile bool SymbolTable::_has_work = 0; |
|
79 volatile bool SymbolTable::_needs_rehashing = false; |
|
80 |
|
81 // For statistics |
|
82 static size_t _symbols_removed = 0; |
|
83 static size_t _symbols_counted = 0; |
|
84 static size_t _current_size = 0; |
|
85 |
|
86 static volatile size_t _items_count = 0; |
|
87 static volatile bool _has_items_to_clean = false; |
|
88 |
|
89 |
|
90 static volatile bool _alt_hash = false; |
|
91 static volatile bool _lookup_shared_first = false; |
|
92 |
76 // Static arena for symbols that are not deallocated |
93 // Static arena for symbols that are not deallocated |
77 Arena* SymbolTable::_arena = NULL; |
94 Arena* SymbolTable::_arena = NULL; |
78 |
95 |
79 static juint murmur_seed = 0; |
96 static juint murmur_seed = 0; |
80 |
97 |
102 static uintx get_hash(Symbol* const& value, bool* is_dead) { |
119 static uintx get_hash(Symbol* const& value, bool* is_dead) { |
103 *is_dead = (value->refcount() == 0); |
120 *is_dead = (value->refcount() == 0); |
104 if (*is_dead) { |
121 if (*is_dead) { |
105 return 0; |
122 return 0; |
106 } else { |
123 } else { |
107 return hash_symbol((const char*)value->bytes(), value->utf8_length(), SymbolTable::_alt_hash); |
124 return hash_symbol((const char*)value->bytes(), value->utf8_length(), _alt_hash); |
108 } |
125 } |
109 } |
126 } |
110 // We use default allocation/deallocation but counted |
127 // We use default allocation/deallocation but counted |
111 static void* allocate_node(size_t size, Symbol* const& value) { |
128 static void* allocate_node(size_t size, Symbol* const& value) { |
112 SymbolTable::item_added(); |
129 SymbolTable::item_added(); |
134 size_t ret; |
151 size_t ret; |
135 for (ret = 1; ((size_t)1 << ret) < value; ++ret); |
152 for (ret = 1; ((size_t)1 << ret) < value; ++ret); |
136 return ret; |
153 return ret; |
137 } |
154 } |
138 |
155 |
139 SymbolTable::SymbolTable() : |
156 void SymbolTable::create_table () { |
140 _symbols_removed(0), _symbols_counted(0), _local_table(NULL), |
|
141 _current_size(0), _has_work(0), _needs_rehashing(false), |
|
142 _items_count(0), _has_items_to_clean(false) { |
|
143 |
|
144 size_t start_size_log_2 = ceil_log2(SymbolTableSize); |
157 size_t start_size_log_2 = ceil_log2(SymbolTableSize); |
145 _current_size = ((size_t)1) << start_size_log_2; |
158 _current_size = ((size_t)1) << start_size_log_2; |
146 log_trace(symboltable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")", |
159 log_trace(symboltable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")", |
147 _current_size, start_size_log_2); |
160 _current_size, start_size_log_2); |
148 _local_table = new SymbolTableHash(start_size_log_2, END_SIZE, REHASH_LEN); |
161 _local_table = new SymbolTableHash(start_size_log_2, END_SIZE, REHASH_LEN); |
|
162 |
|
163 // Initialize the arena for global symbols, size passed in depends on CDS. |
|
164 if (symbol_alloc_arena_size == 0) { |
|
165 _arena = new (mtSymbol) Arena(mtSymbol); |
|
166 } else { |
|
167 _arena = new (mtSymbol) Arena(mtSymbol, symbol_alloc_arena_size); |
|
168 } |
149 } |
169 } |
150 |
170 |
151 void SymbolTable::delete_symbol(Symbol* sym) { |
171 void SymbolTable::delete_symbol(Symbol* sym) { |
152 if (sym->refcount() == PERM_REFCOUNT) { |
172 if (sym->refcount() == PERM_REFCOUNT) { |
153 MutexLocker ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena |
173 MutexLocker ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena |
160 } else { |
180 } else { |
161 delete sym; |
181 delete sym; |
162 } |
182 } |
163 } |
183 } |
164 |
184 |
165 void SymbolTable::update_needs_rehash(bool rehash) { |
|
166 if (rehash) { |
|
167 _needs_rehashing = true; |
|
168 } |
|
169 } |
|
170 |
|
171 void SymbolTable::reset_has_items_to_clean() { Atomic::store(false, &_has_items_to_clean); } |
185 void SymbolTable::reset_has_items_to_clean() { Atomic::store(false, &_has_items_to_clean); } |
172 void SymbolTable::mark_has_items_to_clean() { Atomic::store(true, &_has_items_to_clean); } |
186 void SymbolTable::mark_has_items_to_clean() { Atomic::store(true, &_has_items_to_clean); } |
173 bool SymbolTable::has_items_to_clean() const { return Atomic::load(&_has_items_to_clean); } |
187 bool SymbolTable::has_items_to_clean() { return Atomic::load(&_has_items_to_clean); } |
174 |
188 |
175 void SymbolTable::item_added() { |
189 void SymbolTable::item_added() { |
176 Atomic::inc(&(SymbolTable::the_table()->_items_count)); |
190 Atomic::inc(&_items_count); |
177 } |
191 } |
178 |
192 |
179 void SymbolTable::item_removed() { |
193 void SymbolTable::item_removed() { |
180 Atomic::inc(&(SymbolTable::the_table()->_symbols_removed)); |
194 Atomic::inc(&(_symbols_removed)); |
181 Atomic::dec(&(SymbolTable::the_table()->_items_count)); |
195 Atomic::dec(&_items_count); |
182 } |
196 } |
183 |
197 |
184 double SymbolTable::get_load_factor() const { |
198 double SymbolTable::get_load_factor() { |
185 return (double)_items_count/_current_size; |
199 return (double)_items_count/_current_size; |
186 } |
200 } |
187 |
201 |
188 size_t SymbolTable::table_size() { |
202 size_t SymbolTable::table_size() { |
189 return ((size_t)1) << _local_table->get_size_log2(Thread::current()); |
203 return ((size_t)1) << _local_table->get_size_log2(Thread::current()); |
190 } |
204 } |
191 |
205 |
192 void SymbolTable::trigger_cleanup() { |
206 void SymbolTable::trigger_cleanup() { |
193 MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag); |
207 MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag); |
194 SymbolTable::the_table()->_has_work = true; |
208 _has_work = true; |
195 Service_lock->notify_all(); |
209 Service_lock->notify_all(); |
196 } |
210 } |
197 |
211 |
198 Symbol* SymbolTable::allocate_symbol(const char* name, int len, bool c_heap) { |
212 Symbol* SymbolTable::allocate_symbol(const char* name, int len, bool c_heap) { |
199 assert (len <= Symbol::max_length(), "should be checked by caller"); |
213 assert (len <= Symbol::max_length(), "should be checked by caller"); |
210 // Allocate to global arena |
224 // Allocate to global arena |
211 MutexLocker ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena |
225 MutexLocker ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena |
212 sym = new (len, arena()) Symbol((const u1*)name, len, PERM_REFCOUNT); |
226 sym = new (len, arena()) Symbol((const u1*)name, len, PERM_REFCOUNT); |
213 } |
227 } |
214 return sym; |
228 return sym; |
215 } |
|
216 |
|
217 void SymbolTable::initialize_symbols(int arena_alloc_size) { |
|
218 // Initialize the arena for global symbols, size passed in depends on CDS. |
|
219 if (arena_alloc_size == 0) { |
|
220 _arena = new (mtSymbol) Arena(mtSymbol); |
|
221 } else { |
|
222 _arena = new (mtSymbol) Arena(mtSymbol, arena_alloc_size); |
|
223 } |
|
224 } |
229 } |
225 |
230 |
226 class SymbolsDo : StackObj { |
231 class SymbolsDo : StackObj { |
227 SymbolClosure *_cl; |
232 SymbolClosure *_cl; |
228 public: |
233 public: |
250 SharedSymbolIterator iter(cl); |
255 SharedSymbolIterator iter(cl); |
251 _shared_table.iterate(&iter); |
256 _shared_table.iterate(&iter); |
252 |
257 |
253 // all symbols from the dynamic table |
258 // all symbols from the dynamic table |
254 SymbolsDo sd(cl); |
259 SymbolsDo sd(cl); |
255 if (!SymbolTable::the_table()->_local_table->try_scan(Thread::current(), sd)) { |
260 if (!_local_table->try_scan(Thread::current(), sd)) { |
256 log_info(stringtable)("symbols_do unavailable at this moment"); |
261 log_info(stringtable)("symbols_do unavailable at this moment"); |
257 } |
262 } |
258 } |
263 } |
259 |
264 |
260 class MetaspacePointersDo : StackObj { |
265 class MetaspacePointersDo : StackObj { |
270 }; |
275 }; |
271 |
276 |
272 void SymbolTable::metaspace_pointers_do(MetaspaceClosure* it) { |
277 void SymbolTable::metaspace_pointers_do(MetaspaceClosure* it) { |
273 assert(DumpSharedSpaces, "called only during dump time"); |
278 assert(DumpSharedSpaces, "called only during dump time"); |
274 MetaspacePointersDo mpd(it); |
279 MetaspacePointersDo mpd(it); |
275 SymbolTable::the_table()->_local_table->do_safepoint_scan(mpd); |
280 _local_table->do_safepoint_scan(mpd); |
276 } |
281 } |
277 |
282 |
278 Symbol* SymbolTable::lookup_dynamic(const char* name, |
283 Symbol* SymbolTable::lookup_dynamic(const char* name, |
279 int len, unsigned int hash) { |
284 int len, unsigned int hash) { |
280 Symbol* sym = SymbolTable::the_table()->do_lookup(name, len, hash); |
285 Symbol* sym = do_lookup(name, len, hash); |
281 assert((sym == NULL) || sym->refcount() != 0, "refcount must not be zero"); |
286 assert((sym == NULL) || sym->refcount() != 0, "refcount must not be zero"); |
282 return sym; |
287 return sym; |
283 } |
288 } |
284 |
289 |
285 Symbol* SymbolTable::lookup_shared(const char* name, |
290 Symbol* SymbolTable::lookup_shared(const char* name, |
286 int len, unsigned int hash) { |
291 int len, unsigned int hash) { |
287 if (!_shared_table.empty()) { |
292 if (!_shared_table.empty()) { |
288 if (SymbolTable::_alt_hash) { |
293 if (_alt_hash) { |
289 // hash_code parameter may use alternate hashing algorithm but the shared table |
294 // hash_code parameter may use alternate hashing algorithm but the shared table |
290 // always uses the same original hash code. |
295 // always uses the same original hash code. |
291 hash = hash_shared_symbol(name, len); |
296 hash = hash_shared_symbol(name, len); |
292 } |
297 } |
293 return _shared_table.lookup(name, hash, len); |
298 return _shared_table.lookup(name, hash, len); |
316 } |
321 } |
317 return sym; |
322 return sym; |
318 } |
323 } |
319 |
324 |
320 Symbol* SymbolTable::new_symbol(const char* name, int len) { |
325 Symbol* SymbolTable::new_symbol(const char* name, int len) { |
321 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash); |
326 unsigned int hash = hash_symbol(name, len, _alt_hash); |
322 Symbol* sym = SymbolTable::the_table()->lookup_common(name, len, hash); |
327 Symbol* sym = lookup_common(name, len, hash); |
323 if (sym == NULL) { |
328 if (sym == NULL) { |
324 sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, true); |
329 sym = do_add_if_needed(name, len, hash, true); |
325 } |
330 } |
326 assert(sym->refcount() != 0, "lookup should have incremented the count"); |
331 assert(sym->refcount() != 0, "lookup should have incremented the count"); |
327 assert(sym->equals(name, len), "symbol must be properly initialized"); |
332 assert(sym->equals(name, len), "symbol must be properly initialized"); |
328 return sym; |
333 return sym; |
329 } |
334 } |
331 Symbol* SymbolTable::new_symbol(const Symbol* sym, int begin, int end) { |
336 Symbol* SymbolTable::new_symbol(const Symbol* sym, int begin, int end) { |
332 assert(begin <= end && end <= sym->utf8_length(), "just checking"); |
337 assert(begin <= end && end <= sym->utf8_length(), "just checking"); |
333 assert(sym->refcount() != 0, "require a valid symbol"); |
338 assert(sym->refcount() != 0, "require a valid symbol"); |
334 const char* name = (const char*)sym->base() + begin; |
339 const char* name = (const char*)sym->base() + begin; |
335 int len = end - begin; |
340 int len = end - begin; |
336 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash); |
341 unsigned int hash = hash_symbol(name, len, _alt_hash); |
337 Symbol* found = SymbolTable::the_table()->lookup_common(name, len, hash); |
342 Symbol* found = lookup_common(name, len, hash); |
338 if (found == NULL) { |
343 if (found == NULL) { |
339 found = SymbolTable::the_table()->do_add_if_needed(name, len, hash, true); |
344 found = do_add_if_needed(name, len, hash, true); |
340 } |
345 } |
341 return found; |
346 return found; |
342 } |
347 } |
343 |
348 |
344 class SymbolTableLookup : StackObj { |
349 class SymbolTableLookup : StackObj { |
398 assert((sym == NULL) || sym->refcount() != 0, "found dead symbol"); |
403 assert((sym == NULL) || sym->refcount() != 0, "found dead symbol"); |
399 return sym; |
404 return sym; |
400 } |
405 } |
401 |
406 |
402 Symbol* SymbolTable::lookup_only(const char* name, int len, unsigned int& hash) { |
407 Symbol* SymbolTable::lookup_only(const char* name, int len, unsigned int& hash) { |
403 hash = hash_symbol(name, len, SymbolTable::_alt_hash); |
408 hash = hash_symbol(name, len, _alt_hash); |
404 return SymbolTable::the_table()->lookup_common(name, len, hash); |
409 return lookup_common(name, len, hash); |
405 } |
410 } |
406 |
411 |
407 // Suggestion: Push unicode-based lookup all the way into the hashing |
412 // Suggestion: Push unicode-based lookup all the way into the hashing |
408 // and probing logic, so there is no need for convert_to_utf8 until |
413 // and probing logic, so there is no need for convert_to_utf8 until |
409 // an actual new Symbol* is created. |
414 // an actual new Symbol* is created. |
444 bool c_heap = !loader_data->is_the_null_class_loader_data(); |
449 bool c_heap = !loader_data->is_the_null_class_loader_data(); |
445 for (int i = 0; i < names_count; i++) { |
450 for (int i = 0; i < names_count; i++) { |
446 const char *name = names[i]; |
451 const char *name = names[i]; |
447 int len = lengths[i]; |
452 int len = lengths[i]; |
448 unsigned int hash = hashValues[i]; |
453 unsigned int hash = hashValues[i]; |
449 assert(SymbolTable::the_table()->lookup_shared(name, len, hash) == NULL, "must have checked already"); |
454 assert(lookup_shared(name, len, hash) == NULL, "must have checked already"); |
450 Symbol* sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, c_heap); |
455 Symbol* sym = do_add_if_needed(name, len, hash, c_heap); |
451 assert(sym->refcount() != 0, "lookup should have incremented the count"); |
456 assert(sym->refcount() != 0, "lookup should have incremented the count"); |
452 cp->symbol_at_put(cp_indices[i], sym); |
457 cp->symbol_at_put(cp_indices[i], sym); |
453 } |
458 } |
454 } |
459 } |
455 |
460 |
464 do { |
469 do { |
465 if (_local_table->get(THREAD, lookup, stg, &rehash_warning)) { |
470 if (_local_table->get(THREAD, lookup, stg, &rehash_warning)) { |
466 sym = stg.get_res_sym(); |
471 sym = stg.get_res_sym(); |
467 break; |
472 break; |
468 } |
473 } |
469 sym = SymbolTable::the_table()->allocate_symbol(name, len, heap); |
474 sym = allocate_symbol(name, len, heap); |
470 if (_local_table->insert(THREAD, lookup, sym, &rehash_warning, &clean_hint)) { |
475 if (_local_table->insert(THREAD, lookup, sym, &rehash_warning, &clean_hint)) { |
471 break; |
476 break; |
472 } |
477 } |
473 } while(true); |
478 } while(true); |
474 |
479 |
486 Symbol* SymbolTable::new_permanent_symbol(const char* name) { |
491 Symbol* SymbolTable::new_permanent_symbol(const char* name) { |
487 unsigned int hash = 0; |
492 unsigned int hash = 0; |
488 int len = (int)strlen(name); |
493 int len = (int)strlen(name); |
489 Symbol* sym = SymbolTable::lookup_only(name, len, hash); |
494 Symbol* sym = SymbolTable::lookup_only(name, len, hash); |
490 if (sym == NULL) { |
495 if (sym == NULL) { |
491 sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, false); |
496 sym = do_add_if_needed(name, len, hash, false); |
492 } |
497 } |
493 if (!sym->is_permanent()) { |
498 if (!sym->is_permanent()) { |
494 sym->make_permanent(); |
499 sym->make_permanent(); |
495 log_trace_symboltable_helper(sym, "Asked for a permanent symbol, but got a regular one"); |
500 log_trace_symboltable_helper(sym, "Asked for a permanent symbol, but got a regular one"); |
496 } |
501 } |
558 }; |
563 }; |
559 }; |
564 }; |
560 |
565 |
561 void SymbolTable::dump(outputStream* st, bool verbose) { |
566 void SymbolTable::dump(outputStream* st, bool verbose) { |
562 if (!verbose) { |
567 if (!verbose) { |
563 SymbolTable::the_table()->print_table_statistics(st, "SymbolTable"); |
568 print_table_statistics(st, "SymbolTable"); |
564 } else { |
569 } else { |
565 Thread* thr = Thread::current(); |
570 Thread* thr = Thread::current(); |
566 ResourceMark rm(thr); |
571 ResourceMark rm(thr); |
567 st->print_cr("VERSION: 1.1"); |
572 st->print_cr("VERSION: 1.1"); |
568 DumpSymbol ds(thr, st); |
573 DumpSymbol ds(thr, st); |
569 if (!SymbolTable::the_table()->_local_table->try_scan(thr, ds)) { |
574 if (!_local_table->try_scan(thr, ds)) { |
570 log_info(symboltable)("dump unavailable at this moment"); |
575 log_info(symboltable)("dump unavailable at this moment"); |
571 } |
576 } |
572 } |
577 } |
573 } |
578 } |
574 |
579 |
588 } |
593 } |
589 }; |
594 }; |
590 |
595 |
591 void SymbolTable::copy_shared_symbol_table(CompactHashtableWriter* writer) { |
596 void SymbolTable::copy_shared_symbol_table(CompactHashtableWriter* writer) { |
592 CopyToArchive copy(writer); |
597 CopyToArchive copy(writer); |
593 SymbolTable::the_table()->_local_table->do_safepoint_scan(copy); |
598 _local_table->do_safepoint_scan(copy); |
594 } |
599 } |
595 |
600 |
596 void SymbolTable::write_to_archive() { |
601 void SymbolTable::write_to_archive() { |
597 _shared_table.reset(); |
602 _shared_table.reset(); |
598 |
603 |
599 int num_buckets = CompactHashtableWriter::default_num_buckets( |
604 int num_buckets = CompactHashtableWriter::default_num_buckets( |
600 SymbolTable::the_table()->_items_count); |
605 _items_count); |
601 CompactHashtableWriter writer(num_buckets, |
606 CompactHashtableWriter writer(num_buckets, |
602 &MetaspaceShared::stats()->symbol); |
607 &MetaspaceShared::stats()->symbol); |
603 copy_shared_symbol_table(&writer); |
608 copy_shared_symbol_table(&writer); |
604 writer.dump(&_shared_table, "symbol"); |
609 writer.dump(&_shared_table, "symbol"); |
605 |
610 |
606 // Verify table is correct |
611 // Verify table is correct |
607 Symbol* sym = vmSymbols::java_lang_Object(); |
612 Symbol* sym = vmSymbols::java_lang_Object(); |
608 const char* name = (const char*)sym->bytes(); |
613 const char* name = (const char*)sym->bytes(); |
609 int len = sym->utf8_length(); |
614 int len = sym->utf8_length(); |
610 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash); |
615 unsigned int hash = hash_symbol(name, len, _alt_hash); |
611 assert(sym == _shared_table.lookup(name, hash, len), "sanity"); |
616 assert(sym == _shared_table.lookup(name, hash, len), "sanity"); |
612 } |
617 } |
613 |
618 |
614 void SymbolTable::serialize_shared_table_header(SerializeClosure* soc) { |
619 void SymbolTable::serialize_shared_table_header(SerializeClosure* soc) { |
615 _shared_table.serialize_header(soc); |
620 _shared_table.serialize_header(soc); |
706 get_load_factor(), has_items_to_clean() ? "true" : "false"); |
711 get_load_factor(), has_items_to_clean() ? "true" : "false"); |
707 trigger_cleanup(); |
712 trigger_cleanup(); |
708 } |
713 } |
709 } |
714 } |
710 |
715 |
711 void SymbolTable::concurrent_work(JavaThread* jt) { |
716 void SymbolTable::do_concurrent_work(JavaThread* jt) { |
712 double load_factor = get_load_factor(); |
717 double load_factor = get_load_factor(); |
713 log_debug(symboltable, perf)("Concurrent work, live factor: %g", load_factor); |
718 log_debug(symboltable, perf)("Concurrent work, live factor: %g", load_factor); |
714 // We prefer growing, since that also removes dead items |
719 // We prefer growing, since that also removes dead items |
715 if (load_factor > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) { |
720 if (load_factor > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) { |
716 grow(jt); |
721 grow(jt); |
717 } else { |
722 } else { |
718 clean_dead_entries(jt); |
723 clean_dead_entries(jt); |
719 } |
724 } |
720 _has_work = false; |
725 _has_work = false; |
721 } |
|
722 |
|
723 void SymbolTable::do_concurrent_work(JavaThread* jt) { |
|
724 SymbolTable::the_table()->concurrent_work(jt); |
|
725 } |
726 } |
726 |
727 |
727 // Rehash |
728 // Rehash |
728 bool SymbolTable::do_rehash() { |
729 bool SymbolTable::do_rehash() { |
729 if (!_local_table->is_safepoint_safe()) { |
730 if (!_local_table->is_safepoint_safe()) { |
745 _local_table = new_table; |
746 _local_table = new_table; |
746 |
747 |
747 return true; |
748 return true; |
748 } |
749 } |
749 |
750 |
750 void SymbolTable::try_rehash_table() { |
751 void SymbolTable::rehash_table() { |
751 static bool rehashed = false; |
752 static bool rehashed = false; |
752 log_debug(symboltable)("Table imbalanced, rehashing called."); |
753 log_debug(symboltable)("Table imbalanced, rehashing called."); |
753 |
754 |
754 // Grow instead of rehash. |
755 // Grow instead of rehash. |
755 if (get_load_factor() > PREF_AVG_LIST_LEN && |
756 if (get_load_factor() > PREF_AVG_LIST_LEN && |
828 return true; |
825 return true; |
829 }; |
826 }; |
830 }; |
827 }; |
831 |
828 |
832 void SymbolTable::print_histogram() { |
829 void SymbolTable::print_histogram() { |
833 SymbolTable* st = SymbolTable::the_table(); |
|
834 HistogramIterator hi; |
830 HistogramIterator hi; |
835 st->_local_table->do_scan(Thread::current(), hi); |
831 _local_table->do_scan(Thread::current(), hi); |
836 tty->print_cr("Symbol Table Histogram:"); |
832 tty->print_cr("Symbol Table Histogram:"); |
837 tty->print_cr(" Total number of symbols " SIZE_FORMAT_W(7), hi.total_count); |
833 tty->print_cr(" Total number of symbols " SIZE_FORMAT_W(7), hi.total_count); |
838 tty->print_cr(" Total size in memory " SIZE_FORMAT_W(7) "K", |
834 tty->print_cr(" Total size in memory " SIZE_FORMAT_W(7) "K", |
839 (hi.total_size * wordSize) / 1024); |
835 (hi.total_size * wordSize) / 1024); |
840 tty->print_cr(" Total counted " SIZE_FORMAT_W(7), st->_symbols_counted); |
836 tty->print_cr(" Total counted " SIZE_FORMAT_W(7), _symbols_counted); |
841 tty->print_cr(" Total removed " SIZE_FORMAT_W(7), st->_symbols_removed); |
837 tty->print_cr(" Total removed " SIZE_FORMAT_W(7), _symbols_removed); |
842 if (SymbolTable::the_table()->_symbols_counted > 0) { |
838 if (_symbols_counted > 0) { |
843 tty->print_cr(" Percent removed %3.2f", |
839 tty->print_cr(" Percent removed %3.2f", |
844 ((float)st->_symbols_removed / st->_symbols_counted) * 100); |
840 ((float)_symbols_removed / _symbols_counted) * 100); |
845 } |
841 } |
846 tty->print_cr(" Reference counts " SIZE_FORMAT_W(7), Symbol::_total_count); |
842 tty->print_cr(" Reference counts " SIZE_FORMAT_W(7), Symbol::_total_count); |
847 tty->print_cr(" Symbol arena used " SIZE_FORMAT_W(7) "K", arena()->used() / 1024); |
843 tty->print_cr(" Symbol arena used " SIZE_FORMAT_W(7) "K", arena()->used() / 1024); |
848 tty->print_cr(" Symbol arena size " SIZE_FORMAT_W(7) "K", arena()->size_in_bytes() / 1024); |
844 tty->print_cr(" Symbol arena size " SIZE_FORMAT_W(7) "K", arena()->size_in_bytes() / 1024); |
849 tty->print_cr(" Total symbol length " SIZE_FORMAT_W(7), hi.total_length); |
845 tty->print_cr(" Total symbol length " SIZE_FORMAT_W(7), hi.total_length); |