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(); |