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