8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_VM_UTILITIES_HASHTABLE_HPP
26 #define SHARE_VM_UTILITIES_HASHTABLE_HPP
27
28 #include "classfile/classLoaderData.hpp"
29 #include "memory/allocation.hpp"
30 #include "oops/oop.hpp"
31 #include "oops/symbol.hpp"
32 #include "runtime/handles.hpp"
33
34 // This is a generic hashtable, designed to be used for the symbol
35 // and string tables.
36 //
37 // It is implemented as an open hash table with a fixed number of buckets.
38 //
39 // %note:
40 // - TableEntrys are allocated in blocks to reduce the space overhead.
41
42
43
44 template <MEMFLAGS F> class BasicHashtableEntry : public CHeapObj<F> {
45 friend class VMStructs;
46 private:
47 unsigned int _hash; // 32-bit hash for item
48
49 // Link to next element in the linked list for this bucket. EXCEPT
50 // bit 0 set indicates that this entry is shared and must not be
51 // unlinked from the table. Bit 0 is set during the dumping of the
52 // archive. Since shared entries are immutable, _next fields in the
129 void clear() { _entry = NULL; }
130
131 // The following methods use order access methods to avoid race
132 // conditions in multiprocessor systems.
133 BasicHashtableEntry<F>* get_entry() const;
134 void set_entry(BasicHashtableEntry<F>* l);
135
136 // The following method is not MT-safe and must be done under lock.
137 BasicHashtableEntry<F>** entry_addr() { return &_entry; }
138
139 };
140
141
142 template <MEMFLAGS F> class BasicHashtable : public CHeapObj<F> {
143 friend class VMStructs;
144
145 public:
146 BasicHashtable(int table_size, int entry_size);
147 BasicHashtable(int table_size, int entry_size,
148 HashtableBucket<F>* buckets, int number_of_entries);
149
150 // Bucket handling
151 int hash_to_index(unsigned int full_hash) const {
152 int h = full_hash % _table_size;
153 assert(h >= 0 && h < _table_size, "Illegal hash value");
154 return h;
155 }
156
157 private:
158 // Instance variables
159 int _table_size;
160 HashtableBucket<F>* _buckets;
161 BasicHashtableEntry<F>* volatile _free_list;
162 char* _first_free_entry;
163 char* _end_block;
164 int _entry_size;
165 volatile int _number_of_entries;
166
167 protected:
168
169 void initialize(int table_size, int entry_size, int number_of_entries);
170
171 // Accessor
172 int entry_size() const { return _entry_size; }
173
174 // The following method is MT-safe and may be used with caution.
175 BasicHashtableEntry<F>* bucket(int i) const;
176
177 // The following method is not MT-safe and must be done under lock.
178 BasicHashtableEntry<F>** bucket_addr(int i) { return _buckets[i].entry_addr(); }
179
180 // Attempt to get an entry from the free list
181 BasicHashtableEntry<F>* new_entry_free_list();
182
183 // Table entry management
184 BasicHashtableEntry<F>* new_entry(unsigned int hashValue);
185
216 BucketUnlinkContext() : _num_processed(0), _num_removed(0), _removed_head(NULL), _removed_tail(NULL) {
217 }
218
219 void free_entry(BasicHashtableEntry<F>* entry);
220 };
221 // Add of bucket entries linked together in the given context to the global free list. This method
222 // is mt-safe wrt. to other calls of this method.
223 void bulk_free_entries(BucketUnlinkContext* context);
224 public:
225 int table_size() const { return _table_size; }
226 void set_entry(int index, BasicHashtableEntry<F>* entry);
227
228 void add_entry(int index, BasicHashtableEntry<F>* entry);
229
230 void free_entry(BasicHashtableEntry<F>* entry);
231
232 int number_of_entries() const { return _number_of_entries; }
233
234 bool resize(int new_size);
235
236 template <class T> void verify_table(const char* table_name) PRODUCT_RETURN;
237 };
238
239
240 template <class T, MEMFLAGS F> class Hashtable : public BasicHashtable<F> {
241 friend class VMStructs;
242
243 public:
244 Hashtable(int table_size, int entry_size)
245 : BasicHashtable<F>(table_size, entry_size) { }
246
247 Hashtable(int table_size, int entry_size,
248 HashtableBucket<F>* buckets, int number_of_entries)
249 : BasicHashtable<F>(table_size, entry_size, buckets, number_of_entries) { }
250
251 // Debugging
252 void print() PRODUCT_RETURN;
253
254 unsigned int compute_hash(const Symbol* name) const {
255 return (unsigned int) name->identity_hash();
261
262 void print_table_statistics(outputStream* st, const char *table_name, T (*literal_load_barrier)(HashtableEntry<T, F>*) = NULL);
263
264 protected:
265
266 // Table entry management
267 HashtableEntry<T, F>* new_entry(unsigned int hashValue, T obj);
268 // Don't create and use freelist of HashtableEntry.
269 HashtableEntry<T, F>* allocate_new_entry(unsigned int hashValue, T obj);
270
271 // The following method is MT-safe and may be used with caution.
272 HashtableEntry<T, F>* bucket(int i) const {
273 return (HashtableEntry<T, F>*)BasicHashtable<F>::bucket(i);
274 }
275
276 // The following method is not MT-safe and must be done under lock.
277 HashtableEntry<T, F>** bucket_addr(int i) {
278 return (HashtableEntry<T, F>**)BasicHashtable<F>::bucket_addr(i);
279 }
280 };
281
282 #endif // SHARE_VM_UTILITIES_HASHTABLE_HPP
|
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_VM_UTILITIES_HASHTABLE_HPP
26 #define SHARE_VM_UTILITIES_HASHTABLE_HPP
27
28 #include "memory/allocation.hpp"
29 #include "oops/oop.hpp"
30 #include "oops/symbol.hpp"
31 #include "runtime/handles.hpp"
32 #include "utilities/growableArray.hpp"
33
34 // This is a generic hashtable, designed to be used for the symbol
35 // and string tables.
36 //
37 // It is implemented as an open hash table with a fixed number of buckets.
38 //
39 // %note:
40 // - TableEntrys are allocated in blocks to reduce the space overhead.
41
42
43
44 template <MEMFLAGS F> class BasicHashtableEntry : public CHeapObj<F> {
45 friend class VMStructs;
46 private:
47 unsigned int _hash; // 32-bit hash for item
48
49 // Link to next element in the linked list for this bucket. EXCEPT
50 // bit 0 set indicates that this entry is shared and must not be
51 // unlinked from the table. Bit 0 is set during the dumping of the
52 // archive. Since shared entries are immutable, _next fields in the
129 void clear() { _entry = NULL; }
130
131 // The following methods use order access methods to avoid race
132 // conditions in multiprocessor systems.
133 BasicHashtableEntry<F>* get_entry() const;
134 void set_entry(BasicHashtableEntry<F>* l);
135
136 // The following method is not MT-safe and must be done under lock.
137 BasicHashtableEntry<F>** entry_addr() { return &_entry; }
138
139 };
140
141
142 template <MEMFLAGS F> class BasicHashtable : public CHeapObj<F> {
143 friend class VMStructs;
144
145 public:
146 BasicHashtable(int table_size, int entry_size);
147 BasicHashtable(int table_size, int entry_size,
148 HashtableBucket<F>* buckets, int number_of_entries);
149 ~BasicHashtable();
150
151 // Bucket handling
152 int hash_to_index(unsigned int full_hash) const {
153 int h = full_hash % _table_size;
154 assert(h >= 0 && h < _table_size, "Illegal hash value");
155 return h;
156 }
157
158 private:
159 // Instance variables
160 int _table_size;
161 HashtableBucket<F>* _buckets;
162 BasicHashtableEntry<F>* volatile _free_list;
163 char* _first_free_entry;
164 char* _end_block;
165 int _entry_size;
166 volatile int _number_of_entries;
167 GrowableArray<char*>* _entry_blocks;
168
169 protected:
170
171 void initialize(int table_size, int entry_size, int number_of_entries);
172
173 // Accessor
174 int entry_size() const { return _entry_size; }
175
176 // The following method is MT-safe and may be used with caution.
177 BasicHashtableEntry<F>* bucket(int i) const;
178
179 // The following method is not MT-safe and must be done under lock.
180 BasicHashtableEntry<F>** bucket_addr(int i) { return _buckets[i].entry_addr(); }
181
182 // Attempt to get an entry from the free list
183 BasicHashtableEntry<F>* new_entry_free_list();
184
185 // Table entry management
186 BasicHashtableEntry<F>* new_entry(unsigned int hashValue);
187
218 BucketUnlinkContext() : _num_processed(0), _num_removed(0), _removed_head(NULL), _removed_tail(NULL) {
219 }
220
221 void free_entry(BasicHashtableEntry<F>* entry);
222 };
223 // Add of bucket entries linked together in the given context to the global free list. This method
224 // is mt-safe wrt. to other calls of this method.
225 void bulk_free_entries(BucketUnlinkContext* context);
226 public:
227 int table_size() const { return _table_size; }
228 void set_entry(int index, BasicHashtableEntry<F>* entry);
229
230 void add_entry(int index, BasicHashtableEntry<F>* entry);
231
232 void free_entry(BasicHashtableEntry<F>* entry);
233
234 int number_of_entries() const { return _number_of_entries; }
235
236 bool resize(int new_size);
237
238 // Grow the number of buckets if the average entries per bucket is over the load_factor
239 bool maybe_grow(int load_factor = 8) {
240 if (number_of_entries() / table_size() > load_factor) {
241 resize(table_size() * 2);
242 return true;
243 } else {
244 return false;
245 }
246 }
247
248 template <class T> void verify_table(const char* table_name) PRODUCT_RETURN;
249 };
250
251
252 template <class T, MEMFLAGS F> class Hashtable : public BasicHashtable<F> {
253 friend class VMStructs;
254
255 public:
256 Hashtable(int table_size, int entry_size)
257 : BasicHashtable<F>(table_size, entry_size) { }
258
259 Hashtable(int table_size, int entry_size,
260 HashtableBucket<F>* buckets, int number_of_entries)
261 : BasicHashtable<F>(table_size, entry_size, buckets, number_of_entries) { }
262
263 // Debugging
264 void print() PRODUCT_RETURN;
265
266 unsigned int compute_hash(const Symbol* name) const {
267 return (unsigned int) name->identity_hash();
273
274 void print_table_statistics(outputStream* st, const char *table_name, T (*literal_load_barrier)(HashtableEntry<T, F>*) = NULL);
275
276 protected:
277
278 // Table entry management
279 HashtableEntry<T, F>* new_entry(unsigned int hashValue, T obj);
280 // Don't create and use freelist of HashtableEntry.
281 HashtableEntry<T, F>* allocate_new_entry(unsigned int hashValue, T obj);
282
283 // The following method is MT-safe and may be used with caution.
284 HashtableEntry<T, F>* bucket(int i) const {
285 return (HashtableEntry<T, F>*)BasicHashtable<F>::bucket(i);
286 }
287
288 // The following method is not MT-safe and must be done under lock.
289 HashtableEntry<T, F>** bucket_addr(int i) {
290 return (HashtableEntry<T, F>**)BasicHashtable<F>::bucket_addr(i);
291 }
292 };
293
294 // A subclass of BasicHashtable that allows you to do a simple K -> V mapping
295 // without using tons of boilerplate code.
296 template<
297 typename K, typename V, MEMFLAGS F,
298 unsigned (*HASH) (K const&) = primitive_hash<K>,
299 bool (*EQUALS)(K const&, K const&) = primitive_equals<K>
300 >
301 class KVHashtable : public BasicHashtable<F> {
302 class KVHashtableEntry : public BasicHashtableEntry<F> {
303 public:
304 K _key;
305 V _value;
306 KVHashtableEntry* next() {
307 return (KVHashtableEntry*)BasicHashtableEntry<F>::next();
308 }
309 };
310
311 protected:
312 KVHashtableEntry* bucket(int i) const {
313 return (KVHashtableEntry*)BasicHashtable<F>::bucket(i);
314 }
315
316 KVHashtableEntry* new_entry(unsigned int hashValue, K key, V value) {
317 KVHashtableEntry* entry = (KVHashtableEntry*)BasicHashtable<F>::new_entry(hashValue);
318 entry->_key = key;
319 entry->_value = value;
320 return entry;
321 }
322
323 public:
324 KVHashtable(int table_size) : BasicHashtable<F>(table_size, sizeof(KVHashtableEntry)) {}
325
326 void add(K key, V value) {
327 unsigned int hash = HASH(key);
328 KVHashtableEntry* entry = new_entry(hash, key, value);
329 BasicHashtable<F>::add_entry(BasicHashtable<F>::hash_to_index(hash), entry);
330 }
331
332 V* lookup(K key) {
333 unsigned int hash = HASH(key);
334 int index = BasicHashtable<F>::hash_to_index(hash);
335 for (KVHashtableEntry* e = bucket(index); e != NULL; e = e->next()) {
336 if (e->hash() == hash && e->_key == key) {
337 return &(e->_value);
338 }
339 }
340 return NULL;
341 }
342 };
343
344
345 #endif // SHARE_VM_UTILITIES_HASHTABLE_HPP
|