src/share/vm/utilities/resourceHash.hpp

Thu, 27 Feb 2020 06:41:35 +0000

author
andrew
date
Thu, 27 Feb 2020 06:41:35 +0000
changeset 9845
68172de2a0d7
parent 6461
bdd155477289
child 9852
70aa912cebe5
permissions
-rw-r--r--

8055283: Expand ResourceHashtable with C_HEAP allocation, removal and some unit tests
Reviewed-by: phh

kamg@4245 1 /*
andrew@9845 2 * Copyright (c) 2012, 2015 Oracle and/or its affiliates. All rights reserved.
kamg@4245 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
kamg@4245 4 *
kamg@4245 5 * This code is free software; you can redistribute it and/or modify it
kamg@4245 6 * under the terms of the GNU General Public License version 2 only, as
kamg@4245 7 * published by the Free Software Foundation.
kamg@4245 8 *
kamg@4245 9 * This code is distributed in the hope that it will be useful, but WITHOUT
kamg@4245 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
kamg@4245 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kamg@4245 12 * version 2 for more details (a copy is included in the LICENSE file that
kamg@4245 13 * accompanied this code).
kamg@4245 14 *
kamg@4245 15 * You should have received a copy of the GNU General Public License version
kamg@4245 16 * 2 along with this work; if not, write to the Free Software Foundation,
kamg@4245 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
kamg@4245 18 *
kamg@4245 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
kamg@4245 20 * or visit www.oracle.com if you need additional information or have any
kamg@4245 21 * questions.
kamg@4245 22 *
kamg@4245 23 */
kamg@4245 24
kamg@4245 25 #ifndef SHARE_VM_UTILITIES_RESOURCEHASH_HPP
kamg@4245 26 #define SHARE_VM_UTILITIES_RESOURCEHASH_HPP
kamg@4245 27
kamg@4245 28 #include "memory/allocation.hpp"
kamg@4245 29 #include "utilities/top.hpp"
kamg@4245 30
kamg@4245 31 template<typename K> struct ResourceHashtableFns {
kamg@4245 32 typedef unsigned (*hash_fn)(K const&);
kamg@4245 33 typedef bool (*equals_fn)(K const&, K const&);
kamg@4245 34 };
kamg@4245 35
kamg@4245 36 template<typename K> unsigned primitive_hash(const K& k) {
kamg@4245 37 unsigned hash = (unsigned)((uintptr_t)k);
andrew@9845 38 return hash ^ (hash >> 3); // just in case we're dealing with aligned ptrs
kamg@4245 39 }
kamg@4245 40
kamg@4245 41 template<typename K> bool primitive_equals(const K& k0, const K& k1) {
kamg@4245 42 return k0 == k1;
kamg@4245 43 }
kamg@4245 44
kamg@4245 45 template<
kamg@4245 46 typename K, typename V,
goetz@6461 47 // xlC does not compile this:
goetz@6461 48 // http://stackoverflow.com/questions/8532961/template-argument-of-type-that-is-defined-by-inner-typedef-from-other-template-c
goetz@6461 49 //typename ResourceHashtableFns<K>::hash_fn HASH = primitive_hash<K>,
goetz@6461 50 //typename ResourceHashtableFns<K>::equals_fn EQUALS = primitive_equals<K>,
goetz@6461 51 unsigned (*HASH) (K const&) = primitive_hash<K>,
goetz@6461 52 bool (*EQUALS)(K const&, K const&) = primitive_equals<K>,
andrew@9845 53 unsigned SIZE = 256,
andrew@9845 54 ResourceObj::allocation_type ALLOC_TYPE = ResourceObj::RESOURCE_AREA,
andrew@9845 55 MEMFLAGS MEM_TYPE = mtInternal
kamg@4245 56 >
kamg@4245 57 class ResourceHashtable : public ResourceObj {
kamg@4245 58 private:
kamg@4245 59
kamg@4245 60 class Node : public ResourceObj {
kamg@4245 61 public:
kamg@4245 62 unsigned _hash;
kamg@4245 63 K _key;
kamg@4245 64 V _value;
kamg@4245 65 Node* _next;
kamg@4245 66
kamg@4245 67 Node(unsigned hash, K const& key, V const& value) :
kamg@4245 68 _hash(hash), _key(key), _value(value), _next(NULL) {}
kamg@4245 69 };
kamg@4245 70
kamg@4245 71 Node* _table[SIZE];
kamg@4245 72
kamg@4245 73 // Returns a pointer to where the node where the value would reside if
kamg@4245 74 // it's in the table.
kamg@4245 75 Node** lookup_node(unsigned hash, K const& key) {
kamg@4245 76 unsigned index = hash % SIZE;
kamg@4245 77 Node** ptr = &_table[index];
kamg@4245 78 while (*ptr != NULL) {
kamg@4245 79 Node* node = *ptr;
kamg@4245 80 if (node->_hash == hash && EQUALS(key, node->_key)) {
kamg@4245 81 break;
kamg@4245 82 }
kamg@4245 83 ptr = &(node->_next);
kamg@4245 84 }
kamg@4245 85 return ptr;
kamg@4245 86 }
kamg@4245 87
kamg@4245 88 Node const** lookup_node(unsigned hash, K const& key) const {
kamg@4245 89 return const_cast<Node const**>(
kamg@4245 90 const_cast<ResourceHashtable*>(this)->lookup_node(hash, key));
kamg@4245 91 }
kamg@4245 92
kamg@4245 93 public:
kamg@4245 94 ResourceHashtable() { memset(_table, 0, SIZE * sizeof(Node*)); }
kamg@4245 95
andrew@9845 96 ~ResourceHashtable() {
andrew@9845 97 if (ALLOC_TYPE == C_HEAP) {
andrew@9845 98 Node* const* bucket = _table;
andrew@9845 99 while (bucket < &_table[SIZE]) {
andrew@9845 100 Node* node = *bucket;
andrew@9845 101 while (node != NULL) {
andrew@9845 102 Node* cur = node;
andrew@9845 103 node = node->_next;
andrew@9845 104 delete cur;
andrew@9845 105 }
andrew@9845 106 ++bucket;
andrew@9845 107 }
andrew@9845 108 }
andrew@9845 109 }
andrew@9845 110
kamg@4245 111 bool contains(K const& key) const {
kamg@4245 112 return get(key) != NULL;
kamg@4245 113 }
kamg@4245 114
kamg@4245 115 V* get(K const& key) const {
kamg@4245 116 unsigned hv = HASH(key);
kamg@4245 117 Node const** ptr = lookup_node(hv, key);
kamg@4245 118 if (*ptr != NULL) {
kamg@4245 119 return const_cast<V*>(&(*ptr)->_value);
kamg@4245 120 } else {
kamg@4245 121 return NULL;
kamg@4245 122 }
kamg@4245 123 }
kamg@4245 124
andrew@9845 125 /**
andrew@9845 126 * Inserts or replaces a value in the table.
andrew@9845 127 * @return: true: if a new item is added
andrew@9845 128 * false: if the item already existed and the value is updated
andrew@9845 129 */
andrew@9845 130 bool put(K const& key, V const& value) {
kamg@4245 131 unsigned hv = HASH(key);
kamg@4245 132 Node** ptr = lookup_node(hv, key);
kamg@4245 133 if (*ptr != NULL) {
kamg@4245 134 (*ptr)->_value = value;
andrew@9845 135 return false;
kamg@4245 136 } else {
andrew@9845 137 *ptr = new (ALLOC_TYPE, MEM_TYPE) Node(hv, key, value);
andrew@9845 138 return true;
kamg@4245 139 }
kamg@4245 140 }
kamg@4245 141
andrew@9845 142 bool remove(K const& key) {
andrew@9845 143 unsigned hv = HASH(key);
andrew@9845 144 Node** ptr = lookup_node(hv, key);
andrew@9845 145
andrew@9845 146 Node* node = *ptr;
andrew@9845 147 if (node != NULL) {
andrew@9845 148 *ptr = node->_next;
andrew@9845 149 if (ALLOC_TYPE == C_HEAP) {
andrew@9845 150 delete node;
andrew@9845 151 }
andrew@9845 152 return true;
andrew@9845 153 }
andrew@9845 154 return false;
andrew@9845 155 }
andrew@9845 156
kamg@4245 157 // ITER contains bool do_entry(K const&, V const&), which will be
kamg@4245 158 // called for each entry in the table. If do_entry() returns false,
kamg@4245 159 // the iteration is cancelled.
kamg@4245 160 template<class ITER>
kamg@4245 161 void iterate(ITER* iter) const {
kamg@4245 162 Node* const* bucket = _table;
kamg@4245 163 while (bucket < &_table[SIZE]) {
kamg@4245 164 Node* node = *bucket;
kamg@4245 165 while (node != NULL) {
kamg@4245 166 bool cont = iter->do_entry(node->_key, node->_value);
kamg@4245 167 if (!cont) { return; }
kamg@4245 168 node = node->_next;
kamg@4245 169 }
kamg@4245 170 ++bucket;
kamg@4245 171 }
kamg@4245 172 }
andrew@9845 173
andrew@9845 174 static size_t node_size() {
andrew@9845 175 return sizeof(Node);
andrew@9845 176 }
kamg@4245 177 };
kamg@4245 178
kamg@4245 179
kamg@4245 180 #endif // SHARE_VM_UTILITIES_RESOURCEHASH_HPP

mercurial