Thu, 27 Jan 2011 16:11:27 -0800
6990754: Use native memory and reference counting to implement SymbolTable
Summary: move symbols from permgen into C heap and reference count them
Reviewed-by: never, acorn, jmasa, stefank
1 /*
2 * Copyright (c) 2003, 2010, 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 */
25 #ifndef SHARE_VM_UTILITIES_HASHTABLE_HPP
26 #define SHARE_VM_UTILITIES_HASHTABLE_HPP
28 #include "memory/allocation.hpp"
29 #include "oops/oop.hpp"
30 #include "oops/symbol.hpp"
31 #include "runtime/handles.hpp"
33 // This is a generic hashtable, designed to be used for the symbol
34 // and string tables.
35 //
36 // It is implemented as an open hash table with a fixed number of buckets.
37 //
38 // %note:
39 // - TableEntrys are allocated in blocks to reduce the space overhead.
43 class BasicHashtableEntry : public CHeapObj {
44 friend class VMStructs;
45 private:
46 unsigned int _hash; // 32-bit hash for item
48 // Link to next element in the linked list for this bucket. EXCEPT
49 // bit 0 set indicates that this entry is shared and must not be
50 // unlinked from the table. Bit 0 is set during the dumping of the
51 // archive. Since shared entries are immutable, _next fields in the
52 // shared entries will not change. New entries will always be
53 // unshared and since pointers are align, bit 0 will always remain 0
54 // with no extra effort.
55 BasicHashtableEntry* _next;
57 // Windows IA64 compiler requires subclasses to be able to access these
58 protected:
59 // Entry objects should not be created, they should be taken from the
60 // free list with BasicHashtable.new_entry().
61 BasicHashtableEntry() { ShouldNotReachHere(); }
62 // Entry objects should not be destroyed. They should be placed on
63 // the free list instead with BasicHashtable.free_entry().
64 ~BasicHashtableEntry() { ShouldNotReachHere(); }
66 public:
68 unsigned int hash() const { return _hash; }
69 void set_hash(unsigned int hash) { _hash = hash; }
70 unsigned int* hash_addr() { return &_hash; }
72 static BasicHashtableEntry* make_ptr(BasicHashtableEntry* p) {
73 return (BasicHashtableEntry*)((intptr_t)p & -2);
74 }
76 BasicHashtableEntry* next() const {
77 return make_ptr(_next);
78 }
80 void set_next(BasicHashtableEntry* next) {
81 _next = next;
82 }
84 BasicHashtableEntry** next_addr() {
85 return &_next;
86 }
88 bool is_shared() const {
89 return ((intptr_t)_next & 1) != 0;
90 }
92 void set_shared() {
93 _next = (BasicHashtableEntry*)((intptr_t)_next | 1);
94 }
95 };
99 template <class T> class HashtableEntry : public BasicHashtableEntry {
100 friend class VMStructs;
101 private:
102 T _literal; // ref to item in table.
104 public:
105 // Literal
106 T literal() const { return _literal; }
107 T* literal_addr() { return &_literal; }
108 void set_literal(T s) { _literal = s; }
110 HashtableEntry* next() const {
111 return (HashtableEntry*)BasicHashtableEntry::next();
112 }
113 HashtableEntry** next_addr() {
114 return (HashtableEntry**)BasicHashtableEntry::next_addr();
115 }
116 };
120 class HashtableBucket : public CHeapObj {
121 friend class VMStructs;
122 private:
123 // Instance variable
124 BasicHashtableEntry* _entry;
126 public:
127 // Accessing
128 void clear() { _entry = NULL; }
130 // The following methods use order access methods to avoid race
131 // conditions in multiprocessor systems.
132 BasicHashtableEntry* get_entry() const;
133 void set_entry(BasicHashtableEntry* l);
135 // The following method is not MT-safe and must be done under lock.
136 BasicHashtableEntry** entry_addr() { return &_entry; }
137 };
140 class BasicHashtable : public CHeapObj {
141 friend class VMStructs;
143 public:
144 BasicHashtable(int table_size, int entry_size);
145 BasicHashtable(int table_size, int entry_size,
146 HashtableBucket* buckets, int number_of_entries);
148 // Sharing support.
149 void copy_buckets(char** top, char* end);
150 void copy_table(char** top, char* end);
152 // Bucket handling
153 int hash_to_index(unsigned int full_hash) {
154 int h = full_hash % _table_size;
155 assert(h >= 0 && h < _table_size, "Illegal hash value");
156 return h;
157 }
159 // Reverse the order of elements in each of the buckets.
160 void reverse();
162 static unsigned int hash_symbol(const char* s, int len);
164 private:
165 // Instance variables
166 int _table_size;
167 HashtableBucket* _buckets;
168 BasicHashtableEntry* _free_list;
169 char* _first_free_entry;
170 char* _end_block;
171 int _entry_size;
172 int _number_of_entries;
174 protected:
176 #ifdef ASSERT
177 int _lookup_count;
178 int _lookup_length;
179 void verify_lookup_length(double load);
180 #endif
182 void initialize(int table_size, int entry_size, int number_of_entries);
184 // Accessor
185 int entry_size() const { return _entry_size; }
186 int table_size() { return _table_size; }
188 // The following method is MT-safe and may be used with caution.
189 BasicHashtableEntry* bucket(int i);
191 // The following method is not MT-safe and must be done under lock.
192 BasicHashtableEntry** bucket_addr(int i) { return _buckets[i].entry_addr(); }
194 // Table entry management
195 BasicHashtableEntry* new_entry(unsigned int hashValue);
197 public:
198 void set_entry(int index, BasicHashtableEntry* entry);
200 void add_entry(int index, BasicHashtableEntry* entry);
202 void free_entry(BasicHashtableEntry* entry);
204 int number_of_entries() { return _number_of_entries; }
206 void verify() PRODUCT_RETURN;
207 };
210 template <class T> class Hashtable : public BasicHashtable {
211 friend class VMStructs;
213 public:
214 Hashtable(int table_size, int entry_size)
215 : BasicHashtable(table_size, entry_size) { }
217 Hashtable(int table_size, int entry_size,
218 HashtableBucket* buckets, int number_of_entries)
219 : BasicHashtable(table_size, entry_size, buckets, number_of_entries) { }
221 // Debugging
222 void print() PRODUCT_RETURN;
224 // Reverse the order of elements in each of the buckets. Hashtable
225 // entries which refer to objects at a lower address than 'boundary'
226 // are separated from those which refer to objects at higher
227 // addresses, and appear first in the list.
228 void reverse(void* boundary = NULL);
230 protected:
232 unsigned int compute_hash(Symbol* name) {
233 return (unsigned int) name->identity_hash();
234 }
236 int index_for(Symbol* name) {
237 return hash_to_index(compute_hash(name));
238 }
240 // Table entry management
241 HashtableEntry<T>* new_entry(unsigned int hashValue, T obj);
243 // The following method is MT-safe and may be used with caution.
244 HashtableEntry<T>* bucket(int i) {
245 return (HashtableEntry<T>*)BasicHashtable::bucket(i);
246 }
248 // The following method is not MT-safe and must be done under lock.
249 HashtableEntry<T>** bucket_addr(int i) {
250 return (HashtableEntry<T>**)BasicHashtable::bucket_addr(i);
251 }
252 };
255 // Verions of hashtable where two handles are used to compute the index.
257 template <class T> class TwoOopHashtable : public Hashtable<T> {
258 friend class VMStructs;
259 protected:
260 TwoOopHashtable(int table_size, int entry_size)
261 : Hashtable<T>(table_size, entry_size) {}
263 TwoOopHashtable(int table_size, int entry_size, HashtableBucket* t,
264 int number_of_entries)
265 : Hashtable<T>(table_size, entry_size, t, number_of_entries) {}
267 public:
268 unsigned int compute_hash(Symbol* name, Handle loader) {
269 // Be careful with identity_hash(), it can safepoint and if this
270 // were one expression, the compiler could choose to unhandle each
271 // oop before calling identity_hash() for either of them. If the first
272 // causes a GC, the next would fail.
273 unsigned int name_hash = name->identity_hash();
274 unsigned int loader_hash = loader.is_null() ? 0 : loader->identity_hash();
275 return name_hash ^ loader_hash;
276 }
278 int index_for(Symbol* name, Handle loader) {
279 return hash_to_index(compute_hash(name, loader));
280 }
281 };
283 #endif // SHARE_VM_UTILITIES_HASHTABLE_HPP