46 |
46 |
47 Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS) { |
47 Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS) { |
48 assert (len <= Symbol::max_length(), "should be checked by caller"); |
48 assert (len <= Symbol::max_length(), "should be checked by caller"); |
49 |
49 |
50 Symbol* sym; |
50 Symbol* sym; |
51 // Allocate symbols in the C heap when dumping shared spaces in case there |
51 |
52 // are temporary symbols we can remove. |
52 if (c_heap) { |
53 if (c_heap || DumpSharedSpaces) { |
|
54 // refcount starts as 1 |
53 // refcount starts as 1 |
|
54 assert(!DumpSharedSpaces, "never allocate to C heap"); |
55 sym = new (len, THREAD) Symbol(name, len, 1); |
55 sym = new (len, THREAD) Symbol(name, len, 1); |
|
56 assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted"); |
|
57 } else { |
|
58 if (DumpSharedSpaces) { |
|
59 sym = new (len, ClassLoaderData::the_null_class_loader_data(), THREAD) Symbol(name, len, -1); |
56 } else { |
60 } else { |
57 sym = new (len, arena(), THREAD) Symbol(name, len, -1); |
61 sym = new (len, arena(), THREAD) Symbol(name, len, -1); |
58 } |
62 } |
59 assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted"); |
63 } |
60 return sym; |
64 return sym; |
61 } |
65 } |
62 |
66 |
63 void SymbolTable::initialize_symbols(int arena_alloc_size) { |
67 void SymbolTable::initialize_symbols(int arena_alloc_size) { |
64 // Initialize the arena for global symbols, size passed in depends on CDS. |
68 // Initialize the arena for global symbols, size passed in depends on CDS. |
100 // end of the bucket. |
104 // end of the bucket. |
101 if (entry->is_shared() && !use_alternate_hashcode()) { |
105 if (entry->is_shared() && !use_alternate_hashcode()) { |
102 break; |
106 break; |
103 } |
107 } |
104 Symbol* s = entry->literal(); |
108 Symbol* s = entry->literal(); |
105 memory_total += s->object_size(); |
109 memory_total += s->size(); |
106 total++; |
110 total++; |
107 assert(s != NULL, "just checking"); |
111 assert(s != NULL, "just checking"); |
108 // If reference count is zero, remove. |
112 // If reference count is zero, remove. |
109 if (s->refcount() == 0) { |
113 if (s->refcount() == 0) { |
110 assert(!entry->is_shared(), "shared entries should be kept live"); |
114 assert(!entry->is_shared(), "shared entries should be kept live"); |
300 UNICODE::convert_to_utf8(name, utf16_length, chars); |
304 UNICODE::convert_to_utf8(name, utf16_length, chars); |
301 return lookup_only(chars, utf8_length, hash); |
305 return lookup_only(chars, utf8_length, hash); |
302 } |
306 } |
303 } |
307 } |
304 |
308 |
305 void SymbolTable::add(Handle class_loader, constantPoolHandle cp, |
309 void SymbolTable::add(ClassLoaderData* loader_data, constantPoolHandle cp, |
306 int names_count, |
310 int names_count, |
307 const char** names, int* lengths, int* cp_indices, |
311 const char** names, int* lengths, int* cp_indices, |
308 unsigned int* hashValues, TRAPS) { |
312 unsigned int* hashValues, TRAPS) { |
309 // Grab SymbolTable_lock first. |
313 // Grab SymbolTable_lock first. |
310 MutexLocker ml(SymbolTable_lock, THREAD); |
314 MutexLocker ml(SymbolTable_lock, THREAD); |
311 |
315 |
312 SymbolTable* table = the_table(); |
316 SymbolTable* table = the_table(); |
313 bool added = table->basic_add(class_loader, cp, names_count, names, lengths, |
317 bool added = table->basic_add(loader_data, cp, names_count, names, lengths, |
314 cp_indices, hashValues, CHECK); |
318 cp_indices, hashValues, CHECK); |
315 if (!added) { |
319 if (!added) { |
316 // do it the hard way |
320 // do it the hard way |
317 for (int i=0; i<names_count; i++) { |
321 for (int i=0; i<names_count; i++) { |
318 int index = table->hash_to_index(hashValues[i]); |
322 int index = table->hash_to_index(hashValues[i]); |
319 bool c_heap = class_loader() != NULL; |
323 bool c_heap = !loader_data->is_the_null_class_loader_data(); |
320 Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], hashValues[i], c_heap, CHECK); |
324 Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], hashValues[i], c_heap, CHECK); |
321 cp->symbol_at_put(cp_indices[i], sym); |
325 cp->symbol_at_put(cp_indices[i], sym); |
322 } |
326 } |
323 } |
327 } |
324 } |
328 } |
381 return sym; |
385 return sym; |
382 } |
386 } |
383 |
387 |
384 // This version of basic_add adds symbols in batch from the constant pool |
388 // This version of basic_add adds symbols in batch from the constant pool |
385 // parsing. |
389 // parsing. |
386 bool SymbolTable::basic_add(Handle class_loader, constantPoolHandle cp, |
390 bool SymbolTable::basic_add(ClassLoaderData* loader_data, constantPoolHandle cp, |
387 int names_count, |
391 int names_count, |
388 const char** names, int* lengths, |
392 const char** names, int* lengths, |
389 int* cp_indices, unsigned int* hashValues, |
393 int* cp_indices, unsigned int* hashValues, |
390 TRAPS) { |
394 TRAPS) { |
391 |
395 |
419 cp->symbol_at_put(cp_indices[i], test); |
423 cp->symbol_at_put(cp_indices[i], test); |
420 assert(test->refcount() != 0, "lookup should have incremented the count"); |
424 assert(test->refcount() != 0, "lookup should have incremented the count"); |
421 } else { |
425 } else { |
422 // Create a new symbol. The null class loader is never unloaded so these |
426 // Create a new symbol. The null class loader is never unloaded so these |
423 // are allocated specially in a permanent arena. |
427 // are allocated specially in a permanent arena. |
424 bool c_heap = class_loader() != NULL; |
428 bool c_heap = !loader_data->is_the_null_class_loader_data(); |
425 Symbol* sym = allocate_symbol((const u1*)names[i], lengths[i], c_heap, CHECK_(false)); |
429 Symbol* sym = allocate_symbol((const u1*)names[i], lengths[i], c_heap, CHECK_(false)); |
426 assert(sym->equals(names[i], lengths[i]), "symbol must be properly initialized"); // why wouldn't it be??? |
430 assert(sym->equals(names[i], lengths[i]), "symbol must be properly initialized"); // why wouldn't it be??? |
427 HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym); |
431 HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym); |
428 add_entry(index, entry); |
432 add_entry(index, entry); |
429 cp->symbol_at_put(cp_indices[i], sym); |
433 cp->symbol_at_put(cp_indices[i], sym); |
488 int memory_total = 0; |
492 int memory_total = 0; |
489 int count = 0; |
493 int count = 0; |
490 for (i = 0; i < the_table()->table_size(); i++) { |
494 for (i = 0; i < the_table()->table_size(); i++) { |
491 HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); |
495 HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); |
492 for ( ; p != NULL; p = p->next()) { |
496 for ( ; p != NULL; p = p->next()) { |
493 memory_total += p->literal()->object_size(); |
497 memory_total += p->literal()->size(); |
494 count++; |
498 count++; |
495 int counter = p->literal()->utf8_length(); |
499 int counter = p->literal()->utf8_length(); |
496 total += counter; |
500 total += counter; |
497 if (counter < results_length) { |
501 if (counter < results_length) { |
498 results[counter]++; |
502 results[counter]++; |
693 assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(), |
697 assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(), |
694 "proposed name of symbol must be stable"); |
698 "proposed name of symbol must be stable"); |
695 |
699 |
696 Handle string; |
700 Handle string; |
697 // try to reuse the string if possible |
701 // try to reuse the string if possible |
698 if (!string_or_null.is_null() && (!JavaObjectsInPerm || string_or_null()->is_perm())) { |
702 if (!string_or_null.is_null()) { |
699 string = string_or_null; |
703 string = string_or_null; |
700 } else { |
704 } else { |
701 string = java_lang_String::create_tenured_from_unicode(name, len, CHECK_NULL); |
705 string = java_lang_String::create_from_unicode(name, len, CHECK_NULL); |
702 } |
706 } |
703 |
707 |
704 // Grab the StringTable_lock before getting the_table() because it could |
708 // Grab the StringTable_lock before getting the_table() because it could |
705 // change at safepoint. |
709 // change at safepoint. |
706 MutexLocker ml(StringTable_lock, THREAD); |
710 MutexLocker ml(StringTable_lock, THREAD); |
795 for (int i = 0; i < the_table()->table_size(); ++i) { |
799 for (int i = 0; i < the_table()->table_size(); ++i) { |
796 HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i); |
800 HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i); |
797 for ( ; p != NULL; p = p->next()) { |
801 for ( ; p != NULL; p = p->next()) { |
798 oop s = p->literal(); |
802 oop s = p->literal(); |
799 guarantee(s != NULL, "interned string is NULL"); |
803 guarantee(s != NULL, "interned string is NULL"); |
800 guarantee(s->is_perm() || !JavaObjectsInPerm, "interned string not in permspace"); |
|
801 unsigned int h = java_lang_String::hash_string(s); |
804 unsigned int h = java_lang_String::hash_string(s); |
802 guarantee(p->hash() == h, "broken hash in string table entry"); |
805 guarantee(p->hash() == h, "broken hash in string table entry"); |
803 guarantee(the_table()->hash_to_index(h) == i, |
806 guarantee(the_table()->hash_to_index(h) == i, |
804 "wrong index in string table"); |
807 "wrong index in string table"); |
805 } |
808 } |