Mercurial > hg > truffle
comparison src/share/vm/utilities/hashtable.cpp @ 2177:3582bf76420e
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
author | coleenp |
---|---|
date | Thu, 27 Jan 2011 16:11:27 -0800 |
parents | f95d63e2154a |
children | 1d1603768966 |
comparison
equal
deleted
inserted
replaced
2176:27e4ea99855d | 2177:3582bf76420e |
---|---|
29 #include "runtime/safepoint.hpp" | 29 #include "runtime/safepoint.hpp" |
30 #include "utilities/dtrace.hpp" | 30 #include "utilities/dtrace.hpp" |
31 #include "utilities/hashtable.hpp" | 31 #include "utilities/hashtable.hpp" |
32 #include "utilities/hashtable.inline.hpp" | 32 #include "utilities/hashtable.inline.hpp" |
33 | 33 |
34 | |
34 HS_DTRACE_PROBE_DECL4(hs_private, hashtable__new_entry, | 35 HS_DTRACE_PROBE_DECL4(hs_private, hashtable__new_entry, |
35 void*, unsigned int, oop, void*); | 36 void*, unsigned int, void*, void*); |
36 | 37 |
37 // This is a generic hashtable, designed to be used for the symbol | 38 // This is a generic hashtable, designed to be used for the symbol |
38 // and string tables. | 39 // and string tables. |
39 // | 40 // |
40 // It is implemented as an open hash table with a fixed number of buckets. | 41 // It is implemented as an open hash table with a fixed number of buckets. |
65 entry->set_hash(hashValue); | 66 entry->set_hash(hashValue); |
66 return entry; | 67 return entry; |
67 } | 68 } |
68 | 69 |
69 | 70 |
70 HashtableEntry* Hashtable::new_entry(unsigned int hashValue, oop obj) { | 71 template <class T> HashtableEntry<T>* Hashtable<T>::new_entry(unsigned int hashValue, T obj) { |
71 HashtableEntry* entry; | 72 HashtableEntry<T>* entry; |
72 | 73 |
73 entry = (HashtableEntry*)BasicHashtable::new_entry(hashValue); | 74 entry = (HashtableEntry<T>*)BasicHashtable::new_entry(hashValue); |
74 entry->set_literal(obj); // clears literal string field | 75 entry->set_literal(obj); |
75 HS_DTRACE_PROBE4(hs_private, hashtable__new_entry, | 76 HS_DTRACE_PROBE4(hs_private, hashtable__new_entry, |
76 this, hashValue, obj, entry); | 77 this, hashValue, obj, entry); |
77 return entry; | 78 return entry; |
78 } | |
79 | |
80 | |
81 // GC support | |
82 | |
83 void Hashtable::unlink(BoolObjectClosure* is_alive) { | |
84 // Readers of the table are unlocked, so we should only be removing | |
85 // entries at a safepoint. | |
86 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); | |
87 for (int i = 0; i < table_size(); ++i) { | |
88 for (HashtableEntry** p = bucket_addr(i); *p != NULL; ) { | |
89 HashtableEntry* entry = *p; | |
90 if (entry->is_shared()) { | |
91 break; | |
92 } | |
93 assert(entry->literal() != NULL, "just checking"); | |
94 if (is_alive->do_object_b(entry->literal())) { | |
95 p = entry->next_addr(); | |
96 } else { | |
97 *p = entry->next(); | |
98 free_entry(entry); | |
99 } | |
100 } | |
101 } | |
102 } | |
103 | |
104 | |
105 void Hashtable::oops_do(OopClosure* f) { | |
106 for (int i = 0; i < table_size(); ++i) { | |
107 HashtableEntry** p = bucket_addr(i); | |
108 HashtableEntry* entry = bucket(i); | |
109 while (entry != NULL) { | |
110 f->do_oop(entry->literal_addr()); | |
111 | |
112 // Did the closure remove the literal from the table? | |
113 if (entry->literal() == NULL) { | |
114 assert(!entry->is_shared(), "immutable hashtable entry?"); | |
115 *p = entry->next(); | |
116 free_entry(entry); | |
117 } else { | |
118 p = entry->next_addr(); | |
119 } | |
120 entry = (HashtableEntry*)HashtableEntry::make_ptr(*p); | |
121 } | |
122 } | |
123 } | 79 } |
124 | 80 |
125 | 81 |
126 // Reverse the order of elements in the hash buckets. | 82 // Reverse the order of elements in the hash buckets. |
127 | 83 |
154 for (i = 0; i < _table_size; ++i) { | 110 for (i = 0; i < _table_size; ++i) { |
155 for (BasicHashtableEntry** p = _buckets[i].entry_addr(); | 111 for (BasicHashtableEntry** p = _buckets[i].entry_addr(); |
156 *p != NULL; | 112 *p != NULL; |
157 p = (*p)->next_addr()) { | 113 p = (*p)->next_addr()) { |
158 if (*top + entry_size() > end) { | 114 if (*top + entry_size() > end) { |
159 warning("\nThe shared miscellaneous data space is not large " | 115 report_out_of_shared_space(SharedMiscData); |
160 "enough to \npreload requested classes. Use " | |
161 "-XX:SharedMiscDataSize= to increase \nthe initial " | |
162 "size of the miscellaneous data space.\n"); | |
163 exit(2); | |
164 } | 116 } |
165 *p = (BasicHashtableEntry*)memcpy(*top, *p, entry_size()); | 117 *p = (BasicHashtableEntry*)memcpy(*top, *p, entry_size()); |
166 *top += entry_size(); | 118 *top += entry_size(); |
167 } | 119 } |
168 } | 120 } |
179 | 131 |
180 | 132 |
181 | 133 |
182 // Reverse the order of elements in the hash buckets. | 134 // Reverse the order of elements in the hash buckets. |
183 | 135 |
184 void Hashtable::reverse(void* boundary) { | 136 template <class T> void Hashtable<T>::reverse(void* boundary) { |
185 | 137 |
186 for (int i = 0; i < table_size(); ++i) { | 138 for (int i = 0; i < table_size(); ++i) { |
187 HashtableEntry* high_list = NULL; | 139 HashtableEntry<T>* high_list = NULL; |
188 HashtableEntry* low_list = NULL; | 140 HashtableEntry<T>* low_list = NULL; |
189 HashtableEntry* last_low_entry = NULL; | 141 HashtableEntry<T>* last_low_entry = NULL; |
190 HashtableEntry* p = bucket(i); | 142 HashtableEntry<T>* p = bucket(i); |
191 while (p != NULL) { | 143 while (p != NULL) { |
192 HashtableEntry* next = p->next(); | 144 HashtableEntry<T>* next = p->next(); |
193 if ((void*)p->literal() >= boundary) { | 145 if ((void*)p->literal() >= boundary) { |
194 p->set_next(high_list); | 146 p->set_next(high_list); |
195 high_list = p; | 147 high_list = p; |
196 } else { | 148 } else { |
197 p->set_next(low_list); | 149 p->set_next(low_list); |
221 | 173 |
222 *(intptr_t*)(*top) = _number_of_entries; | 174 *(intptr_t*)(*top) = _number_of_entries; |
223 *top += sizeof(intptr_t); | 175 *top += sizeof(intptr_t); |
224 | 176 |
225 if (*top + len > end) { | 177 if (*top + len > end) { |
226 warning("\nThe shared miscellaneous data space is not large " | 178 report_out_of_shared_space(SharedMiscData); |
227 "enough to \npreload requested classes. Use " | |
228 "-XX:SharedMiscDataSize= to increase \nthe initial " | |
229 "size of the miscellaneous data space.\n"); | |
230 exit(2); | |
231 } | 179 } |
232 _buckets = (HashtableBucket*)memcpy(*top, _buckets, len); | 180 _buckets = (HashtableBucket*)memcpy(*top, _buckets, len); |
233 *top += len; | 181 *top += len; |
234 } | 182 } |
235 | 183 |
236 | 184 |
237 #ifndef PRODUCT | 185 #ifndef PRODUCT |
238 | 186 |
239 void Hashtable::print() { | 187 template <class T> void Hashtable<T>::print() { |
240 ResourceMark rm; | 188 ResourceMark rm; |
241 | 189 |
242 for (int i = 0; i < table_size(); i++) { | 190 for (int i = 0; i < table_size(); i++) { |
243 HashtableEntry* entry = bucket(i); | 191 HashtableEntry<T>* entry = bucket(i); |
244 while(entry != NULL) { | 192 while(entry != NULL) { |
245 tty->print("%d : ", i); | 193 tty->print("%d : ", i); |
246 entry->literal()->print(); | 194 entry->literal()->print(); |
247 tty->cr(); | 195 tty->cr(); |
248 entry = entry->next(); | 196 entry = entry->next(); |
275 (double) _lookup_length / _lookup_count, load); | 223 (double) _lookup_length / _lookup_count, load); |
276 } | 224 } |
277 } | 225 } |
278 | 226 |
279 #endif | 227 #endif |
228 | |
229 // Explicitly instantiate these types | |
230 template class Hashtable<constantPoolOop>; | |
231 template class Hashtable<Symbol*>; | |
232 template class Hashtable<klassOop>; | |
233 template class Hashtable<oop>; | |
234 |