95 bool operator == (Symbol* o) const { return _temp == o; } |
83 bool operator == (Symbol* o) const { return _temp == o; } |
96 operator Symbol*() { return _temp; } |
84 operator Symbol*() { return _temp; } |
97 }; |
85 }; |
98 |
86 |
99 template <class T, class N> class CompactHashtable; |
87 template <class T, class N> class CompactHashtable; |
100 |
88 class CompactSymbolTableWriter; |
101 class SymbolTable : public RehashableHashtable<Symbol*, mtSymbol> { |
89 class SerializeClosure; |
|
90 |
|
91 class SymbolTableConfig; |
|
92 typedef ConcurrentHashTable<Symbol*, |
|
93 SymbolTableConfig, mtSymbol> SymbolTableHash; |
|
94 |
|
95 class SymbolTableCreateEntry; |
|
96 |
|
97 class SymbolTable : public CHeapObj<mtSymbol> { |
102 friend class VMStructs; |
98 friend class VMStructs; |
|
99 friend class Symbol; |
103 friend class ClassFileParser; |
100 friend class ClassFileParser; |
|
101 friend class SymbolTableConfig; |
|
102 friend class SymbolTableCreateEntry; |
104 |
103 |
105 private: |
104 private: |
|
105 static void delete_symbol(Symbol* sym); |
|
106 void grow(JavaThread* jt); |
|
107 void clean_dead_entries(JavaThread* jt); |
|
108 |
106 // The symbol table |
109 // The symbol table |
107 static SymbolTable* _the_table; |
110 static SymbolTable* _the_table; |
108 |
111 // Shared symbol table. |
|
112 static CompactHashtable<Symbol*, char> _shared_table; |
|
113 static volatile bool _lookup_shared_first; |
|
114 static volatile bool _alt_hash; |
|
115 |
|
116 // For statistics |
|
117 volatile size_t _symbols_removed; |
|
118 volatile size_t _symbols_counted; |
|
119 |
|
120 SymbolTableHash* _local_table; |
|
121 size_t _current_size; |
|
122 volatile bool _has_work; |
109 // Set if one bucket is out of balance due to hash algorithm deficiency |
123 // Set if one bucket is out of balance due to hash algorithm deficiency |
110 static bool _needs_rehashing; |
124 volatile bool _needs_rehashing; |
111 static bool _lookup_shared_first; |
125 |
112 |
126 volatile size_t _items_count; |
113 // For statistics |
127 volatile size_t _uncleaned_items_count; |
114 static int _symbols_removed; |
128 |
115 static int _symbols_counted; |
129 double get_load_factor(); |
116 |
130 double get_dead_factor(); |
117 // shared symbol table. |
131 |
118 static CompactHashtable<Symbol*, char> _shared_table; |
132 void check_concurrent_work(); |
119 |
133 void trigger_concurrent_work(); |
120 Symbol* allocate_symbol(const u1* name, int len, bool c_heap, TRAPS); // Assumes no characters larger than 0x7F |
134 |
|
135 static void item_added(); |
|
136 static void item_removed(); |
|
137 static void set_item_clean_count(size_t ncl); |
|
138 static void mark_item_clean_count(); |
|
139 |
|
140 SymbolTable(); |
|
141 |
|
142 Symbol* allocate_symbol(const char* name, int len, bool c_heap, TRAPS); // Assumes no characters larger than 0x7F |
|
143 Symbol* do_lookup(const char* name, int len, uintx hash); |
|
144 Symbol* do_add_if_needed(const char* name, int len, uintx hash, bool heap, TRAPS); |
121 |
145 |
122 // Adding elements |
146 // Adding elements |
123 Symbol* basic_add(int index, u1* name, int len, unsigned int hashValue, |
147 static void add(ClassLoaderData* loader_data, |
124 bool c_heap, TRAPS); |
148 const constantPoolHandle& cp, int names_count, |
125 bool basic_add(ClassLoaderData* loader_data, |
149 const char** names, int* lengths, int* cp_indices, |
126 const constantPoolHandle& cp, int names_count, |
150 unsigned int* hashValues, TRAPS); |
127 const char** names, int* lengths, int* cp_indices, |
|
128 unsigned int* hashValues, TRAPS); |
|
129 |
151 |
130 static void new_symbols(ClassLoaderData* loader_data, |
152 static void new_symbols(ClassLoaderData* loader_data, |
131 const constantPoolHandle& cp, int names_count, |
153 const constantPoolHandle& cp, int names_count, |
132 const char** name, int* lengths, |
154 const char** name, int* lengths, |
133 int* cp_indices, unsigned int* hashValues, |
155 int* cp_indices, unsigned int* hashValues, |
134 TRAPS) { |
156 TRAPS) { |
135 add(loader_data, cp, names_count, name, lengths, cp_indices, hashValues, THREAD); |
157 add(loader_data, cp, names_count, name, lengths, cp_indices, hashValues, THREAD); |
136 } |
158 } |
137 |
159 |
138 static Symbol* lookup_shared(const char* name, int len, unsigned int hash); |
160 static Symbol* lookup_shared(const char* name, int len, unsigned int hash); |
139 Symbol* lookup_dynamic(int index, const char* name, int len, unsigned int hash); |
161 Symbol* lookup_dynamic(const char* name, int len, unsigned int hash); |
140 Symbol* lookup(int index, const char* name, int len, unsigned int hash); |
162 Symbol* lookup_common(const char* name, int len, unsigned int hash); |
141 |
|
142 SymbolTable() |
|
143 : RehashableHashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>)) {} |
|
144 |
|
145 SymbolTable(HashtableBucket<mtSymbol>* t, int number_of_entries) |
|
146 : RehashableHashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>), t, |
|
147 number_of_entries) {} |
|
148 |
163 |
149 // Arena for permanent symbols (null class loader) that are never unloaded |
164 // Arena for permanent symbols (null class loader) that are never unloaded |
150 static Arena* _arena; |
165 static Arena* _arena; |
151 static Arena* arena() { return _arena; } // called for statistics |
166 static Arena* arena() { return _arena; } // called for statistics |
152 |
167 |
153 static void initialize_symbols(int arena_alloc_size = 0); |
168 static void initialize_symbols(int arena_alloc_size = 0); |
154 |
169 |
155 static volatile int _parallel_claimed_idx; |
170 void concurrent_work(JavaThread* jt); |
156 |
171 void print_table_statistics(outputStream* st, const char* table_name); |
157 typedef SymbolTable::BucketUnlinkContext BucketUnlinkContext; |
172 |
158 // Release any dead symbols. Unlinked bucket entries are collected in the given |
173 void try_rehash_table(); |
159 // context to be freed later. |
174 bool do_rehash(); |
160 // This allows multiple threads to work on the table at once. |
175 |
161 static void buckets_unlink(int start_idx, int end_idx, BucketUnlinkContext* context); |
|
162 public: |
176 public: |
|
177 // The symbol table |
|
178 static SymbolTable* the_table() { return _the_table; } |
|
179 size_t table_size(); |
|
180 |
163 enum { |
181 enum { |
164 symbol_alloc_batch_size = 8, |
182 symbol_alloc_batch_size = 8, |
165 // Pick initial size based on java -version size measurements |
183 // Pick initial size based on java -version size measurements |
166 symbol_alloc_arena_size = 360*K |
184 symbol_alloc_arena_size = 360*K // TODO (revisit) |
167 }; |
185 }; |
168 |
|
169 // The symbol table |
|
170 static SymbolTable* the_table() { return _the_table; } |
|
171 |
|
172 // Size of one bucket in the string table. Used when checking for rollover. |
|
173 static uint bucket_size() { return sizeof(HashtableBucket<mtSymbol>); } |
|
174 |
186 |
175 static void create_table() { |
187 static void create_table() { |
176 assert(_the_table == NULL, "One symbol table allowed."); |
188 assert(_the_table == NULL, "One symbol table allowed."); |
177 _the_table = new SymbolTable(); |
189 _the_table = new SymbolTable(); |
178 initialize_symbols(symbol_alloc_arena_size); |
190 initialize_symbols(symbol_alloc_arena_size); |
179 } |
191 } |
180 |
192 |
181 static unsigned int hash_symbol(const char* s, int len); |
193 static void unlink() { |
182 static unsigned int hash_shared_symbol(const char* s, int len); |
194 do_check_concurrent_work(); |
183 |
195 } |
|
196 static void do_check_concurrent_work(); |
|
197 static void do_concurrent_work(JavaThread* jt); |
|
198 static bool has_work() { return the_table()->_has_work; } |
|
199 |
|
200 // Probing |
184 static Symbol* lookup(const char* name, int len, TRAPS); |
201 static Symbol* lookup(const char* name, int len, TRAPS); |
185 // lookup only, won't add. Also calculate hash. |
202 // lookup only, won't add. Also calculate hash. |
186 static Symbol* lookup_only(const char* name, int len, unsigned int& hash); |
203 static Symbol* lookup_only(const char* name, int len, unsigned int& hash); |
187 // Only copy to C string to be added if lookup failed. |
204 // adds new symbol if not found |
188 static Symbol* lookup(const Symbol* sym, int begin, int end, TRAPS); |
205 static Symbol* lookup(const Symbol* sym, int begin, int end, TRAPS); |
189 |
|
190 static void release(Symbol* sym); |
|
191 |
|
192 // Look up the address of the literal in the SymbolTable for this Symbol* |
|
193 static Symbol** lookup_symbol_addr(Symbol* sym); |
|
194 |
|
195 // jchar (UTF16) version of lookups |
206 // jchar (UTF16) version of lookups |
196 static Symbol* lookup_unicode(const jchar* name, int len, TRAPS); |
207 static Symbol* lookup_unicode(const jchar* name, int len, TRAPS); |
197 static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash); |
208 static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash); |
198 |
|
199 static void add(ClassLoaderData* loader_data, |
|
200 const constantPoolHandle& cp, int names_count, |
|
201 const char** names, int* lengths, int* cp_indices, |
|
202 unsigned int* hashValues, TRAPS); |
|
203 |
|
204 // Release any dead symbols |
|
205 static void unlink() { |
|
206 int processed = 0; |
|
207 int removed = 0; |
|
208 unlink(&processed, &removed); |
|
209 } |
|
210 static void unlink(int* processed, int* removed); |
|
211 // Release any dead symbols, possibly parallel version |
|
212 static void possibly_parallel_unlink(int* processed, int* removed); |
|
213 |
|
214 // iterate over symbols |
|
215 static void symbols_do(SymbolClosure *cl); |
|
216 static void metaspace_pointers_do(MetaspaceClosure* it); |
|
217 |
|
218 // Symbol creation |
|
219 static Symbol* new_symbol(const char* utf8_buffer, int length, TRAPS) { |
|
220 assert(utf8_buffer != NULL, "just checking"); |
|
221 return lookup(utf8_buffer, length, THREAD); |
|
222 } |
|
223 static Symbol* new_symbol(const char* name, TRAPS) { |
|
224 return new_symbol(name, (int)strlen(name), THREAD); |
|
225 } |
|
226 static Symbol* new_symbol(const Symbol* sym, int begin, int end, TRAPS) { |
|
227 assert(begin <= end && end <= sym->utf8_length(), "just checking"); |
|
228 return lookup(sym, begin, end, THREAD); |
|
229 } |
|
230 |
|
231 // Create a symbol in the arena for symbols that are not deleted |
|
232 static Symbol* new_permanent_symbol(const char* name, TRAPS); |
|
233 |
|
234 // Symbol lookup |
|
235 static Symbol* lookup(int index, const char* name, int len, TRAPS); |
|
236 |
|
237 // Needed for preloading classes in signatures when compiling. |
209 // Needed for preloading classes in signatures when compiling. |
238 // Returns the symbol is already present in symbol table, otherwise |
210 // Returns the symbol is already present in symbol table, otherwise |
239 // NULL. NO ALLOCATION IS GUARANTEED! |
211 // NULL. NO ALLOCATION IS GUARANTEED! |
240 static Symbol* probe(const char* name, int len) { |
212 static Symbol* probe(const char* name, int len) { |
241 unsigned int ignore_hash; |
213 unsigned int ignore_hash; |
244 static Symbol* probe_unicode(const jchar* name, int len) { |
216 static Symbol* probe_unicode(const jchar* name, int len) { |
245 unsigned int ignore_hash; |
217 unsigned int ignore_hash; |
246 return lookup_only_unicode(name, len, ignore_hash); |
218 return lookup_only_unicode(name, len, ignore_hash); |
247 } |
219 } |
248 |
220 |
249 // Histogram |
221 // Symbol creation |
250 static void print_histogram() PRODUCT_RETURN; |
222 static Symbol* new_symbol(const char* utf8_buffer, int length, TRAPS) { |
251 static void print() PRODUCT_RETURN; |
223 assert(utf8_buffer != NULL, "just checking"); |
252 |
224 return lookup(utf8_buffer, length, THREAD); |
|
225 } |
|
226 static Symbol* new_symbol(const char* name, TRAPS) { |
|
227 return new_symbol(name, (int)strlen(name), THREAD); |
|
228 } |
|
229 static Symbol* new_symbol(const Symbol* sym, int begin, int end, TRAPS) { |
|
230 assert(begin <= end && end <= sym->utf8_length(), "just checking"); |
|
231 return lookup(sym, begin, end, THREAD); |
|
232 } |
|
233 // Create a symbol in the arena for symbols that are not deleted |
|
234 static Symbol* new_permanent_symbol(const char* name, TRAPS); |
|
235 |
|
236 // Rehash the string table if it gets out of balance |
|
237 static void rehash_table(); |
|
238 static bool needs_rehashing() |
|
239 { return SymbolTable::the_table()->_needs_rehashing; } |
|
240 |
|
241 // Heap dumper and CDS |
|
242 static void symbols_do(SymbolClosure *cl); |
|
243 |
|
244 // Sharing |
|
245 private: |
|
246 static void copy_shared_symbol_table(CompactSymbolTableWriter* ch_table); |
|
247 public: |
|
248 static void write_to_archive() NOT_CDS_RETURN; |
|
249 static void serialize(SerializeClosure* soc) NOT_CDS_RETURN; |
|
250 static void metaspace_pointers_do(MetaspaceClosure* it); |
|
251 |
|
252 // Jcmd |
|
253 static void dump(outputStream* st, bool verbose=false); |
253 // Debugging |
254 // Debugging |
254 static void verify(); |
255 static void verify(); |
255 static void dump(outputStream* st, bool verbose=false); |
|
256 static void read(const char* filename, TRAPS); |
256 static void read(const char* filename, TRAPS); |
257 |
257 |
258 // Sharing |
258 // Histogram |
259 static void write_to_archive(); |
259 static void print_histogram() PRODUCT_RETURN; |
260 static void serialize(SerializeClosure* soc); |
|
261 static u4 encode_shared(Symbol* sym); |
|
262 static Symbol* decode_shared(u4 offset); |
|
263 |
|
264 // Rehash the symbol table if it gets out of balance |
|
265 static void rehash_table(); |
|
266 static bool needs_rehashing() { return _needs_rehashing; } |
|
267 // Parallel chunked scanning |
|
268 static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; } |
|
269 static int parallel_claimed_index() { return _parallel_claimed_idx; } |
|
270 }; |
260 }; |
271 |
261 |
272 #endif // SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP |
262 #endif // SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP |