Mon, 03 Jan 2011 14:09:11 -0500
6302804: Hotspot VM dies ungraceful death when C heap is exhausted in various places.
Summary: enhance the error reporting mechanism to help user to fix the problem rather than making it look like a VM error.
Reviewed-by: kvn, kamg
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/symbolOop.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 class HashtableEntry : public BasicHashtableEntry {
100 friend class VMStructs;
101 private:
102 oop _literal; // ref to item in table.
104 public:
105 // Literal
106 oop literal() const { return _literal; }
107 oop* literal_addr() { return &_literal; }
108 void set_literal(oop 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 void initialize(int table_size, int entry_size, int number_of_entries);
182 // Accessor
183 int entry_size() const { return _entry_size; }
184 int table_size() { return _table_size; }
186 // The following method is MT-safe and may be used with caution.
187 BasicHashtableEntry* bucket(int i);
189 // The following method is not MT-safe and must be done under lock.
190 BasicHashtableEntry** bucket_addr(int i) { return _buckets[i].entry_addr(); }
192 // Table entry management
193 BasicHashtableEntry* new_entry(unsigned int hashValue);
195 public:
196 void set_entry(int index, BasicHashtableEntry* entry);
198 void add_entry(int index, BasicHashtableEntry* entry);
200 void free_entry(BasicHashtableEntry* entry);
202 int number_of_entries() { return _number_of_entries; }
204 void verify() PRODUCT_RETURN;
205 };
208 class Hashtable : public BasicHashtable {
209 friend class VMStructs;
211 public:
212 Hashtable(int table_size, int entry_size)
213 : BasicHashtable(table_size, entry_size) { }
215 Hashtable(int table_size, int entry_size,
216 HashtableBucket* buckets, int number_of_entries)
217 : BasicHashtable(table_size, entry_size, buckets, number_of_entries) { }
219 // Invoke "f->do_oop" on the locations of all oops in the table.
220 void oops_do(OopClosure* f);
222 // Debugging
223 void print() PRODUCT_RETURN;
225 // GC support
226 // Delete pointers to otherwise-unreachable objects.
227 void unlink(BoolObjectClosure* cl);
229 // Reverse the order of elements in each of the buckets. Hashtable
230 // entries which refer to objects at a lower address than 'boundary'
231 // are separated from those which refer to objects at higher
232 // addresses, and appear first in the list.
233 void reverse(void* boundary = NULL);
235 protected:
237 static unsigned int hash_symbol(const char* s, int len);
239 unsigned int compute_hash(symbolHandle name) {
240 return (unsigned int) name->identity_hash();
241 }
243 int index_for(symbolHandle name) {
244 return hash_to_index(compute_hash(name));
245 }
247 // Table entry management
248 HashtableEntry* new_entry(unsigned int hashValue, oop obj);
250 // The following method is MT-safe and may be used with caution.
251 HashtableEntry* bucket(int i) {
252 return (HashtableEntry*)BasicHashtable::bucket(i);
253 }
255 // The following method is not MT-safe and must be done under lock.
256 HashtableEntry** bucket_addr(int i) {
257 return (HashtableEntry**)BasicHashtable::bucket_addr(i);
258 }
259 };
262 // Verions of hashtable where two handles are used to compute the index.
264 class TwoOopHashtable : public Hashtable {
265 friend class VMStructs;
266 protected:
267 TwoOopHashtable(int table_size, int entry_size)
268 : Hashtable(table_size, entry_size) {}
270 TwoOopHashtable(int table_size, int entry_size, HashtableBucket* t,
271 int number_of_entries)
272 : Hashtable(table_size, entry_size, t, number_of_entries) {}
274 public:
275 unsigned int compute_hash(symbolHandle name, Handle loader) {
276 // Be careful with identity_hash(), it can safepoint and if this
277 // were one expression, the compiler could choose to unhandle each
278 // oop before calling identity_hash() for either of them. If the first
279 // causes a GC, the next would fail.
280 unsigned int name_hash = name->identity_hash();
281 unsigned int loader_hash = loader.is_null() ? 0 : loader->identity_hash();
282 return name_hash ^ loader_hash;
283 }
285 int index_for(symbolHandle name, Handle loader) {
286 return hash_to_index(compute_hash(name, loader));
287 }
288 };
290 #endif // SHARE_VM_UTILITIES_HASHTABLE_HPP