Mercurial > hg > graal-jvmci-8
comparison src/share/vm/classfile/symbolTable.cpp @ 18041:52b4284cb496
Merge with jdk8u20-b26
author | Gilles Duboscq <duboscq@ssw.jku.at> |
---|---|
date | Wed, 15 Oct 2014 16:02:50 +0200 |
parents | 4ca6dc0799b6 78bbf4d43a14 |
children | 7848fc12602b |
comparison
equal
deleted
inserted
replaced
17606:45d7b2c7029d | 18041:52b4284cb496 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
33 #include "memory/gcLocker.inline.hpp" | 33 #include "memory/gcLocker.inline.hpp" |
34 #include "oops/oop.inline.hpp" | 34 #include "oops/oop.inline.hpp" |
35 #include "oops/oop.inline2.hpp" | 35 #include "oops/oop.inline2.hpp" |
36 #include "runtime/mutexLocker.hpp" | 36 #include "runtime/mutexLocker.hpp" |
37 #include "utilities/hashtable.inline.hpp" | 37 #include "utilities/hashtable.inline.hpp" |
38 #if INCLUDE_ALL_GCS | |
39 #include "gc_implementation/g1/g1StringDedup.hpp" | |
40 #endif | |
41 | |
42 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC | |
38 | 43 |
39 // -------------------------------------------------------------------------- | 44 // -------------------------------------------------------------------------- |
45 | |
46 // the number of buckets a thread claims | |
47 const int ClaimChunkSize = 32; | |
40 | 48 |
41 SymbolTable* SymbolTable::_the_table = NULL; | 49 SymbolTable* SymbolTable::_the_table = NULL; |
42 // Static arena for symbols that are not deallocated | 50 // Static arena for symbols that are not deallocated |
43 Arena* SymbolTable::_arena = NULL; | 51 Arena* SymbolTable::_arena = NULL; |
44 bool SymbolTable::_needs_rehashing = false; | 52 bool SymbolTable::_needs_rehashing = false; |
81 cl->do_symbol(p->literal_addr()); | 89 cl->do_symbol(p->literal_addr()); |
82 } | 90 } |
83 } | 91 } |
84 } | 92 } |
85 | 93 |
86 int SymbolTable::symbols_removed = 0; | 94 int SymbolTable::_symbols_removed = 0; |
87 int SymbolTable::symbols_counted = 0; | 95 int SymbolTable::_symbols_counted = 0; |
88 | 96 volatile int SymbolTable::_parallel_claimed_idx = 0; |
89 // Remove unreferenced symbols from the symbol table | 97 |
90 // This is done late during GC. | 98 void SymbolTable::buckets_unlink(int start_idx, int end_idx, int* processed, int* removed, size_t* memory_total) { |
91 void SymbolTable::unlink() { | 99 for (int i = start_idx; i < end_idx; ++i) { |
92 int removed = 0; | |
93 int total = 0; | |
94 size_t memory_total = 0; | |
95 for (int i = 0; i < the_table()->table_size(); ++i) { | |
96 HashtableEntry<Symbol*, mtSymbol>** p = the_table()->bucket_addr(i); | 100 HashtableEntry<Symbol*, mtSymbol>** p = the_table()->bucket_addr(i); |
97 HashtableEntry<Symbol*, mtSymbol>* entry = the_table()->bucket(i); | 101 HashtableEntry<Symbol*, mtSymbol>* entry = the_table()->bucket(i); |
98 while (entry != NULL) { | 102 while (entry != NULL) { |
99 // Shared entries are normally at the end of the bucket and if we run into | 103 // Shared entries are normally at the end of the bucket and if we run into |
100 // a shared entry, then there is nothing more to remove. However, if we | 104 // a shared entry, then there is nothing more to remove. However, if we |
102 // end of the bucket. | 106 // end of the bucket. |
103 if (entry->is_shared() && !use_alternate_hashcode()) { | 107 if (entry->is_shared() && !use_alternate_hashcode()) { |
104 break; | 108 break; |
105 } | 109 } |
106 Symbol* s = entry->literal(); | 110 Symbol* s = entry->literal(); |
107 memory_total += s->size(); | 111 (*memory_total) += s->size(); |
108 total++; | 112 (*processed)++; |
109 assert(s != NULL, "just checking"); | 113 assert(s != NULL, "just checking"); |
110 // If reference count is zero, remove. | 114 // If reference count is zero, remove. |
111 if (s->refcount() == 0) { | 115 if (s->refcount() == 0) { |
112 assert(!entry->is_shared(), "shared entries should be kept live"); | 116 assert(!entry->is_shared(), "shared entries should be kept live"); |
113 delete s; | 117 delete s; |
114 removed++; | 118 (*removed)++; |
115 *p = entry->next(); | 119 *p = entry->next(); |
116 the_table()->free_entry(entry); | 120 the_table()->free_entry(entry); |
117 } else { | 121 } else { |
118 p = entry->next_addr(); | 122 p = entry->next_addr(); |
119 } | 123 } |
120 // get next entry | 124 // get next entry |
121 entry = (HashtableEntry<Symbol*, mtSymbol>*)HashtableEntry<Symbol*, mtSymbol>::make_ptr(*p); | 125 entry = (HashtableEntry<Symbol*, mtSymbol>*)HashtableEntry<Symbol*, mtSymbol>::make_ptr(*p); |
122 } | 126 } |
123 } | 127 } |
124 symbols_removed += removed; | 128 } |
125 symbols_counted += total; | 129 |
130 // Remove unreferenced symbols from the symbol table | |
131 // This is done late during GC. | |
132 void SymbolTable::unlink(int* processed, int* removed) { | |
133 size_t memory_total = 0; | |
134 buckets_unlink(0, the_table()->table_size(), processed, removed, &memory_total); | |
135 _symbols_removed += *removed; | |
136 _symbols_counted += *processed; | |
126 // Exclude printing for normal PrintGCDetails because people parse | 137 // Exclude printing for normal PrintGCDetails because people parse |
127 // this output. | 138 // this output. |
128 if (PrintGCDetails && Verbose && WizardMode) { | 139 if (PrintGCDetails && Verbose && WizardMode) { |
129 gclog_or_tty->print(" [Symbols=%d size=" SIZE_FORMAT "K] ", total, | 140 gclog_or_tty->print(" [Symbols=%d size=" SIZE_FORMAT "K] ", *processed, |
141 (memory_total*HeapWordSize)/1024); | |
142 } | |
143 } | |
144 | |
145 void SymbolTable::possibly_parallel_unlink(int* processed, int* removed) { | |
146 const int limit = the_table()->table_size(); | |
147 | |
148 size_t memory_total = 0; | |
149 | |
150 for (;;) { | |
151 // Grab next set of buckets to scan | |
152 int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize; | |
153 if (start_idx >= limit) { | |
154 // End of table | |
155 break; | |
156 } | |
157 | |
158 int end_idx = MIN2(limit, start_idx + ClaimChunkSize); | |
159 buckets_unlink(start_idx, end_idx, processed, removed, &memory_total); | |
160 } | |
161 Atomic::add(*processed, &_symbols_counted); | |
162 Atomic::add(*removed, &_symbols_removed); | |
163 // Exclude printing for normal PrintGCDetails because people parse | |
164 // this output. | |
165 if (PrintGCDetails && Verbose && WizardMode) { | |
166 gclog_or_tty->print(" [Symbols: scanned=%d removed=%d size=" SIZE_FORMAT "K] ", *processed, *removed, | |
130 (memory_total*HeapWordSize)/1024); | 167 (memory_total*HeapWordSize)/1024); |
131 } | 168 } |
132 } | 169 } |
133 | 170 |
134 // Create a new table and using alternate hash code, populate the new table | 171 // Create a new table and using alternate hash code, populate the new table |
492 } | 529 } |
493 tty->print_cr("Symbol Table:"); | 530 tty->print_cr("Symbol Table:"); |
494 tty->print_cr("Total number of symbols %5d", count); | 531 tty->print_cr("Total number of symbols %5d", count); |
495 tty->print_cr("Total size in memory %5dK", | 532 tty->print_cr("Total size in memory %5dK", |
496 (memory_total*HeapWordSize)/1024); | 533 (memory_total*HeapWordSize)/1024); |
497 tty->print_cr("Total counted %5d", symbols_counted); | 534 tty->print_cr("Total counted %5d", _symbols_counted); |
498 tty->print_cr("Total removed %5d", symbols_removed); | 535 tty->print_cr("Total removed %5d", _symbols_removed); |
499 if (symbols_counted > 0) { | 536 if (_symbols_counted > 0) { |
500 tty->print_cr("Percent removed %3.2f", | 537 tty->print_cr("Percent removed %3.2f", |
501 ((float)symbols_removed/(float)symbols_counted)* 100); | 538 ((float)_symbols_removed/(float)_symbols_counted)* 100); |
502 } | 539 } |
503 tty->print_cr("Reference counts %5d", Symbol::_total_count); | 540 tty->print_cr("Reference counts %5d", Symbol::_total_count); |
504 tty->print_cr("Symbol arena size %5d used %5d", | 541 tty->print_cr("Symbol arena size %5d used %5d", |
505 arena()->size_in_bytes(), arena()->used()); | 542 arena()->size_in_bytes(), arena()->used()); |
506 tty->print_cr("Histogram of symbol length:"); | 543 tty->print_cr("Histogram of symbol length:"); |
694 string = string_or_null; | 731 string = string_or_null; |
695 } else { | 732 } else { |
696 string = java_lang_String::create_from_unicode(name, len, CHECK_NULL); | 733 string = java_lang_String::create_from_unicode(name, len, CHECK_NULL); |
697 } | 734 } |
698 | 735 |
736 #if INCLUDE_ALL_GCS | |
737 if (G1StringDedup::is_enabled()) { | |
738 // Deduplicate the string before it is interned. Note that we should never | |
739 // deduplicate a string after it has been interned. Doing so will counteract | |
740 // compiler optimizations done on e.g. interned string literals. | |
741 G1StringDedup::deduplicate(string()); | |
742 } | |
743 #endif | |
744 | |
699 // Grab the StringTable_lock before getting the_table() because it could | 745 // Grab the StringTable_lock before getting the_table() because it could |
700 // change at safepoint. | 746 // change at safepoint. |
701 MutexLocker ml(StringTable_lock, THREAD); | 747 MutexLocker ml(StringTable_lock, THREAD); |
702 | 748 |
703 // Otherwise, add to symbol to table | 749 // Otherwise, add to symbol to table |
737 Handle string; | 783 Handle string; |
738 oop result = intern(string, chars, length, CHECK_NULL); | 784 oop result = intern(string, chars, length, CHECK_NULL); |
739 return result; | 785 return result; |
740 } | 786 } |
741 | 787 |
742 void StringTable::unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f) { | 788 void StringTable::unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int* processed, int* removed) { |
789 buckets_unlink_or_oops_do(is_alive, f, 0, the_table()->table_size(), processed, removed); | |
790 } | |
791 | |
792 void StringTable::possibly_parallel_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int* processed, int* removed) { | |
743 // Readers of the table are unlocked, so we should only be removing | 793 // Readers of the table are unlocked, so we should only be removing |
744 // entries at a safepoint. | 794 // entries at a safepoint. |
745 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); | 795 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); |
746 for (int i = 0; i < the_table()->table_size(); ++i) { | 796 const int limit = the_table()->table_size(); |
797 | |
798 for (;;) { | |
799 // Grab next set of buckets to scan | |
800 int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize; | |
801 if (start_idx >= limit) { | |
802 // End of table | |
803 break; | |
804 } | |
805 | |
806 int end_idx = MIN2(limit, start_idx + ClaimChunkSize); | |
807 buckets_unlink_or_oops_do(is_alive, f, start_idx, end_idx, processed, removed); | |
808 } | |
809 } | |
810 | |
811 void StringTable::buckets_oops_do(OopClosure* f, int start_idx, int end_idx) { | |
812 const int limit = the_table()->table_size(); | |
813 | |
814 assert(0 <= start_idx && start_idx <= limit, | |
815 err_msg("start_idx (" INT32_FORMAT ") is out of bounds", start_idx)); | |
816 assert(0 <= end_idx && end_idx <= limit, | |
817 err_msg("end_idx (" INT32_FORMAT ") is out of bounds", end_idx)); | |
818 assert(start_idx <= end_idx, | |
819 err_msg("Index ordering: start_idx=" INT32_FORMAT", end_idx=" INT32_FORMAT, | |
820 start_idx, end_idx)); | |
821 | |
822 for (int i = start_idx; i < end_idx; i += 1) { | |
823 HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i); | |
824 while (entry != NULL) { | |
825 assert(!entry->is_shared(), "CDS not used for the StringTable"); | |
826 | |
827 f->do_oop((oop*)entry->literal_addr()); | |
828 | |
829 entry = entry->next(); | |
830 } | |
831 } | |
832 } | |
833 | |
834 void StringTable::buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, int* processed, int* removed) { | |
835 const int limit = the_table()->table_size(); | |
836 | |
837 assert(0 <= start_idx && start_idx <= limit, | |
838 err_msg("start_idx (" INT32_FORMAT ") is out of bounds", start_idx)); | |
839 assert(0 <= end_idx && end_idx <= limit, | |
840 err_msg("end_idx (" INT32_FORMAT ") is out of bounds", end_idx)); | |
841 assert(start_idx <= end_idx, | |
842 err_msg("Index ordering: start_idx=" INT32_FORMAT", end_idx=" INT32_FORMAT, | |
843 start_idx, end_idx)); | |
844 | |
845 for (int i = start_idx; i < end_idx; ++i) { | |
747 HashtableEntry<oop, mtSymbol>** p = the_table()->bucket_addr(i); | 846 HashtableEntry<oop, mtSymbol>** p = the_table()->bucket_addr(i); |
748 HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i); | 847 HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i); |
749 while (entry != NULL) { | 848 while (entry != NULL) { |
750 assert(!entry->is_shared(), "CDS not used for the StringTable"); | 849 assert(!entry->is_shared(), "CDS not used for the StringTable"); |
751 | 850 |
755 } | 854 } |
756 p = entry->next_addr(); | 855 p = entry->next_addr(); |
757 } else { | 856 } else { |
758 *p = entry->next(); | 857 *p = entry->next(); |
759 the_table()->free_entry(entry); | 858 the_table()->free_entry(entry); |
760 } | 859 (*removed)++; |
860 } | |
861 (*processed)++; | |
761 entry = *p; | 862 entry = *p; |
762 } | 863 } |
763 } | 864 } |
764 } | 865 } |
765 | 866 |
766 void StringTable::buckets_do(OopClosure* f, int start_idx, int end_idx) { | |
767 const int limit = the_table()->table_size(); | |
768 | |
769 assert(0 <= start_idx && start_idx <= limit, | |
770 err_msg("start_idx (" INT32_FORMAT ") oob?", start_idx)); | |
771 assert(0 <= end_idx && end_idx <= limit, | |
772 err_msg("end_idx (" INT32_FORMAT ") oob?", end_idx)); | |
773 assert(start_idx <= end_idx, | |
774 err_msg("Ordering: start_idx=" INT32_FORMAT", end_idx=" INT32_FORMAT, | |
775 start_idx, end_idx)); | |
776 | |
777 for (int i = start_idx; i < end_idx; i += 1) { | |
778 HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i); | |
779 while (entry != NULL) { | |
780 assert(!entry->is_shared(), "CDS not used for the StringTable"); | |
781 | |
782 f->do_oop((oop*)entry->literal_addr()); | |
783 | |
784 entry = entry->next(); | |
785 } | |
786 } | |
787 } | |
788 | |
789 void StringTable::oops_do(OopClosure* f) { | 867 void StringTable::oops_do(OopClosure* f) { |
790 buckets_do(f, 0, the_table()->table_size()); | 868 buckets_oops_do(f, 0, the_table()->table_size()); |
791 } | 869 } |
792 | 870 |
793 void StringTable::possibly_parallel_oops_do(OopClosure* f) { | 871 void StringTable::possibly_parallel_oops_do(OopClosure* f) { |
794 const int ClaimChunkSize = 32; | |
795 const int limit = the_table()->table_size(); | 872 const int limit = the_table()->table_size(); |
796 | 873 |
797 for (;;) { | 874 for (;;) { |
798 // Grab next set of buckets to scan | 875 // Grab next set of buckets to scan |
799 int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize; | 876 int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize; |
801 // End of table | 878 // End of table |
802 break; | 879 break; |
803 } | 880 } |
804 | 881 |
805 int end_idx = MIN2(limit, start_idx + ClaimChunkSize); | 882 int end_idx = MIN2(limit, start_idx + ClaimChunkSize); |
806 buckets_do(f, start_idx, end_idx); | 883 buckets_oops_do(f, start_idx, end_idx); |
807 } | 884 } |
808 } | 885 } |
809 | 886 |
810 // This verification is part of Universe::verify() and needs to be quick. | 887 // This verification is part of Universe::verify() and needs to be quick. |
811 // See StringTable::verify_and_compare() below for exhaustive verification. | 888 // See StringTable::verify_and_compare() below for exhaustive verification. |