src/share/vm/utilities/hashtable.hpp

Mon, 09 Aug 2010 17:51:56 -0700

author
never
date
Mon, 09 Aug 2010 17:51:56 -0700
changeset 2044
f4f596978298
parent 1907
c18cbe5936b8
child 2314
f95d63e2154a
permissions
-rw-r--r--

Merge

duke@435 1 /*
trims@1907 2 * Copyright (c) 2003, 2005, Oracle and/or its affiliates. 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 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * 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