< prev index next >
src/hotspot/share/utilities/hashtable.hpp
Print this page
*** 23,37 ****
*/
#ifndef SHARE_VM_UTILITIES_HASHTABLE_HPP
#define SHARE_VM_UTILITIES_HASHTABLE_HPP
- #include "classfile/classLoaderData.hpp"
#include "memory/allocation.hpp"
#include "oops/oop.hpp"
#include "oops/symbol.hpp"
#include "runtime/handles.hpp"
// This is a generic hashtable, designed to be used for the symbol
// and string tables.
//
// It is implemented as an open hash table with a fixed number of buckets.
--- 23,37 ----
*/
#ifndef SHARE_VM_UTILITIES_HASHTABLE_HPP
#define SHARE_VM_UTILITIES_HASHTABLE_HPP
#include "memory/allocation.hpp"
#include "oops/oop.hpp"
#include "oops/symbol.hpp"
#include "runtime/handles.hpp"
+ #include "utilities/growableArray.hpp"
// This is a generic hashtable, designed to be used for the symbol
// and string tables.
//
// It is implemented as an open hash table with a fixed number of buckets.
*** 144,153 ****
--- 144,154 ----
public:
BasicHashtable(int table_size, int entry_size);
BasicHashtable(int table_size, int entry_size,
HashtableBucket<F>* buckets, int number_of_entries);
+ ~BasicHashtable();
// Bucket handling
int hash_to_index(unsigned int full_hash) const {
int h = full_hash % _table_size;
assert(h >= 0 && h < _table_size, "Illegal hash value");
*** 161,170 ****
--- 162,172 ----
BasicHashtableEntry<F>* volatile _free_list;
char* _first_free_entry;
char* _end_block;
int _entry_size;
volatile int _number_of_entries;
+ GrowableArray<char*>* _entry_blocks;
protected:
void initialize(int table_size, int entry_size, int number_of_entries);
*** 231,240 ****
--- 233,252 ----
int number_of_entries() const { return _number_of_entries; }
bool resize(int new_size);
+ // Grow the number of buckets if the average entries per bucket is over the load_factor
+ bool maybe_grow(int load_factor = 8) {
+ if (number_of_entries() / table_size() > load_factor) {
+ resize(table_size() * 2);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
template <class T> void verify_table(const char* table_name) PRODUCT_RETURN;
};
template <class T, MEMFLAGS F> class Hashtable : public BasicHashtable<F> {
*** 277,282 ****
--- 289,345 ----
HashtableEntry<T, F>** bucket_addr(int i) {
return (HashtableEntry<T, F>**)BasicHashtable<F>::bucket_addr(i);
}
};
+ // A subclass of BasicHashtable that allows you to do a simple K -> V mapping
+ // without using tons of boilerplate code.
+ template<
+ typename K, typename V, MEMFLAGS F,
+ unsigned (*HASH) (K const&) = primitive_hash<K>,
+ bool (*EQUALS)(K const&, K const&) = primitive_equals<K>
+ >
+ class KVHashtable : public BasicHashtable<F> {
+ class KVHashtableEntry : public BasicHashtableEntry<F> {
+ public:
+ K _key;
+ V _value;
+ KVHashtableEntry* next() {
+ return (KVHashtableEntry*)BasicHashtableEntry<F>::next();
+ }
+ };
+
+ protected:
+ KVHashtableEntry* bucket(int i) const {
+ return (KVHashtableEntry*)BasicHashtable<F>::bucket(i);
+ }
+
+ KVHashtableEntry* new_entry(unsigned int hashValue, K key, V value) {
+ KVHashtableEntry* entry = (KVHashtableEntry*)BasicHashtable<F>::new_entry(hashValue);
+ entry->_key = key;
+ entry->_value = value;
+ return entry;
+ }
+
+ public:
+ KVHashtable(int table_size) : BasicHashtable<F>(table_size, sizeof(KVHashtableEntry)) {}
+
+ void add(K key, V value) {
+ unsigned int hash = HASH(key);
+ KVHashtableEntry* entry = new_entry(hash, key, value);
+ BasicHashtable<F>::add_entry(BasicHashtable<F>::hash_to_index(hash), entry);
+ }
+
+ V* lookup(K key) {
+ unsigned int hash = HASH(key);
+ int index = BasicHashtable<F>::hash_to_index(hash);
+ for (KVHashtableEntry* e = bucket(index); e != NULL; e = e->next()) {
+ if (e->hash() == hash && e->_key == key) {
+ return &(e->_value);
+ }
+ }
+ return NULL;
+ }
+ };
+
+
#endif // SHARE_VM_UTILITIES_HASHTABLE_HPP
< prev index next >