41 // We used to not resize at all, so let's be conservative
42 // and not set it too short before we decide to resize,
43 // to match previous startup behavior
44 #define PREF_AVG_LIST_LEN 8
45 // 2^17 (131,072) is max size, which is about 6.5 times as large
46 // as the previous table size (used to be 20,011),
47 // which never resized
48 #define END_SIZE 17
49 // If a chain gets to 100 something might be wrong
50 #define REHASH_LEN 100
51 // We only get a chance to check whether we need
52 // to clean infrequently (on class unloading),
53 // so if we have even one dead entry then mark table for cleaning
54 #define CLEAN_DEAD_HIGH_WATER_MARK 0.0
55
56 #define ON_STACK_BUFFER_LENGTH 128
57
58 // --------------------------------------------------------------------------
59 SymbolTable* SymbolTable::_the_table = NULL;
60 CompactHashtable<Symbol*, char> SymbolTable::_shared_table;
61 bool SymbolTable::_alt_hash = false;
62 // Static arena for symbols that are not deallocated
63 Arena* SymbolTable::_arena = NULL;
64 bool SymbolTable::_lookup_shared_first = false;
65 int SymbolTable::_symbols_removed = 0;
66 int SymbolTable::_symbols_counted = 0;
67
68 static juint murmur_seed = 0;
69
70 static inline void _log_trace_symboltable_helper(Symbol* sym, const char* msg) {
71 #ifndef PRODUCT
72 if (log_is_enabled(Trace, symboltable)) {
73 char *s;
74 {
75 ResourceMark rm;
76 s = sym->as_quoted_ascii();
77 s = os::strdup(s);
78 }
79 if (s == NULL) {
80 log_trace(symboltable)("%s [%s]", msg, "NULL");
81 } else {
82 log_trace(symboltable)("%s [%s]", msg, s);
83 os::free(s);
84 }
85 }
86 #endif // PRODUCT
87 }
88
89 // Pick hashing algorithm.
90 static uintx hash_symbol(const char* s, int len, bool useAlt) {
91 return useAlt ?
92 AltHashing::murmur3_32(murmur_seed, (const jbyte*)s, len) :
93 java_lang_String::hash_code((const jbyte*)s, len);
94 }
95
96 static uintx hash_shared_symbol(const char* s, int len) {
97 return java_lang_String::hash_code((const jbyte*)s, len);
98 }
99
100 class SymbolTableConfig : public SymbolTableHash::BaseConfig {
101 private:
102 public:
103 static uintx get_hash(Symbol* const& value, bool* is_dead) {
104 *is_dead = (value->refcount() == 0);
105 if (*is_dead) {
106 return 0;
107 } else {
108 return hash_symbol((char*)value->bytes(), value->utf8_length(), SymbolTable::_alt_hash);
109 }
110 }
111 // We use default allocation/deallocation but counted
112 static void* allocate_node(size_t size, Symbol* const& value) {
113 SymbolTable::item_added();
114 return SymbolTableHash::BaseConfig::allocate_node(size, value);
115 }
116 static void free_node(void* memory, Symbol* const& value) {
117 // We get here either because #1 some threads lost a race
118 // to insert a newly created Symbol, or #2 we are freeing
119 // a symbol during normal cleanup deletion.
120 // If #1, then the symbol can be a permanent (refcount==PERM_REFCOUNT),
121 // or regular newly created one but with refcount==0 (see SymbolTableCreateEntry)
122 // If #2, then the symbol must have refcount==0
123 assert((value->refcount() == PERM_REFCOUNT) || (value->refcount() == 0),
124 "refcount %d", value->refcount());
125 SymbolTable::delete_symbol(value);
126 SymbolTableHash::BaseConfig::free_node(memory, value);
127 SymbolTable::item_removed();
128 }
129 };
130
131 static size_t ceil_pow_2(uintx value) {
132 size_t ret;
133 for (ret = 1; ((size_t)1 << ret) < value; ++ret);
134 return ret;
135 }
136
137 SymbolTable::SymbolTable() : _local_table(NULL), _current_size(0), _has_work(0),
138 _needs_rehashing(false), _items(0), _uncleaned_items(0) {
139
140 size_t start_size_log_2 = ceil_pow_2(SymbolTableSize);
141 _current_size = ((size_t)1) << start_size_log_2;
142 log_trace(symboltable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")",
143 _current_size, start_size_log_2);
144 _local_table = new SymbolTableHash(start_size_log_2, END_SIZE, REHASH_LEN);
145 }
146
147 void SymbolTable::delete_symbol(Symbol* sym) {
148 if (sym->refcount() == PERM_REFCOUNT) {
149 MutexLocker ml(SymbolTable_lock); // Protect arena
150 // Deleting permanent symbol should not occur very often (insert race condition),
151 // so log it.
152 _log_trace_symboltable_helper(sym, "Freeing permanent symbol");
153 if (!arena()->Afree(sym, sym->size())) {
154 _log_trace_symboltable_helper(sym, "Leaked permanent symbol");
155 }
156 } else {
157 delete sym;
158 }
159 }
160
161 size_t SymbolTable::item_added() {
162 return Atomic::add(1, &(SymbolTable::the_table()->_items));
163 }
164
165 void SymbolTable::set_item_clean_count(size_t ncl) {
166 Atomic::store((int)ncl, &(SymbolTable::the_table()->_uncleaned_items));
167 log_trace(symboltable)("Set uncleaned items:" INT32_FORMAT, SymbolTable::the_table()->_uncleaned_items);
168 }
169
170 void SymbolTable::mark_item_clean_count() {
171 if (Atomic::cmpxchg(1, &(SymbolTable::the_table()->_uncleaned_items), 0) == 0) { // only mark if unset
172 log_trace(symboltable)("Marked uncleaned items:" INT32_FORMAT, SymbolTable::the_table()->_uncleaned_items);
173 }
174 }
175
176 void SymbolTable::item_removed() {
177 Atomic::add(1, &(SymbolTable::the_table()->_symbols_removed));
178 Atomic::sub(1, &(SymbolTable::the_table()->_items));
179 }
180
181 double SymbolTable::get_load_factor() {
182 return (_items*1.0)/_current_size;
183 }
184
185 double SymbolTable::get_dead_factor() {
186 return (_uncleaned_items*1.0)/_current_size;
187 }
188
189 size_t SymbolTable::table_size(Thread* thread) {
190 return ((size_t)(1)) << _local_table->get_size_log2(thread != NULL ? thread
191 : Thread::current());
192 }
193
194 void SymbolTable::trigger_concurrent_work() {
195 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
196 SymbolTable::the_table()->_has_work = true;
197 Service_lock->notify_all();
198 }
199
200 Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS) {
201 assert (len <= Symbol::max_length(), "should be checked by caller");
202
203 Symbol* sym;
204 if (DumpSharedSpaces) {
205 c_heap = false;
206 }
207 if (c_heap) {
208 // refcount starts as 1
209 sym = new (len, THREAD) Symbol(name, len, 1);
210 assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted");
211 } else {
212 // Allocate to global arena
213 MutexLocker ml(SymbolTable_lock); // Protect arena
214 sym = new (len, arena(), THREAD) Symbol(name, len, PERM_REFCOUNT);
215 }
216 return sym;
217 }
218
219 void SymbolTable::initialize_symbols(int arena_alloc_size) {
220 // Initialize the arena for global symbols, size passed in depends on CDS.
221 if (arena_alloc_size == 0) {
222 _arena = new (mtSymbol) Arena(mtSymbol);
223 } else {
224 _arena = new (mtSymbol) Arena(mtSymbol, arena_alloc_size);
225 }
226 }
227
228 class SymbolsDo : StackObj {
229 SymbolClosure *_cl;
230 public:
231 SymbolsDo(SymbolClosure *cl) : _cl(cl) {}
232 bool operator()(Symbol** value) {
233 assert(value != NULL, "expected valid value");
234 assert(*value != NULL, "value should point to a symbol");
252 class MetaspacePointersDo : StackObj {
253 MetaspaceClosure *_it;
254 public:
255 MetaspacePointersDo(MetaspaceClosure *it) : _it(it) {}
256 bool operator()(Symbol** value) {
257 assert(value != NULL, "expected valid value");
258 assert(*value != NULL, "value should point to a symbol");
259 _it->push(value);
260 return true;
261 };
262 };
263
264 void SymbolTable::metaspace_pointers_do(MetaspaceClosure* it) {
265 assert(DumpSharedSpaces, "called only during dump time");
266 MetaspacePointersDo mpd(it);
267 SymbolTable::the_table()->_local_table->do_scan(Thread::current(), mpd);
268 }
269
270 Symbol* SymbolTable::lookup_dynamic(const char* name,
271 int len, unsigned int hash) {
272 Symbol* sym = SymbolTable::the_table()->do_lookup((char*)name, len, hash);
273 assert((sym == NULL) || sym->refcount() != 0, "refcount must not be zero");
274 return sym;
275 }
276
277 Symbol* SymbolTable::lookup_shared(const char* name,
278 int len, unsigned int hash) {
279 if (!_shared_table.empty()) {
280 if (SymbolTable::_alt_hash) {
281 // hash_code parameter may use alternate hashing algorithm but the shared table
282 // always uses the same original hash code.
283 hash = hash_shared_symbol(name, len);
284 }
285 return _shared_table.lookup(name, hash, len);
286 } else {
287 return NULL;
288 }
289 }
290
291 Symbol* SymbolTable::lookup_common(const char* name,
292 int len, unsigned int hash) {
296 if (sym == NULL) {
297 _lookup_shared_first = false;
298 sym = lookup_dynamic(name, len, hash);
299 }
300 } else {
301 sym = lookup_dynamic(name, len, hash);
302 if (sym == NULL) {
303 sym = lookup_shared(name, len, hash);
304 if (sym != NULL) {
305 _lookup_shared_first = true;
306 }
307 }
308 }
309 return sym;
310 }
311
312 Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) {
313 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash);
314 Symbol* sym = SymbolTable::the_table()->lookup_common(name, len, hash);
315 if (sym == NULL) {
316 sym = SymbolTable::the_table()->do_add_if_needed((char*)name, len, hash, true, CHECK_NULL);
317 }
318 assert(sym->refcount() != 0, "lookup should have incremented the count");
319 assert(sym->equals((char*)name, len), "symbol must be properly initialized");
320 return sym;
321 }
322
323 Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) {
324 Symbol* found = NULL;
325 {
326 debug_only(NoSafepointVerifier nsv;)
327
328 char* name = (char*)sym->base() + begin;
329 int len = end - begin;
330 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash);
331 found = SymbolTable::the_table()->do_add_if_needed(name, len, hash, true, THREAD);
332 }
333 return found;
334 }
335
336 class SymbolTableLookupChar : StackObj {
337 private:
338 Thread* _thread;
339 uintx _hash;
340 int _len;
341 const char* _str;
342 Symbol* _found;
343 public:
344 SymbolTableLookupChar(Thread* thread, const char* key, int len, uintx hash)
345 : _thread(thread), _hash(hash), _str(key), _len(len) , _found(NULL) {
346 }
347 uintx get_hash() const {
348 return _hash;
349 }
350 bool equals(Symbol** value, bool* is_dead) {
351 assert(value != NULL, "expected valid value");
352 assert(*value != NULL, "value should point to a symbol");
353 Symbol *sym = *value;
354 if (sym->equals(_str, _len)) {
355 if (sym->try_increment_refcount()) {
356 // something is referencing this symbol now.
357 _found = sym;
358 return true;
359 } else {
360 *is_dead = (sym->refcount() == 0);
361 return false;
362 }
363 } else {
364 return false;
365 }
366 }
367 };
368
369 class SymbolTableGet : public StackObj {
370 Symbol* _return;
371 public:
372 SymbolTableGet() : _return(NULL) { }
373 void operator()(Symbol** value) {
374 assert(value != NULL, "expected valid value");
375 assert(*value != NULL, "value should point to a symbol");
376 _return = *value;
377 }
378 Symbol* get_res_sym() {
379 return _return;
380 }
381 };
382
383 Symbol* SymbolTable::do_lookup(char* name, int len, uintx hash) {
384 Thread* thread = Thread::current();
385 SymbolTableLookupChar lookup(thread, name, len, hash);
386 SymbolTableGet stg;
387 bool rehash_warning;
388 _local_table->get(thread, lookup, stg, &rehash_warning);
389 if (rehash_warning) {
390 _needs_rehashing = true;
391 }
392 Symbol* sym = stg.get_res_sym();
393 assert((sym == NULL) || sym->refcount() != 0, "found dead symbol");
394 return sym;
395 }
396
397 Symbol* SymbolTable::lookup_only(const char* name, int len, unsigned int& hash) {
398 hash = hash_symbol(name, len, SymbolTable::_alt_hash);
399 return SymbolTable::the_table()->lookup_common(name, len, hash);
400 }
401
402 // Suggestion: Push unicode-based lookup all the way into the hashing
403 // and probing logic, so there is no need for convert_to_utf8 until
404 // an actual new Symbol* is created.
405 Symbol* SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) {
406 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length);
407 char stack_buf[ON_STACK_BUFFER_LENGTH];
420 Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length,
421 unsigned int& hash) {
422 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length);
423 char stack_buf[ON_STACK_BUFFER_LENGTH];
424 if (utf8_length < (int) sizeof(stack_buf)) {
425 char* chars = stack_buf;
426 UNICODE::convert_to_utf8(name, utf16_length, chars);
427 return lookup_only(chars, utf8_length, hash);
428 } else {
429 ResourceMark rm;
430 char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);
431 UNICODE::convert_to_utf8(name, utf16_length, chars);
432 return lookup_only(chars, utf8_length, hash);
433 }
434 }
435
436 void SymbolTable::add(ClassLoaderData* loader_data, const constantPoolHandle& cp,
437 int names_count, const char** names, int* lengths,
438 int* cp_indices, unsigned int* hashValues, TRAPS) {
439 bool c_heap = !loader_data->is_the_null_class_loader_data();
440 for (int i=0; i<names_count; i++) {
441 char *name = (char*)names[i];
442 int len = lengths[i];
443 unsigned int hash = hashValues[i];
444 Symbol* sym = SymbolTable::the_table()->lookup_common(name, len, hash);
445 if (sym == NULL) {
446 sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, c_heap, CHECK);
447 }
448 assert(sym->refcount()!=0, "lookup should have incremented the count");
449 cp->symbol_at_put(cp_indices[i], sym);
450 }
451 }
452
453 class SymbolTableCreateEntry : public StackObj {
454 private:
455 Thread* _thread;
456 const char* _name;
457 int _len;
458 bool _heap;
459 Symbol* _return;
460 Symbol* _created;
461
462 #ifdef ASSERT
463 void _assert_for_name(Symbol* sym, const char* where) const {
464 assert(sym->utf8_length() == _len, "%s [%d,%d]", where, sym->utf8_length(), _len);
465 for (int i=0; i<_len; i++) {
466 assert(sym->byte_at(i) == _name[i],
467 "%s [%d,%d,%d]", where, i, sym->byte_at(i), _name[i]);
468 }
469 }
470 #endif
471
472 public:
473 SymbolTableCreateEntry(Thread* thread, const char* name, int len, bool heap)
474 : _thread(thread), _name(name) , _len(len), _heap(heap), _return(NULL) , _created(NULL) {
475 assert(_name != NULL, "expected valid name");
476 }
477 Symbol* operator()() {
478 _created = SymbolTable::the_table()->allocate_symbol((const u1*)_name, _len, _heap, _thread);
479 assert(_created != NULL, "expected created symbol");
480 #ifdef ASSERT
481 _assert_for_name(_created, "operator()()");
482 #endif
483 assert(_created->equals((char*)_name, _len),
484 "symbol must be properly initialized [%p,%d,%d]", _name, _len, (int)_heap);
485 return _created;
486 }
487 void operator()(bool inserted, Symbol** value) {
488 assert(value != NULL, "expected valid value");
489 assert(*value != NULL, "value should point to a symbol");
490 if (!inserted && (_created != NULL)) {
491 // We created our symbol, but someone else inserted
492 // theirs first, so ours will be destroyed.
493 // Since symbols are created with refcount of 1,
494 // we must decrement it here to 0 to delete,
495 // unless it's a permanent one.
496 if (_created->refcount() != PERM_REFCOUNT) {
497 assert(_created->refcount() == 1, "expected newly created symbol");
498 _created->decrement_refcount();
499 assert(_created->refcount() == 0, "expected dead symbol");
500 }
501 }
502 _return = *value;
503 #ifdef ASSERT
504 _assert_for_name(_return, "operator()");
505 #endif
506 }
507 Symbol* get_new_sym() const {
508 #ifdef ASSERT
509 _assert_for_name(_return, "get_new_sym");
510 #endif
511 return _return;
512 }
513 };
514
515 Symbol* SymbolTable::do_add_if_needed(char* name, int len, uintx hash, bool heap, TRAPS) {
516 SymbolTableLookupChar lookup(THREAD, name, len, hash);
517 SymbolTableCreateEntry stce(THREAD, name, len, heap);
518 bool rehash_warning;
519 bool clean_hint;
520 _local_table->get_insert_lazy(THREAD, lookup, stce, stce, &rehash_warning, &clean_hint);
521 if (rehash_warning) {
522 _needs_rehashing = true;
523 }
524 if (clean_hint) {
525 // we just found out that there is a dead item,
526 // which we were unable to clean right now,
527 // but we have no way of telling whether it's
528 // been previously counted or not, so mark
529 // it only if no other items were found yet
530 mark_item_clean_count();
531 check_concurrent_work();
532 }
533 Symbol* sym = stce.get_new_sym();
534 assert(sym->refcount() != 0, "zero is invalid");
535 return sym;
536 }
537
538 Symbol* SymbolTable::new_permanent_symbol(const char* name, TRAPS) {
539 unsigned int hash = 0;
540 int len = (int)strlen(name);
541 Symbol* sym = SymbolTable::lookup_only(name, len, hash);
542 if (sym == NULL) {
543 sym = SymbolTable::the_table()->do_add_if_needed((char*)name, len, hash, false, CHECK_NULL);
544 }
545 if (sym->refcount() != PERM_REFCOUNT) {
546 sym->increment_refcount();
547 _log_trace_symboltable_helper(sym, "Asked for a permanent symbol, but got a regular one");
548 }
549 return sym;
550 }
551
552 struct SizeFunc : StackObj {
553 size_t operator()(Symbol** value) {
554 assert(value != NULL, "expected valid value");
555 assert(*value != NULL, "value should point to a symbol");
556 return (*value)->size() * HeapWordSize;
557 };
558 };
559
560 void SymbolTable::print_table_statistics(outputStream* st,
561 const char* table_name) {
562 SizeFunc sz;
563 _local_table->statistics_to(Thread::current(), sz, st, table_name);
564 }
565
566 // Verification
567 class VerifySymbols : StackObj {
568 public:
569 bool operator()(Symbol** value) {
570 guarantee(value != NULL, "expected valid value");
571 guarantee(*value != NULL, "value should point to a symbol");
572 Symbol* sym = *value;
573 guarantee(sym->equals((char*)sym->bytes(), sym->utf8_length()),
574 "symbol must be internally consistent");
575 return true;
576 };
577 };
578
579 void SymbolTable::verify() {
580 Thread* thr = Thread::current();
581 VerifySymbols vs;
582 if (!SymbolTable::the_table()->_local_table->try_scan(thr, vs)) {
583 log_info(stringtable)("verify unavailable at this moment");
584 }
585 }
586
587 // Dumping
588 class DumpSymbol : StackObj {
589 Thread* _thr;
590 outputStream* _st;
591 public:
592 DumpSymbol(Thread* thr, outputStream* st) : _thr(thr), _st(st) {}
593 bool operator()(Symbol** value) {
608 SymbolTable::the_table()->print_table_statistics(st, "SymbolTable");
609 } else {
610 Thread* thr = Thread::current();
611 ResourceMark rm(thr);
612 st->print_cr("VERSION: 1.1");
613 DumpSymbol ds(thr, st);
614 if (!SymbolTable::the_table()->_local_table->try_scan(thr, ds)) {
615 log_info(symboltable)("dump unavailable at this moment");
616 }
617 }
618 }
619
620 #if INCLUDE_CDS
621 struct CopyToArchive : StackObj {
622 CompactSymbolTableWriter* _writer;
623 CopyToArchive(CompactSymbolTableWriter* writer) : _writer(writer) {}
624 bool operator()(Symbol** value) {
625 assert(value != NULL, "expected valid value");
626 assert(*value != NULL, "value should point to a symbol");
627 Symbol* sym = *value;
628 unsigned int fixed_hash = hash_shared_symbol((char*)sym->bytes(), sym->utf8_length());
629 if (fixed_hash == 0) {
630 return true;
631 }
632 assert(fixed_hash == hash_symbol((char*)sym->bytes(), sym->utf8_length(), false),
633 "must not rehash during dumping");
634
635 // add to the compact table
636 _writer->add(fixed_hash, sym);
637
638 return true;
639 }
640 };
641
642 void SymbolTable::copy_shared_symbol_table(CompactSymbolTableWriter* writer) {
643 CopyToArchive copy(writer);
644 SymbolTable::the_table()->_local_table->do_scan(Thread::current(), copy);
645 }
646
647 void SymbolTable::write_to_archive() {
648 _shared_table.reset();
649
650 int num_buckets = (SymbolTable::the_table()->_items / SharedSymbolTableBucketSize);
651 // calculation of num_buckets can result in zero buckets, we need at least one
652 CompactSymbolTableWriter writer(num_buckets > 1 ? num_buckets : 1,
653 &MetaspaceShared::stats()->symbol);
654 copy_shared_symbol_table(&writer);
655 writer.dump(&_shared_table);
656
657 // Verify table is correct
658 Symbol* sym = vmSymbols::java_lang_Object();
659 const char* name = (const char*)sym->bytes();
660 int len = sym->utf8_length();
661 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash);
662 assert(sym == _shared_table.lookup(name, hash, len), "sanity");
663 }
664
665 void SymbolTable::serialize(SerializeClosure* soc) {
666 _shared_table.set_type(CompactHashtable<Symbol*, char>::_symbol_table);
667 _shared_table.serialize(soc);
668
669 if (soc->writing()) {
670 // Sanity. Make sure we don't use the shared table at dump time
698 struct SymbolTableDoDelete : StackObj {
699 int _deleted;
700 SymbolTableDoDelete() : _deleted(0) {}
701 void operator()(Symbol** value) {
702 assert(value != NULL, "expected valid value");
703 assert(*value != NULL, "value should point to a symbol");
704 Symbol *sym = *value;
705 assert(sym->refcount() == 0, "refcount");
706 _deleted++;
707 }
708 };
709
710 struct SymbolTableDeleteCheck : StackObj {
711 int _processed;
712 SymbolTableDeleteCheck() : _processed(0) {}
713 bool operator()(Symbol** value) {
714 assert(value != NULL, "expected valid value");
715 assert(*value != NULL, "value should point to a symbol");
716 _processed++;
717 Symbol *sym = *value;
718 if (sym->refcount() == 0) {
719 return true;
720 } else {
721 return false;
722 }
723 }
724 };
725
726 void SymbolTable::clean_dead_entries(JavaThread* jt) {
727 SymbolTableHash::BulkDeleteTask bdt(_local_table);
728 if (!bdt.prepare(jt)) {
729 return;
730 }
731
732 SymbolTableDeleteCheck stdc;
733 SymbolTableDoDelete stdd;
734 {
735 TraceTime timer("Clean", TRACETIME_LOG(Debug, symboltable, perf));
736 while (bdt.do_task(jt, stdc, stdd)) {
737 bdt.pause(jt);
738 {
739 ThreadBlockInVM tbivm(jt);
740 }
741 bdt.cont(jt);
742 }
743 SymbolTable::the_table()->set_item_clean_count(0);
744 bdt.done(jt);
745 }
746
747 Atomic::add(stdc._processed, &_symbols_counted);
748
749 log_debug(symboltable)("Cleaned " INT32_FORMAT " of " INT32_FORMAT,
750 stdd._deleted, stdc._processed);
751 }
752
753 void SymbolTable::check_concurrent_work() {
754 if (_has_work) {
755 return;
756 }
757 double load_factor = SymbolTable::get_load_factor();
758 double dead_factor = SymbolTable::get_dead_factor();
759 // We should clean/resize if we have more dead than alive,
760 // more items than preferred load factor or
761 // more dead items than water mark.
762 if ((dead_factor > load_factor) ||
763 (load_factor > PREF_AVG_LIST_LEN) ||
764 (dead_factor > CLEAN_DEAD_HIGH_WATER_MARK)) {
765 log_debug(symboltable)("Concurrent work triggered, live factor:%f dead factor:%f",
766 load_factor, dead_factor);
767 trigger_concurrent_work();
861 if (do_rehash()) {
862 rehashed = true;
863 } else {
864 log_info(symboltable)("Resizes in progress rehashing skipped.");
865 }
866
867 _needs_rehashing = false;
868 }
869
870 void SymbolTable::rehash_table() {
871 SymbolTable::the_table()->try_rehash_table();
872 }
873
874 //---------------------------------------------------------------------------
875 // Non-product code
876
877 #ifndef PRODUCT
878
879 class HistogramIterator : StackObj {
880 public:
881 static const int results_length = 100;
882 int counts[results_length];
883 int sizes[results_length];
884 int total_size;
885 int total_count;
886 int total_length;
887 int max_length;
888 int out_of_range_count;
889 int out_of_range_size;
890 HistogramIterator() : total_size(0), total_count(0), total_length(0),
891 max_length(0), out_of_range_count(0), out_of_range_size(0) {
892 // initialize results to zero
893 for (int i = 0; i < results_length; i++) {
894 counts[i] = 0;
895 sizes[i] = 0;
896 }
897 }
898 bool operator()(Symbol** value) {
899 assert(value != NULL, "expected valid value");
900 assert(*value != NULL, "value should point to a symbol");
901 Symbol* sym = *value;
902 int size = sym->size();
903 int len = sym->utf8_length();
904 if (len < results_length) {
905 counts[len]++;
906 sizes[len] += size;
907 } else {
908 out_of_range_count++;
909 out_of_range_size += size;
910 }
911 total_count++;
912 total_size += size;
913 total_length += len;
914 max_length = MAX2(max_length, len);
915
916 return true;
917 };
918 };
919
920 void SymbolTable::print_histogram() {
921 HistogramIterator hi;
922 SymbolTable::the_table()->_local_table->do_scan(Thread::current(), hi);
923 tty->print_cr("Symbol Table Histogram:");
924 tty->print_cr(" Total number of symbols %7d", hi.total_count);
925 tty->print_cr(" Total size in memory %7dK",
926 (hi.total_size*wordSize)/1024);
927 tty->print_cr(" Total counted %7d", _symbols_counted);
928 tty->print_cr(" Total removed %7d", _symbols_removed);
929 if (_symbols_counted > 0) {
930 tty->print_cr(" Percent removed %3.2f",
931 ((float)_symbols_removed/(float)_symbols_counted)* 100);
932 }
933 tty->print_cr(" Reference counts %7d", Symbol::_total_count);
934 tty->print_cr(" Symbol arena used " SIZE_FORMAT_W(7) "K", arena()->used()/1024);
935 tty->print_cr(" Symbol arena size " SIZE_FORMAT_W(7) "K", arena()->size_in_bytes()/1024);
936 tty->print_cr(" Total symbol length %7d", hi.total_length);
937 tty->print_cr(" Maximum symbol length %7d", hi.max_length);
938 tty->print_cr(" Average symbol length %7.2f", ((float) hi.total_length / (float) hi.total_count));
939 tty->print_cr(" Symbol length histogram:");
940 tty->print_cr(" %6s %10s %10s", "Length", "#Symbols", "Size");
941 for (int i = 0; i < hi.results_length; i++) {
942 if (hi.counts[i] > 0) {
943 tty->print_cr(" %6d %10d %10dK", i, hi.counts[i], (hi.sizes[i]*wordSize)/1024);
944 }
945 }
946 tty->print_cr(" >=%6d %10d %10dK\n", hi.results_length,
947 hi.out_of_range_count, (hi.out_of_range_size*wordSize)/1024);
948 }
949 #endif // PRODUCT
950
951 // Utility for dumping symbols
952 SymboltableDCmd::SymboltableDCmd(outputStream* output, bool heap) :
953 DCmdWithParser(output, heap),
954 _verbose("-verbose", "Dump the content of each symbol in the table",
955 "BOOLEAN", false, "false") {
956 _dcmdparser.add_dcmd_option(&_verbose);
957 }
958
959 void SymboltableDCmd::execute(DCmdSource source, TRAPS) {
960 VM_DumpHashtable dumper(output(), VM_DumpHashtable::DumpSymbols,
961 _verbose.value());
962 VMThread::execute(&dumper);
963 }
964
965 int SymboltableDCmd::num_arguments() {
966 ResourceMark rm;
967 SymboltableDCmd* dcmd = new SymboltableDCmd(NULL, false);
|
41 // We used to not resize at all, so let's be conservative
42 // and not set it too short before we decide to resize,
43 // to match previous startup behavior
44 #define PREF_AVG_LIST_LEN 8
45 // 2^17 (131,072) is max size, which is about 6.5 times as large
46 // as the previous table size (used to be 20,011),
47 // which never resized
48 #define END_SIZE 17
49 // If a chain gets to 100 something might be wrong
50 #define REHASH_LEN 100
51 // We only get a chance to check whether we need
52 // to clean infrequently (on class unloading),
53 // so if we have even one dead entry then mark table for cleaning
54 #define CLEAN_DEAD_HIGH_WATER_MARK 0.0
55
56 #define ON_STACK_BUFFER_LENGTH 128
57
58 // --------------------------------------------------------------------------
59 SymbolTable* SymbolTable::_the_table = NULL;
60 CompactHashtable<Symbol*, char> SymbolTable::_shared_table;
61 volatile bool SymbolTable::_alt_hash = false;
62 volatile bool SymbolTable::_lookup_shared_first = false;
63 // Static arena for symbols that are not deallocated
64 Arena* SymbolTable::_arena = NULL;
65
66 static juint murmur_seed = 0;
67
68 static inline void _log_trace_symboltable_helper(Symbol* sym, const char* msg) {
69 #ifndef PRODUCT
70 if (log_is_enabled(Trace, symboltable)) {
71 if (sym->as_quoted_ascii() == NULL) {
72 log_trace(symboltable)("%s [%s]", msg, "NULL");
73 } else {
74 log_trace(symboltable)("%s [%s]", msg, sym->as_quoted_ascii());
75 }
76 }
77 #endif // PRODUCT
78 }
79
80 // Pick hashing algorithm.
81 static uintx hash_symbol(const char* s, int len, bool useAlt) {
82 return useAlt ?
83 AltHashing::murmur3_32(murmur_seed, (const jbyte*)s, len) :
84 java_lang_String::hash_code((const jbyte*)s, len);
85 }
86
87 static uintx hash_shared_symbol(const char* s, int len) {
88 return java_lang_String::hash_code((const jbyte*)s, len);
89 }
90
91 class SymbolTableConfig : public SymbolTableHash::BaseConfig {
92 private:
93 public:
94 static uintx get_hash(Symbol* const& value, bool* is_dead) {
95 *is_dead = (value->refcount() == 0);
96 if (*is_dead) {
97 return 0;
98 } else {
99 return hash_symbol((const char*)value->bytes(), value->utf8_length(), SymbolTable::_alt_hash);
100 }
101 }
102 // We use default allocation/deallocation but counted
103 static void* allocate_node(size_t size, Symbol* const& value) {
104 SymbolTable::item_added();
105 return SymbolTableHash::BaseConfig::allocate_node(size, value);
106 }
107 static void free_node(void* memory, Symbol* const& value) {
108 // We get here either because #1 some threads lost a race
109 // to insert a newly created Symbol, or #2 we are freeing
110 // a symbol during normal cleanup deletion.
111 // If #1, then the symbol can be a permanent (refcount==PERM_REFCOUNT),
112 // or regular newly created one but with refcount==0 (see SymbolTableCreateEntry)
113 // If #2, then the symbol must have refcount==0
114 assert((value->refcount() == PERM_REFCOUNT) || (value->refcount() == 0),
115 "refcount %d", value->refcount());
116 SymbolTable::delete_symbol(value);
117 SymbolTableHash::BaseConfig::free_node(memory, value);
118 SymbolTable::item_removed();
119 }
120 };
121
122 static size_t log2_ceil(uintx value) {
123 size_t ret;
124 for (ret = 1; ((size_t)1 << ret) < value; ++ret);
125 return ret;
126 }
127
128 SymbolTable::SymbolTable() : _local_table(NULL), _current_size(0), _has_work(0),
129 _needs_rehashing(false), _items_count(0), _uncleaned_items_count(0),
130 _symbols_removed(0), _symbols_counted(0) {
131
132 size_t start_size_log_2 = log2_ceil(SymbolTableSize);
133 _current_size = ((size_t)1) << start_size_log_2;
134 log_trace(symboltable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")",
135 _current_size, start_size_log_2);
136 _local_table = new SymbolTableHash(start_size_log_2, END_SIZE, REHASH_LEN);
137 }
138
139 void SymbolTable::delete_symbol(Symbol* sym) {
140 if (sym->refcount() == PERM_REFCOUNT) {
141 MutexLocker ml(SymbolTable_lock); // Protect arena
142 // Deleting permanent symbol should not occur very often (insert race condition),
143 // so log it.
144 _log_trace_symboltable_helper(sym, "Freeing permanent symbol");
145 if (!arena()->Afree(sym, sym->size())) {
146 _log_trace_symboltable_helper(sym, "Leaked permanent symbol");
147 }
148 } else {
149 delete sym;
150 }
151 }
152
153 void SymbolTable::item_added() {
154 Atomic::inc(&(SymbolTable::the_table()->_items_count));
155 }
156
157 void SymbolTable::set_item_clean_count(size_t ncl) {
158 Atomic::store(ncl, &(SymbolTable::the_table()->_uncleaned_items_count));
159 log_trace(symboltable)("Set uncleaned items:" SIZE_FORMAT, SymbolTable::the_table()->_uncleaned_items_count);
160 }
161
162 void SymbolTable::mark_item_clean_count() {
163 if (Atomic::cmpxchg((size_t)1, &(SymbolTable::the_table()->_uncleaned_items_count), (size_t)0) == 0) { // only mark if unset
164 log_trace(symboltable)("Marked uncleaned items:" SIZE_FORMAT, SymbolTable::the_table()->_uncleaned_items_count);
165 }
166 }
167
168 void SymbolTable::item_removed() {
169 Atomic::inc(&(SymbolTable::the_table()->_symbols_removed));
170 Atomic::dec(&(SymbolTable::the_table()->_items_count));
171 }
172
173 double SymbolTable::get_load_factor() {
174 return (double)_items_count/_current_size;
175 }
176
177 double SymbolTable::get_dead_factor() {
178 return (double)_uncleaned_items_count/_current_size;
179 }
180
181 size_t SymbolTable::table_size(Thread* thread) {
182 return ((size_t)(1)) << _local_table->get_size_log2(thread != NULL ? thread
183 : Thread::current());
184 }
185
186 void SymbolTable::trigger_concurrent_work() {
187 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
188 SymbolTable::the_table()->_has_work = true;
189 Service_lock->notify_all();
190 }
191
192 Symbol* SymbolTable::allocate_symbol(const char* name, int len, bool c_heap, TRAPS) {
193 assert (len <= Symbol::max_length(), "should be checked by caller");
194
195 Symbol* sym;
196 if (DumpSharedSpaces) {
197 c_heap = false;
198 }
199 if (c_heap) {
200 // refcount starts as 1
201 sym = new (len, THREAD) Symbol((const u1*)name, len, 1);
202 assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted");
203 } else {
204 // Allocate to global arena
205 MutexLocker ml(SymbolTable_lock); // Protect arena
206 sym = new (len, arena(), THREAD) Symbol((const u1*)name, len, PERM_REFCOUNT);
207 }
208 return sym;
209 }
210
211 void SymbolTable::initialize_symbols(int arena_alloc_size) {
212 // Initialize the arena for global symbols, size passed in depends on CDS.
213 if (arena_alloc_size == 0) {
214 _arena = new (mtSymbol) Arena(mtSymbol);
215 } else {
216 _arena = new (mtSymbol) Arena(mtSymbol, arena_alloc_size);
217 }
218 }
219
220 class SymbolsDo : StackObj {
221 SymbolClosure *_cl;
222 public:
223 SymbolsDo(SymbolClosure *cl) : _cl(cl) {}
224 bool operator()(Symbol** value) {
225 assert(value != NULL, "expected valid value");
226 assert(*value != NULL, "value should point to a symbol");
244 class MetaspacePointersDo : StackObj {
245 MetaspaceClosure *_it;
246 public:
247 MetaspacePointersDo(MetaspaceClosure *it) : _it(it) {}
248 bool operator()(Symbol** value) {
249 assert(value != NULL, "expected valid value");
250 assert(*value != NULL, "value should point to a symbol");
251 _it->push(value);
252 return true;
253 };
254 };
255
256 void SymbolTable::metaspace_pointers_do(MetaspaceClosure* it) {
257 assert(DumpSharedSpaces, "called only during dump time");
258 MetaspacePointersDo mpd(it);
259 SymbolTable::the_table()->_local_table->do_scan(Thread::current(), mpd);
260 }
261
262 Symbol* SymbolTable::lookup_dynamic(const char* name,
263 int len, unsigned int hash) {
264 Symbol* sym = SymbolTable::the_table()->do_lookup(name, len, hash);
265 assert((sym == NULL) || sym->refcount() != 0, "refcount must not be zero");
266 return sym;
267 }
268
269 Symbol* SymbolTable::lookup_shared(const char* name,
270 int len, unsigned int hash) {
271 if (!_shared_table.empty()) {
272 if (SymbolTable::_alt_hash) {
273 // hash_code parameter may use alternate hashing algorithm but the shared table
274 // always uses the same original hash code.
275 hash = hash_shared_symbol(name, len);
276 }
277 return _shared_table.lookup(name, hash, len);
278 } else {
279 return NULL;
280 }
281 }
282
283 Symbol* SymbolTable::lookup_common(const char* name,
284 int len, unsigned int hash) {
288 if (sym == NULL) {
289 _lookup_shared_first = false;
290 sym = lookup_dynamic(name, len, hash);
291 }
292 } else {
293 sym = lookup_dynamic(name, len, hash);
294 if (sym == NULL) {
295 sym = lookup_shared(name, len, hash);
296 if (sym != NULL) {
297 _lookup_shared_first = true;
298 }
299 }
300 }
301 return sym;
302 }
303
304 Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) {
305 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash);
306 Symbol* sym = SymbolTable::the_table()->lookup_common(name, len, hash);
307 if (sym == NULL) {
308 sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, true, CHECK_NULL);
309 }
310 assert(sym->refcount() != 0, "lookup should have incremented the count");
311 assert(sym->equals(name, len), "symbol must be properly initialized");
312 return sym;
313 }
314
315 Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) {
316 assert(sym->refcount() != 0, "require a valid symbol");
317 const char* name = (const char*)sym->base() + begin;
318 int len = end - begin;
319 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash);
320 Symbol* found = SymbolTable::the_table()->lookup_common(name, len, hash);
321 if (found == NULL) {
322 found = SymbolTable::the_table()->do_add_if_needed(name, len, hash, true, THREAD);
323 }
324 return found;
325 }
326
327 class SymbolTableLookup : StackObj {
328 private:
329 Thread* _thread;
330 uintx _hash;
331 int _len;
332 const char* _str;
333 public:
334 SymbolTableLookup(Thread* thread, const char* key, int len, uintx hash)
335 : _thread(thread), _hash(hash), _str(key), _len(len) {}
336 uintx get_hash() const {
337 return _hash;
338 }
339 bool equals(Symbol** value, bool* is_dead) {
340 assert(value != NULL, "expected valid value");
341 assert(*value != NULL, "value should point to a symbol");
342 Symbol *sym = *value;
343 if (sym->equals(_str, _len)) {
344 if (sym->try_increment_refcount()) {
345 // something is referencing this symbol now.
346 return true;
347 } else {
348 assert(sym->refcount() == 0, "expected dead symbol");
349 *is_dead = true;
350 return false;
351 }
352 } else {
353 *is_dead = (sym->refcount() == 0);
354 return false;
355 }
356 }
357 };
358
359 class SymbolTableGet : public StackObj {
360 Symbol* _return;
361 public:
362 SymbolTableGet() : _return(NULL) { }
363 void operator()(Symbol** value) {
364 assert(value != NULL, "expected valid value");
365 assert(*value != NULL, "value should point to a symbol");
366 _return = *value;
367 }
368 Symbol* get_res_sym() {
369 return _return;
370 }
371 };
372
373 Symbol* SymbolTable::do_lookup(const char* name, int len, uintx hash) {
374 Thread* thread = Thread::current();
375 SymbolTableLookup lookup(thread, name, len, hash);
376 SymbolTableGet stg;
377 bool rehash_warning = false;
378 _local_table->get(thread, lookup, stg, &rehash_warning);
379 if (rehash_warning) {
380 _needs_rehashing = true;
381 }
382 Symbol* sym = stg.get_res_sym();
383 assert((sym == NULL) || sym->refcount() != 0, "found dead symbol");
384 return sym;
385 }
386
387 Symbol* SymbolTable::lookup_only(const char* name, int len, unsigned int& hash) {
388 hash = hash_symbol(name, len, SymbolTable::_alt_hash);
389 return SymbolTable::the_table()->lookup_common(name, len, hash);
390 }
391
392 // Suggestion: Push unicode-based lookup all the way into the hashing
393 // and probing logic, so there is no need for convert_to_utf8 until
394 // an actual new Symbol* is created.
395 Symbol* SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) {
396 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length);
397 char stack_buf[ON_STACK_BUFFER_LENGTH];
410 Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length,
411 unsigned int& hash) {
412 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length);
413 char stack_buf[ON_STACK_BUFFER_LENGTH];
414 if (utf8_length < (int) sizeof(stack_buf)) {
415 char* chars = stack_buf;
416 UNICODE::convert_to_utf8(name, utf16_length, chars);
417 return lookup_only(chars, utf8_length, hash);
418 } else {
419 ResourceMark rm;
420 char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);
421 UNICODE::convert_to_utf8(name, utf16_length, chars);
422 return lookup_only(chars, utf8_length, hash);
423 }
424 }
425
426 void SymbolTable::add(ClassLoaderData* loader_data, const constantPoolHandle& cp,
427 int names_count, const char** names, int* lengths,
428 int* cp_indices, unsigned int* hashValues, TRAPS) {
429 bool c_heap = !loader_data->is_the_null_class_loader_data();
430 for (int i = 0; i < names_count; i++) {
431 const char *name = names[i];
432 int len = lengths[i];
433 unsigned int hash = hashValues[i];
434 Symbol* sym = SymbolTable::the_table()->lookup_common(name, len, hash);
435 if (sym == NULL) {
436 sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, c_heap, CHECK);
437 }
438 assert(sym->refcount() != 0, "lookup should have incremented the count");
439 cp->symbol_at_put(cp_indices[i], sym);
440 }
441 }
442
443 class SymbolTableCreateEntry : public StackObj {
444 private:
445 Thread* _thread;
446 const char* _name;
447 int _len;
448 bool _heap;
449 Symbol* _return;
450 Symbol* _created;
451
452 void assert_for_name(Symbol* sym, const char* where) const {
453 #ifdef ASSERT
454 assert(sym->utf8_length() == _len, "%s [%d,%d]", where, sym->utf8_length(), _len);
455 for (int i = 0; i < _len; i++) {
456 assert(sym->byte_at(i) == _name[i],
457 "%s [%d,%d,%d]", where, i, sym->byte_at(i), _name[i]);
458 }
459 #endif
460 }
461
462 public:
463 SymbolTableCreateEntry(Thread* thread, const char* name, int len, bool heap)
464 : _thread(thread), _name(name) , _len(len), _heap(heap), _return(NULL) , _created(NULL) {
465 assert(_name != NULL, "expected valid name");
466 }
467 Symbol* operator()() {
468 _created = SymbolTable::the_table()->allocate_symbol(_name, _len, _heap, _thread);
469 assert(_created != NULL, "expected created symbol");
470 assert_for_name(_created, "operator()()");
471 assert(_created->equals(_name, _len),
472 "symbol must be properly initialized [%p,%d,%d]", _name, _len, (int)_heap);
473 return _created;
474 }
475 void operator()(bool inserted, Symbol** value) {
476 assert(value != NULL, "expected valid value");
477 assert(*value != NULL, "value should point to a symbol");
478 if (!inserted && (_created != NULL)) {
479 // We created our symbol, but someone else inserted
480 // theirs first, so ours will be destroyed.
481 // Since symbols are created with refcount of 1,
482 // we must decrement it here to 0 to delete,
483 // unless it's a permanent one.
484 if (_created->refcount() != PERM_REFCOUNT) {
485 assert(_created->refcount() == 1, "expected newly created symbol");
486 _created->decrement_refcount();
487 assert(_created->refcount() == 0, "expected dead symbol");
488 }
489 }
490 _return = *value;
491 assert_for_name(_return, "operator()");
492 }
493 Symbol* get_new_sym() const {
494 assert_for_name(_return, "get_new_sym");
495 return _return;
496 }
497 };
498
499 Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, bool heap, TRAPS) {
500 SymbolTableLookup lookup(THREAD, name, len, hash);
501 SymbolTableCreateEntry stce(THREAD, name, len, heap);
502 bool rehash_warning = false;
503 bool clean_hint = false;
504 _local_table->get_insert_lazy(THREAD, lookup, stce, stce, &rehash_warning, &clean_hint);
505 if (rehash_warning) {
506 _needs_rehashing = true;
507 }
508 if (clean_hint) {
509 // we just found out that there is a dead item,
510 // which we were unable to clean right now,
511 // but we have no way of telling whether it's
512 // been previously counted or not, so mark
513 // it only if no other items were found yet
514 mark_item_clean_count();
515 check_concurrent_work();
516 }
517 Symbol* sym = stce.get_new_sym();
518 assert(sym->refcount() != 0, "zero is invalid");
519 return sym;
520 }
521
522 Symbol* SymbolTable::new_permanent_symbol(const char* name, TRAPS) {
523 unsigned int hash = 0;
524 int len = (int)strlen(name);
525 Symbol* sym = SymbolTable::lookup_only(name, len, hash);
526 if (sym == NULL) {
527 sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, false, CHECK_NULL);
528 }
529 if (sym->refcount() != PERM_REFCOUNT) {
530 sym->increment_refcount();
531 _log_trace_symboltable_helper(sym, "Asked for a permanent symbol, but got a regular one");
532 }
533 return sym;
534 }
535
536 struct SizeFunc : StackObj {
537 size_t operator()(Symbol** value) {
538 assert(value != NULL, "expected valid value");
539 assert(*value != NULL, "value should point to a symbol");
540 return (*value)->size() * HeapWordSize;
541 };
542 };
543
544 void SymbolTable::print_table_statistics(outputStream* st,
545 const char* table_name) {
546 SizeFunc sz;
547 _local_table->statistics_to(Thread::current(), sz, st, table_name);
548 }
549
550 // Verification
551 class VerifySymbols : StackObj {
552 public:
553 bool operator()(Symbol** value) {
554 guarantee(value != NULL, "expected valid value");
555 guarantee(*value != NULL, "value should point to a symbol");
556 Symbol* sym = *value;
557 guarantee(sym->equals((const char*)sym->bytes(), sym->utf8_length()),
558 "symbol must be internally consistent");
559 return true;
560 };
561 };
562
563 void SymbolTable::verify() {
564 Thread* thr = Thread::current();
565 VerifySymbols vs;
566 if (!SymbolTable::the_table()->_local_table->try_scan(thr, vs)) {
567 log_info(stringtable)("verify unavailable at this moment");
568 }
569 }
570
571 // Dumping
572 class DumpSymbol : StackObj {
573 Thread* _thr;
574 outputStream* _st;
575 public:
576 DumpSymbol(Thread* thr, outputStream* st) : _thr(thr), _st(st) {}
577 bool operator()(Symbol** value) {
592 SymbolTable::the_table()->print_table_statistics(st, "SymbolTable");
593 } else {
594 Thread* thr = Thread::current();
595 ResourceMark rm(thr);
596 st->print_cr("VERSION: 1.1");
597 DumpSymbol ds(thr, st);
598 if (!SymbolTable::the_table()->_local_table->try_scan(thr, ds)) {
599 log_info(symboltable)("dump unavailable at this moment");
600 }
601 }
602 }
603
604 #if INCLUDE_CDS
605 struct CopyToArchive : StackObj {
606 CompactSymbolTableWriter* _writer;
607 CopyToArchive(CompactSymbolTableWriter* writer) : _writer(writer) {}
608 bool operator()(Symbol** value) {
609 assert(value != NULL, "expected valid value");
610 assert(*value != NULL, "value should point to a symbol");
611 Symbol* sym = *value;
612 unsigned int fixed_hash = hash_shared_symbol((const char*)sym->bytes(), sym->utf8_length());
613 if (fixed_hash == 0) {
614 return true;
615 }
616 assert(fixed_hash == hash_symbol((const char*)sym->bytes(), sym->utf8_length(), false),
617 "must not rehash during dumping");
618
619 // add to the compact table
620 _writer->add(fixed_hash, sym);
621
622 return true;
623 }
624 };
625
626 void SymbolTable::copy_shared_symbol_table(CompactSymbolTableWriter* writer) {
627 CopyToArchive copy(writer);
628 SymbolTable::the_table()->_local_table->do_scan(Thread::current(), copy);
629 }
630
631 void SymbolTable::write_to_archive() {
632 _shared_table.reset();
633
634 int num_buckets = (SymbolTable::the_table()->_items_count / SharedSymbolTableBucketSize);
635 // calculation of num_buckets can result in zero buckets, we need at least one
636 CompactSymbolTableWriter writer(num_buckets > 1 ? num_buckets : 1,
637 &MetaspaceShared::stats()->symbol);
638 copy_shared_symbol_table(&writer);
639 writer.dump(&_shared_table);
640
641 // Verify table is correct
642 Symbol* sym = vmSymbols::java_lang_Object();
643 const char* name = (const char*)sym->bytes();
644 int len = sym->utf8_length();
645 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash);
646 assert(sym == _shared_table.lookup(name, hash, len), "sanity");
647 }
648
649 void SymbolTable::serialize(SerializeClosure* soc) {
650 _shared_table.set_type(CompactHashtable<Symbol*, char>::_symbol_table);
651 _shared_table.serialize(soc);
652
653 if (soc->writing()) {
654 // Sanity. Make sure we don't use the shared table at dump time
682 struct SymbolTableDoDelete : StackObj {
683 int _deleted;
684 SymbolTableDoDelete() : _deleted(0) {}
685 void operator()(Symbol** value) {
686 assert(value != NULL, "expected valid value");
687 assert(*value != NULL, "value should point to a symbol");
688 Symbol *sym = *value;
689 assert(sym->refcount() == 0, "refcount");
690 _deleted++;
691 }
692 };
693
694 struct SymbolTableDeleteCheck : StackObj {
695 int _processed;
696 SymbolTableDeleteCheck() : _processed(0) {}
697 bool operator()(Symbol** value) {
698 assert(value != NULL, "expected valid value");
699 assert(*value != NULL, "value should point to a symbol");
700 _processed++;
701 Symbol *sym = *value;
702 return (sym->refcount() == 0);
703 }
704 };
705
706 void SymbolTable::clean_dead_entries(JavaThread* jt) {
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 SymbolTable::the_table()->set_item_clean_count(0);
724 bdt.done(jt);
725 }
726
727 Atomic::add((size_t)stdc._processed, &_symbols_counted);
728
729 log_debug(symboltable)("Cleaned " INT32_FORMAT " of " INT32_FORMAT,
730 stdd._deleted, stdc._processed);
731 }
732
733 void SymbolTable::check_concurrent_work() {
734 if (_has_work) {
735 return;
736 }
737 double load_factor = SymbolTable::get_load_factor();
738 double dead_factor = SymbolTable::get_dead_factor();
739 // We should clean/resize if we have more dead than alive,
740 // more items than preferred load factor or
741 // more dead items than water mark.
742 if ((dead_factor > load_factor) ||
743 (load_factor > PREF_AVG_LIST_LEN) ||
744 (dead_factor > CLEAN_DEAD_HIGH_WATER_MARK)) {
745 log_debug(symboltable)("Concurrent work triggered, live factor:%f dead factor:%f",
746 load_factor, dead_factor);
747 trigger_concurrent_work();
841 if (do_rehash()) {
842 rehashed = true;
843 } else {
844 log_info(symboltable)("Resizes in progress rehashing skipped.");
845 }
846
847 _needs_rehashing = false;
848 }
849
850 void SymbolTable::rehash_table() {
851 SymbolTable::the_table()->try_rehash_table();
852 }
853
854 //---------------------------------------------------------------------------
855 // Non-product code
856
857 #ifndef PRODUCT
858
859 class HistogramIterator : StackObj {
860 public:
861 static const size_t results_length = 100;
862 size_t counts[results_length];
863 size_t sizes[results_length];
864 size_t total_size;
865 size_t total_count;
866 size_t total_length;
867 size_t max_length;
868 size_t out_of_range_count;
869 size_t out_of_range_size;
870 HistogramIterator() : total_size(0), total_count(0), total_length(0),
871 max_length(0), out_of_range_count(0), out_of_range_size(0) {
872 // initialize results to zero
873 for (size_t i = 0; i < results_length; i++) {
874 counts[i] = 0;
875 sizes[i] = 0;
876 }
877 }
878 bool operator()(Symbol** value) {
879 assert(value != NULL, "expected valid value");
880 assert(*value != NULL, "value should point to a symbol");
881 Symbol* sym = *value;
882 size_t size = sym->size();
883 size_t len = sym->utf8_length();
884 if (len < results_length) {
885 counts[len]++;
886 sizes[len] += size;
887 } else {
888 out_of_range_count++;
889 out_of_range_size += size;
890 }
891 total_count++;
892 total_size += size;
893 total_length += len;
894 max_length = MAX2(max_length, len);
895
896 return true;
897 };
898 };
899
900 void SymbolTable::print_histogram() {
901 SymbolTable* st = SymbolTable::the_table();
902 HistogramIterator hi;
903 st->_local_table->do_scan(Thread::current(), hi);
904 tty->print_cr("Symbol Table Histogram:");
905 tty->print_cr(" Total number of symbols " SIZE_FORMAT_W(7), hi.total_count);
906 tty->print_cr(" Total size in memory " SIZE_FORMAT_W(7) "K",
907 (hi.total_size * wordSize) / 1024);
908 tty->print_cr(" Total counted " SIZE_FORMAT_W(7), st->_symbols_counted);
909 tty->print_cr(" Total removed " SIZE_FORMAT_W(7), st->_symbols_removed);
910 if (SymbolTable::the_table()->_symbols_counted > 0) {
911 tty->print_cr(" Percent removed %3.2f",
912 ((float)st->_symbols_removed / st->_symbols_counted) * 100);
913 }
914 tty->print_cr(" Reference counts " SIZE_FORMAT_W(7), Symbol::_total_count);
915 tty->print_cr(" Symbol arena used " SIZE_FORMAT_W(7) "K", arena()->used() / 1024);
916 tty->print_cr(" Symbol arena size " SIZE_FORMAT_W(7) "K", arena()->size_in_bytes() / 1024);
917 tty->print_cr(" Total symbol length " SIZE_FORMAT_W(7), hi.total_length);
918 tty->print_cr(" Maximum symbol length " SIZE_FORMAT_W(7), hi.max_length);
919 tty->print_cr(" Average symbol length %7.2f", ((float)hi.total_length / hi.total_count));
920 tty->print_cr(" Symbol length histogram:");
921 tty->print_cr(" %6s %10s %10s", "Length", "#Symbols", "Size");
922 for (size_t i = 0; i < hi.results_length; i++) {
923 if (hi.counts[i] > 0) {
924 tty->print_cr(" " SIZE_FORMAT_W(6) " " SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10) "K",
925 i, hi.counts[i], (hi.sizes[i] * wordSize) / 1024);
926 }
927 }
928 tty->print_cr(" >=" SIZE_FORMAT_W(6) " " SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10) "K\n",
929 hi.results_length, hi.out_of_range_count, (hi.out_of_range_size*wordSize) / 1024);
930 }
931 #endif // PRODUCT
932
933 // Utility for dumping symbols
934 SymboltableDCmd::SymboltableDCmd(outputStream* output, bool heap) :
935 DCmdWithParser(output, heap),
936 _verbose("-verbose", "Dump the content of each symbol in the table",
937 "BOOLEAN", false, "false") {
938 _dcmdparser.add_dcmd_option(&_verbose);
939 }
940
941 void SymboltableDCmd::execute(DCmdSource source, TRAPS) {
942 VM_DumpHashtable dumper(output(), VM_DumpHashtable::DumpSymbols,
943 _verbose.value());
944 VMThread::execute(&dumper);
945 }
946
947 int SymboltableDCmd::num_arguments() {
948 ResourceMark rm;
949 SymboltableDCmd* dcmd = new SymboltableDCmd(NULL, false);
|