00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 # include "incls/_precompiled.incl"
00026 # include "incls/_symbolTable.cpp.incl"
00027 
00028 # define FOR_ALL_ENTRIES(entry) \
00029   for (entry = firstBucket(); entry <= lastBucket(); entry ++)
00030 
00031 # define FOR_ALL_SYMBOL_ADDR(bucket, var, code)                         \
00032     { if (bucket->is_symbol()) {                                        \
00033          var = (symbolOop*) bucket; code;                               \
00034       } else {                                                          \
00035         for (symbolTableLink* l = bucket->get_link(); l; l = l->next) { \
00036           var = &l->symbol; code;                                       \
00037         }                                                               \
00038       }                                                                 \
00039     }
00040 
00041 int hash(char* name, int len) {
00042   
00043   int increment;
00044  
00045   if (len < 32) {
00046     increment = 1;
00047   } else {
00048     increment = len >> 5;
00049   }
00050  
00051   
00052  
00053   assert(BitsPerByte * BytesPerWord == 32, "assumes 32-bit words");
00054   long unsigned h = 0;
00055   long unsigned g;
00056   char* s = name;
00057   char* end = s + len;
00058   for (; s < end; s = s + increment) {
00059     h = (h << 4) + (long unsigned) *s;
00060     if (g = h & 0xf0000000) h ^= g | (g >> 24);
00061   }
00062   return h;
00063 }
00064 
00065 symbolTable::symbolTable() {
00066   for (int i = 0; i < symbol_table_size; i ++) buckets[i].clear();
00067   free_list = first_free_link = end_block = NULL;
00068 }
00069 
00070 symbolOop symbolTable::basic_add(char *name, int len, int hashValue) {
00071   symbolKlass* sk = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
00072   symbolOop str =   sk->allocateSymbol(name, len);
00073   basic_add(str, hashValue);
00074   return str;
00075 }
00076 
00077 bool symbolTable::is_present(symbolOop sym) {
00078   char* name = (char*) sym->bytes();
00079   int   len  = sym->length();
00080   int hashValue = hash(name, len);
00081   symbolTableEntry* bucket = bucketFor(hashValue);
00082   if (bucket->is_empty()) return false;
00083   if (bucket->is_symbol())
00084     return bucket->get_symbol()->equals(name, len);
00085   for (symbolTableLink* l = bucket->get_link(); l; l = l->next)
00086     if (l->symbol->equals(name, len)) return true;
00087   return false;
00088 }
00089 
00090 symbolOop symbolTable::lookup(char* name, int len) {
00091   int hashValue = hash(name, len);
00092   symbolTableEntry* bucket = bucketFor(hashValue);
00093   if (!bucket->is_empty()) {
00094     if (bucket->is_symbol()) {
00095       if (bucket->get_symbol()->equals(name, len)) return bucket->get_symbol();
00096     } else {
00097       for (symbolTableLink* l = bucket->get_link(); l; l = l->next)
00098         if (l->symbol->equals(name, len)) return l->symbol;
00099     }
00100   }
00101   return basic_add(name, len, hashValue);
00102 }
00103 
00104 void symbolTable::add(symbolOop s) {
00105   assert(s->is_symbol(),
00106          "adding something that's not a symbol to the symbol table");
00107   assert(s->is_old(), "all symbols should be tenured");
00108   int hashValue = hash((char*) s->bytes(), s->length());
00109   basic_add(s, hashValue);
00110 }
00111 
00112 void symbolTable::add_symbol(symbolOop s) {
00113   basic_add(s, hash((char*) s->bytes(), s->length()));
00114 }
00115 
00116 symbolOop symbolTable::basic_add(symbolOop s, int hashValue) {
00117   assert(s->is_symbol(),
00118          "adding something that's not a symbol to the symbol table");
00119   assert(s->is_old(), "all symbols should be tenured");
00120 
00121   
00122   s->hash_value();
00123   assert(!s->mark()->has_valid_hash(), "should not have a hash yet");
00124   s->set_mark(s->mark()->set_hash(s->hash_value()));
00125   assert(s->mark()->has_valid_hash(), "should have a hash now");
00126 
00127   symbolTableEntry* bucket = bucketFor(hashValue);
00128 
00129   if (bucket->is_empty()) {
00130     bucket->set_symbol(s);
00131   } else {
00132     symbolTableLink*  old_link;
00133     if (bucket->is_symbol()) {
00134       old_link = Universe::symbol_table->new_link(bucket->get_symbol());
00135     } else {
00136       old_link = bucket->get_link();
00137     }
00138     bucket->set_link(Universe::symbol_table->new_link(s, old_link));
00139   }
00140   return s;
00141 }
00142 
00143 void symbolTable::switch_pointers(oop from, oop to) {
00144   if (! from->is_symbol()) return;
00145   assert(to->is_symbol(),
00146          "cannot replace a symbol with a non-symbol");
00147 
00148   symbolTableEntry* e;
00149   FOR_ALL_ENTRIES(e) {
00150     symbolOop* addr;
00151     FOR_ALL_SYMBOL_ADDR(e, addr, SWITCH_POINTERS_TEMPLATE(addr));
00152   }
00153 }
00154 
00155 void symbolTable::follow_used_symbols() {
00156   
00157   symbolTableEntry* e;
00158   FOR_ALL_ENTRIES(e) {
00159     
00160     
00161     
00162     if (e->get_link() && !e->get_link()->next) {
00163       symbolTableLink* old = e->get_link();
00164       e->set_symbol(old->symbol);
00165       delete_link(old);
00166     }
00167 
00168     if (e->is_symbol()) {
00169       if (e->get_symbol()->is_gc_marked()) 
00170         MarkSweep::follow_root((oop*) e);
00171       else
00172         e->clear(); 
00173     } else {
00174       symbolTableLink** p    = (symbolTableLink**) e;
00175       symbolTableLink*  link = e->get_link();
00176       while (link) {
00177         if (link->symbol->is_gc_marked()) {
00178           MarkSweep::follow_root((oop*) &link->symbol);
00179           p    = &link->next;
00180           link = link->next;
00181         } else {
00182           
00183           symbolTableLink* old = link;
00184           *p   = link->next;
00185           link = link->next;
00186           old->next = NULL;
00187           delete_link(old);
00188         }
00189       }
00190     }
00191   }
00192 }
00193 
00194 void symbolTableEntry::deallocate() {
00195   if(!is_symbol() && get_link()) 
00196     Universe::symbol_table->delete_link(get_link());
00197 }
00198 
00199 bool symbolTableEntry::verify(int i) {
00200   bool flag = true;
00201   if (is_symbol()) {
00202     if (!get_symbol()->is_symbol()) {
00203       error("entry %#lx in symbol table isn't a symbol", get_symbol());
00204       flag = false;
00205     }
00206   } else {
00207     if (get_link()) flag = get_link()->verify(i);
00208   }
00209   return flag;
00210 }
00211 
00212 void symbolTable::verify() {
00213   for (int i = 0; i < symbol_table_size; i ++)
00214     if (!buckets[i].verify(i))
00215       lprintf("\tof bucket %ld of symbol table\n", long(i));
00216 }
00217 
00218 
00219 void symbolTable::relocate() {
00220   symbolTableEntry* e;
00221   FOR_ALL_ENTRIES(e) {
00222     symbolOop* addr;
00223     FOR_ALL_SYMBOL_ADDR(e, addr, RELOCATE_TEMPLATE(addr));
00224   }
00225 }
00226 
00227 bool symbolTableLink::verify(int i) {
00228   bool flag = true;
00229   for (symbolTableLink* l = this; l; l = l->next) {
00230     if (! l->symbol->is_symbol()) {
00231       error("entry %#lx in symbol table isn't a symbol", l->symbol);
00232       flag = false;
00233     } else if (hash((char*) l->symbol->bytes(), l->symbol->length()) 
00234                % symbol_table_size != i) {
00235       error("entry %#lx in symbol table has wrong hash value", l->symbol);
00236       flag = false;
00237     } else if (!l->symbol->is_old()) {
00238       error("entry %#lx in symbol table isn't tenured", l->symbol);
00239       flag = false;
00240     }
00241   }
00242   return flag;
00243 }
00244 
00245 int symbolTableEntry::length() {
00246   if (is_symbol()) return 1;
00247   if (!get_link()) return 0;
00248   int count = 0;
00249   for (symbolTableLink* l = get_link(); l; l = l->next) count ++;
00250   return count;
00251 }
00252 
00253 symbolTableLink* symbolTable::new_link(symbolOop s, symbolTableLink* n) {
00254   symbolTableLink* res;
00255   if (free_list) {
00256     res = free_list;
00257     free_list = free_list->next;
00258   } else {
00259     const int block_size = 500;
00260     if (first_free_link == end_block) {
00261       first_free_link = NEW_C_HEAP_ARRAY(symbolTableLink, block_size);
00262       end_block = first_free_link + block_size;
00263     }
00264     res = first_free_link++;
00265   } 
00266   res->symbol = s;
00267   res->next   = n;
00268   return res;
00269 }
00270 
00271 void symbolTable::delete_link(symbolTableLink* l) {
00272   
00273   symbolTableLink* end = l;
00274   while(end->next) end = end->next;
00275   end->next = free_list;
00276   free_list = l;
00277 }
00278 
00279 
00280 
00281 void symbolTable::print_histogram() {
00282   const int results_length = 100;
00283   int results[results_length];
00284   
00285   
00286   for (int j = 0; j < results_length; j++) {
00287     results[j] = 0;
00288   }
00289 
00290   int total = 0;
00291   int min_symbols = 0;
00292   int max_symbols = 0;
00293   int out_of_range = 0;
00294   for (int i = 0; i < symbol_table_size; i++) {
00295     symbolTableEntry curr = buckets[i];
00296     int counter = curr.length();
00297     total += counter;
00298     if (counter < results_length) {
00299       results[counter]++;
00300     } else {
00301       out_of_range++;
00302     }
00303     min_symbols = min(min_symbols, counter);
00304     max_symbols = max(max_symbols, counter);
00305   }
00306   lprintf("Symbol Table:\n");
00307   lprintf("%8s %5d\n", "Total  ", total);
00308   lprintf("%8s %5d\n", "Minimum", min_symbols);
00309   lprintf("%8s %5d\n", "Maximum", max_symbols);
00310   lprintf("%8s %3.2f\n", "Average",
00311           ((float) total / (float) symbol_table_size));
00312   lprintf("%s\n", "Histogram:");
00313   lprintf(" %s %29s\n", "Length", "Number chains that length");
00314   for (i = 0; i < results_length; i++) {
00315     if (results[i] > 0) {
00316       lprintf("%6d %10d\n", i, results[i]);
00317     }
00318   }
00319   int line_length = 70;    
00320   lprintf("%s %30s\n", " Length", "Number chains that length");
00321   for (i = 0; i < results_length; i++) {
00322     if (results[i] > 0) {
00323       lprintf("%4d", i);
00324       for (j = 0; (j < results[i]) && (j < line_length);  j++) {
00325         lprintf("%1s", "*");
00326       }
00327       if (j == line_length) {
00328         lprintf("%1s", "+");
00329       }
00330       lprintf("\n");
00331     }
00332   }  
00333   lprintf(" %s %d: %d\n", "Number chains longer than",
00334           results_length, out_of_range);
00335 }