193 MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag); |
193 MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag); |
194 SymbolTable::the_table()->_has_work = true; |
194 SymbolTable::the_table()->_has_work = true; |
195 Service_lock->notify_all(); |
195 Service_lock->notify_all(); |
196 } |
196 } |
197 |
197 |
198 Symbol* SymbolTable::allocate_symbol(const char* name, int len, bool c_heap, TRAPS) { |
198 Symbol* SymbolTable::allocate_symbol(const char* name, int len, bool c_heap) { |
199 assert (len <= Symbol::max_length(), "should be checked by caller"); |
199 assert (len <= Symbol::max_length(), "should be checked by caller"); |
200 |
200 |
201 Symbol* sym; |
201 Symbol* sym; |
202 if (DumpSharedSpaces) { |
202 if (DumpSharedSpaces) { |
203 c_heap = false; |
203 c_heap = false; |
204 } |
204 } |
205 if (c_heap) { |
205 if (c_heap) { |
206 // refcount starts as 1 |
206 // refcount starts as 1 |
207 sym = new (len, THREAD) Symbol((const u1*)name, len, 1); |
207 sym = new (len) Symbol((const u1*)name, len, 1); |
208 assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted"); |
208 assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted"); |
209 } else { |
209 } else { |
210 // Allocate to global arena |
210 // Allocate to global arena |
211 MutexLocker ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena |
211 MutexLocker ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena |
212 sym = new (len, arena(), THREAD) Symbol((const u1*)name, len, PERM_REFCOUNT); |
212 sym = new (len, arena()) Symbol((const u1*)name, len, PERM_REFCOUNT); |
213 } |
213 } |
214 return sym; |
214 return sym; |
215 } |
215 } |
216 |
216 |
217 void SymbolTable::initialize_symbols(int arena_alloc_size) { |
217 void SymbolTable::initialize_symbols(int arena_alloc_size) { |
315 } |
315 } |
316 } |
316 } |
317 return sym; |
317 return sym; |
318 } |
318 } |
319 |
319 |
320 Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) { |
320 Symbol* SymbolTable::new_symbol(const char* name, int len) { |
321 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash); |
321 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash); |
322 Symbol* sym = SymbolTable::the_table()->lookup_common(name, len, hash); |
322 Symbol* sym = SymbolTable::the_table()->lookup_common(name, len, hash); |
323 if (sym == NULL) { |
323 if (sym == NULL) { |
324 sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, true, CHECK_NULL); |
324 sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, true); |
325 } |
325 } |
326 assert(sym->refcount() != 0, "lookup should have incremented the count"); |
326 assert(sym->refcount() != 0, "lookup should have incremented the count"); |
327 assert(sym->equals(name, len), "symbol must be properly initialized"); |
327 assert(sym->equals(name, len), "symbol must be properly initialized"); |
328 return sym; |
328 return sym; |
329 } |
329 } |
330 |
330 |
331 Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) { |
331 Symbol* SymbolTable::new_symbol(const Symbol* sym, int begin, int end) { |
|
332 assert(begin <= end && end <= sym->utf8_length(), "just checking"); |
332 assert(sym->refcount() != 0, "require a valid symbol"); |
333 assert(sym->refcount() != 0, "require a valid symbol"); |
333 const char* name = (const char*)sym->base() + begin; |
334 const char* name = (const char*)sym->base() + begin; |
334 int len = end - begin; |
335 int len = end - begin; |
335 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash); |
336 unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash); |
336 Symbol* found = SymbolTable::the_table()->lookup_common(name, len, hash); |
337 Symbol* found = SymbolTable::the_table()->lookup_common(name, len, hash); |
337 if (found == NULL) { |
338 if (found == NULL) { |
338 found = SymbolTable::the_table()->do_add_if_needed(name, len, hash, true, THREAD); |
339 found = SymbolTable::the_table()->do_add_if_needed(name, len, hash, true); |
339 } |
340 } |
340 return found; |
341 return found; |
341 } |
342 } |
342 |
343 |
343 class SymbolTableLookup : StackObj { |
344 class SymbolTableLookup : StackObj { |
345 Thread* _thread; |
346 Thread* _thread; |
346 uintx _hash; |
347 uintx _hash; |
347 int _len; |
348 int _len; |
348 const char* _str; |
349 const char* _str; |
349 public: |
350 public: |
350 SymbolTableLookup(Thread* thread, const char* key, int len, uintx hash) |
351 SymbolTableLookup(const char* key, int len, uintx hash) |
351 : _thread(thread), _hash(hash), _len(len), _str(key) {} |
352 : _hash(hash), _len(len), _str(key) {} |
352 uintx get_hash() const { |
353 uintx get_hash() const { |
353 return _hash; |
354 return _hash; |
354 } |
355 } |
355 bool equals(Symbol** value, bool* is_dead) { |
356 bool equals(Symbol** value, bool* is_dead) { |
356 assert(value != NULL, "expected valid value"); |
357 assert(value != NULL, "expected valid value"); |
386 } |
387 } |
387 }; |
388 }; |
388 |
389 |
389 Symbol* SymbolTable::do_lookup(const char* name, int len, uintx hash) { |
390 Symbol* SymbolTable::do_lookup(const char* name, int len, uintx hash) { |
390 Thread* thread = Thread::current(); |
391 Thread* thread = Thread::current(); |
391 SymbolTableLookup lookup(thread, name, len, hash); |
392 SymbolTableLookup lookup(name, len, hash); |
392 SymbolTableGet stg; |
393 SymbolTableGet stg; |
393 bool rehash_warning = false; |
394 bool rehash_warning = false; |
394 _local_table->get(thread, lookup, stg, &rehash_warning); |
395 _local_table->get(thread, lookup, stg, &rehash_warning); |
395 update_needs_rehash(rehash_warning); |
396 update_needs_rehash(rehash_warning); |
396 Symbol* sym = stg.get_res_sym(); |
397 Symbol* sym = stg.get_res_sym(); |
404 } |
405 } |
405 |
406 |
406 // Suggestion: Push unicode-based lookup all the way into the hashing |
407 // Suggestion: Push unicode-based lookup all the way into the hashing |
407 // and probing logic, so there is no need for convert_to_utf8 until |
408 // and probing logic, so there is no need for convert_to_utf8 until |
408 // an actual new Symbol* is created. |
409 // an actual new Symbol* is created. |
409 Symbol* SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) { |
410 Symbol* SymbolTable::new_symbol(const jchar* name, int utf16_length) { |
410 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); |
411 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); |
411 char stack_buf[ON_STACK_BUFFER_LENGTH]; |
412 char stack_buf[ON_STACK_BUFFER_LENGTH]; |
412 if (utf8_length < (int) sizeof(stack_buf)) { |
413 if (utf8_length < (int) sizeof(stack_buf)) { |
413 char* chars = stack_buf; |
414 char* chars = stack_buf; |
414 UNICODE::convert_to_utf8(name, utf16_length, chars); |
415 UNICODE::convert_to_utf8(name, utf16_length, chars); |
415 return lookup(chars, utf8_length, THREAD); |
416 return new_symbol(chars, utf8_length); |
416 } else { |
417 } else { |
417 ResourceMark rm(THREAD); |
418 ResourceMark rm; |
418 char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1); |
419 char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1); |
419 UNICODE::convert_to_utf8(name, utf16_length, chars); |
420 UNICODE::convert_to_utf8(name, utf16_length, chars); |
420 return lookup(chars, utf8_length, THREAD); |
421 return new_symbol(chars, utf8_length); |
421 } |
422 } |
422 } |
423 } |
423 |
424 |
424 Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length, |
425 Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length, |
425 unsigned int& hash) { |
426 unsigned int& hash) { |
426 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); |
427 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); |
427 char stack_buf[ON_STACK_BUFFER_LENGTH]; |
428 char stack_buf[ON_STACK_BUFFER_LENGTH]; |
428 if (utf8_length < (int) sizeof(stack_buf)) { |
429 if (utf8_length < (int) sizeof(stack_buf)) { |
429 char* chars = stack_buf; |
430 char* chars = stack_buf; |
430 UNICODE::convert_to_utf8(name, utf16_length, chars); |
431 UNICODE::convert_to_utf8(name, utf16_length, chars); |
437 } |
438 } |
438 } |
439 } |
439 |
440 |
440 void SymbolTable::new_symbols(ClassLoaderData* loader_data, const constantPoolHandle& cp, |
441 void SymbolTable::new_symbols(ClassLoaderData* loader_data, const constantPoolHandle& cp, |
441 int names_count, const char** names, int* lengths, |
442 int names_count, const char** names, int* lengths, |
442 int* cp_indices, unsigned int* hashValues, TRAPS) { |
443 int* cp_indices, unsigned int* hashValues) { |
443 bool c_heap = !loader_data->is_the_null_class_loader_data(); |
444 bool c_heap = !loader_data->is_the_null_class_loader_data(); |
444 for (int i = 0; i < names_count; i++) { |
445 for (int i = 0; i < names_count; i++) { |
445 const char *name = names[i]; |
446 const char *name = names[i]; |
446 int len = lengths[i]; |
447 int len = lengths[i]; |
447 unsigned int hash = hashValues[i]; |
448 unsigned int hash = hashValues[i]; |
448 assert(SymbolTable::the_table()->lookup_shared(name, len, hash) == NULL, "must have checked already"); |
449 assert(SymbolTable::the_table()->lookup_shared(name, len, hash) == NULL, "must have checked already"); |
449 Symbol* sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, c_heap, CHECK); |
450 Symbol* sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, c_heap); |
450 assert(sym->refcount() != 0, "lookup should have incremented the count"); |
451 assert(sym->refcount() != 0, "lookup should have incremented the count"); |
451 cp->symbol_at_put(cp_indices[i], sym); |
452 cp->symbol_at_put(cp_indices[i], sym); |
452 } |
453 } |
453 } |
454 } |
454 |
455 |
455 Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, bool heap, TRAPS) { |
456 Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, bool heap) { |
456 SymbolTableLookup lookup(THREAD, name, len, hash); |
457 SymbolTableLookup lookup(name, len, hash); |
457 SymbolTableGet stg; |
458 SymbolTableGet stg; |
458 bool clean_hint = false; |
459 bool clean_hint = false; |
459 bool rehash_warning = false; |
460 bool rehash_warning = false; |
460 Symbol* sym = NULL; |
461 Symbol* sym = NULL; |
|
462 Thread* THREAD = Thread::current(); |
461 |
463 |
462 do { |
464 do { |
463 if (_local_table->get(THREAD, lookup, stg, &rehash_warning)) { |
465 if (_local_table->get(THREAD, lookup, stg, &rehash_warning)) { |
464 sym = stg.get_res_sym(); |
466 sym = stg.get_res_sym(); |
465 break; |
467 break; |
466 } |
468 } |
467 sym = SymbolTable::the_table()->allocate_symbol(name, len, heap, THREAD); |
469 sym = SymbolTable::the_table()->allocate_symbol(name, len, heap); |
468 if (_local_table->insert(THREAD, lookup, sym, &rehash_warning, &clean_hint)) { |
470 if (_local_table->insert(THREAD, lookup, sym, &rehash_warning, &clean_hint)) { |
469 break; |
471 break; |
470 } |
472 } |
471 } while(true); |
473 } while(true); |
472 |
474 |
479 |
481 |
480 assert((sym == NULL) || sym->refcount() != 0, "found dead symbol"); |
482 assert((sym == NULL) || sym->refcount() != 0, "found dead symbol"); |
481 return sym; |
483 return sym; |
482 } |
484 } |
483 |
485 |
484 Symbol* SymbolTable::new_permanent_symbol(const char* name, TRAPS) { |
486 Symbol* SymbolTable::new_permanent_symbol(const char* name) { |
485 unsigned int hash = 0; |
487 unsigned int hash = 0; |
486 int len = (int)strlen(name); |
488 int len = (int)strlen(name); |
487 Symbol* sym = SymbolTable::lookup_only(name, len, hash); |
489 Symbol* sym = SymbolTable::lookup_only(name, len, hash); |
488 if (sym == NULL) { |
490 if (sym == NULL) { |
489 sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, false, CHECK_NULL); |
491 sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, false); |
490 } |
492 } |
491 if (!sym->is_permanent()) { |
493 if (!sym->is_permanent()) { |
492 sym->make_permanent(); |
494 sym->make_permanent(); |
493 log_trace_symboltable_helper(sym, "Asked for a permanent symbol, but got a regular one"); |
495 log_trace_symboltable_helper(sym, "Asked for a permanent symbol, but got a regular one"); |
494 } |
496 } |