src/share/vm/utilities/hashtable.hpp

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

author
ysr
date
Thu, 20 Nov 2008 16:56:09 -0800
changeset 888
c96030fff130
parent 435
a61af66fc99e
child 1907
c18cbe5936b8
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 // This is a generic hashtable, designed to be used for the symbol
duke@435 26 // and string tables.
duke@435 27 //
duke@435 28 // It is implemented as an open hash table with a fixed number of buckets.
duke@435 29 //
duke@435 30 // %note:
duke@435 31 // - TableEntrys are allocated in blocks to reduce the space overhead.
duke@435 32
duke@435 33
duke@435 34
duke@435 35 class BasicHashtableEntry : public CHeapObj {
duke@435 36 friend class VMStructs;
duke@435 37 private:
duke@435 38 unsigned int _hash; // 32-bit hash for item
duke@435 39
duke@435 40 // Link to next element in the linked list for this bucket. EXCEPT
duke@435 41 // bit 0 set indicates that this entry is shared and must not be
duke@435 42 // unlinked from the table. Bit 0 is set during the dumping of the
duke@435 43 // archive. Since shared entries are immutable, _next fields in the
duke@435 44 // shared entries will not change. New entries will always be
duke@435 45 // unshared and since pointers are align, bit 0 will always remain 0
duke@435 46 // with no extra effort.
duke@435 47 BasicHashtableEntry* _next;
duke@435 48
duke@435 49 // Windows IA64 compiler requires subclasses to be able to access these
duke@435 50 protected:
duke@435 51 // Entry objects should not be created, they should be taken from the
duke@435 52 // free list with BasicHashtable.new_entry().
duke@435 53 BasicHashtableEntry() { ShouldNotReachHere(); }
duke@435 54 // Entry objects should not be destroyed. They should be placed on
duke@435 55 // the free list instead with BasicHashtable.free_entry().
duke@435 56 ~BasicHashtableEntry() { ShouldNotReachHere(); }
duke@435 57
duke@435 58 public:
duke@435 59
duke@435 60 unsigned int hash() const { return _hash; }
duke@435 61 void set_hash(unsigned int hash) { _hash = hash; }
duke@435 62 unsigned int* hash_addr() { return &_hash; }
duke@435 63
duke@435 64 static BasicHashtableEntry* make_ptr(BasicHashtableEntry* p) {
duke@435 65 return (BasicHashtableEntry*)((intptr_t)p & -2);
duke@435 66 }
duke@435 67
duke@435 68 BasicHashtableEntry* next() const {
duke@435 69 return make_ptr(_next);
duke@435 70 }
duke@435 71
duke@435 72 void set_next(BasicHashtableEntry* next) {
duke@435 73 _next = next;
duke@435 74 }
duke@435 75
duke@435 76 BasicHashtableEntry** next_addr() {
duke@435 77 return &_next;
duke@435 78 }
duke@435 79
duke@435 80 bool is_shared() const {
duke@435 81 return ((intptr_t)_next & 1) != 0;
duke@435 82 }
duke@435 83
duke@435 84 void set_shared() {
duke@435 85 _next = (BasicHashtableEntry*)((intptr_t)_next | 1);
duke@435 86 }
duke@435 87 };
duke@435 88
duke@435 89
duke@435 90
duke@435 91 class HashtableEntry : public BasicHashtableEntry {
duke@435 92 friend class VMStructs;
duke@435 93 private:
duke@435 94 oop _literal; // ref to item in table.
duke@435 95
duke@435 96 public:
duke@435 97 // Literal
duke@435 98 oop literal() const { return _literal; }
duke@435 99 oop* literal_addr() { return &_literal; }
duke@435 100 void set_literal(oop s) { _literal = s; }
duke@435 101
duke@435 102 HashtableEntry* next() const {
duke@435 103 return (HashtableEntry*)BasicHashtableEntry::next();
duke@435 104 }
duke@435 105 HashtableEntry** next_addr() {
duke@435 106 return (HashtableEntry**)BasicHashtableEntry::next_addr();
duke@435 107 }
duke@435 108 };
duke@435 109
duke@435 110
duke@435 111
duke@435 112 class HashtableBucket : public CHeapObj {
duke@435 113 friend class VMStructs;
duke@435 114 private:
duke@435 115 // Instance variable
duke@435 116 BasicHashtableEntry* _entry;
duke@435 117
duke@435 118 public:
duke@435 119 // Accessing
duke@435 120 void clear() { _entry = NULL; }
duke@435 121
duke@435 122 // The following methods use order access methods to avoid race
duke@435 123 // conditions in multiprocessor systems.
duke@435 124 BasicHashtableEntry* get_entry() const;
duke@435 125 void set_entry(BasicHashtableEntry* l);
duke@435 126
duke@435 127 // The following method is not MT-safe and must be done under lock.
duke@435 128 BasicHashtableEntry** entry_addr() { return &_entry; }
duke@435 129 };
duke@435 130
duke@435 131
duke@435 132 class BasicHashtable : public CHeapObj {
duke@435 133 friend class VMStructs;
duke@435 134
duke@435 135 public:
duke@435 136 BasicHashtable(int table_size, int entry_size);
duke@435 137 BasicHashtable(int table_size, int entry_size,
duke@435 138 HashtableBucket* buckets, int number_of_entries);
duke@435 139
duke@435 140 // Sharing support.
duke@435 141 void copy_buckets(char** top, char* end);
duke@435 142 void copy_table(char** top, char* end);
duke@435 143
duke@435 144 // Bucket handling
duke@435 145 int hash_to_index(unsigned int full_hash) {
duke@435 146 int h = full_hash % _table_size;
duke@435 147 assert(h >= 0 && h < _table_size, "Illegal hash value");
duke@435 148 return h;
duke@435 149 }
duke@435 150
duke@435 151 // Reverse the order of elements in each of the buckets.
duke@435 152 void reverse();
duke@435 153
duke@435 154 private:
duke@435 155 // Instance variables
duke@435 156 int _table_size;
duke@435 157 HashtableBucket* _buckets;
duke@435 158 BasicHashtableEntry* _free_list;
duke@435 159 char* _first_free_entry;
duke@435 160 char* _end_block;
duke@435 161 int _entry_size;
duke@435 162 int _number_of_entries;
duke@435 163
duke@435 164 protected:
duke@435 165
duke@435 166 #ifdef ASSERT
duke@435 167 int _lookup_count;
duke@435 168 int _lookup_length;
duke@435 169 void verify_lookup_length(double load);
duke@435 170 #endif
duke@435 171
duke@435 172 void initialize(int table_size, int entry_size, int number_of_entries);
duke@435 173
duke@435 174 // Accessor
duke@435 175 int entry_size() const { return _entry_size; }
duke@435 176 int table_size() { return _table_size; }
duke@435 177
duke@435 178 // The following method is MT-safe and may be used with caution.
duke@435 179 BasicHashtableEntry* bucket(int i);
duke@435 180
duke@435 181 // The following method is not MT-safe and must be done under lock.
duke@435 182 BasicHashtableEntry** bucket_addr(int i) { return _buckets[i].entry_addr(); }
duke@435 183
duke@435 184 // Table entry management
duke@435 185 BasicHashtableEntry* new_entry(unsigned int hashValue);
duke@435 186
duke@435 187 public:
duke@435 188 void set_entry(int index, BasicHashtableEntry* entry);
duke@435 189
duke@435 190 void add_entry(int index, BasicHashtableEntry* entry);
duke@435 191
duke@435 192 void free_entry(BasicHashtableEntry* entry);
duke@435 193
duke@435 194 int number_of_entries() { return _number_of_entries; }
duke@435 195
duke@435 196 void verify() PRODUCT_RETURN;
duke@435 197 };
duke@435 198
duke@435 199
duke@435 200 class Hashtable : public BasicHashtable {
duke@435 201 friend class VMStructs;
duke@435 202
duke@435 203 public:
duke@435 204 Hashtable(int table_size, int entry_size)
duke@435 205 : BasicHashtable(table_size, entry_size) { }
duke@435 206
duke@435 207 Hashtable(int table_size, int entry_size,
duke@435 208 HashtableBucket* buckets, int number_of_entries)
duke@435 209 : BasicHashtable(table_size, entry_size, buckets, number_of_entries) { }
duke@435 210
duke@435 211 // Invoke "f->do_oop" on the locations of all oops in the table.
duke@435 212 void oops_do(OopClosure* f);
duke@435 213
duke@435 214 // Debugging
duke@435 215 void print() PRODUCT_RETURN;
duke@435 216
duke@435 217 // GC support
duke@435 218 // Delete pointers to otherwise-unreachable objects.
duke@435 219 void unlink(BoolObjectClosure* cl);
duke@435 220
duke@435 221 // Reverse the order of elements in each of the buckets. Hashtable
duke@435 222 // entries which refer to objects at a lower address than 'boundary'
duke@435 223 // are separated from those which refer to objects at higher
duke@435 224 // addresses, and appear first in the list.
duke@435 225 void reverse(void* boundary = NULL);
duke@435 226
duke@435 227 protected:
duke@435 228
duke@435 229 static unsigned int hash_symbol(const char* s, int len);
duke@435 230
duke@435 231 unsigned int compute_hash(symbolHandle name) {
duke@435 232 return (unsigned int) name->identity_hash();
duke@435 233 }
duke@435 234
duke@435 235 int index_for(symbolHandle name) {
duke@435 236 return hash_to_index(compute_hash(name));
duke@435 237 }
duke@435 238
duke@435 239 // Table entry management
duke@435 240 HashtableEntry* new_entry(unsigned int hashValue, oop obj);
duke@435 241
duke@435 242 // The following method is MT-safe and may be used with caution.
duke@435 243 HashtableEntry* bucket(int i) {
duke@435 244 return (HashtableEntry*)BasicHashtable::bucket(i);
duke@435 245 }
duke@435 246
duke@435 247 // The following method is not MT-safe and must be done under lock.
duke@435 248 HashtableEntry** bucket_addr(int i) {
duke@435 249 return (HashtableEntry**)BasicHashtable::bucket_addr(i);
duke@435 250 }
duke@435 251 };
duke@435 252
duke@435 253
duke@435 254 // Verions of hashtable where two handles are used to compute the index.
duke@435 255
duke@435 256 class TwoOopHashtable : public Hashtable {
duke@435 257 friend class VMStructs;
duke@435 258 protected:
duke@435 259 TwoOopHashtable(int table_size, int entry_size)
duke@435 260 : Hashtable(table_size, entry_size) {}
duke@435 261
duke@435 262 TwoOopHashtable(int table_size, int entry_size, HashtableBucket* t,
duke@435 263 int number_of_entries)
duke@435 264 : Hashtable(table_size, entry_size, t, number_of_entries) {}
duke@435 265
duke@435 266 public:
duke@435 267 unsigned int compute_hash(symbolHandle name, Handle loader) {
duke@435 268 // Be careful with identity_hash(), it can safepoint and if this
duke@435 269 // were one expression, the compiler could choose to unhandle each
duke@435 270 // oop before calling identity_hash() for either of them. If the first
duke@435 271 // causes a GC, the next would fail.
duke@435 272 unsigned int name_hash = name->identity_hash();
duke@435 273 unsigned int loader_hash = loader.is_null() ? 0 : loader->identity_hash();
duke@435 274 return name_hash ^ loader_hash;
duke@435 275 }
duke@435 276
duke@435 277 int index_for(symbolHandle name, Handle loader) {
duke@435 278 return hash_to_index(compute_hash(name, loader));
duke@435 279 }
duke@435 280 };

mercurial