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 */
24
25 #include "precompiled.hpp"
26 #include "classfile/altHashing.hpp"
27 #include "classfile/compactHashtable.inline.hpp"
28 #include "classfile/javaClasses.inline.hpp"
29 #include "classfile/stringTable.hpp"
30 #include "classfile/systemDictionary.hpp"
31 #include "gc/shared/collectedHeap.inline.hpp"
32 #include "gc/shared/gcLocker.inline.hpp"
33 #include "memory/allocation.inline.hpp"
34 #include "memory/filemap.hpp"
35 #include "memory/resourceArea.hpp"
36 #include "oops/oop.inline.hpp"
37 #include "runtime/atomic.hpp"
38 #include "runtime/mutexLocker.hpp"
39 #include "utilities/hashtable.inline.hpp"
40 #include "utilities/macros.hpp"
41 #if INCLUDE_ALL_GCS
42 #include "gc/g1/g1CollectedHeap.hpp"
43 #include "gc/g1/g1SATBCardTableModRefBS.hpp"
44 #include "gc/g1/g1StringDedup.hpp"
45 #endif
46
47 // the number of buckets a thread claims
48 const int ClaimChunkSize = 32;
49
50 #ifdef ASSERT
51 class StableMemoryChecker : public StackObj {
52 enum { _bufsize = wordSize*4 };
53
54 address _region;
55 jint _size;
56 u1 _save_buf[_bufsize];
57
58 int sample(u1* save_buf) {
59 if (_size <= _bufsize) {
60 memcpy(save_buf, _region, _size);
61 return _size;
62 } else {
63 // copy head and tail
116 if (chars != NULL) {
117 return hash_string(chars, length);
118 } else {
119 vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "unable to create Unicode string for verification");
120 return 0;
121 }
122 }
123
124 oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) {
125 assert(hash == java_lang_String::hash_code(name, len),
126 "hash must be computed using java_lang_String::hash_code");
127 return _shared_table.lookup((const char*)name, hash, len);
128 }
129
130 oop StringTable::lookup_in_main_table(int index, jchar* name,
131 int len, unsigned int hash) {
132 int count = 0;
133 for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
134 count++;
135 if (l->hash() == hash) {
136 if (java_lang_String::equals(l->literal(), name, len)) {
137 return l->literal();
138 }
139 }
140 }
141 // If the bucket size is too deep check if this hash code is insufficient.
142 if (count >= rehash_count && !needs_rehashing()) {
143 _needs_rehashing = check_rehash_table(count);
144 }
145 return NULL;
146 }
147
148
149 oop StringTable::basic_add(int index_arg, Handle string, jchar* name,
150 int len, unsigned int hashValue_arg, TRAPS) {
151
152 assert(java_lang_String::equals(string(), name, len),
153 "string must be properly initialized");
154 // Cannot hit a safepoint in this function because the "this" pointer can move.
155 NoSafepointVerifier nsv;
156
157 // Check if the symbol table has been rehashed, if so, need to recalculate
172 // No need to lookup the shared table from here since the caller (intern()) already did
173 oop test = lookup_in_main_table(index, name, len, hashValue); // calls lookup(u1*, int)
174 if (test != NULL) {
175 // Entry already added
176 return test;
177 }
178
179 HashtableEntry<oop, mtSymbol>* entry = new_entry(hashValue, string());
180 add_entry(index, entry);
181 return string();
182 }
183
184
185 oop StringTable::lookup(Symbol* symbol) {
186 ResourceMark rm;
187 int length;
188 jchar* chars = symbol->as_unicode(length);
189 return lookup(chars, length);
190 }
191
192 // Tell the GC that this string was looked up in the StringTable.
193 static void ensure_string_alive(oop string) {
194 // A lookup in the StringTable could return an object that was previously
195 // considered dead. The SATB part of G1 needs to get notified about this
196 // potential resurrection, otherwise the marking might not find the object.
197 #if INCLUDE_ALL_GCS
198 if (UseG1GC && string != NULL) {
199 G1SATBCardTableModRefBS::enqueue(string);
200 }
201 #endif
202 }
203
204 oop StringTable::lookup(jchar* name, int len) {
205 // shared table always uses java_lang_String::hash_code
206 unsigned int hash = java_lang_String::hash_code(name, len);
207 oop string = lookup_shared(name, len, hash);
208 if (string != NULL) {
209 return string;
210 }
211 if (use_alternate_hashcode()) {
212 hash = alt_hash_string(name, len);
213 }
214 int index = the_table()->hash_to_index(hash);
215 string = the_table()->lookup_in_main_table(index, name, len, hash);
216
217 ensure_string_alive(string);
218
219 return string;
220 }
221
222 oop StringTable::intern(Handle string_or_null, jchar* name,
223 int len, TRAPS) {
224 // shared table always uses java_lang_String::hash_code
225 unsigned int hashValue = java_lang_String::hash_code(name, len);
226 oop found_string = lookup_shared(name, len, hashValue);
227 if (found_string != NULL) {
228 return found_string;
229 }
230 if (use_alternate_hashcode()) {
231 hashValue = alt_hash_string(name, len);
232 }
233 int index = the_table()->hash_to_index(hashValue);
234 found_string = the_table()->lookup_in_main_table(index, name, len, hashValue);
235
236 // Found
237 if (found_string != NULL) {
238 if (found_string != string_or_null()) {
239 ensure_string_alive(found_string);
240 }
241 return found_string;
242 }
243
244 debug_only(StableMemoryChecker smc(name, len * sizeof(name[0])));
245 assert(!Universe::heap()->is_in_reserved(name),
246 "proposed name of symbol must be stable");
247
248 HandleMark hm(THREAD); // cleanup strings created
249 Handle string;
250 // try to reuse the string if possible
251 if (!string_or_null.is_null()) {
252 string = string_or_null;
253 } else {
254 string = java_lang_String::create_from_unicode(name, len, CHECK_NULL);
255 }
256
257 #if INCLUDE_ALL_GCS
258 if (G1StringDedup::is_enabled()) {
259 // Deduplicate the string before it is interned. Note that we should never
260 // deduplicate a string after it has been interned. Doing so will counteract
261 // compiler optimizations done on e.g. interned string literals.
262 G1StringDedup::deduplicate(string());
263 }
264 #endif
265
266 // Grab the StringTable_lock before getting the_table() because it could
267 // change at safepoint.
268 oop added_or_found;
269 {
270 MutexLocker ml(StringTable_lock, THREAD);
271 // Otherwise, add to symbol to table
272 added_or_found = the_table()->basic_add(index, string, name, len,
273 hashValue, CHECK_NULL);
274 }
275
276 if (added_or_found != string()) {
277 ensure_string_alive(added_or_found);
278 }
279
280 return added_or_found;
281 }
282
283 oop StringTable::intern(Symbol* symbol, TRAPS) {
284 if (symbol == NULL) return NULL;
285 ResourceMark rm(THREAD);
286 int length;
287 jchar* chars = symbol->as_unicode(length);
288 Handle string;
289 oop result = intern(string, chars, length, CHECK_NULL);
290 return result;
291 }
292
293
294 oop StringTable::intern(oop string, TRAPS)
295 {
296 if (string == NULL) return NULL;
297 ResourceMark rm(THREAD);
298 int length;
299 Handle h_string (THREAD, string);
761 }
762 }
763 }
764
765 _shared_table.set_type(CompactHashtable<oop, char>::_string_table);
766 _shared_table.serialize(soc);
767
768 if (soc->writing()) {
769 _shared_table.reset(); // Sanity. Make sure we don't use the shared table at dump time
770 } else if (_ignore_shared_strings) {
771 _shared_table.reset();
772 }
773 #endif
774 }
775
776 void StringTable::shared_oops_do(OopClosure* f) {
777 #if INCLUDE_CDS && defined(_LP64) && !defined(_WINDOWS)
778 _shared_table.oops_do(f);
779 #endif
780 }
781
|
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 */
24
25 #include "precompiled.hpp"
26 #include "classfile/altHashing.hpp"
27 #include "classfile/compactHashtable.inline.hpp"
28 #include "classfile/javaClasses.inline.hpp"
29 #include "classfile/stringTable.hpp"
30 #include "classfile/systemDictionary.hpp"
31 #include "gc/shared/collectedHeap.inline.hpp"
32 #include "gc/shared/gcLocker.inline.hpp"
33 #include "memory/allocation.inline.hpp"
34 #include "memory/filemap.hpp"
35 #include "memory/resourceArea.hpp"
36 #include "oops/oop.inline.hpp"
37 #include "runtime/access.inline.hpp"
38 #include "runtime/atomic.hpp"
39 #include "runtime/mutexLocker.hpp"
40 #include "utilities/hashtable.inline.hpp"
41 #include "utilities/macros.hpp"
42 #if INCLUDE_ALL_GCS
43 #include "gc/g1/g1BarrierSet.hpp"
44 #include "gc/g1/g1CollectedHeap.hpp"
45 #include "gc/g1/g1StringDedup.hpp"
46 #endif
47
48 // the number of buckets a thread claims
49 const int ClaimChunkSize = 32;
50
51 #ifdef ASSERT
52 class StableMemoryChecker : public StackObj {
53 enum { _bufsize = wordSize*4 };
54
55 address _region;
56 jint _size;
57 u1 _save_buf[_bufsize];
58
59 int sample(u1* save_buf) {
60 if (_size <= _bufsize) {
61 memcpy(save_buf, _region, _size);
62 return _size;
63 } else {
64 // copy head and tail
117 if (chars != NULL) {
118 return hash_string(chars, length);
119 } else {
120 vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "unable to create Unicode string for verification");
121 return 0;
122 }
123 }
124
125 oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) {
126 assert(hash == java_lang_String::hash_code(name, len),
127 "hash must be computed using java_lang_String::hash_code");
128 return _shared_table.lookup((const char*)name, hash, len);
129 }
130
131 oop StringTable::lookup_in_main_table(int index, jchar* name,
132 int len, unsigned int hash) {
133 int count = 0;
134 for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
135 count++;
136 if (l->hash() == hash) {
137 oop* string_addr = l->literal_addr();
138 // The ACCESS_WEAK peeks at the oop without keeping it alive.
139 // This is *very dangerous* in general but is okay in this specific
140 // case. The subsequent oop_load keeps the oop alive if it it matched
141 // the jchar* string.
142 oop string = RootAccess<GC_ACCESS_ON_PHANTOM | ACCESS_WEAK>::oop_load(string_addr);
143 typeArrayOop value = HeapAccess<GC_ACCESS_ON_STRONG | ACCESS_WEAK>::oop_load_at(string, java_lang_String::value_offset_in_bytes());
144 int length = java_lang_String::length(string, value);
145 if (java_lang_String::equals(value, length, string, name, len)) {
146 return RootAccess<GC_ACCESS_ON_PHANTOM>::oop_load(string_addr);
147 }
148 }
149 }
150 // If the bucket size is too deep check if this hash code is insufficient.
151 if (count >= rehash_count && !needs_rehashing()) {
152 _needs_rehashing = check_rehash_table(count);
153 }
154 return NULL;
155 }
156
157
158 oop StringTable::basic_add(int index_arg, Handle string, jchar* name,
159 int len, unsigned int hashValue_arg, TRAPS) {
160
161 assert(java_lang_String::equals(string(), name, len),
162 "string must be properly initialized");
163 // Cannot hit a safepoint in this function because the "this" pointer can move.
164 NoSafepointVerifier nsv;
165
166 // Check if the symbol table has been rehashed, if so, need to recalculate
181 // No need to lookup the shared table from here since the caller (intern()) already did
182 oop test = lookup_in_main_table(index, name, len, hashValue); // calls lookup(u1*, int)
183 if (test != NULL) {
184 // Entry already added
185 return test;
186 }
187
188 HashtableEntry<oop, mtSymbol>* entry = new_entry(hashValue, string());
189 add_entry(index, entry);
190 return string();
191 }
192
193
194 oop StringTable::lookup(Symbol* symbol) {
195 ResourceMark rm;
196 int length;
197 jchar* chars = symbol->as_unicode(length);
198 return lookup(chars, length);
199 }
200
201 oop StringTable::lookup(jchar* name, int len) {
202 // shared table always uses java_lang_String::hash_code
203 unsigned int hash = java_lang_String::hash_code(name, len);
204 oop string = lookup_shared(name, len, hash);
205 if (string != NULL) {
206 return string;
207 }
208 if (use_alternate_hashcode()) {
209 hash = alt_hash_string(name, len);
210 }
211 int index = the_table()->hash_to_index(hash);
212 string = the_table()->lookup_in_main_table(index, name, len, hash);
213
214 return string;
215 }
216
217 oop StringTable::intern(Handle string_or_null, jchar* name,
218 int len, TRAPS) {
219 // shared table always uses java_lang_String::hash_code
220 unsigned int hashValue = java_lang_String::hash_code(name, len);
221 oop found_string = lookup_shared(name, len, hashValue);
222 if (found_string != NULL) {
223 return found_string;
224 }
225 if (use_alternate_hashcode()) {
226 hashValue = alt_hash_string(name, len);
227 }
228 int index = the_table()->hash_to_index(hashValue);
229 found_string = the_table()->lookup_in_main_table(index, name, len, hashValue);
230
231 // Found
232 if (found_string != NULL) {
233 return found_string;
234 }
235
236 debug_only(StableMemoryChecker smc(name, len * sizeof(name[0])));
237 assert(!Universe::heap()->is_in_reserved(name),
238 "proposed name of symbol must be stable");
239
240 HandleMark hm(THREAD); // cleanup strings created
241 Handle string;
242 // try to reuse the string if possible
243 if (!string_or_null.is_null()) {
244 string = string_or_null;
245 } else {
246 string = java_lang_String::create_from_unicode(name, len, CHECK_NULL);
247 }
248
249 #if INCLUDE_ALL_GCS
250 if (G1StringDedup::is_enabled()) {
251 // Deduplicate the string before it is interned. Note that we should never
252 // deduplicate a string after it has been interned. Doing so will counteract
253 // compiler optimizations done on e.g. interned string literals.
254 G1StringDedup::deduplicate(string());
255 }
256 #endif
257
258 // Grab the StringTable_lock before getting the_table() because it could
259 // change at safepoint.
260 oop added_or_found;
261 {
262 MutexLocker ml(StringTable_lock, THREAD);
263 // Otherwise, add to symbol to table
264 added_or_found = the_table()->basic_add(index, string, name, len,
265 hashValue, CHECK_NULL);
266 }
267
268 return added_or_found;
269 }
270
271 oop StringTable::intern(Symbol* symbol, TRAPS) {
272 if (symbol == NULL) return NULL;
273 ResourceMark rm(THREAD);
274 int length;
275 jchar* chars = symbol->as_unicode(length);
276 Handle string;
277 oop result = intern(string, chars, length, CHECK_NULL);
278 return result;
279 }
280
281
282 oop StringTable::intern(oop string, TRAPS)
283 {
284 if (string == NULL) return NULL;
285 ResourceMark rm(THREAD);
286 int length;
287 Handle h_string (THREAD, string);
749 }
750 }
751 }
752
753 _shared_table.set_type(CompactHashtable<oop, char>::_string_table);
754 _shared_table.serialize(soc);
755
756 if (soc->writing()) {
757 _shared_table.reset(); // Sanity. Make sure we don't use the shared table at dump time
758 } else if (_ignore_shared_strings) {
759 _shared_table.reset();
760 }
761 #endif
762 }
763
764 void StringTable::shared_oops_do(OopClosure* f) {
765 #if INCLUDE_CDS && defined(_LP64) && !defined(_WINDOWS)
766 _shared_table.oops_do(f);
767 #endif
768 }
|