1.1 --- a/src/share/vm/classfile/symbolTable.cpp Thu Jan 27 13:42:28 2011 -0800 1.2 +++ b/src/share/vm/classfile/symbolTable.cpp Thu Jan 27 16:11:27 2011 -0800 1.3 @@ -31,7 +31,6 @@ 1.4 #include "memory/gcLocker.inline.hpp" 1.5 #include "oops/oop.inline.hpp" 1.6 #include "oops/oop.inline2.hpp" 1.7 -#include "oops/symbolKlass.hpp" 1.8 #include "runtime/mutexLocker.hpp" 1.9 #include "utilities/hashtable.inline.hpp" 1.10 1.11 @@ -39,14 +38,97 @@ 1.12 1.13 SymbolTable* SymbolTable::_the_table = NULL; 1.14 1.15 +Symbol* SymbolTable::allocate_symbol(const u1* name, int len, TRAPS) { 1.16 + // Don't allow symbols to be created which cannot fit in a Symbol*. 1.17 + if (len > Symbol::max_length()) { 1.18 + THROW_MSG_0(vmSymbols::java_lang_InternalError(), 1.19 + "name is too long to represent"); 1.20 + } 1.21 + Symbol* sym = new (len) Symbol(name, len); 1.22 + assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted"); 1.23 + return sym; 1.24 +} 1.25 + 1.26 +bool SymbolTable::allocate_symbols(int names_count, const u1** names, 1.27 + int* lengths, Symbol** syms, TRAPS) { 1.28 + for (int i = 0; i< names_count; i++) { 1.29 + if (lengths[i] > Symbol::max_length()) { 1.30 + THROW_MSG_0(vmSymbols::java_lang_InternalError(), 1.31 + "name is too long to represent"); 1.32 + } 1.33 + } 1.34 + 1.35 + for (int i = 0; i< names_count; i++) { 1.36 + int len = lengths[i]; 1.37 + syms[i] = new (len) Symbol(names[i], len); 1.38 + assert(syms[i] != NULL, "new should call vm_exit_out_of_memory if " 1.39 + "C_HEAP is exhausted"); 1.40 + } 1.41 + return true; 1.42 +} 1.43 + 1.44 +// Call function for all symbols in the symbol table. 1.45 +void SymbolTable::symbols_do(SymbolClosure *cl) { 1.46 + const int n = the_table()->table_size(); 1.47 + for (int i = 0; i < n; i++) { 1.48 + for (HashtableEntry<Symbol*>* p = the_table()->bucket(i); 1.49 + p != NULL; 1.50 + p = p->next()) { 1.51 + cl->do_symbol(p->literal_addr()); 1.52 + } 1.53 + } 1.54 +} 1.55 + 1.56 +int SymbolTable::symbols_removed = 0; 1.57 +int SymbolTable::symbols_counted = 0; 1.58 + 1.59 +// Remove unreferenced symbols from the symbol table 1.60 +// This is done late during GC. This doesn't use the hash table unlink because 1.61 +// it assumes that the literals are oops. 1.62 +void SymbolTable::unlink() { 1.63 + int removed = 0; 1.64 + int total = 0; 1.65 + int memory_total = 0; 1.66 + for (int i = 0; i < the_table()->table_size(); ++i) { 1.67 + for (HashtableEntry<Symbol*>** p = the_table()->bucket_addr(i); *p != NULL; ) { 1.68 + HashtableEntry<Symbol*>* entry = *p; 1.69 + if (entry->is_shared()) { 1.70 + break; 1.71 + } 1.72 + Symbol* s = entry->literal(); 1.73 + memory_total += s->object_size(); 1.74 + total++; 1.75 + assert(s != NULL, "just checking"); 1.76 + // If reference count is zero, remove. 1.77 + if (s->refcount() == 0) { 1.78 + delete s; 1.79 + removed++; 1.80 + *p = entry->next(); 1.81 + the_table()->free_entry(entry); 1.82 + } else { 1.83 + p = entry->next_addr(); 1.84 + } 1.85 + } 1.86 + } 1.87 + symbols_removed += removed; 1.88 + symbols_counted += total; 1.89 + if (PrintGCDetails) { 1.90 + gclog_or_tty->print(" [Symbols=%d size=%dK] ", total, 1.91 + (memory_total*HeapWordSize)/1024); 1.92 + } 1.93 +} 1.94 + 1.95 + 1.96 // Lookup a symbol in a bucket. 1.97 1.98 -symbolOop SymbolTable::lookup(int index, const char* name, 1.99 +Symbol* SymbolTable::lookup(int index, const char* name, 1.100 int len, unsigned int hash) { 1.101 - for (HashtableEntry* e = bucket(index); e != NULL; e = e->next()) { 1.102 + for (HashtableEntry<Symbol*>* e = bucket(index); e != NULL; e = e->next()) { 1.103 if (e->hash() == hash) { 1.104 - symbolOop sym = symbolOop(e->literal()); 1.105 + Symbol* sym = e->literal(); 1.106 if (sym->equals(name, len)) { 1.107 + // something is referencing this symbol now. 1.108 + sym->increment_refcount(); 1.109 return sym; 1.110 } 1.111 } 1.112 @@ -62,11 +144,11 @@ 1.113 // entries in the symbol table during normal execution (only during 1.114 // safepoints). 1.115 1.116 -symbolOop SymbolTable::lookup(const char* name, int len, TRAPS) { 1.117 +Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) { 1.118 unsigned int hashValue = hash_symbol(name, len); 1.119 int index = the_table()->hash_to_index(hashValue); 1.120 1.121 - symbolOop s = the_table()->lookup(index, name, len, hashValue); 1.122 + Symbol* s = the_table()->lookup(index, name, len, hashValue); 1.123 1.124 // Found 1.125 if (s != NULL) return s; 1.126 @@ -75,7 +157,7 @@ 1.127 return the_table()->basic_add(index, (u1*)name, len, hashValue, CHECK_NULL); 1.128 } 1.129 1.130 -symbolOop SymbolTable::lookup(symbolHandle sym, int begin, int end, TRAPS) { 1.131 +Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) { 1.132 char* buffer; 1.133 int index, len; 1.134 unsigned int hashValue; 1.135 @@ -87,7 +169,7 @@ 1.136 len = end - begin; 1.137 hashValue = hash_symbol(name, len); 1.138 index = the_table()->hash_to_index(hashValue); 1.139 - symbolOop s = the_table()->lookup(index, name, len, hashValue); 1.140 + Symbol* s = the_table()->lookup(index, name, len, hashValue); 1.141 1.142 // Found 1.143 if (s != NULL) return s; 1.144 @@ -111,18 +193,19 @@ 1.145 return the_table()->basic_add(index, (u1*)buffer, len, hashValue, CHECK_NULL); 1.146 } 1.147 1.148 -symbolOop SymbolTable::lookup_only(const char* name, int len, 1.149 +Symbol* SymbolTable::lookup_only(const char* name, int len, 1.150 unsigned int& hash) { 1.151 hash = hash_symbol(name, len); 1.152 int index = the_table()->hash_to_index(hash); 1.153 1.154 - return the_table()->lookup(index, name, len, hash); 1.155 + Symbol* s = the_table()->lookup(index, name, len, hash); 1.156 + return s; 1.157 } 1.158 1.159 // Suggestion: Push unicode-based lookup all the way into the hashing 1.160 // and probing logic, so there is no need for convert_to_utf8 until 1.161 -// an actual new symbolOop is created. 1.162 -symbolOop SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) { 1.163 +// an actual new Symbol* is created. 1.164 +Symbol* SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) { 1.165 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); 1.166 char stack_buf[128]; 1.167 if (utf8_length < (int) sizeof(stack_buf)) { 1.168 @@ -137,7 +220,7 @@ 1.169 } 1.170 } 1.171 1.172 -symbolOop SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length, 1.173 +Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length, 1.174 unsigned int& hash) { 1.175 int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); 1.176 char stack_buf[128]; 1.177 @@ -163,25 +246,23 @@ 1.178 // do it the hard way 1.179 for (int i=0; i<names_count; i++) { 1.180 int index = table->hash_to_index(hashValues[i]); 1.181 - symbolOop sym = table->basic_add(index, (u1*)names[i], lengths[i], 1.182 + Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], 1.183 hashValues[i], CHECK); 1.184 cp->symbol_at_put(cp_indices[i], sym); 1.185 } 1.186 } 1.187 } 1.188 1.189 -symbolOop SymbolTable::basic_add(int index, u1 *name, int len, 1.190 +Symbol* SymbolTable::basic_add(int index, u1 *name, int len, 1.191 unsigned int hashValue, TRAPS) { 1.192 assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(), 1.193 "proposed name of symbol must be stable"); 1.194 1.195 // We assume that lookup() has been called already, that it failed, 1.196 // and symbol was not found. We create the symbol here. 1.197 - symbolKlass* sk = (symbolKlass*) Universe::symbolKlassObj()->klass_part(); 1.198 - symbolOop s_oop = sk->allocate_symbol(name, len, CHECK_NULL); 1.199 - symbolHandle sym (THREAD, s_oop); 1.200 + Symbol* sym = allocate_symbol(name, len, CHECK_NULL); 1.201 1.202 - // Allocation must be done before grapping the SymbolTable_lock lock 1.203 + // Allocation must be done before grabbing the SymbolTable_lock lock 1.204 MutexLocker ml(SymbolTable_lock, THREAD); 1.205 1.206 assert(sym->equals((char*)name, len), "symbol must be properly initialized"); 1.207 @@ -189,51 +270,51 @@ 1.208 // Since look-up was done lock-free, we need to check if another 1.209 // thread beat us in the race to insert the symbol. 1.210 1.211 - symbolOop test = lookup(index, (char*)name, len, hashValue); 1.212 + Symbol* test = lookup(index, (char*)name, len, hashValue); 1.213 if (test != NULL) { 1.214 // A race occurred and another thread introduced the symbol, this one 1.215 // will be dropped and collected. 1.216 + delete sym; 1.217 + assert(test->refcount() != 0, "lookup should have incremented the count"); 1.218 return test; 1.219 } 1.220 1.221 - HashtableEntry* entry = new_entry(hashValue, sym()); 1.222 + HashtableEntry<Symbol*>* entry = new_entry(hashValue, sym); 1.223 + sym->increment_refcount(); 1.224 add_entry(index, entry); 1.225 - return sym(); 1.226 + return sym; 1.227 } 1.228 1.229 bool SymbolTable::basic_add(constantPoolHandle cp, int names_count, 1.230 const char** names, int* lengths, 1.231 int* cp_indices, unsigned int* hashValues, 1.232 TRAPS) { 1.233 - symbolKlass* sk = (symbolKlass*) Universe::symbolKlassObj()->klass_part(); 1.234 - symbolOop sym_oops[symbol_alloc_batch_size]; 1.235 - bool allocated = sk->allocate_symbols(names_count, names, lengths, 1.236 - sym_oops, CHECK_false); 1.237 + Symbol* syms[symbol_alloc_batch_size]; 1.238 + bool allocated = allocate_symbols(names_count, (const u1**)names, lengths, 1.239 + syms, CHECK_false); 1.240 if (!allocated) { 1.241 return false; 1.242 } 1.243 - symbolHandle syms[symbol_alloc_batch_size]; 1.244 - int i; 1.245 - for (i=0; i<names_count; i++) { 1.246 - syms[i] = symbolHandle(THREAD, sym_oops[i]); 1.247 - } 1.248 1.249 // Allocation must be done before grabbing the SymbolTable_lock lock 1.250 MutexLocker ml(SymbolTable_lock, THREAD); 1.251 1.252 - for (i=0; i<names_count; i++) { 1.253 + for (int i=0; i<names_count; i++) { 1.254 assert(syms[i]->equals(names[i], lengths[i]), "symbol must be properly initialized"); 1.255 // Since look-up was done lock-free, we need to check if another 1.256 // thread beat us in the race to insert the symbol. 1.257 int index = hash_to_index(hashValues[i]); 1.258 - symbolOop test = lookup(index, names[i], lengths[i], hashValues[i]); 1.259 + Symbol* test = lookup(index, names[i], lengths[i], hashValues[i]); 1.260 if (test != NULL) { 1.261 // A race occurred and another thread introduced the symbol, this one 1.262 // will be dropped and collected. Use test instead. 1.263 cp->symbol_at_put(cp_indices[i], test); 1.264 + assert(test->refcount() != 0, "lookup should have incremented the count"); 1.265 + delete syms[i]; 1.266 } else { 1.267 - symbolOop sym = syms[i](); 1.268 - HashtableEntry* entry = new_entry(hashValues[i], sym); 1.269 + Symbol* sym = syms[i]; 1.270 + HashtableEntry<Symbol*>* entry = new_entry(hashValues[i], sym); 1.271 + sym->increment_refcount(); // increment refcount in external hashtable 1.272 add_entry(index, entry); 1.273 cp->symbol_at_put(cp_indices[i], sym); 1.274 } 1.275 @@ -245,12 +326,10 @@ 1.276 1.277 void SymbolTable::verify() { 1.278 for (int i = 0; i < the_table()->table_size(); ++i) { 1.279 - HashtableEntry* p = the_table()->bucket(i); 1.280 + HashtableEntry<Symbol*>* p = the_table()->bucket(i); 1.281 for ( ; p != NULL; p = p->next()) { 1.282 - symbolOop s = symbolOop(p->literal()); 1.283 + Symbol* s = (Symbol*)(p->literal()); 1.284 guarantee(s != NULL, "symbol is NULL"); 1.285 - s->verify(); 1.286 - guarantee(s->is_perm(), "symbol not in permspace"); 1.287 unsigned int h = hash_symbol((char*)s->bytes(), s->utf8_length()); 1.288 guarantee(p->hash() == h, "broken hash in symbol table entry"); 1.289 guarantee(the_table()->hash_to_index(h) == i, 1.290 @@ -279,10 +358,14 @@ 1.291 int total = 0; 1.292 int max_symbols = 0; 1.293 int out_of_range = 0; 1.294 + int memory_total = 0; 1.295 + int count = 0; 1.296 for (i = 0; i < the_table()->table_size(); i++) { 1.297 - HashtableEntry* p = the_table()->bucket(i); 1.298 + HashtableEntry<Symbol*>* p = the_table()->bucket(i); 1.299 for ( ; p != NULL; p = p->next()) { 1.300 - int counter = symbolOop(p->literal())->utf8_length(); 1.301 + memory_total += p->literal()->object_size(); 1.302 + count++; 1.303 + int counter = p->literal()->utf8_length(); 1.304 total += counter; 1.305 if (counter < results_length) { 1.306 results[counter]++; 1.307 @@ -293,6 +376,17 @@ 1.308 } 1.309 } 1.310 tty->print_cr("Symbol Table:"); 1.311 + tty->print_cr("Total number of symbols %5d", count); 1.312 + tty->print_cr("Total size in memory %5dK", 1.313 + (memory_total*HeapWordSize)/1024); 1.314 + tty->print_cr("Total counted %5d", symbols_counted); 1.315 + tty->print_cr("Total removed %5d", symbols_removed); 1.316 + if (symbols_counted > 0) { 1.317 + tty->print_cr("Percent removed %3.2f", 1.318 + ((float)symbols_removed/(float)symbols_counted)* 100); 1.319 + } 1.320 + tty->print_cr("Reference counts %5d", Symbol::_total_count); 1.321 + tty->print_cr("Histogram of symbol length:"); 1.322 tty->print_cr("%8s %5d", "Total ", total); 1.323 tty->print_cr("%8s %5d", "Maximum", max_symbols); 1.324 tty->print_cr("%8s %3.2f", "Average", 1.325 @@ -304,22 +398,41 @@ 1.326 tty->print_cr("%6d %10d", i, results[i]); 1.327 } 1.328 } 1.329 - int line_length = 70; 1.330 - tty->print_cr("%s %30s", " Length", "Number chains that length"); 1.331 - for (i = 0; i < results_length; i++) { 1.332 - if (results[i] > 0) { 1.333 - tty->print("%4d", i); 1.334 - for (j = 0; (j < results[i]) && (j < line_length); j++) { 1.335 - tty->print("%1s", "*"); 1.336 + if (Verbose) { 1.337 + int line_length = 70; 1.338 + tty->print_cr("%s %30s", " Length", "Number chains that length"); 1.339 + for (i = 0; i < results_length; i++) { 1.340 + if (results[i] > 0) { 1.341 + tty->print("%4d", i); 1.342 + for (j = 0; (j < results[i]) && (j < line_length); j++) { 1.343 + tty->print("%1s", "*"); 1.344 + } 1.345 + if (j == line_length) { 1.346 + tty->print("%1s", "+"); 1.347 + } 1.348 + tty->cr(); 1.349 } 1.350 - if (j == line_length) { 1.351 - tty->print("%1s", "+"); 1.352 + } 1.353 + } 1.354 + tty->print_cr(" %s %d: %d\n", "Number chains longer than", 1.355 + results_length, out_of_range); 1.356 +} 1.357 + 1.358 +void SymbolTable::print() { 1.359 + for (int i = 0; i < the_table()->table_size(); ++i) { 1.360 + HashtableEntry<Symbol*>** p = the_table()->bucket_addr(i); 1.361 + HashtableEntry<Symbol*>* entry = the_table()->bucket(i); 1.362 + if (entry != NULL) { 1.363 + while (entry != NULL) { 1.364 + tty->print(PTR_FORMAT " ", entry->literal()); 1.365 + entry->literal()->print(); 1.366 + tty->print(" %d", entry->literal()->refcount()); 1.367 + p = entry->next_addr(); 1.368 + entry = (HashtableEntry<Symbol*>*)HashtableEntry<Symbol*>::make_ptr(*p); 1.369 } 1.370 tty->cr(); 1.371 } 1.372 } 1.373 - tty->print_cr(" %s %d: %d\n", "Number chains longer than", 1.374 - results_length, out_of_range); 1.375 } 1.376 1.377 #endif // PRODUCT 1.378 @@ -396,7 +509,7 @@ 1.379 1.380 oop StringTable::lookup(int index, jchar* name, 1.381 int len, unsigned int hash) { 1.382 - for (HashtableEntry* l = bucket(index); l != NULL; l = l->next()) { 1.383 + for (HashtableEntry<oop>* l = bucket(index); l != NULL; l = l->next()) { 1.384 if (l->hash() == hash) { 1.385 if (java_lang_String::equals(l->literal(), name, len)) { 1.386 return l->literal(); 1.387 @@ -436,13 +549,13 @@ 1.388 return test; 1.389 } 1.390 1.391 - HashtableEntry* entry = new_entry(hashValue, string()); 1.392 + HashtableEntry<oop>* entry = new_entry(hashValue, string()); 1.393 add_entry(index, entry); 1.394 return string(); 1.395 } 1.396 1.397 1.398 -oop StringTable::lookup(symbolOop symbol) { 1.399 +oop StringTable::lookup(Symbol* symbol) { 1.400 ResourceMark rm; 1.401 int length; 1.402 jchar* chars = symbol->as_unicode(length); 1.403 @@ -466,7 +579,7 @@ 1.404 hashValue, CHECK_NULL); 1.405 } 1.406 1.407 -oop StringTable::intern(symbolOop symbol, TRAPS) { 1.408 +oop StringTable::intern(Symbol* symbol, TRAPS) { 1.409 if (symbol == NULL) return NULL; 1.410 ResourceMark rm(THREAD); 1.411 int length; 1.412 @@ -500,9 +613,50 @@ 1.413 return result; 1.414 } 1.415 1.416 +void StringTable::unlink(BoolObjectClosure* is_alive) { 1.417 + // Readers of the table are unlocked, so we should only be removing 1.418 + // entries at a safepoint. 1.419 + assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); 1.420 + for (int i = 0; i < the_table()->table_size(); ++i) { 1.421 + for (HashtableEntry<oop>** p = the_table()->bucket_addr(i); *p != NULL; ) { 1.422 + HashtableEntry<oop>* entry = *p; 1.423 + if (entry->is_shared()) { 1.424 + break; 1.425 + } 1.426 + assert(entry->literal() != NULL, "just checking"); 1.427 + if (is_alive->do_object_b(entry->literal())) { 1.428 + p = entry->next_addr(); 1.429 + } else { 1.430 + *p = entry->next(); 1.431 + the_table()->free_entry(entry); 1.432 + } 1.433 + } 1.434 + } 1.435 +} 1.436 + 1.437 +void StringTable::oops_do(OopClosure* f) { 1.438 + for (int i = 0; i < the_table()->table_size(); ++i) { 1.439 + HashtableEntry<oop>** p = the_table()->bucket_addr(i); 1.440 + HashtableEntry<oop>* entry = the_table()->bucket(i); 1.441 + while (entry != NULL) { 1.442 + f->do_oop((oop*)entry->literal_addr()); 1.443 + 1.444 + // Did the closure remove the literal from the table? 1.445 + if (entry->literal() == NULL) { 1.446 + assert(!entry->is_shared(), "immutable hashtable entry?"); 1.447 + *p = entry->next(); 1.448 + the_table()->free_entry(entry); 1.449 + } else { 1.450 + p = entry->next_addr(); 1.451 + } 1.452 + entry = (HashtableEntry<oop>*)HashtableEntry<oop>::make_ptr(*p); 1.453 + } 1.454 + } 1.455 +} 1.456 + 1.457 void StringTable::verify() { 1.458 for (int i = 0; i < the_table()->table_size(); ++i) { 1.459 - HashtableEntry* p = the_table()->bucket(i); 1.460 + HashtableEntry<oop>* p = the_table()->bucket(i); 1.461 for ( ; p != NULL; p = p->next()) { 1.462 oop s = p->literal(); 1.463 guarantee(s != NULL, "interned string is NULL");