78 } else { |
210 } else { |
79 _arena = new (mtSymbol) Arena(mtSymbol, arena_alloc_size); |
211 _arena = new (mtSymbol) Arena(mtSymbol, arena_alloc_size); |
80 } |
212 } |
81 } |
213 } |
82 |
214 |
|
215 class SymbolsDo : StackObj { |
|
216 SymbolClosure *_cl; |
|
217 public: |
|
218 SymbolsDo(SymbolClosure *cl) : _cl(cl) {} |
|
219 bool operator()(Symbol** value) { |
|
220 assert(value != NULL, "expected valid value"); |
|
221 assert(*value != NULL, "value should point to a symbol"); |
|
222 _cl->do_symbol(value); |
|
223 return true; |
|
224 }; |
|
225 }; |
|
226 |
83 // Call function for all symbols in the symbol table. |
227 // Call function for all symbols in the symbol table. |
84 void SymbolTable::symbols_do(SymbolClosure *cl) { |
228 void SymbolTable::symbols_do(SymbolClosure *cl) { |
85 // all symbols from shared table |
229 // all symbols from shared table |
86 _shared_table.symbols_do(cl); |
230 _shared_table.symbols_do(cl); |
87 |
231 |
88 // all symbols from the dynamic table |
232 // all symbols from the dynamic table |
89 const int n = the_table()->table_size(); |
233 SymbolsDo sd(cl); |
90 for (int i = 0; i < n; i++) { |
234 if (!SymbolTable::the_table()->_local_table->try_scan(Thread::current(), sd)) { |
91 for (HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); |
235 log_info(stringtable)("symbols_do unavailable at this moment"); |
92 p != NULL; |
236 } |
93 p = p->next()) { |
237 } |
94 cl->do_symbol(p->literal_addr()); |
238 |
95 } |
239 class MetaspacePointersDo : StackObj { |
96 } |
240 MetaspaceClosure *_it; |
97 } |
241 public: |
|
242 MetaspacePointersDo(MetaspaceClosure *it) : _it(it) {} |
|
243 bool operator()(Symbol** value) { |
|
244 assert(value != NULL, "expected valid value"); |
|
245 assert(*value != NULL, "value should point to a symbol"); |
|
246 _it->push(value); |
|
247 return true; |
|
248 }; |
|
249 }; |
98 |
250 |
99 void SymbolTable::metaspace_pointers_do(MetaspaceClosure* it) { |
251 void SymbolTable::metaspace_pointers_do(MetaspaceClosure* it) { |
100 assert(DumpSharedSpaces, "called only during dump time"); |
252 assert(DumpSharedSpaces, "called only during dump time"); |
101 const int n = the_table()->table_size(); |
253 MetaspacePointersDo mpd(it); |
102 for (int i = 0; i < n; i++) { |
254 SymbolTable::the_table()->_local_table->do_scan(Thread::current(), mpd); |
103 for (HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); |
255 } |
104 p != NULL; |
256 |
105 p = p->next()) { |
257 Symbol* SymbolTable::lookup_dynamic(const char* name, |
106 it->push(p->literal_addr()); |
|
107 } |
|
108 } |
|
109 } |
|
110 |
|
111 int SymbolTable::_symbols_removed = 0; |
|
112 int SymbolTable::_symbols_counted = 0; |
|
113 volatile int SymbolTable::_parallel_claimed_idx = 0; |
|
114 |
|
115 void SymbolTable::buckets_unlink(int start_idx, int end_idx, BucketUnlinkContext* context) { |
|
116 for (int i = start_idx; i < end_idx; ++i) { |
|
117 HashtableEntry<Symbol*, mtSymbol>** p = the_table()->bucket_addr(i); |
|
118 HashtableEntry<Symbol*, mtSymbol>* entry = the_table()->bucket(i); |
|
119 while (entry != NULL) { |
|
120 // Shared entries are normally at the end of the bucket and if we run into |
|
121 // a shared entry, then there is nothing more to remove. However, if we |
|
122 // have rehashed the table, then the shared entries are no longer at the |
|
123 // end of the bucket. |
|
124 if (entry->is_shared() && !use_alternate_hashcode()) { |
|
125 break; |
|
126 } |
|
127 Symbol* s = entry->literal(); |
|
128 context->_num_processed++; |
|
129 assert(s != NULL, "just checking"); |
|
130 // If reference count is zero, remove. |
|
131 if (s->refcount() == 0) { |
|
132 assert(!entry->is_shared(), "shared entries should be kept live"); |
|
133 delete s; |
|
134 *p = entry->next(); |
|
135 context->free_entry(entry); |
|
136 } else { |
|
137 p = entry->next_addr(); |
|
138 } |
|
139 // get next entry |
|
140 entry = (HashtableEntry<Symbol*, mtSymbol>*)HashtableEntry<Symbol*, mtSymbol>::make_ptr(*p); |
|
141 } |
|
142 } |
|
143 } |
|
144 |
|
145 // Remove unreferenced symbols from the symbol table |
|
146 // This is done late during GC. |
|
147 void SymbolTable::unlink(int* processed, int* removed) { |
|
148 BucketUnlinkContext context; |
|
149 buckets_unlink(0, the_table()->table_size(), &context); |
|
150 _the_table->bulk_free_entries(&context); |
|
151 *processed = context._num_processed; |
|
152 *removed = context._num_removed; |
|
153 |
|
154 _symbols_removed = context._num_removed; |
|
155 _symbols_counted = context._num_processed; |
|
156 } |
|
157 |
|
158 void SymbolTable::possibly_parallel_unlink(int* processed, int* removed) { |
|
159 const int limit = the_table()->table_size(); |
|
160 |
|
161 BucketUnlinkContext context; |
|
162 for (;;) { |
|
163 // Grab next set of buckets to scan |
|
164 int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize; |
|
165 if (start_idx >= limit) { |
|
166 // End of table |
|
167 break; |
|
168 } |
|
169 |
|
170 int end_idx = MIN2(limit, start_idx + ClaimChunkSize); |
|
171 buckets_unlink(start_idx, end_idx, &context); |
|
172 } |
|
173 |
|
174 _the_table->bulk_free_entries(&context); |
|
175 *processed = context._num_processed; |
|
176 *removed = context._num_removed; |
|
177 |
|
178 Atomic::add(context._num_processed, &_symbols_counted); |
|
179 Atomic::add(context._num_removed, &_symbols_removed); |
|
180 } |
|
181 |
|
182 // Create a new table and using alternate hash code, populate the new table |
|
183 // with the existing strings. Set flag to use the alternate hash code afterwards. |
|
184 void SymbolTable::rehash_table() { |
|
185 if (DumpSharedSpaces) { |
|
186 tty->print_cr("Warning: rehash_table should not be called while dumping archive"); |
|
187 return; |
|
188 } |
|
189 |
|
190 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); |
|
191 // This should never happen with -Xshare:dump but it might in testing mode. |
|
192 if (DumpSharedSpaces) return; |
|
193 |
|
194 // Create a new symbol table |
|
195 SymbolTable* new_table = new SymbolTable(); |
|
196 |
|
197 the_table()->move_to(new_table); |
|
198 |
|
199 // Delete the table and buckets (entries are reused in new table). |
|
200 delete _the_table; |
|
201 // Don't check if we need rehashing until the table gets unbalanced again. |
|
202 // Then rehash with a new global seed. |
|
203 _needs_rehashing = false; |
|
204 _the_table = new_table; |
|
205 } |
|
206 |
|
207 // Lookup a symbol in a bucket. |
|
208 |
|
209 Symbol* SymbolTable::lookup_dynamic(int index, const char* name, |
|
210 int len, unsigned int hash) { |
258 int len, unsigned int hash) { |
211 int count = 0; |
259 Symbol* sym = SymbolTable::the_table()->do_lookup(name, len, hash); |
212 for (HashtableEntry<Symbol*, mtSymbol>* e = bucket(index); e != NULL; e = e->next()) { |
260 assert((sym == NULL) || sym->refcount() != 0, "refcount must not be zero"); |
213 count++; // count all entries in this bucket, not just ones with same hash |
261 return sym; |
214 if (e->hash() == hash) { |
|
215 Symbol* sym = e->literal(); |
|
216 // Skip checking already dead symbols in the bucket. |
|
217 if (sym->refcount() == 0) { |
|
218 count--; // Don't count this symbol towards rehashing. |
|
219 } else if (sym->equals(name, len)) { |
|
220 if (sym->try_increment_refcount()) { |
|
221 // something is referencing this symbol now. |
|
222 return sym; |
|
223 } else { |
|
224 count--; // don't count this symbol. |
|
225 } |
|
226 } |
|
227 } |
|
228 } |
|
229 // If the bucket size is too deep check if this hash code is insufficient. |
|
230 if (count >= rehash_count && !needs_rehashing()) { |
|
231 _needs_rehashing = check_rehash_table(count); |
|
232 } |
|
233 return NULL; |
|
234 } |
262 } |
235 |
263 |
236 Symbol* SymbolTable::lookup_shared(const char* name, |
264 Symbol* SymbolTable::lookup_shared(const char* name, |
237 int len, unsigned int hash) { |
265 int len, unsigned int hash) { |
238 if (use_alternate_hashcode()) { |
266 if (!_shared_table.empty()) { |
239 // hash_code parameter may use alternate hashing algorithm but the shared table |
267 if (SymbolTable::_alt_hash) { |
240 // always uses the same original hash code. |
268 // hash_code parameter may use alternate hashing algorithm but the shared table |
241 hash = hash_shared_symbol(name, len); |
269 // always uses the same original hash code. |
242 } |
270 hash = hash_shared_symbol(name, len); |
243 return _shared_table.lookup(name, hash, len); |
271 } |
244 } |
272 return _shared_table.lookup(name, hash, len); |
245 |
273 } else { |
246 Symbol* SymbolTable::lookup(int index, const char* name, |
274 return NULL; |
|
275 } |
|
276 } |
|
277 |
|
278 Symbol* SymbolTable::lookup_common(const char* name, |
247 int len, unsigned int hash) { |
279 int len, unsigned int hash) { |
248 Symbol* sym; |
280 Symbol* sym; |
249 if (_lookup_shared_first) { |
281 if (_lookup_shared_first) { |
250 sym = lookup_shared(name, len, hash); |
282 sym = lookup_shared(name, len, hash); |
251 if (sym != NULL) { |
283 if (sym == NULL) { |
252 return sym; |
284 _lookup_shared_first = false; |
253 } |
285 sym = lookup_dynamic(name, len, hash); |
254 _lookup_shared_first = false; |
286 } |
255 return lookup_dynamic(index, name, len, hash); |
287 } else { |
256 } else { |
288 sym = lookup_dynamic(name, len, hash); |
257 sym = lookup_dynamic(index, name, len, hash); |
289 if (sym == NULL) { |
258 if (sym != NULL) { |
290 sym = lookup_shared(name, len, hash); |
259 return sym; |
291 if (sym != NULL) { |
260 } |
292 _lookup_shared_first = true; |
261 sym = lookup_shared(name, len, hash); |
293 } |
262 if (sym != NULL) { |
294 } |
263 _lookup_shared_first = true; |
295 } |
264 } |
|
265 return sym; |
|
266 } |
|
267 } |
|
268 |
|
269 u4 SymbolTable::encode_shared(Symbol* sym) { |
|
270 assert(DumpSharedSpaces, "called only during dump time"); |
|
271 uintx base_address = uintx(MetaspaceShared::shared_rs()->base()); |
|
272 uintx offset = uintx(sym) - base_address; |
|
273 assert(offset < 0x7fffffff, "sanity"); |
|
274 return u4(offset); |
|
275 } |
|
276 |
|
277 Symbol* SymbolTable::decode_shared(u4 offset) { |
|
278 assert(!DumpSharedSpaces, "called only during runtime"); |
|
279 uintx base_address = _shared_table.base_address(); |
|
280 Symbol* sym = (Symbol*)(base_address + offset); |
|
281 |
|
282 #ifndef PRODUCT |
|
283 const char* s = (const char*)sym->bytes(); |
|
284 int len = sym->utf8_length(); |
|
285 unsigned int hash = hash_symbol(s, len); |
|
286 assert(sym == lookup_shared(s, len, hash), "must be shared symbol"); |
|
287 #endif |
|
288 |
|
289 return sym; |
296 return sym; |
290 } |
297 } |
291 |
298 |
292 // Pick hashing algorithm. |
|
293 unsigned int SymbolTable::hash_symbol(const char* s, int len) { |
|
294 return use_alternate_hashcode() ? |
|
295 AltHashing::murmur3_32(seed(), (const jbyte*)s, len) : |
|
296 java_lang_String::hash_code((const jbyte*)s, len); |
|
297 } |
|
298 |
|
299 unsigned int SymbolTable::hash_shared_symbol(const char* s, int len) { |
|
300 return java_lang_String::hash_code((const jbyte*)s, len); |
|
301 } |
|
302 |
|
303 |
|
304 // We take care not to be blocking while holding the |
|
305 // SymbolTable_lock. Otherwise, the system might deadlock, since the |
|
306 // symboltable is used during compilation (VM_thread) The lock free |
|
307 // synchronization is simplified by the fact that we do not delete |
|
308 // entries in the symbol table during normal execution (only during |
|
309 // safepoints). |
|
310 |
|
311 Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) { |
299 Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) { |
312 unsigned int hashValue = hash_symbol(name, len); |
300 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash); |
313 int index = the_table()->hash_to_index(hashValue); |
301 Symbol* sym = SymbolTable::the_table()->lookup_common(name, len, hash); |
314 |
302 if (sym == NULL) { |
315 Symbol* s = the_table()->lookup(index, name, len, hashValue); |
303 sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, true, CHECK_NULL); |
316 |
304 } |
317 // Found |
305 assert(sym->refcount() != 0, "lookup should have incremented the count"); |
318 if (s != NULL) return s; |
306 assert(sym->equals(name, len), "symbol must be properly initialized"); |
319 |
307 return sym; |
320 // Grab SymbolTable_lock first. |
|
321 MutexLocker ml(SymbolTable_lock, THREAD); |
|
322 |
|
323 // Otherwise, add to symbol to table |
|
324 return the_table()->basic_add(index, (u1*)name, len, hashValue, true, THREAD); |
|
325 } |
308 } |
326 |
309 |
327 Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) { |
310 Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) { |
328 char* buffer; |
311 assert(sym->refcount() != 0, "require a valid symbol"); |
329 int index, len; |
312 const char* name = (const char*)sym->base() + begin; |
330 unsigned int hashValue; |
313 int len = end - begin; |
331 char* name; |
314 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash); |
332 { |
315 Symbol* found = SymbolTable::the_table()->lookup_common(name, len, hash); |
333 debug_only(NoSafepointVerifier nsv;) |
316 if (found == NULL) { |
334 |
317 found = SymbolTable::the_table()->do_add_if_needed(name, len, hash, true, THREAD); |
335 name = (char*)sym->base() + begin; |
318 } |
336 len = end - begin; |
319 return found; |
337 hashValue = hash_symbol(name, len); |
320 } |
338 index = the_table()->hash_to_index(hashValue); |
321 |
339 Symbol* s = the_table()->lookup(index, name, len, hashValue); |
322 class SymbolTableLookup : StackObj { |
340 |
323 private: |
341 // Found |
324 Thread* _thread; |
342 if (s != NULL) return s; |
325 uintx _hash; |
343 } |
326 int _len; |
344 |
327 const char* _str; |
345 // Otherwise, add to symbol to table. Copy to a C string first. |
328 public: |
346 char stack_buf[128]; |
329 SymbolTableLookup(Thread* thread, const char* key, int len, uintx hash) |
347 ResourceMark rm(THREAD); |
330 : _thread(thread), _hash(hash), _len(len), _str(key) {} |
348 if (len <= 128) { |
331 uintx get_hash() const { |
349 buffer = stack_buf; |
332 return _hash; |
350 } else { |
333 } |
351 buffer = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len); |
334 bool equals(Symbol** value, bool* is_dead) { |
352 } |
335 assert(value != NULL, "expected valid value"); |
353 for (int i=0; i<len; i++) { |
336 assert(*value != NULL, "value should point to a symbol"); |
354 buffer[i] = name[i]; |
337 Symbol *sym = *value; |
355 } |
338 if (sym->equals(_str, _len)) { |
356 // Make sure there is no safepoint in the code above since name can't move. |
339 if (sym->try_increment_refcount()) { |
357 // We can't include the code in NoSafepointVerifier because of the |
340 // something is referencing this symbol now. |
358 // ResourceMark. |
341 return true; |
359 |
342 } else { |
360 // Grab SymbolTable_lock first. |
343 assert(sym->refcount() == 0, "expected dead symbol"); |
361 MutexLocker ml(SymbolTable_lock, THREAD); |
344 *is_dead = true; |
362 |
345 return false; |
363 return the_table()->basic_add(index, (u1*)buffer, len, hashValue, true, THREAD); |
|
364 } |
|
365 |
|
366 Symbol* SymbolTable::lookup_only(const char* name, int len, |
|
367 unsigned int& hash) { |
|
368 hash = hash_symbol(name, len); |
|
369 int index = the_table()->hash_to_index(hash); |
|
370 |
|
371 Symbol* s = the_table()->lookup(index, name, len, hash); |
|
372 return s; |
|
373 } |
|
374 |
|
375 // Look up the address of the literal in the SymbolTable for this Symbol* |
|
376 // Do not create any new symbols |
|
377 // Do not increment the reference count to keep this alive |
|
378 Symbol** SymbolTable::lookup_symbol_addr(Symbol* sym){ |
|
379 unsigned int hash = hash_symbol((char*)sym->bytes(), sym->utf8_length()); |
|
380 int index = the_table()->hash_to_index(hash); |
|
381 |
|
382 for (HashtableEntry<Symbol*, mtSymbol>* e = the_table()->bucket(index); e != NULL; e = e->next()) { |
|
383 if (e->hash() == hash) { |
|
384 Symbol* literal_sym = e->literal(); |
|
385 if (sym == literal_sym) { |
|
386 return e->literal_addr(); |
|
387 } |
346 } |
388 } |
347 } else { |
389 } |
348 *is_dead = (sym->refcount() == 0); |
390 return NULL; |
349 return false; |
|
350 } |
|
351 } |
|
352 }; |
|
353 |
|
354 class SymbolTableGet : public StackObj { |
|
355 Symbol* _return; |
|
356 public: |
|
357 SymbolTableGet() : _return(NULL) {} |
|
358 void operator()(Symbol** value) { |
|
359 assert(value != NULL, "expected valid value"); |
|
360 assert(*value != NULL, "value should point to a symbol"); |
|
361 _return = *value; |
|
362 } |
|
363 Symbol* get_res_sym() { |
|
364 return _return; |
|
365 } |
|
366 }; |
|
367 |
|
368 Symbol* SymbolTable::do_lookup(const char* name, int len, uintx hash) { |
|
369 Thread* thread = Thread::current(); |
|
370 SymbolTableLookup lookup(thread, name, len, hash); |
|
371 SymbolTableGet stg; |
|
372 bool rehash_warning = false; |
|
373 _local_table->get(thread, lookup, stg, &rehash_warning); |
|
374 if (rehash_warning) { |
|
375 _needs_rehashing = true; |
|
376 } |
|
377 Symbol* sym = stg.get_res_sym(); |
|
378 assert((sym == NULL) || sym->refcount() != 0, "found dead symbol"); |
|
379 return sym; |
|
380 } |
|
381 |
|
382 Symbol* SymbolTable::lookup_only(const char* name, int len, unsigned int& hash) { |
|
383 hash = hash_symbol(name, len, SymbolTable::_alt_hash); |
|
384 return SymbolTable::the_table()->lookup_common(name, len, hash); |
391 } |
385 } |
392 |
386 |
393 // Suggestion: Push unicode-based lookup all the way into the hashing |
387 // Suggestion: Push unicode-based lookup all the way into the hashing |
394 // and probing logic, so there is no need for convert_to_utf8 until |
388 // and probing logic, so there is no need for convert_to_utf8 until |
395 // an actual new Symbol* is created. |
389 // an actual new Symbol* is created. |
396 Symbol* SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) { |
390 Symbol* SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) { |
397 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); |
391 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); |
398 char stack_buf[128]; |
392 char stack_buf[ON_STACK_BUFFER_LENGTH]; |
399 if (utf8_length < (int) sizeof(stack_buf)) { |
393 if (utf8_length < (int) sizeof(stack_buf)) { |
400 char* chars = stack_buf; |
394 char* chars = stack_buf; |
401 UNICODE::convert_to_utf8(name, utf16_length, chars); |
395 UNICODE::convert_to_utf8(name, utf16_length, chars); |
402 return lookup(chars, utf8_length, THREAD); |
396 return lookup(chars, utf8_length, THREAD); |
403 } else { |
397 } else { |
404 ResourceMark rm(THREAD); |
398 ResourceMark rm(THREAD); |
405 char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);; |
399 char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1); |
406 UNICODE::convert_to_utf8(name, utf16_length, chars); |
400 UNICODE::convert_to_utf8(name, utf16_length, chars); |
407 return lookup(chars, utf8_length, THREAD); |
401 return lookup(chars, utf8_length, THREAD); |
408 } |
402 } |
409 } |
403 } |
410 |
404 |
411 Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length, |
405 Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length, |
412 unsigned int& hash) { |
406 unsigned int& hash) { |
413 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); |
407 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); |
414 char stack_buf[128]; |
408 char stack_buf[ON_STACK_BUFFER_LENGTH]; |
415 if (utf8_length < (int) sizeof(stack_buf)) { |
409 if (utf8_length < (int) sizeof(stack_buf)) { |
416 char* chars = stack_buf; |
410 char* chars = stack_buf; |
417 UNICODE::convert_to_utf8(name, utf16_length, chars); |
411 UNICODE::convert_to_utf8(name, utf16_length, chars); |
418 return lookup_only(chars, utf8_length, hash); |
412 return lookup_only(chars, utf8_length, hash); |
419 } else { |
413 } else { |
420 ResourceMark rm; |
414 ResourceMark rm; |
421 char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);; |
415 char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1); |
422 UNICODE::convert_to_utf8(name, utf16_length, chars); |
416 UNICODE::convert_to_utf8(name, utf16_length, chars); |
423 return lookup_only(chars, utf8_length, hash); |
417 return lookup_only(chars, utf8_length, hash); |
424 } |
418 } |
425 } |
419 } |
426 |
420 |
427 void SymbolTable::add(ClassLoaderData* loader_data, const constantPoolHandle& cp, |
421 void SymbolTable::add(ClassLoaderData* loader_data, const constantPoolHandle& cp, |
428 int names_count, |
422 int names_count, const char** names, int* lengths, |
429 const char** names, int* lengths, int* cp_indices, |
423 int* cp_indices, unsigned int* hashValues, TRAPS) { |
430 unsigned int* hashValues, TRAPS) { |
424 bool c_heap = !loader_data->is_the_null_class_loader_data(); |
431 // Grab SymbolTable_lock first. |
425 for (int i = 0; i < names_count; i++) { |
432 MutexLocker ml(SymbolTable_lock, THREAD); |
426 const char *name = names[i]; |
433 |
427 int len = lengths[i]; |
434 SymbolTable* table = the_table(); |
428 unsigned int hash = hashValues[i]; |
435 bool added = table->basic_add(loader_data, cp, names_count, names, lengths, |
429 Symbol* sym = SymbolTable::the_table()->lookup_common(name, len, hash); |
436 cp_indices, hashValues, CHECK); |
430 if (sym == NULL) { |
437 if (!added) { |
431 sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, c_heap, CHECK); |
438 // do it the hard way |
432 } |
439 for (int i=0; i<names_count; i++) { |
433 assert(sym->refcount() != 0, "lookup should have incremented the count"); |
440 int index = table->hash_to_index(hashValues[i]); |
434 cp->symbol_at_put(cp_indices[i], sym); |
441 bool c_heap = !loader_data->is_the_null_class_loader_data(); |
435 } |
442 Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], hashValues[i], c_heap, CHECK); |
436 } |
443 cp->symbol_at_put(cp_indices[i], sym); |
437 |
444 } |
438 class SymbolTableCreateEntry : public StackObj { |
445 } |
439 private: |
|
440 Thread* _thread; |
|
441 const char* _name; |
|
442 int _len; |
|
443 bool _heap; |
|
444 Symbol* _return; |
|
445 Symbol* _created; |
|
446 |
|
447 void assert_for_name(Symbol* sym, const char* where) const { |
|
448 #ifdef ASSERT |
|
449 assert(sym->utf8_length() == _len, "%s [%d,%d]", where, sym->utf8_length(), _len); |
|
450 for (int i = 0; i < _len; i++) { |
|
451 assert(sym->byte_at(i) == _name[i], |
|
452 "%s [%d,%d,%d]", where, i, sym->byte_at(i), _name[i]); |
|
453 } |
|
454 #endif |
|
455 } |
|
456 |
|
457 public: |
|
458 SymbolTableCreateEntry(Thread* thread, const char* name, int len, bool heap) |
|
459 : _thread(thread), _name(name) , _len(len), _heap(heap), _return(NULL) , _created(NULL) { |
|
460 assert(_name != NULL, "expected valid name"); |
|
461 } |
|
462 Symbol* operator()() { |
|
463 _created = SymbolTable::the_table()->allocate_symbol(_name, _len, _heap, _thread); |
|
464 assert(_created != NULL, "expected created symbol"); |
|
465 assert_for_name(_created, "operator()()"); |
|
466 assert(_created->equals(_name, _len), |
|
467 "symbol must be properly initialized [%p,%d,%d]", _name, _len, (int)_heap); |
|
468 return _created; |
|
469 } |
|
470 void operator()(bool inserted, Symbol** value) { |
|
471 assert(value != NULL, "expected valid value"); |
|
472 assert(*value != NULL, "value should point to a symbol"); |
|
473 if (!inserted && (_created != NULL)) { |
|
474 // We created our symbol, but someone else inserted |
|
475 // theirs first, so ours will be destroyed. |
|
476 // Since symbols are created with refcount of 1, |
|
477 // we must decrement it here to 0 to delete, |
|
478 // unless it's a permanent one. |
|
479 if (_created->refcount() != PERM_REFCOUNT) { |
|
480 assert(_created->refcount() == 1, "expected newly created symbol"); |
|
481 _created->decrement_refcount(); |
|
482 assert(_created->refcount() == 0, "expected dead symbol"); |
|
483 } |
|
484 } |
|
485 _return = *value; |
|
486 assert_for_name(_return, "operator()"); |
|
487 } |
|
488 Symbol* get_new_sym() const { |
|
489 assert_for_name(_return, "get_new_sym"); |
|
490 return _return; |
|
491 } |
|
492 }; |
|
493 |
|
494 Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, bool heap, TRAPS) { |
|
495 SymbolTableLookup lookup(THREAD, name, len, hash); |
|
496 SymbolTableCreateEntry stce(THREAD, name, len, heap); |
|
497 bool rehash_warning = false; |
|
498 bool clean_hint = false; |
|
499 _local_table->get_insert_lazy(THREAD, lookup, stce, stce, &rehash_warning, &clean_hint); |
|
500 if (rehash_warning) { |
|
501 _needs_rehashing = true; |
|
502 } |
|
503 if (clean_hint) { |
|
504 // we just found out that there is a dead item, |
|
505 // which we were unable to clean right now, |
|
506 // but we have no way of telling whether it's |
|
507 // been previously counted or not, so mark |
|
508 // it only if no other items were found yet |
|
509 mark_item_clean_count(); |
|
510 check_concurrent_work(); |
|
511 } |
|
512 Symbol* sym = stce.get_new_sym(); |
|
513 assert(sym->refcount() != 0, "zero is invalid"); |
|
514 return sym; |
446 } |
515 } |
447 |
516 |
448 Symbol* SymbolTable::new_permanent_symbol(const char* name, TRAPS) { |
517 Symbol* SymbolTable::new_permanent_symbol(const char* name, TRAPS) { |
449 unsigned int hash; |
518 unsigned int hash = 0; |
450 Symbol* result = SymbolTable::lookup_only((char*)name, (int)strlen(name), hash); |
519 int len = (int)strlen(name); |
451 if (result != NULL) { |
520 Symbol* sym = SymbolTable::lookup_only(name, len, hash); |
452 return result; |
521 if (sym == NULL) { |
453 } |
522 sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, false, CHECK_NULL); |
454 // Grab SymbolTable_lock first. |
523 } |
455 MutexLocker ml(SymbolTable_lock, THREAD); |
524 if (sym->refcount() != PERM_REFCOUNT) { |
456 |
525 sym->increment_refcount(); |
457 SymbolTable* table = the_table(); |
526 log_trace_symboltable_helper(sym, "Asked for a permanent symbol, but got a regular one"); |
458 int index = table->hash_to_index(hash); |
527 } |
459 return table->basic_add(index, (u1*)name, (int)strlen(name), hash, false, THREAD); |
|
460 } |
|
461 |
|
462 Symbol* SymbolTable::basic_add(int index_arg, u1 *name, int len, |
|
463 unsigned int hashValue_arg, bool c_heap, TRAPS) { |
|
464 assert(!Universe::heap()->is_in_reserved(name), |
|
465 "proposed name of symbol must be stable"); |
|
466 |
|
467 // Don't allow symbols to be created which cannot fit in a Symbol*. |
|
468 if (len > Symbol::max_length()) { |
|
469 THROW_MSG_0(vmSymbols::java_lang_InternalError(), |
|
470 "name is too long to represent"); |
|
471 } |
|
472 |
|
473 // Cannot hit a safepoint in this function because the "this" pointer can move. |
|
474 NoSafepointVerifier nsv; |
|
475 |
|
476 // Check if the symbol table has been rehashed, if so, need to recalculate |
|
477 // the hash value and index. |
|
478 unsigned int hashValue; |
|
479 int index; |
|
480 if (use_alternate_hashcode()) { |
|
481 hashValue = hash_symbol((const char*)name, len); |
|
482 index = hash_to_index(hashValue); |
|
483 } else { |
|
484 hashValue = hashValue_arg; |
|
485 index = index_arg; |
|
486 } |
|
487 |
|
488 // Since look-up was done lock-free, we need to check if another |
|
489 // thread beat us in the race to insert the symbol. |
|
490 Symbol* test = lookup(index, (char*)name, len, hashValue); |
|
491 if (test != NULL) { |
|
492 // A race occurred and another thread introduced the symbol. |
|
493 assert(test->refcount() != 0, "lookup should have incremented the count"); |
|
494 return test; |
|
495 } |
|
496 |
|
497 // Create a new symbol. |
|
498 Symbol* sym = allocate_symbol(name, len, c_heap, CHECK_NULL); |
|
499 assert(sym->equals((char*)name, len), "symbol must be properly initialized"); |
|
500 |
|
501 HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym); |
|
502 add_entry(index, entry); |
|
503 return sym; |
528 return sym; |
504 } |
529 } |
505 |
530 |
506 // This version of basic_add adds symbols in batch from the constant pool |
531 struct SizeFunc : StackObj { |
507 // parsing. |
532 size_t operator()(Symbol** value) { |
508 bool SymbolTable::basic_add(ClassLoaderData* loader_data, const constantPoolHandle& cp, |
533 assert(value != NULL, "expected valid value"); |
509 int names_count, |
534 assert(*value != NULL, "value should point to a symbol"); |
510 const char** names, int* lengths, |
535 return (*value)->size() * HeapWordSize; |
511 int* cp_indices, unsigned int* hashValues, |
536 }; |
512 TRAPS) { |
537 }; |
513 |
538 |
514 // Check symbol names are not too long. If any are too long, don't add any. |
539 void SymbolTable::print_table_statistics(outputStream* st, |
515 for (int i = 0; i< names_count; i++) { |
540 const char* table_name) { |
516 if (lengths[i] > Symbol::max_length()) { |
541 SizeFunc sz; |
517 THROW_MSG_0(vmSymbols::java_lang_InternalError(), |
542 _local_table->statistics_to(Thread::current(), sz, st, table_name); |
518 "name is too long to represent"); |
543 } |
519 } |
544 |
520 } |
545 // Verification |
521 |
546 class VerifySymbols : StackObj { |
522 // Cannot hit a safepoint in this function because the "this" pointer can move. |
547 public: |
523 NoSafepointVerifier nsv; |
548 bool operator()(Symbol** value) { |
524 |
549 guarantee(value != NULL, "expected valid value"); |
525 for (int i=0; i<names_count; i++) { |
550 guarantee(*value != NULL, "value should point to a symbol"); |
526 // Check if the symbol table has been rehashed, if so, need to recalculate |
551 Symbol* sym = *value; |
527 // the hash value. |
552 guarantee(sym->equals((const char*)sym->bytes(), sym->utf8_length()), |
528 unsigned int hashValue; |
553 "symbol must be internally consistent"); |
529 if (use_alternate_hashcode()) { |
554 return true; |
530 hashValue = hash_symbol(names[i], lengths[i]); |
555 }; |
531 } else { |
556 }; |
532 hashValue = hashValues[i]; |
|
533 } |
|
534 // Since look-up was done lock-free, we need to check if another |
|
535 // thread beat us in the race to insert the symbol. |
|
536 int index = hash_to_index(hashValue); |
|
537 Symbol* test = lookup(index, names[i], lengths[i], hashValue); |
|
538 if (test != NULL) { |
|
539 // A race occurred and another thread introduced the symbol, this one |
|
540 // will be dropped and collected. Use test instead. |
|
541 cp->symbol_at_put(cp_indices[i], test); |
|
542 assert(test->refcount() != 0, "lookup should have incremented the count"); |
|
543 } else { |
|
544 // Create a new symbol. The null class loader is never unloaded so these |
|
545 // are allocated specially in a permanent arena. |
|
546 bool c_heap = !loader_data->is_the_null_class_loader_data(); |
|
547 Symbol* sym = allocate_symbol((const u1*)names[i], lengths[i], c_heap, CHECK_(false)); |
|
548 assert(sym->equals(names[i], lengths[i]), "symbol must be properly initialized"); // why wouldn't it be??? |
|
549 HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym); |
|
550 add_entry(index, entry); |
|
551 cp->symbol_at_put(cp_indices[i], sym); |
|
552 } |
|
553 } |
|
554 return true; |
|
555 } |
|
556 |
|
557 |
557 |
558 void SymbolTable::verify() { |
558 void SymbolTable::verify() { |
559 for (int i = 0; i < the_table()->table_size(); ++i) { |
559 Thread* thr = Thread::current(); |
560 HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); |
560 VerifySymbols vs; |
561 for ( ; p != NULL; p = p->next()) { |
561 if (!SymbolTable::the_table()->_local_table->try_scan(thr, vs)) { |
562 Symbol* s = (Symbol*)(p->literal()); |
562 log_info(stringtable)("verify unavailable at this moment"); |
563 guarantee(s != NULL, "symbol is NULL"); |
563 } |
564 unsigned int h = hash_symbol((char*)s->bytes(), s->utf8_length()); |
564 } |
565 guarantee(p->hash() == h, "broken hash in symbol table entry"); |
565 |
566 guarantee(the_table()->hash_to_index(h) == i, |
566 // Dumping |
567 "wrong index in symbol table"); |
567 class DumpSymbol : StackObj { |
568 } |
568 Thread* _thr; |
569 } |
569 outputStream* _st; |
570 } |
570 public: |
|
571 DumpSymbol(Thread* thr, outputStream* st) : _thr(thr), _st(st) {} |
|
572 bool operator()(Symbol** value) { |
|
573 assert(value != NULL, "expected valid value"); |
|
574 assert(*value != NULL, "value should point to a symbol"); |
|
575 Symbol* sym = *value; |
|
576 const char* utf8_string = (const char*)sym->bytes(); |
|
577 int utf8_length = sym->utf8_length(); |
|
578 _st->print("%d %d: ", utf8_length, sym->refcount()); |
|
579 HashtableTextDump::put_utf8(_st, utf8_string, utf8_length); |
|
580 _st->cr(); |
|
581 return true; |
|
582 }; |
|
583 }; |
571 |
584 |
572 void SymbolTable::dump(outputStream* st, bool verbose) { |
585 void SymbolTable::dump(outputStream* st, bool verbose) { |
573 if (!verbose) { |
586 if (!verbose) { |
574 the_table()->print_table_statistics(st, "SymbolTable"); |
587 SymbolTable::the_table()->print_table_statistics(st, "SymbolTable"); |
575 } else { |
588 } else { |
576 st->print_cr("VERSION: 1.0"); |
589 Thread* thr = Thread::current(); |
577 for (int i = 0; i < the_table()->table_size(); ++i) { |
590 ResourceMark rm(thr); |
578 HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); |
591 st->print_cr("VERSION: 1.1"); |
579 for ( ; p != NULL; p = p->next()) { |
592 DumpSymbol ds(thr, st); |
580 Symbol* s = (Symbol*)(p->literal()); |
593 if (!SymbolTable::the_table()->_local_table->try_scan(thr, ds)) { |
581 const char* utf8_string = (const char*)s->bytes(); |
594 log_info(symboltable)("dump unavailable at this moment"); |
582 int utf8_length = s->utf8_length(); |
595 } |
583 st->print("%d %d: ", utf8_length, s->refcount()); |
596 } |
584 HashtableTextDump::put_utf8(st, utf8_string, utf8_length); |
597 } |
585 st->cr(); |
598 |
586 } |
599 #if INCLUDE_CDS |
587 } |
600 struct CopyToArchive : StackObj { |
588 } |
601 CompactSymbolTableWriter* _writer; |
|
602 CopyToArchive(CompactSymbolTableWriter* writer) : _writer(writer) {} |
|
603 bool operator()(Symbol** value) { |
|
604 assert(value != NULL, "expected valid value"); |
|
605 assert(*value != NULL, "value should point to a symbol"); |
|
606 Symbol* sym = *value; |
|
607 unsigned int fixed_hash = hash_shared_symbol((const char*)sym->bytes(), sym->utf8_length()); |
|
608 if (fixed_hash == 0) { |
|
609 return true; |
|
610 } |
|
611 assert(fixed_hash == hash_symbol((const char*)sym->bytes(), sym->utf8_length(), false), |
|
612 "must not rehash during dumping"); |
|
613 |
|
614 // add to the compact table |
|
615 _writer->add(fixed_hash, sym); |
|
616 |
|
617 return true; |
|
618 } |
|
619 }; |
|
620 |
|
621 void SymbolTable::copy_shared_symbol_table(CompactSymbolTableWriter* writer) { |
|
622 CopyToArchive copy(writer); |
|
623 SymbolTable::the_table()->_local_table->do_scan(Thread::current(), copy); |
589 } |
624 } |
590 |
625 |
591 void SymbolTable::write_to_archive() { |
626 void SymbolTable::write_to_archive() { |
592 #if INCLUDE_CDS |
627 _shared_table.reset(); |
593 _shared_table.reset(); |
628 |
594 |
629 int num_buckets = (int)(SymbolTable::the_table()->_items_count / SharedSymbolTableBucketSize); |
595 int num_buckets = the_table()->number_of_entries() / |
630 // calculation of num_buckets can result in zero buckets, we need at least one |
596 SharedSymbolTableBucketSize; |
631 CompactSymbolTableWriter writer(num_buckets > 1 ? num_buckets : 1, |
597 CompactSymbolTableWriter writer(num_buckets, |
632 &MetaspaceShared::stats()->symbol); |
598 &MetaspaceShared::stats()->symbol); |
633 copy_shared_symbol_table(&writer); |
599 for (int i = 0; i < the_table()->table_size(); ++i) { |
634 writer.dump(&_shared_table); |
600 HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); |
635 |
601 for ( ; p != NULL; p = p->next()) { |
636 // Verify table is correct |
602 Symbol* s = (Symbol*)(p->literal()); |
637 Symbol* sym = vmSymbols::java_lang_Object(); |
603 unsigned int fixed_hash = hash_shared_symbol((char*)s->bytes(), s->utf8_length()); |
638 const char* name = (const char*)sym->bytes(); |
604 assert(fixed_hash == p->hash(), "must not rehash during dumping"); |
639 int len = sym->utf8_length(); |
605 writer.add(fixed_hash, s); |
640 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash); |
606 } |
641 assert(sym == _shared_table.lookup(name, hash, len), "sanity"); |
607 } |
|
608 |
|
609 writer.dump(&_shared_table); |
|
610 |
|
611 // Verify table is correct |
|
612 Symbol* sym = vmSymbols::java_lang_Object(); |
|
613 const char* name = (const char*)sym->bytes(); |
|
614 int len = sym->utf8_length(); |
|
615 unsigned int hash = hash_symbol(name, len); |
|
616 assert(sym == _shared_table.lookup(name, hash, len), "sanity"); |
|
617 #endif |
|
618 } |
642 } |
619 |
643 |
620 void SymbolTable::serialize(SerializeClosure* soc) { |
644 void SymbolTable::serialize(SerializeClosure* soc) { |
621 #if INCLUDE_CDS |
|
622 _shared_table.set_type(CompactHashtable<Symbol*, char>::_symbol_table); |
645 _shared_table.set_type(CompactHashtable<Symbol*, char>::_symbol_table); |
623 _shared_table.serialize(soc); |
646 _shared_table.serialize(soc); |
624 |
647 |
625 if (soc->writing()) { |
648 if (soc->writing()) { |
626 // Sanity. Make sure we don't use the shared table at dump time |
649 // Sanity. Make sure we don't use the shared table at dump time |
627 _shared_table.reset(); |
650 _shared_table.reset(); |
628 } |
651 } |
629 #endif |
652 } |
|
653 #endif //INCLUDE_CDS |
|
654 |
|
655 // Concurrent work |
|
656 void SymbolTable::grow(JavaThread* jt) { |
|
657 SymbolTableHash::GrowTask gt(_local_table); |
|
658 if (!gt.prepare(jt)) { |
|
659 return; |
|
660 } |
|
661 log_trace(symboltable)("Started to grow"); |
|
662 { |
|
663 TraceTime timer("Grow", TRACETIME_LOG(Debug, symboltable, perf)); |
|
664 while (gt.do_task(jt)) { |
|
665 gt.pause(jt); |
|
666 { |
|
667 ThreadBlockInVM tbivm(jt); |
|
668 } |
|
669 gt.cont(jt); |
|
670 } |
|
671 } |
|
672 gt.done(jt); |
|
673 _current_size = table_size(); |
|
674 log_debug(symboltable)("Grown to size:" SIZE_FORMAT, _current_size); |
|
675 } |
|
676 |
|
677 struct SymbolTableDoDelete : StackObj { |
|
678 int _deleted; |
|
679 SymbolTableDoDelete() : _deleted(0) {} |
|
680 void operator()(Symbol** value) { |
|
681 assert(value != NULL, "expected valid value"); |
|
682 assert(*value != NULL, "value should point to a symbol"); |
|
683 Symbol *sym = *value; |
|
684 assert(sym->refcount() == 0, "refcount"); |
|
685 _deleted++; |
|
686 } |
|
687 }; |
|
688 |
|
689 struct SymbolTableDeleteCheck : StackObj { |
|
690 int _processed; |
|
691 SymbolTableDeleteCheck() : _processed(0) {} |
|
692 bool operator()(Symbol** value) { |
|
693 assert(value != NULL, "expected valid value"); |
|
694 assert(*value != NULL, "value should point to a symbol"); |
|
695 _processed++; |
|
696 Symbol *sym = *value; |
|
697 return (sym->refcount() == 0); |
|
698 } |
|
699 }; |
|
700 |
|
701 void SymbolTable::clean_dead_entries(JavaThread* jt) { |
|
702 SymbolTableHash::BulkDeleteTask bdt(_local_table); |
|
703 if (!bdt.prepare(jt)) { |
|
704 return; |
|
705 } |
|
706 |
|
707 SymbolTableDeleteCheck stdc; |
|
708 SymbolTableDoDelete stdd; |
|
709 { |
|
710 TraceTime timer("Clean", TRACETIME_LOG(Debug, symboltable, perf)); |
|
711 while (bdt.do_task(jt, stdc, stdd)) { |
|
712 bdt.pause(jt); |
|
713 { |
|
714 ThreadBlockInVM tbivm(jt); |
|
715 } |
|
716 bdt.cont(jt); |
|
717 } |
|
718 SymbolTable::the_table()->set_item_clean_count(0); |
|
719 bdt.done(jt); |
|
720 } |
|
721 |
|
722 Atomic::add((size_t)stdc._processed, &_symbols_counted); |
|
723 |
|
724 log_debug(symboltable)("Cleaned " INT32_FORMAT " of " INT32_FORMAT, |
|
725 stdd._deleted, stdc._processed); |
|
726 } |
|
727 |
|
728 void SymbolTable::check_concurrent_work() { |
|
729 if (_has_work) { |
|
730 return; |
|
731 } |
|
732 double load_factor = SymbolTable::get_load_factor(); |
|
733 double dead_factor = SymbolTable::get_dead_factor(); |
|
734 // We should clean/resize if we have more dead than alive, |
|
735 // more items than preferred load factor or |
|
736 // more dead items than water mark. |
|
737 if ((dead_factor > load_factor) || |
|
738 (load_factor > PREF_AVG_LIST_LEN) || |
|
739 (dead_factor > CLEAN_DEAD_HIGH_WATER_MARK)) { |
|
740 log_debug(symboltable)("Concurrent work triggered, live factor:%f dead factor:%f", |
|
741 load_factor, dead_factor); |
|
742 trigger_concurrent_work(); |
|
743 } |
|
744 } |
|
745 |
|
746 void SymbolTable::concurrent_work(JavaThread* jt) { |
|
747 double load_factor = get_load_factor(); |
|
748 log_debug(symboltable, perf)("Concurrent work, live factor: %g", load_factor); |
|
749 // We prefer growing, since that also removes dead items |
|
750 if (load_factor > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) { |
|
751 grow(jt); |
|
752 } else { |
|
753 clean_dead_entries(jt); |
|
754 } |
|
755 _has_work = false; |
|
756 } |
|
757 |
|
758 class CountDead : StackObj { |
|
759 int _count; |
|
760 public: |
|
761 CountDead() : _count(0) {} |
|
762 bool operator()(Symbol** value) { |
|
763 assert(value != NULL, "expected valid value"); |
|
764 assert(*value != NULL, "value should point to a symbol"); |
|
765 Symbol* sym = *value; |
|
766 if (sym->refcount() == 0) { |
|
767 _count++; |
|
768 } |
|
769 return true; |
|
770 }; |
|
771 int get_dead_count() { |
|
772 return _count; |
|
773 } |
|
774 }; |
|
775 |
|
776 void SymbolTable::do_check_concurrent_work() { |
|
777 CountDead counter; |
|
778 if (!SymbolTable::the_table()->_local_table->try_scan(Thread::current(), counter)) { |
|
779 log_info(symboltable)("count dead unavailable at this moment"); |
|
780 } else { |
|
781 SymbolTable::the_table()->set_item_clean_count(counter.get_dead_count()); |
|
782 SymbolTable::the_table()->check_concurrent_work(); |
|
783 } |
|
784 } |
|
785 |
|
786 void SymbolTable::do_concurrent_work(JavaThread* jt) { |
|
787 SymbolTable::the_table()->concurrent_work(jt); |
|
788 } |
|
789 |
|
790 // Rehash |
|
791 bool SymbolTable::do_rehash() { |
|
792 if (!_local_table->is_safepoint_safe()) { |
|
793 return false; |
|
794 } |
|
795 |
|
796 // We use max size |
|
797 SymbolTableHash* new_table = new SymbolTableHash(END_SIZE, END_SIZE, REHASH_LEN); |
|
798 // Use alt hash from now on |
|
799 _alt_hash = true; |
|
800 if (!_local_table->try_move_nodes_to(Thread::current(), new_table)) { |
|
801 _alt_hash = false; |
|
802 delete new_table; |
|
803 return false; |
|
804 } |
|
805 |
|
806 // free old table |
|
807 delete _local_table; |
|
808 _local_table = new_table; |
|
809 |
|
810 return true; |
|
811 } |
|
812 |
|
813 void SymbolTable::try_rehash_table() { |
|
814 static bool rehashed = false; |
|
815 log_debug(symboltable)("Table imbalanced, rehashing called."); |
|
816 |
|
817 // Grow instead of rehash. |
|
818 if (get_load_factor() > PREF_AVG_LIST_LEN && |
|
819 !_local_table->is_max_size_reached()) { |
|
820 log_debug(symboltable)("Choosing growing over rehashing."); |
|
821 trigger_concurrent_work(); |
|
822 _needs_rehashing = false; |
|
823 return; |
|
824 } |
|
825 |
|
826 // Already rehashed. |
|
827 if (rehashed) { |
|
828 log_warning(symboltable)("Rehashing already done, still long lists."); |
|
829 trigger_concurrent_work(); |
|
830 _needs_rehashing = false; |
|
831 return; |
|
832 } |
|
833 |
|
834 murmur_seed = AltHashing::compute_seed(); |
|
835 |
|
836 if (do_rehash()) { |
|
837 rehashed = true; |
|
838 } else { |
|
839 log_info(symboltable)("Resizes in progress rehashing skipped."); |
|
840 } |
|
841 |
|
842 _needs_rehashing = false; |
|
843 } |
|
844 |
|
845 void SymbolTable::rehash_table() { |
|
846 SymbolTable::the_table()->try_rehash_table(); |
630 } |
847 } |
631 |
848 |
632 //--------------------------------------------------------------------------- |
849 //--------------------------------------------------------------------------- |
633 // Non-product code |
850 // Non-product code |
634 |
851 |
635 #ifndef PRODUCT |
852 #ifndef PRODUCT |
636 |
853 |
|
854 class HistogramIterator : StackObj { |
|
855 public: |
|
856 static const size_t results_length = 100; |
|
857 size_t counts[results_length]; |
|
858 size_t sizes[results_length]; |
|
859 size_t total_size; |
|
860 size_t total_count; |
|
861 size_t total_length; |
|
862 size_t max_length; |
|
863 size_t out_of_range_count; |
|
864 size_t out_of_range_size; |
|
865 HistogramIterator() : total_size(0), total_count(0), total_length(0), |
|
866 max_length(0), out_of_range_count(0), out_of_range_size(0) { |
|
867 // initialize results to zero |
|
868 for (size_t i = 0; i < results_length; i++) { |
|
869 counts[i] = 0; |
|
870 sizes[i] = 0; |
|
871 } |
|
872 } |
|
873 bool operator()(Symbol** value) { |
|
874 assert(value != NULL, "expected valid value"); |
|
875 assert(*value != NULL, "value should point to a symbol"); |
|
876 Symbol* sym = *value; |
|
877 size_t size = sym->size(); |
|
878 size_t len = sym->utf8_length(); |
|
879 if (len < results_length) { |
|
880 counts[len]++; |
|
881 sizes[len] += size; |
|
882 } else { |
|
883 out_of_range_count++; |
|
884 out_of_range_size += size; |
|
885 } |
|
886 total_count++; |
|
887 total_size += size; |
|
888 total_length += len; |
|
889 max_length = MAX2(max_length, len); |
|
890 |
|
891 return true; |
|
892 }; |
|
893 }; |
|
894 |
637 void SymbolTable::print_histogram() { |
895 void SymbolTable::print_histogram() { |
638 MutexLocker ml(SymbolTable_lock); |
896 SymbolTable* st = SymbolTable::the_table(); |
639 const int results_length = 100; |
897 HistogramIterator hi; |
640 int counts[results_length]; |
898 st->_local_table->do_scan(Thread::current(), hi); |
641 int sizes[results_length]; |
|
642 int i,j; |
|
643 |
|
644 // initialize results to zero |
|
645 for (j = 0; j < results_length; j++) { |
|
646 counts[j] = 0; |
|
647 sizes[j] = 0; |
|
648 } |
|
649 |
|
650 int total_size = 0; |
|
651 int total_count = 0; |
|
652 int total_length = 0; |
|
653 int max_length = 0; |
|
654 int out_of_range_count = 0; |
|
655 int out_of_range_size = 0; |
|
656 for (i = 0; i < the_table()->table_size(); i++) { |
|
657 HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); |
|
658 for ( ; p != NULL; p = p->next()) { |
|
659 int size = p->literal()->size(); |
|
660 int len = p->literal()->utf8_length(); |
|
661 if (len < results_length) { |
|
662 counts[len]++; |
|
663 sizes[len] += size; |
|
664 } else { |
|
665 out_of_range_count++; |
|
666 out_of_range_size += size; |
|
667 } |
|
668 total_count++; |
|
669 total_size += size; |
|
670 total_length += len; |
|
671 max_length = MAX2(max_length, len); |
|
672 } |
|
673 } |
|
674 tty->print_cr("Symbol Table Histogram:"); |
899 tty->print_cr("Symbol Table Histogram:"); |
675 tty->print_cr(" Total number of symbols %7d", total_count); |
900 tty->print_cr(" Total number of symbols " SIZE_FORMAT_W(7), hi.total_count); |
676 tty->print_cr(" Total size in memory %7dK", |
901 tty->print_cr(" Total size in memory " SIZE_FORMAT_W(7) "K", |
677 (total_size*wordSize)/1024); |
902 (hi.total_size * wordSize) / 1024); |
678 tty->print_cr(" Total counted %7d", _symbols_counted); |
903 tty->print_cr(" Total counted " SIZE_FORMAT_W(7), st->_symbols_counted); |
679 tty->print_cr(" Total removed %7d", _symbols_removed); |
904 tty->print_cr(" Total removed " SIZE_FORMAT_W(7), st->_symbols_removed); |
680 if (_symbols_counted > 0) { |
905 if (SymbolTable::the_table()->_symbols_counted > 0) { |
681 tty->print_cr(" Percent removed %3.2f", |
906 tty->print_cr(" Percent removed %3.2f", |
682 ((float)_symbols_removed/(float)_symbols_counted)* 100); |
907 ((float)st->_symbols_removed / st->_symbols_counted) * 100); |
683 } |
908 } |
684 tty->print_cr(" Reference counts %7d", Symbol::_total_count); |
909 tty->print_cr(" Reference counts " SIZE_FORMAT_W(7), Symbol::_total_count); |
685 tty->print_cr(" Symbol arena used " SIZE_FORMAT_W(7) "K", arena()->used()/1024); |
910 tty->print_cr(" Symbol arena used " SIZE_FORMAT_W(7) "K", arena()->used() / 1024); |
686 tty->print_cr(" Symbol arena size " SIZE_FORMAT_W(7) "K", arena()->size_in_bytes()/1024); |
911 tty->print_cr(" Symbol arena size " SIZE_FORMAT_W(7) "K", arena()->size_in_bytes() / 1024); |
687 tty->print_cr(" Total symbol length %7d", total_length); |
912 tty->print_cr(" Total symbol length " SIZE_FORMAT_W(7), hi.total_length); |
688 tty->print_cr(" Maximum symbol length %7d", max_length); |
913 tty->print_cr(" Maximum symbol length " SIZE_FORMAT_W(7), hi.max_length); |
689 tty->print_cr(" Average symbol length %7.2f", ((float) total_length / (float) total_count)); |
914 tty->print_cr(" Average symbol length %7.2f", ((float)hi.total_length / hi.total_count)); |
690 tty->print_cr(" Symbol length histogram:"); |
915 tty->print_cr(" Symbol length histogram:"); |
691 tty->print_cr(" %6s %10s %10s", "Length", "#Symbols", "Size"); |
916 tty->print_cr(" %6s %10s %10s", "Length", "#Symbols", "Size"); |
692 for (i = 0; i < results_length; i++) { |
917 for (size_t i = 0; i < hi.results_length; i++) { |
693 if (counts[i] > 0) { |
918 if (hi.counts[i] > 0) { |
694 tty->print_cr(" %6d %10d %10dK", i, counts[i], (sizes[i]*wordSize)/1024); |
919 tty->print_cr(" " SIZE_FORMAT_W(6) " " SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10) "K", |
695 } |
920 i, hi.counts[i], (hi.sizes[i] * wordSize) / 1024); |
696 } |
921 } |
697 tty->print_cr(" >=%6d %10d %10dK\n", results_length, |
922 } |
698 out_of_range_count, (out_of_range_size*wordSize)/1024); |
923 tty->print_cr(" >=" SIZE_FORMAT_W(6) " " SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10) "K\n", |
699 } |
924 hi.results_length, hi.out_of_range_count, (hi.out_of_range_size*wordSize) / 1024); |
700 |
|
701 void SymbolTable::print() { |
|
702 for (int i = 0; i < the_table()->table_size(); ++i) { |
|
703 HashtableEntry<Symbol*, mtSymbol>** p = the_table()->bucket_addr(i); |
|
704 HashtableEntry<Symbol*, mtSymbol>* entry = the_table()->bucket(i); |
|
705 if (entry != NULL) { |
|
706 while (entry != NULL) { |
|
707 tty->print(PTR_FORMAT " ", p2i(entry->literal())); |
|
708 entry->literal()->print(); |
|
709 tty->print(" %d", entry->literal()->refcount()); |
|
710 p = entry->next_addr(); |
|
711 entry = (HashtableEntry<Symbol*, mtSymbol>*)HashtableEntry<Symbol*, mtSymbol>::make_ptr(*p); |
|
712 } |
|
713 tty->cr(); |
|
714 } |
|
715 } |
|
716 } |
925 } |
717 #endif // PRODUCT |
926 #endif // PRODUCT |
718 |
|
719 |
927 |
720 // Utility for dumping symbols |
928 // Utility for dumping symbols |
721 SymboltableDCmd::SymboltableDCmd(outputStream* output, bool heap) : |
929 SymboltableDCmd::SymboltableDCmd(outputStream* output, bool heap) : |
722 DCmdWithParser(output, heap), |
930 DCmdWithParser(output, heap), |
723 _verbose("-verbose", "Dump the content of each symbol in the table", |
931 _verbose("-verbose", "Dump the content of each symbol in the table", |