src/share/vm/utilities/hashtable.cpp

Thu, 20 Nov 2008 16:56:09 -0800

author
ysr
date
Thu, 20 Nov 2008 16:56:09 -0800
changeset 888
c96030fff130
parent 867
275a3b7ff0d6
child 905
ad8c8ca4ab0f
permissions
-rw-r--r--

6684579: SoftReference processing can be made more efficient
Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not.
Reviewed-by: jmasa

duke@435 1 /*
duke@435 2 * Copyright 2003-2005 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