src/share/vm/utilities/hashtable.cpp

Mon, 15 Dec 2008 16:55:11 -0800

author
xdono
date
Mon, 15 Dec 2008 16:55:11 -0800
changeset 905
ad8c8ca4ab0f
parent 867
275a3b7ff0d6
child 1907
c18cbe5936b8
permissions
-rw-r--r--

6785258: Update copyright year
Summary: Update copyright for files that have been modified starting July 2008 to Dec 2008
Reviewed-by: katleman, ohair, tbell

duke@435 1 /*
xdono@905 2 * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
duke@435 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
duke@435 20 * CA 95054 USA or visit www.sun.com if you need additional information or
duke@435 21 * have any questions.
duke@435 22 *
duke@435 23 */
duke@435 24
duke@435 25 # include "incls/_precompiled.incl"
duke@435 26 # include "incls/_hashtable.cpp.incl"
duke@435 27
duke@435 28 HS_DTRACE_PROBE_DECL4(hs_private, hashtable__new_entry,
duke@435 29 void*, unsigned int, oop, void*);
duke@435 30
duke@435 31 // This is a generic hashtable, designed to be used for the symbol
duke@435 32 // and string tables.
duke@435 33 //
duke@435 34 // It is implemented as an open hash table with a fixed number of buckets.
duke@435 35 //
duke@435 36 // %note:
duke@435 37 // - HashtableEntrys are allocated in blocks to reduce the space overhead.
duke@435 38
duke@435 39 BasicHashtableEntry* BasicHashtable::new_entry(unsigned int hashValue) {
duke@435 40 BasicHashtableEntry* entry;
duke@435 41
duke@435 42 if (_free_list) {
duke@435 43 entry = _free_list;
duke@435 44 _free_list = _free_list->next();
duke@435 45 } else {
jrose@867 46 if (_first_free_entry + _entry_size >= _end_block) {
jrose@867 47 int block_size = MIN2(512, MAX2((int)_table_size / 2, (int)_number_of_entries));
duke@435 48 int len = _entry_size * block_size;
jrose@867 49 len = 1 << log2_intptr(len); // round down to power of 2
jrose@867 50 assert(len >= _entry_size, "");
duke@435 51 _first_free_entry = NEW_C_HEAP_ARRAY(char, len);
duke@435 52 _end_block = _first_free_entry + len;
duke@435 53 }
duke@435 54 entry = (BasicHashtableEntry*)_first_free_entry;
duke@435 55 _first_free_entry += _entry_size;
duke@435 56 }
duke@435 57
jrose@867 58 assert(_entry_size % HeapWordSize == 0, "");
duke@435 59 entry->set_hash(hashValue);
duke@435 60 return entry;
duke@435 61 }
duke@435 62
duke@435 63
duke@435 64 HashtableEntry* Hashtable::new_entry(unsigned int hashValue, oop obj) {
duke@435 65 HashtableEntry* entry;
duke@435 66
duke@435 67 entry = (HashtableEntry*)BasicHashtable::new_entry(hashValue);
duke@435 68 entry->set_literal(obj); // clears literal string field
duke@435 69 HS_DTRACE_PROBE4(hs_private, hashtable__new_entry,
duke@435 70 this, hashValue, obj, entry);
duke@435 71 return entry;
duke@435 72 }
duke@435 73
duke@435 74
duke@435 75 // GC support
duke@435 76
duke@435 77 void Hashtable::unlink(BoolObjectClosure* is_alive) {
duke@435 78 // Readers of the table are unlocked, so we should only be removing
duke@435 79 // entries at a safepoint.
duke@435 80 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
duke@435 81 for (int i = 0; i < table_size(); ++i) {
duke@435 82 for (HashtableEntry** p = bucket_addr(i); *p != NULL; ) {
duke@435 83 HashtableEntry* entry = *p;
duke@435 84 if (entry->is_shared()) {
duke@435 85 break;
duke@435 86 }
duke@435 87 assert(entry->literal() != NULL, "just checking");
duke@435 88 if (is_alive->do_object_b(entry->literal())) {
duke@435 89 p = entry->next_addr();
duke@435 90 } else {
duke@435 91 *p = entry->next();
duke@435 92 free_entry(entry);
duke@435 93 }
duke@435 94 }
duke@435 95 }
duke@435 96 }
duke@435 97
duke@435 98
duke@435 99 void Hashtable::oops_do(OopClosure* f) {
duke@435 100 for (int i = 0; i < table_size(); ++i) {
duke@435 101 HashtableEntry** p = bucket_addr(i);
duke@435 102 HashtableEntry* entry = bucket(i);
duke@435 103 while (entry != NULL) {
duke@435 104 f->do_oop(entry->literal_addr());
duke@435 105
duke@435 106 // Did the closure remove the literal from the table?
duke@435 107 if (entry->literal() == NULL) {
duke@435 108 assert(!entry->is_shared(), "immutable hashtable entry?");
duke@435 109 *p = entry->next();
duke@435 110 free_entry(entry);
duke@435 111 } else {
duke@435 112 p = entry->next_addr();
duke@435 113 }
duke@435 114 entry = (HashtableEntry*)HashtableEntry::make_ptr(*p);
duke@435 115 }
duke@435 116 }
duke@435 117 }
duke@435 118
duke@435 119
duke@435 120 // Reverse the order of elements in the hash buckets.
duke@435 121
duke@435 122 void BasicHashtable::reverse() {
duke@435 123
duke@435 124 for (int i = 0; i < _table_size; ++i) {
duke@435 125 BasicHashtableEntry* new_list = NULL;
duke@435 126 BasicHashtableEntry* p = bucket(i);
duke@435 127 while (p != NULL) {
duke@435 128 BasicHashtableEntry* next = p->next();
duke@435 129 p->set_next(new_list);
duke@435 130 new_list = p;
duke@435 131 p = next;
duke@435 132 }
duke@435 133 *bucket_addr(i) = new_list;
duke@435 134 }
duke@435 135 }
duke@435 136
duke@435 137
duke@435 138 // Copy the table to the shared space.
duke@435 139
duke@435 140 void BasicHashtable::copy_table(char** top, char* end) {
duke@435 141
duke@435 142 // Dump the hash table entries.
duke@435 143
duke@435 144 intptr_t *plen = (intptr_t*)(*top);
duke@435 145 *top += sizeof(*plen);
duke@435 146
duke@435 147 int i;
duke@435 148 for (i = 0; i < _table_size; ++i) {
duke@435 149 for (BasicHashtableEntry** p = _buckets[i].entry_addr();
duke@435 150 *p != NULL;
duke@435 151 p = (*p)->next_addr()) {
duke@435 152 if (*top + entry_size() > end) {
duke@435 153 warning("\nThe shared miscellaneous data space is not large "
duke@435 154 "enough to \npreload requested classes. Use "
duke@435 155 "-XX:SharedMiscDataSize= to increase \nthe initial "
duke@435 156 "size of the miscellaneous data space.\n");
duke@435 157 exit(2);
duke@435 158 }
duke@435 159 *p = (BasicHashtableEntry*)memcpy(*top, *p, entry_size());
duke@435 160 *top += entry_size();
duke@435 161 }
duke@435 162 }
duke@435 163 *plen = (char*)(*top) - (char*)plen - sizeof(*plen);
duke@435 164
duke@435 165 // Set the shared bit.
duke@435 166
duke@435 167 for (i = 0; i < _table_size; ++i) {
duke@435 168 for (BasicHashtableEntry* p = bucket(i); p != NULL; p = p->next()) {
duke@435 169 p->set_shared();
duke@435 170 }
duke@435 171 }
duke@435 172 }
duke@435 173
duke@435 174
duke@435 175
duke@435 176 // Reverse the order of elements in the hash buckets.
duke@435 177
duke@435 178 void Hashtable::reverse(void* boundary) {
duke@435 179
duke@435 180 for (int i = 0; i < table_size(); ++i) {
duke@435 181 HashtableEntry* high_list = NULL;
duke@435 182 HashtableEntry* low_list = NULL;
duke@435 183 HashtableEntry* last_low_entry = NULL;
duke@435 184 HashtableEntry* p = bucket(i);
duke@435 185 while (p != NULL) {
duke@435 186 HashtableEntry* next = p->next();
duke@435 187 if ((void*)p->literal() >= boundary) {
duke@435 188 p->set_next(high_list);
duke@435 189 high_list = p;
duke@435 190 } else {
duke@435 191 p->set_next(low_list);
duke@435 192 low_list = p;
duke@435 193 if (last_low_entry == NULL) {
duke@435 194 last_low_entry = p;
duke@435 195 }
duke@435 196 }
duke@435 197 p = next;
duke@435 198 }
duke@435 199 if (low_list != NULL) {
duke@435 200 *bucket_addr(i) = low_list;
duke@435 201 last_low_entry->set_next(high_list);
duke@435 202 } else {
duke@435 203 *bucket_addr(i) = high_list;
duke@435 204 }
duke@435 205 }
duke@435 206 }
duke@435 207
duke@435 208
duke@435 209 // Dump the hash table buckets.
duke@435 210
duke@435 211 void BasicHashtable::copy_buckets(char** top, char* end) {
duke@435 212 intptr_t len = _table_size * sizeof(HashtableBucket);
duke@435 213 *(intptr_t*)(*top) = len;
duke@435 214 *top += sizeof(intptr_t);
duke@435 215
duke@435 216 *(intptr_t*)(*top) = _number_of_entries;
duke@435 217 *top += sizeof(intptr_t);
duke@435 218
duke@435 219 if (*top + len > end) {
duke@435 220 warning("\nThe shared miscellaneous data space is not large "
duke@435 221 "enough to \npreload requested classes. Use "
duke@435 222 "-XX:SharedMiscDataSize= to increase \nthe initial "
duke@435 223 "size of the miscellaneous data space.\n");
duke@435 224 exit(2);
duke@435 225 }
duke@435 226 _buckets = (HashtableBucket*)memcpy(*top, _buckets, len);
duke@435 227 *top += len;
duke@435 228 }
duke@435 229
duke@435 230
duke@435 231 #ifndef PRODUCT
duke@435 232
duke@435 233 void Hashtable::print() {
duke@435 234 ResourceMark rm;
duke@435 235
duke@435 236 for (int i = 0; i < table_size(); i++) {
duke@435 237 HashtableEntry* entry = bucket(i);
duke@435 238 while(entry != NULL) {
duke@435 239 tty->print("%d : ", i);
duke@435 240 entry->literal()->print();
duke@435 241 tty->cr();
duke@435 242 entry = entry->next();
duke@435 243 }
duke@435 244 }
duke@435 245 }
duke@435 246
duke@435 247
duke@435 248 void BasicHashtable::verify() {
duke@435 249 int count = 0;
duke@435 250 for (int i = 0; i < table_size(); i++) {
duke@435 251 for (BasicHashtableEntry* p = bucket(i); p != NULL; p = p->next()) {
duke@435 252 ++count;
duke@435 253 }
duke@435 254 }
duke@435 255 assert(count == number_of_entries(), "number of hashtable entries incorrect");
duke@435 256 }
duke@435 257
duke@435 258
duke@435 259 #endif // PRODUCT
duke@435 260
duke@435 261
duke@435 262 #ifdef ASSERT
duke@435 263
duke@435 264 void BasicHashtable::verify_lookup_length(double load) {
duke@435 265 if ((double)_lookup_length / (double)_lookup_count > load * 2.0) {
duke@435 266 warning("Performance bug: SystemDictionary lookup_count=%d "
duke@435 267 "lookup_length=%d average=%lf load=%f",
duke@435 268 _lookup_count, _lookup_length,
duke@435 269 (double) _lookup_length / _lookup_count, load);
duke@435 270 }
duke@435 271 }
duke@435 272
duke@435 273 #endif

mercurial