Mon, 25 Jun 2012 21:33:35 -0400
7178670: runtime/7158800/BadUtf8.java fails in SymbolTable::rehash_table
Summary: Cannot delete _buckets and HashtableEntries in shared space (CDS)
Reviewed-by: acorn, kvn, dlong, dcubed, kamg
1 /*
2 * Copyright (c) 2003, 2012, 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 private:
163 // Instance variables
164 int _table_size;
165 HashtableBucket* _buckets;
166 BasicHashtableEntry* _free_list;
167 char* _first_free_entry;
168 char* _end_block;
169 int _entry_size;
170 int _number_of_entries;
172 protected:
174 #ifdef ASSERT
175 int _lookup_count;
176 int _lookup_length;
177 void verify_lookup_length(double load);
178 #endif
180 enum {
181 rehash_count = 100,
182 rehash_multiple = 60
183 };
185 void initialize(int table_size, int entry_size, int number_of_entries);
187 // Accessor
188 int entry_size() const { return _entry_size; }
190 // The following method is MT-safe and may be used with caution.
191 BasicHashtableEntry* bucket(int i);
193 // The following method is not MT-safe and must be done under lock.
194 BasicHashtableEntry** bucket_addr(int i) { return _buckets[i].entry_addr(); }
196 // Table entry management
197 BasicHashtableEntry* new_entry(unsigned int hashValue);
199 // Check that the table is unbalanced
200 bool check_rehash_table(int count);
202 // Used when moving the entry to another table
203 // Clean up links, but do not add to free_list
204 void unlink_entry(BasicHashtableEntry* entry) {
205 entry->set_next(NULL);
206 --_number_of_entries;
207 }
209 // Move over freelist and free block for allocation
210 void copy_freelist(BasicHashtable* src) {
211 _free_list = src->_free_list;
212 src->_free_list = NULL;
213 _first_free_entry = src->_first_free_entry;
214 src->_first_free_entry = NULL;
215 _end_block = src->_end_block;
216 src->_end_block = NULL;
217 }
219 // Free the buckets in this hashtable
220 void free_buckets();
222 public:
223 int table_size() { return _table_size; }
224 void set_entry(int index, BasicHashtableEntry* entry);
226 void add_entry(int index, BasicHashtableEntry* entry);
228 void free_entry(BasicHashtableEntry* entry);
230 int number_of_entries() { return _number_of_entries; }
232 void verify() PRODUCT_RETURN;
233 };
236 template <class T> class Hashtable : public BasicHashtable {
237 friend class VMStructs;
239 public:
240 Hashtable(int table_size, int entry_size)
241 : BasicHashtable(table_size, entry_size) { }
243 Hashtable(int table_size, int entry_size,
244 HashtableBucket* buckets, int number_of_entries)
245 : BasicHashtable(table_size, entry_size, buckets, number_of_entries) { }
247 // Debugging
248 void print() PRODUCT_RETURN;
250 // Reverse the order of elements in each of the buckets. Hashtable
251 // entries which refer to objects at a lower address than 'boundary'
252 // are separated from those which refer to objects at higher
253 // addresses, and appear first in the list.
254 void reverse(void* boundary = NULL);
256 protected:
258 unsigned int compute_hash(Symbol* name) {
259 return (unsigned int) name->identity_hash();
260 }
262 int index_for(Symbol* name) {
263 return hash_to_index(compute_hash(name));
264 }
266 // Table entry management
267 HashtableEntry<T>* new_entry(unsigned int hashValue, T obj);
269 // The following method is MT-safe and may be used with caution.
270 HashtableEntry<T>* bucket(int i) {
271 return (HashtableEntry<T>*)BasicHashtable::bucket(i);
272 }
274 // The following method is not MT-safe and must be done under lock.
275 HashtableEntry<T>** bucket_addr(int i) {
276 return (HashtableEntry<T>**)BasicHashtable::bucket_addr(i);
277 }
279 // Function to move these elements into the new table.
280 void move_to(Hashtable<T>* new_table);
281 virtual unsigned int new_hash(T) { ShouldNotReachHere(); return 0; } // should be overridden
282 };
285 // Verions of hashtable where two handles are used to compute the index.
287 template <class T> class TwoOopHashtable : public Hashtable<T> {
288 friend class VMStructs;
289 protected:
290 TwoOopHashtable(int table_size, int entry_size)
291 : Hashtable<T>(table_size, entry_size) {}
293 TwoOopHashtable(int table_size, int entry_size, HashtableBucket* t,
294 int number_of_entries)
295 : Hashtable<T>(table_size, entry_size, t, number_of_entries) {}
297 public:
298 unsigned int compute_hash(Symbol* name, Handle loader) {
299 // Be careful with identity_hash(), it can safepoint and if this
300 // were one expression, the compiler could choose to unhandle each
301 // oop before calling identity_hash() for either of them. If the first
302 // causes a GC, the next would fail.
303 unsigned int name_hash = name->identity_hash();
304 unsigned int loader_hash = loader.is_null() ? 0 : loader->identity_hash();
305 return name_hash ^ loader_hash;
306 }
308 int index_for(Symbol* name, Handle loader) {
309 return this->hash_to_index(compute_hash(name, loader));
310 }
311 };
313 #endif // SHARE_VM_UTILITIES_HASHTABLE_HPP