1 /*
2 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
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 *
24
25 #ifndef SHARE_VM_UTILITIES_RESOURCEHASH_HPP
26 #define SHARE_VM_UTILITIES_RESOURCEHASH_HPP
27
28 #include "memory/allocation.hpp"
29
30 template<typename K> struct ResourceHashtableFns {
31 typedef unsigned (*hash_fn)(K const&);
32 typedef bool (*equals_fn)(K const&, K const&);
33 };
34
35 template<typename K> unsigned primitive_hash(const K& k) {
36 unsigned hash = (unsigned)((uintptr_t)k);
37 return hash ^ (hash >> 3); // just in case we're dealing with aligned ptrs
38 }
39
40 template<typename K> bool primitive_equals(const K& k0, const K& k1) {
41 return k0 == k1;
42 }
43
44 template<
45 typename K, typename V,
46 // xlC does not compile this:
47 // http://stackoverflow.com/questions/8532961/template-argument-of-type-that-is-defined-by-inner-typedef-from-other-template-c
48 //typename ResourceHashtableFns<K>::hash_fn HASH = primitive_hash<K>,
49 //typename ResourceHashtableFns<K>::equals_fn EQUALS = primitive_equals<K>,
50 unsigned (*HASH) (K const&) = primitive_hash<K>,
51 bool (*EQUALS)(K const&, K const&) = primitive_equals<K>,
52 unsigned SIZE = 256,
53 ResourceObj::allocation_type ALLOC_TYPE = ResourceObj::RESOURCE_AREA,
54 MEMFLAGS MEM_TYPE = mtInternal
55 >
56 class ResourceHashtable : public ResourceObj {
57 private:
58
59 class Node : public ResourceObj {
60 public:
61 unsigned _hash;
62 K _key;
63 V _value;
64 Node* _next;
65
66 Node(unsigned hash, K const& key, V const& value) :
67 _hash(hash), _key(key), _value(value), _next(NULL) {}
68 };
69
70 Node* _table[SIZE];
71
72 // Returns a pointer to where the node where the value would reside if
73 // it's in the table.
74 Node** lookup_node(unsigned hash, K const& key) {
75 unsigned index = hash % SIZE;
76 Node** ptr = &_table[index];
77 while (*ptr != NULL) {
78 Node* node = *ptr;
79 if (node->_hash == hash && EQUALS(key, node->_key)) {
80 break;
81 }
82 ptr = &(node->_next);
83 }
84 return ptr;
85 }
86
87 Node const** lookup_node(unsigned hash, K const& key) const {
88 return const_cast<Node const**>(
89 const_cast<ResourceHashtable*>(this)->lookup_node(hash, key));
90 }
91
92 public:
93 ResourceHashtable() { memset(_table, 0, SIZE * sizeof(Node*)); }
94
95 ~ResourceHashtable() {
96 if (ALLOC_TYPE == C_HEAP) {
97 Node* const* bucket = _table;
98 while (bucket < &_table[SIZE]) {
99 Node* node = *bucket;
100 while (node != NULL) {
101 Node* cur = node;
102 node = node->_next;
103 delete cur;
104 }
105 ++bucket;
106 }
107 }
108 }
109
110 bool contains(K const& key) const {
111 return get(key) != NULL;
112 }
113
114 V* get(K const& key) const {
115 unsigned hv = HASH(key);
116 Node const** ptr = lookup_node(hv, key);
117 if (*ptr != NULL) {
118 return const_cast<V*>(&(*ptr)->_value);
119 } else {
120 return NULL;
121 }
122 }
123
124 /**
125 * Inserts or replaces a value in the table.
126 * @return: true: if a new item is added
141 bool remove(K const& key) {
142 unsigned hv = HASH(key);
143 Node** ptr = lookup_node(hv, key);
144
145 Node* node = *ptr;
146 if (node != NULL) {
147 *ptr = node->_next;
148 if (ALLOC_TYPE == C_HEAP) {
149 delete node;
150 }
151 return true;
152 }
153 return false;
154 }
155
156 // ITER contains bool do_entry(K const&, V const&), which will be
157 // called for each entry in the table. If do_entry() returns false,
158 // the iteration is cancelled.
159 template<class ITER>
160 void iterate(ITER* iter) const {
161 Node* const* bucket = _table;
162 while (bucket < &_table[SIZE]) {
163 Node* node = *bucket;
164 while (node != NULL) {
165 bool cont = iter->do_entry(node->_key, node->_value);
166 if (!cont) { return; }
167 node = node->_next;
168 }
169 ++bucket;
170 }
171 }
172
173 static size_t node_size() {
174 return sizeof(Node);
175 }
176 };
177
178
179 #endif // SHARE_VM_UTILITIES_RESOURCEHASH_HPP
|
1 /*
2 * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
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 *
24
25 #ifndef SHARE_VM_UTILITIES_RESOURCEHASH_HPP
26 #define SHARE_VM_UTILITIES_RESOURCEHASH_HPP
27
28 #include "memory/allocation.hpp"
29
30 template<typename K> struct ResourceHashtableFns {
31 typedef unsigned (*hash_fn)(K const&);
32 typedef bool (*equals_fn)(K const&, K const&);
33 };
34
35 template<typename K> unsigned primitive_hash(const K& k) {
36 unsigned hash = (unsigned)((uintptr_t)k);
37 return hash ^ (hash >> 3); // just in case we're dealing with aligned ptrs
38 }
39
40 template<typename K> bool primitive_equals(const K& k0, const K& k1) {
41 return k0 == k1;
42 }
43
44 enum {
45 CONFIGURABLE_SIZE = 0
46 };
47
48 template<
49 typename K, typename V,
50 // xlC does not compile this:
51 // http://stackoverflow.com/questions/8532961/template-argument-of-type-that-is-defined-by-inner-typedef-from-other-template-c
52 //typename ResourceHashtableFns<K>::hash_fn HASH = primitive_hash<K>,
53 //typename ResourceHashtableFns<K>::equals_fn EQUALS = primitive_equals<K>,
54 unsigned (*HASH) (K const&) = primitive_hash<K>,
55 bool (*EQUALS)(K const&, K const&) = primitive_equals<K>,
56 unsigned SIZE = 256,
57 ResourceObj::allocation_type ALLOC_TYPE = ResourceObj::RESOURCE_AREA,
58 MEMFLAGS MEM_TYPE = mtInternal
59 >
60 class ResourceHashtable : public ResourceObj {
61 private:
62
63 class Node : public ResourceObj {
64 public:
65 unsigned _hash;
66 K _key;
67 V _value;
68 Node* _next;
69
70 Node(unsigned hash, K const& key, V const& value) :
71 _hash(hash), _key(key), _value(value), _next(NULL) {}
72 };
73
74 Node* _static_table[SIZE == 0 ? 1 : SIZE];
75 unsigned _configured_table_size;
76 Node** _configured_table;
77
78 // Returns a pointer to where the node where the value would reside if
79 // it's in the table.
80 Node** lookup_node(unsigned hash, K const& key) {
81 unsigned index = hash % size();
82 Node** table = get_table();
83 Node** ptr = &table[index];
84 while (*ptr != NULL) {
85 Node* node = *ptr;
86 if (node->_hash == hash && EQUALS(key, node->_key)) {
87 break;
88 }
89 ptr = &(node->_next);
90 }
91 return ptr;
92 }
93
94 Node const** lookup_node(unsigned hash, K const& key) const {
95 return const_cast<Node const**>(
96 const_cast<ResourceHashtable*>(this)->lookup_node(hash, key));
97 }
98
99 public:
100 ResourceHashtable() {
101 assert(SIZE != CONFIGURABLE_SIZE, "must be");
102 memset(_static_table, 0, SIZE * sizeof(Node*));
103 _configured_table = NULL;
104 }
105
106 ResourceHashtable(unsigned configured_table_size) : _configured_table_size(configured_table_size) {
107 assert(SIZE == CONFIGURABLE_SIZE, "must be");
108 _configured_table = (Node**)operator new(size() * sizeof(Node*), ALLOC_TYPE, MEM_TYPE);
109 memset(_configured_table, 0, size() * sizeof(Node*));
110 }
111
112 ALWAYSINLINE unsigned size() const {
113 if (SIZE != CONFIGURABLE_SIZE) {
114 return SIZE;
115 } else {
116 return _configured_table_size;
117 }
118 }
119
120 ALWAYSINLINE Node** get_table() const {
121 if (SIZE != CONFIGURABLE_SIZE) {
122 return (Node**)(&_static_table[0]);
123 } else {
124 return _configured_table;
125 }
126 }
127
128 ~ResourceHashtable() {
129 if (ALLOC_TYPE == C_HEAP) {
130 Node** table = get_table();
131 Node* const* bucket = table;
132 while (bucket < &table[size()]) {
133 Node* node = *bucket;
134 while (node != NULL) {
135 Node* cur = node;
136 node = node->_next;
137 delete cur;
138 }
139 ++bucket;
140 }
141 if (_configured_table != NULL) {
142 FreeHeap((void*)_configured_table);
143 }
144 }
145 }
146
147 bool contains(K const& key) const {
148 return get(key) != NULL;
149 }
150
151 V* get(K const& key) const {
152 unsigned hv = HASH(key);
153 Node const** ptr = lookup_node(hv, key);
154 if (*ptr != NULL) {
155 return const_cast<V*>(&(*ptr)->_value);
156 } else {
157 return NULL;
158 }
159 }
160
161 /**
162 * Inserts or replaces a value in the table.
163 * @return: true: if a new item is added
178 bool remove(K const& key) {
179 unsigned hv = HASH(key);
180 Node** ptr = lookup_node(hv, key);
181
182 Node* node = *ptr;
183 if (node != NULL) {
184 *ptr = node->_next;
185 if (ALLOC_TYPE == C_HEAP) {
186 delete node;
187 }
188 return true;
189 }
190 return false;
191 }
192
193 // ITER contains bool do_entry(K const&, V const&), which will be
194 // called for each entry in the table. If do_entry() returns false,
195 // the iteration is cancelled.
196 template<class ITER>
197 void iterate(ITER* iter) const {
198 Node** table = get_table();
199 Node* const* bucket = table;
200 while (bucket < &table[size()]) {
201 Node* node = *bucket;
202 while (node != NULL) {
203 bool cont = iter->do_entry(node->_key, node->_value);
204 if (!cont) { return; }
205 node = node->_next;
206 }
207 ++bucket;
208 }
209 }
210
211 static size_t node_size() {
212 return sizeof(Node);
213 }
214 };
215
216
217 #endif // SHARE_VM_UTILITIES_RESOURCEHASH_HPP
|