src/share/vm/classfile/symbolTable.cpp

changeset 2497
3582bf76420e
parent 2314
f95d63e2154a
child 2618
df1347358fe6
     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");

mercurial