src/share/vm/utilities/resourceHash.hpp

Wed, 28 Nov 2012 17:50:21 -0500

author
coleenp
date
Wed, 28 Nov 2012 17:50:21 -0500
changeset 4295
59c790074993
parent 4245
4735d2c84362
child 6461
bdd155477289
permissions
-rw-r--r--

8003635: NPG: AsynchGetCallTrace broken by Method* virtual call
Summary: Make metaspace::contains be lock free and used to see if something is in metaspace, also compare Method* with vtbl pointer.
Reviewed-by: dholmes, sspitsyn, dcubed, jmasa

kamg@4245 1 /*
kamg@4245 2 * Copyright (c) 2012, 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);
kamg@4245 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,
kamg@4245 47 typename ResourceHashtableFns<K>::hash_fn HASH = primitive_hash<K>,
kamg@4245 48 typename ResourceHashtableFns<K>::equals_fn EQUALS = primitive_equals<K>,
kamg@4245 49 unsigned SIZE = 256
kamg@4245 50 >
kamg@4245 51 class ResourceHashtable : public ResourceObj {
kamg@4245 52 private:
kamg@4245 53
kamg@4245 54 class Node : public ResourceObj {
kamg@4245 55 public:
kamg@4245 56 unsigned _hash;
kamg@4245 57 K _key;
kamg@4245 58 V _value;
kamg@4245 59 Node* _next;
kamg@4245 60
kamg@4245 61 Node(unsigned hash, K const& key, V const& value) :
kamg@4245 62 _hash(hash), _key(key), _value(value), _next(NULL) {}
kamg@4245 63 };
kamg@4245 64
kamg@4245 65 Node* _table[SIZE];
kamg@4245 66
kamg@4245 67 // Returns a pointer to where the node where the value would reside if
kamg@4245 68 // it's in the table.
kamg@4245 69 Node** lookup_node(unsigned hash, K const& key) {
kamg@4245 70 unsigned index = hash % SIZE;
kamg@4245 71 Node** ptr = &_table[index];
kamg@4245 72 while (*ptr != NULL) {
kamg@4245 73 Node* node = *ptr;
kamg@4245 74 if (node->_hash == hash && EQUALS(key, node->_key)) {
kamg@4245 75 break;
kamg@4245 76 }
kamg@4245 77 ptr = &(node->_next);
kamg@4245 78 }
kamg@4245 79 return ptr;
kamg@4245 80 }
kamg@4245 81
kamg@4245 82 Node const** lookup_node(unsigned hash, K const& key) const {
kamg@4245 83 return const_cast<Node const**>(
kamg@4245 84 const_cast<ResourceHashtable*>(this)->lookup_node(hash, key));
kamg@4245 85 }
kamg@4245 86
kamg@4245 87 public:
kamg@4245 88 ResourceHashtable() { memset(_table, 0, SIZE * sizeof(Node*)); }
kamg@4245 89
kamg@4245 90 bool contains(K const& key) const {
kamg@4245 91 return get(key) != NULL;
kamg@4245 92 }
kamg@4245 93
kamg@4245 94 V* get(K const& key) const {
kamg@4245 95 unsigned hv = HASH(key);
kamg@4245 96 Node const** ptr = lookup_node(hv, key);
kamg@4245 97 if (*ptr != NULL) {
kamg@4245 98 return const_cast<V*>(&(*ptr)->_value);
kamg@4245 99 } else {
kamg@4245 100 return NULL;
kamg@4245 101 }
kamg@4245 102 }
kamg@4245 103
kamg@4245 104 // Inserts or replaces a value in the table
kamg@4245 105 void put(K const& key, V const& value) {
kamg@4245 106 unsigned hv = HASH(key);
kamg@4245 107 Node** ptr = lookup_node(hv, key);
kamg@4245 108 if (*ptr != NULL) {
kamg@4245 109 (*ptr)->_value = value;
kamg@4245 110 } else {
kamg@4245 111 *ptr = new Node(hv, key, value);
kamg@4245 112 }
kamg@4245 113 }
kamg@4245 114
kamg@4245 115 // ITER contains bool do_entry(K const&, V const&), which will be
kamg@4245 116 // called for each entry in the table. If do_entry() returns false,
kamg@4245 117 // the iteration is cancelled.
kamg@4245 118 template<class ITER>
kamg@4245 119 void iterate(ITER* iter) const {
kamg@4245 120 Node* const* bucket = _table;
kamg@4245 121 while (bucket < &_table[SIZE]) {
kamg@4245 122 Node* node = *bucket;
kamg@4245 123 while (node != NULL) {
kamg@4245 124 bool cont = iter->do_entry(node->_key, node->_value);
kamg@4245 125 if (!cont) { return; }
kamg@4245 126 node = node->_next;
kamg@4245 127 }
kamg@4245 128 ++bucket;
kamg@4245 129 }
kamg@4245 130 }
kamg@4245 131 };
kamg@4245 132
kamg@4245 133
kamg@4245 134 #endif // SHARE_VM_UTILITIES_RESOURCEHASH_HPP

mercurial