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 }