1 /*
2 * Copyright (c) 2003, 2020, 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 *
23 */
24
25 #ifndef SHARE_UTILITIES_HASHTABLE_INLINE_HPP
26 #define SHARE_UTILITIES_HASHTABLE_INLINE_HPP
27
28 #include "memory/allocation.inline.hpp"
29 #include "runtime/atomic.hpp"
30 #include "services/memTracker.hpp"
31 #include "utilities/hashtable.hpp"
32 #include "utilities/dtrace.hpp"
33
34 // Inline function definitions for hashtable.hpp.
35
36 // --------------------------------------------------------------------------
37
38 // Initialize a table.
39
BasicHashtable(int table_size,int entry_size)40 template <MEMFLAGS F> inline BasicHashtable<F>::BasicHashtable(int table_size, int entry_size) :
41 _entry_blocks(4) {
42 // Called on startup, no locking needed
43 initialize(table_size, entry_size, 0);
44 _buckets = NEW_C_HEAP_ARRAY2(HashtableBucket<F>, table_size, F, CURRENT_PC);
45 for (int index = 0; index < _table_size; index++) {
46 _buckets[index].clear();
47 }
48 _stats_rate = TableRateStatistics();
49 }
50
51
BasicHashtable(int table_size,int entry_size,HashtableBucket<F> * buckets,int number_of_entries)52 template <MEMFLAGS F> inline BasicHashtable<F>::BasicHashtable(int table_size, int entry_size,
53 HashtableBucket<F>* buckets,
54 int number_of_entries) :
55 _entry_blocks(4) {
56 // Called on startup, no locking needed
57 initialize(table_size, entry_size, number_of_entries);
58 _buckets = buckets;
59 _stats_rate = TableRateStatistics();
60 }
61
~BasicHashtable()62 template <MEMFLAGS F> inline BasicHashtable<F>::~BasicHashtable() {
63 for (int i = 0; i < _entry_blocks.length(); i++) {
64 FREE_C_HEAP_ARRAY(char, _entry_blocks.at(i));
65 }
66 free_buckets();
67 }
68
initialize(int table_size,int entry_size,int number_of_entries)69 template <MEMFLAGS F> inline void BasicHashtable<F>::initialize(int table_size, int entry_size,
70 int number_of_entries) {
71 // Called on startup, no locking needed
72 _table_size = table_size;
73 _entry_size = entry_size;
74 _free_list = NULL;
75 _first_free_entry = NULL;
76 _end_block = NULL;
77 _number_of_entries = number_of_entries;
78 }
79
80
81 // The following method is MT-safe and may be used with caution.
bucket(int i) const82 template <MEMFLAGS F> inline BasicHashtableEntry<F>* BasicHashtable<F>::bucket(int i) const {
83 return _buckets[i].get_entry();
84 }
85
86
set_entry(BasicHashtableEntry<F> * l)87 template <MEMFLAGS F> inline void HashtableBucket<F>::set_entry(BasicHashtableEntry<F>* l) {
88 // Warning: Preserve store ordering. The PackageEntryTable, ModuleEntryTable and
89 // SystemDictionary are read without locks. The new entry must be
90 // complete before other threads can be allowed to see it
91 // via a store to _buckets[index].
92 Atomic::release_store(&_entry, l);
93 }
94
95
get_entry() const96 template <MEMFLAGS F> inline BasicHashtableEntry<F>* HashtableBucket<F>::get_entry() const {
97 // Warning: Preserve load ordering. The PackageEntryTable, ModuleEntryTable and
98 // SystemDictionary are read without locks. The new entry must be
99 // complete before other threads can be allowed to see it
100 // via a store to _buckets[index].
101 return Atomic::load_acquire(&_entry);
102 }
103
104
set_entry(int index,BasicHashtableEntry<F> * entry)105 template <MEMFLAGS F> inline void BasicHashtable<F>::set_entry(int index, BasicHashtableEntry<F>* entry) {
106 _buckets[index].set_entry(entry);
107 if (entry != NULL) {
108 JFR_ONLY(_stats_rate.add();)
109 } else {
110 JFR_ONLY(_stats_rate.remove();)
111 }
112 }
113
114
add_entry(int index,BasicHashtableEntry<F> * entry)115 template <MEMFLAGS F> inline void BasicHashtable<F>::add_entry(int index, BasicHashtableEntry<F>* entry) {
116 entry->set_next(bucket(index));
117 _buckets[index].set_entry(entry);
118 ++_number_of_entries;
119 JFR_ONLY(_stats_rate.add();)
120 }
121
free_entry(BasicHashtableEntry<F> * entry)122 template <MEMFLAGS F> inline void BasicHashtable<F>::free_entry(BasicHashtableEntry<F>* entry) {
123 entry->set_next(_free_list);
124 _free_list = entry;
125 --_number_of_entries;
126 JFR_ONLY(_stats_rate.remove();)
127 }
128
129 #endif // SHARE_UTILITIES_HASHTABLE_INLINE_HPP
130