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 "logging/log.hpp"
34 #include "memory/allocation.inline.hpp"
35 #include "memory/filemap.hpp"
36 #include "memory/metaspaceShared.hpp"
37 #include "memory/resourceArea.hpp"
38 #include "oops/oop.inline.hpp"
39 #include "runtime/atomic.hpp"
40 #include "runtime/mutexLocker.hpp"
41 #include "services/diagnosticCommand.hpp"
42 #include "utilities/hashtable.inline.hpp"
43 #include "utilities/macros.hpp"
44 #if INCLUDE_ALL_GCS
45 #include "gc/g1/g1CollectedHeap.hpp"
46 #include "gc/g1/g1SATBCardTableModRefBS.hpp"
47 #include "gc/g1/g1StringDedup.hpp"
48 #endif
49
50 // the number of buckets a thread claims
51 const int ClaimChunkSize = 32;
52
53 #ifdef ASSERT
54 class StableMemoryChecker : public StackObj {
55 enum { _bufsize = wordSize*4 };
56
57 address _region;
58 jint _size;
59 u1 _save_buf[_bufsize];
60
61 int sample(u1* save_buf) {
62 if (_size <= _bufsize) {
63 memcpy(save_buf, _region, _size);
64 return _size;
65 } else {
66 // copy head and tail
107 return AltHashing::murmur3_32(seed(), s, len);
108 }
109
110 unsigned int StringTable::hash_string(oop string) {
111 EXCEPTION_MARK;
112 if (string == NULL) {
113 return hash_string((jchar*)NULL, 0);
114 }
115 ResourceMark rm(THREAD);
116 // All String oops are hashed as unicode
117 int length;
118 jchar* chars = java_lang_String::as_unicode_string(string, length, THREAD);
119 if (chars != NULL) {
120 return hash_string(chars, length);
121 } else {
122 vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "unable to create Unicode string for verification");
123 return 0;
124 }
125 }
126
127 oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) {
128 assert(hash == java_lang_String::hash_code(name, len),
129 "hash must be computed using java_lang_String::hash_code");
130 return _shared_table.lookup((const char*)name, hash, len);
131 }
132
133 oop StringTable::lookup_in_main_table(int index, jchar* name,
134 int len, unsigned int hash) {
135 int count = 0;
136 for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
137 count++;
138 if (l->hash() == hash) {
139 if (java_lang_String::equals(l->literal(), name, len)) {
140 return l->literal();
141 }
142 }
143 }
144 // If the bucket size is too deep check if this hash code is insufficient.
145 if (count >= rehash_count && !needs_rehashing()) {
146 _needs_rehashing = check_rehash_table(count);
147 }
148 return NULL;
149 }
150
151
152 oop StringTable::basic_add(int index_arg, Handle string, jchar* name,
153 int len, unsigned int hashValue_arg, TRAPS) {
154
155 assert(java_lang_String::equals(string(), name, len),
156 "string must be properly initialized");
157 // Cannot hit a safepoint in this function because the "this" pointer can move.
158 NoSafepointVerifier nsv;
159
160 // Check if the symbol table has been rehashed, if so, need to recalculate
175 // No need to lookup the shared table from here since the caller (intern()) already did
176 oop test = lookup_in_main_table(index, name, len, hashValue); // calls lookup(u1*, int)
177 if (test != NULL) {
178 // Entry already added
179 return test;
180 }
181
182 HashtableEntry<oop, mtSymbol>* entry = new_entry(hashValue, string());
183 add_entry(index, entry);
184 return string();
185 }
186
187
188 oop StringTable::lookup(Symbol* symbol) {
189 ResourceMark rm;
190 int length;
191 jchar* chars = symbol->as_unicode(length);
192 return lookup(chars, length);
193 }
194
195 // Tell the GC that this string was looked up in the StringTable.
196 static void ensure_string_alive(oop string) {
197 // A lookup in the StringTable could return an object that was previously
198 // considered dead. The SATB part of G1 needs to get notified about this
199 // potential resurrection, otherwise the marking might not find the object.
200 #if INCLUDE_ALL_GCS
201 if (UseG1GC && string != NULL) {
202 G1SATBCardTableModRefBS::enqueue(string);
203 }
204 #endif
205 }
206
207 oop StringTable::lookup(jchar* name, int len) {
208 // shared table always uses java_lang_String::hash_code
209 unsigned int hash = java_lang_String::hash_code(name, len);
210 oop string = lookup_shared(name, len, hash);
211 if (string != NULL) {
212 return string;
213 }
214 if (use_alternate_hashcode()) {
215 hash = alt_hash_string(name, len);
216 }
217 int index = the_table()->hash_to_index(hash);
218 string = the_table()->lookup_in_main_table(index, name, len, hash);
219
220 ensure_string_alive(string);
221
222 return string;
223 }
224
225 oop StringTable::intern(Handle string_or_null, jchar* name,
226 int len, TRAPS) {
227 // shared table always uses java_lang_String::hash_code
228 unsigned int hashValue = java_lang_String::hash_code(name, len);
229 oop found_string = lookup_shared(name, len, hashValue);
230 if (found_string != NULL) {
231 return found_string;
232 }
233 if (use_alternate_hashcode()) {
234 hashValue = alt_hash_string(name, len);
235 }
236 int index = the_table()->hash_to_index(hashValue);
237 found_string = the_table()->lookup_in_main_table(index, name, len, hashValue);
238
239 // Found
240 if (found_string != NULL) {
241 if (found_string != string_or_null()) {
242 ensure_string_alive(found_string);
243 }
244 return found_string;
245 }
246
247 debug_only(StableMemoryChecker smc(name, len * sizeof(name[0])));
248 assert(!Universe::heap()->is_in_reserved(name),
249 "proposed name of symbol must be stable");
250
251 HandleMark hm(THREAD); // cleanup strings created
252 Handle string;
253 // try to reuse the string if possible
254 if (!string_or_null.is_null()) {
255 string = string_or_null;
256 } else {
257 string = java_lang_String::create_from_unicode(name, len, CHECK_NULL);
258 }
259
260 #if INCLUDE_ALL_GCS
261 if (G1StringDedup::is_enabled()) {
262 // Deduplicate the string before it is interned. Note that we should never
263 // deduplicate a string after it has been interned. Doing so will counteract
264 // compiler optimizations done on e.g. interned string literals.
265 G1StringDedup::deduplicate(string());
266 }
267 #endif
268
269 // Grab the StringTable_lock before getting the_table() because it could
270 // change at safepoint.
271 oop added_or_found;
272 {
273 MutexLocker ml(StringTable_lock, THREAD);
274 // Otherwise, add to symbol to table
275 added_or_found = the_table()->basic_add(index, string, name, len,
276 hashValue, CHECK_NULL);
277 }
278
279 if (added_or_found != string()) {
280 ensure_string_alive(added_or_found);
281 }
282
283 return added_or_found;
284 }
285
286 oop StringTable::intern(Symbol* symbol, TRAPS) {
287 if (symbol == NULL) return NULL;
288 ResourceMark rm(THREAD);
289 int length;
290 jchar* chars = symbol->as_unicode(length);
291 Handle string;
292 oop result = intern(string, chars, length, CHECK_NULL);
293 return result;
294 }
295
296
297 oop StringTable::intern(oop string, TRAPS)
298 {
299 if (string == NULL) return NULL;
300 ResourceMark rm(THREAD);
301 int length;
302 Handle h_string (THREAD, string);
371 }
372 }
373
374 void StringTable::buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, BucketUnlinkContext* context) {
375 const int limit = the_table()->table_size();
376
377 assert(0 <= start_idx && start_idx <= limit,
378 "start_idx (%d) is out of bounds", start_idx);
379 assert(0 <= end_idx && end_idx <= limit,
380 "end_idx (%d) is out of bounds", end_idx);
381 assert(start_idx <= end_idx,
382 "Index ordering: start_idx=%d, end_idx=%d",
383 start_idx, end_idx);
384
385 for (int i = start_idx; i < end_idx; ++i) {
386 HashtableEntry<oop, mtSymbol>** p = the_table()->bucket_addr(i);
387 HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
388 while (entry != NULL) {
389 assert(!entry->is_shared(), "CDS not used for the StringTable");
390
391 if (is_alive->do_object_b(entry->literal())) {
392 if (f != NULL) {
393 f->do_oop((oop*)entry->literal_addr());
394 }
395 p = entry->next_addr();
396 } else {
397 *p = entry->next();
398 context->free_entry(entry);
399 }
400 context->_num_processed++;
401 entry = *p;
402 }
403 }
404 }
405
406 void StringTable::oops_do(OopClosure* f) {
407 buckets_oops_do(f, 0, the_table()->table_size());
408 }
409
410 void StringTable::possibly_parallel_oops_do(OopClosure* f) {
411 const int limit = the_table()->table_size();
412
413 for (;;) {
414 // Grab next set of buckets to scan
415 int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize;
416 if (start_idx >= limit) {
417 // End of table
418 break;
419 }
420
421 int end_idx = MIN2(limit, start_idx + ClaimChunkSize);
422 buckets_oops_do(f, start_idx, end_idx);
423 }
424 }
425
426 // This verification is part of Universe::verify() and needs to be quick.
427 // See StringTable::verify_and_compare() below for exhaustive verification.
428 void StringTable::verify() {
429 for (int i = 0; i < the_table()->table_size(); ++i) {
430 HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
431 for ( ; p != NULL; p = p->next()) {
432 oop s = p->literal();
433 guarantee(s != NULL, "interned string is NULL");
434 unsigned int h = hash_string(s);
435 guarantee(p->hash() == h, "broken hash in string table entry");
436 guarantee(the_table()->hash_to_index(h) == i,
437 "wrong index in string table");
438 }
439 }
440 }
441
442 void StringTable::dump(outputStream* st, bool verbose) {
443 if (!verbose) {
444 the_table()->print_table_statistics(st, "StringTable");
445 } else {
446 Thread* THREAD = Thread::current();
447 st->print_cr("VERSION: 1.1");
448 for (int i = 0; i < the_table()->table_size(); ++i) {
449 HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
450 for ( ; p != NULL; p = p->next()) {
451 oop s = p->literal();
452 typeArrayOop value = java_lang_String::value(s);
453 int length = java_lang_String::length(s);
454 bool is_latin1 = java_lang_String::is_latin1(s);
455
456 if (length <= 0) {
457 st->print("%d: ", length);
458 } else {
459 ResourceMark rm(THREAD);
460 int utf8_length = length;
461 char* utf8_string;
462
463 if (!is_latin1) {
464 jchar* chars = value->char_at_addr(0);
465 utf8_string = UNICODE::as_utf8(chars, utf8_length);
466 } else {
467 jbyte* bytes = value->byte_at_addr(0);
468 utf8_string = UNICODE::as_utf8(bytes, utf8_length);
469 }
470
471 st->print("%d: ", utf8_length);
472 HashtableTextDump::put_utf8(st, utf8_string, utf8_length);
473 }
474 st->cr();
475 }
476 }
477 }
478 }
479
480 StringTable::VerifyRetTypes StringTable::compare_entries(
481 int bkt1, int e_cnt1,
482 HashtableEntry<oop, mtSymbol>* e_ptr1,
483 int bkt2, int e_cnt2,
484 HashtableEntry<oop, mtSymbol>* e_ptr2) {
485 // These entries are sanity checked by verify_and_compare_entries()
486 // before this function is called.
487 oop str1 = e_ptr1->literal();
488 oop str2 = e_ptr2->literal();
489
490 if (str1 == str2) {
491 tty->print_cr("ERROR: identical oop values (0x" PTR_FORMAT ") "
492 "in entry @ bucket[%d][%d] and entry @ bucket[%d][%d]",
493 p2i(str1), bkt1, e_cnt1, bkt2, e_cnt2);
494 return _verify_fail_continue;
495 }
496
497 if (java_lang_String::equals(str1, str2)) {
498 tty->print_cr("ERROR: identical String values in entry @ "
499 "bucket[%d][%d] and entry @ bucket[%d][%d]",
500 bkt1, e_cnt1, bkt2, e_cnt2);
501 return _verify_fail_continue;
502 }
503
504 return _verify_pass;
505 }
506
507 StringTable::VerifyRetTypes StringTable::verify_entry(int bkt, int e_cnt,
508 HashtableEntry<oop, mtSymbol>* e_ptr,
509 StringTable::VerifyMesgModes mesg_mode) {
510
511 VerifyRetTypes ret = _verify_pass; // be optimistic
512
513 oop str = e_ptr->literal();
514 if (str == NULL) {
515 if (mesg_mode == _verify_with_mesgs) {
516 tty->print_cr("ERROR: NULL oop value in entry @ bucket[%d][%d]", bkt,
517 e_cnt);
518 }
519 // NULL oop means no more verifications are possible
520 return _verify_fail_done;
521 }
522
523 if (str->klass() != SystemDictionary::String_klass()) {
524 if (mesg_mode == _verify_with_mesgs) {
525 tty->print_cr("ERROR: oop is not a String in entry @ bucket[%d][%d]",
526 bkt, e_cnt);
527 }
528 // not a String means no more verifications are possible
529 return _verify_fail_done;
530 }
531
532 unsigned int h = hash_string(str);
533 if (e_ptr->hash() != h) {
667 VMThread::execute(&dumper);
668 }
669
670 int StringtableDCmd::num_arguments() {
671 ResourceMark rm;
672 StringtableDCmd* dcmd = new StringtableDCmd(NULL, false);
673 if (dcmd != NULL) {
674 DCmdMark mark(dcmd);
675 return dcmd->_dcmdparser.num_arguments();
676 } else {
677 return 0;
678 }
679 }
680
681 #if INCLUDE_CDS_JAVA_HEAP
682 // Sharing
683 oop StringTable::create_archived_string(oop s, Thread* THREAD) {
684 assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
685
686 oop new_s = NULL;
687 typeArrayOop v = java_lang_String::value(s);
688 typeArrayOop new_v = (typeArrayOop)MetaspaceShared::archive_heap_object(v, THREAD);
689 if (new_v == NULL) {
690 return NULL;
691 }
692 new_s = MetaspaceShared::archive_heap_object(s, THREAD);
693 if (new_s == NULL) {
694 return NULL;
695 }
696
697 // adjust the pointer to the 'value' field in the new String oop
698 java_lang_String::set_value_raw(new_s, new_v);
699 return new_s;
700 }
701
702 bool StringTable::copy_shared_string(GrowableArray<MemRegion> *string_space,
703 CompactStringTableWriter* writer) {
704 assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
705
706 Thread* THREAD = Thread::current();
707 G1CollectedHeap::heap()->begin_archive_alloc_range();
708 for (int i = 0; i < the_table()->table_size(); ++i) {
709 HashtableEntry<oop, mtSymbol>* bucket = the_table()->bucket(i);
710 for ( ; bucket != NULL; bucket = bucket->next()) {
711 oop s = bucket->literal();
712 unsigned int hash = java_lang_String::hash_code(s);
713 if (hash == 0) {
714 continue;
715 }
716
717 java_lang_String::set_hash(s, hash);
718 oop new_s = create_archived_string(s, THREAD);
719 if (new_s == NULL) {
720 continue;
721 }
722
723 // set the archived string in bucket
724 bucket->set_literal(new_s);
725
726 // add to the compact table
727 writer->add(hash, new_s);
728 }
729 }
730
731 G1CollectedHeap::heap()->end_archive_alloc_range(string_space, os::vm_allocation_granularity());
732 return true;
733 }
734
735 void StringTable::write_to_archive(GrowableArray<MemRegion> *string_space) {
736 assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
737
738 _shared_table.reset();
739 int num_buckets = the_table()->number_of_entries() /
740 SharedSymbolTableBucketSize;
741 // calculation of num_buckets can result in zero buckets, we need at least one
742 CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1,
743 &MetaspaceShared::stats()->string);
744
746 if (copy_shared_string(string_space, &writer)) {
747 writer.dump(&_shared_table);
748 }
749 }
750
751 void StringTable::serialize(SerializeClosure* soc) {
752 _shared_table.set_type(CompactHashtable<oop, char>::_string_table);
753 _shared_table.serialize(soc);
754
755 if (soc->writing()) {
756 _shared_table.reset(); // Sanity. Make sure we don't use the shared table at dump time
757 } else if (!_shared_string_mapped) {
758 _shared_table.reset();
759 }
760 }
761
762 void StringTable::shared_oops_do(OopClosure* f) {
763 _shared_table.oops_do(f);
764 }
765 #endif //INCLUDE_CDS_JAVA_HEAP
766
|
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 "logging/log.hpp"
34 #include "memory/allocation.inline.hpp"
35 #include "memory/filemap.hpp"
36 #include "memory/metaspaceShared.hpp"
37 #include "memory/resourceArea.hpp"
38 #include "oops/access.inline.hpp"
39 #include "oops/oop.inline.hpp"
40 #include "runtime/atomic.hpp"
41 #include "runtime/mutexLocker.hpp"
42 #include "services/diagnosticCommand.hpp"
43 #include "utilities/hashtable.inline.hpp"
44 #include "utilities/macros.hpp"
45 #if INCLUDE_ALL_GCS
46 #include "gc/g1/g1CollectedHeap.hpp"
47 #include "gc/g1/g1StringDedup.hpp"
48 #endif
49
50 // the number of buckets a thread claims
51 const int ClaimChunkSize = 32;
52
53 #ifdef ASSERT
54 class StableMemoryChecker : public StackObj {
55 enum { _bufsize = wordSize*4 };
56
57 address _region;
58 jint _size;
59 u1 _save_buf[_bufsize];
60
61 int sample(u1* save_buf) {
62 if (_size <= _bufsize) {
63 memcpy(save_buf, _region, _size);
64 return _size;
65 } else {
66 // copy head and tail
107 return AltHashing::murmur3_32(seed(), s, len);
108 }
109
110 unsigned int StringTable::hash_string(oop string) {
111 EXCEPTION_MARK;
112 if (string == NULL) {
113 return hash_string((jchar*)NULL, 0);
114 }
115 ResourceMark rm(THREAD);
116 // All String oops are hashed as unicode
117 int length;
118 jchar* chars = java_lang_String::as_unicode_string(string, length, THREAD);
119 if (chars != NULL) {
120 return hash_string(chars, length);
121 } else {
122 vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "unable to create Unicode string for verification");
123 return 0;
124 }
125 }
126
127 oop StringTable::string_object(HashtableEntry<oop, mtSymbol>* entry) {
128 return RootAccess<ON_PHANTOM_OOP_REF>::oop_load(entry->literal_addr());
129 }
130
131 oop StringTable::string_object_no_keepalive(HashtableEntry<oop, mtSymbol>* entry) {
132 // The AS_NO_KEEPALIVE peeks at the oop without keeping it alive.
133 // This is *very dangerous* in general but is okay in this specific
134 // case. The subsequent oop_load keeps the oop alive if it it matched
135 // the jchar* string.
136 return RootAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(entry->literal_addr());
137 }
138
139 void StringTable::set_string_object(HashtableEntry<oop, mtSymbol>* entry, oop string) {
140 RootAccess<ON_PHANTOM_OOP_REF>::oop_store(entry->literal_addr(), string);
141 }
142
143 oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) {
144 assert(hash == java_lang_String::hash_code(name, len),
145 "hash must be computed using java_lang_String::hash_code");
146 return _shared_table.lookup((const char*)name, hash, len);
147 }
148
149 oop StringTable::lookup_in_main_table(int index, jchar* name,
150 int len, unsigned int hash) {
151 int count = 0;
152 for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
153 count++;
154 if (l->hash() == hash) {
155 if (java_lang_String::equals(string_object_no_keepalive(l), name, len)) {
156 // We must perform a new load with string_object() that keeps the string
157 // alive as we must expose the oop as strongly reachable when exiting
158 // this context, in case the oop gets published.
159 return string_object(l);
160 }
161 }
162 }
163 // If the bucket size is too deep check if this hash code is insufficient.
164 if (count >= rehash_count && !needs_rehashing()) {
165 _needs_rehashing = check_rehash_table(count);
166 }
167 return NULL;
168 }
169
170
171 oop StringTable::basic_add(int index_arg, Handle string, jchar* name,
172 int len, unsigned int hashValue_arg, TRAPS) {
173
174 assert(java_lang_String::equals(string(), name, len),
175 "string must be properly initialized");
176 // Cannot hit a safepoint in this function because the "this" pointer can move.
177 NoSafepointVerifier nsv;
178
179 // Check if the symbol table has been rehashed, if so, need to recalculate
194 // No need to lookup the shared table from here since the caller (intern()) already did
195 oop test = lookup_in_main_table(index, name, len, hashValue); // calls lookup(u1*, int)
196 if (test != NULL) {
197 // Entry already added
198 return test;
199 }
200
201 HashtableEntry<oop, mtSymbol>* entry = new_entry(hashValue, string());
202 add_entry(index, entry);
203 return string();
204 }
205
206
207 oop StringTable::lookup(Symbol* symbol) {
208 ResourceMark rm;
209 int length;
210 jchar* chars = symbol->as_unicode(length);
211 return lookup(chars, length);
212 }
213
214 oop StringTable::lookup(jchar* name, int len) {
215 // shared table always uses java_lang_String::hash_code
216 unsigned int hash = java_lang_String::hash_code(name, len);
217 oop string = lookup_shared(name, len, hash);
218 if (string != NULL) {
219 return string;
220 }
221 if (use_alternate_hashcode()) {
222 hash = alt_hash_string(name, len);
223 }
224 int index = the_table()->hash_to_index(hash);
225 string = the_table()->lookup_in_main_table(index, name, len, hash);
226
227 return string;
228 }
229
230 oop StringTable::intern(Handle string_or_null, jchar* name,
231 int len, TRAPS) {
232 // shared table always uses java_lang_String::hash_code
233 unsigned int hashValue = java_lang_String::hash_code(name, len);
234 oop found_string = lookup_shared(name, len, hashValue);
235 if (found_string != NULL) {
236 return found_string;
237 }
238 if (use_alternate_hashcode()) {
239 hashValue = alt_hash_string(name, len);
240 }
241 int index = the_table()->hash_to_index(hashValue);
242 found_string = the_table()->lookup_in_main_table(index, name, len, hashValue);
243
244 // Found
245 if (found_string != NULL) {
246 return found_string;
247 }
248
249 debug_only(StableMemoryChecker smc(name, len * sizeof(name[0])));
250 assert(!Universe::heap()->is_in_reserved(name),
251 "proposed name of symbol must be stable");
252
253 HandleMark hm(THREAD); // cleanup strings created
254 Handle string;
255 // try to reuse the string if possible
256 if (!string_or_null.is_null()) {
257 string = string_or_null;
258 } else {
259 string = java_lang_String::create_from_unicode(name, len, CHECK_NULL);
260 }
261
262 #if INCLUDE_ALL_GCS
263 if (G1StringDedup::is_enabled()) {
264 // Deduplicate the string before it is interned. Note that we should never
265 // deduplicate a string after it has been interned. Doing so will counteract
266 // compiler optimizations done on e.g. interned string literals.
267 G1StringDedup::deduplicate(string());
268 }
269 #endif
270
271 // Grab the StringTable_lock before getting the_table() because it could
272 // change at safepoint.
273 oop added_or_found;
274 {
275 MutexLocker ml(StringTable_lock, THREAD);
276 // Otherwise, add to symbol to table
277 added_or_found = the_table()->basic_add(index, string, name, len,
278 hashValue, CHECK_NULL);
279 }
280
281 return added_or_found;
282 }
283
284 oop StringTable::intern(Symbol* symbol, TRAPS) {
285 if (symbol == NULL) return NULL;
286 ResourceMark rm(THREAD);
287 int length;
288 jchar* chars = symbol->as_unicode(length);
289 Handle string;
290 oop result = intern(string, chars, length, CHECK_NULL);
291 return result;
292 }
293
294
295 oop StringTable::intern(oop string, TRAPS)
296 {
297 if (string == NULL) return NULL;
298 ResourceMark rm(THREAD);
299 int length;
300 Handle h_string (THREAD, string);
369 }
370 }
371
372 void StringTable::buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, BucketUnlinkContext* context) {
373 const int limit = the_table()->table_size();
374
375 assert(0 <= start_idx && start_idx <= limit,
376 "start_idx (%d) is out of bounds", start_idx);
377 assert(0 <= end_idx && end_idx <= limit,
378 "end_idx (%d) is out of bounds", end_idx);
379 assert(start_idx <= end_idx,
380 "Index ordering: start_idx=%d, end_idx=%d",
381 start_idx, end_idx);
382
383 for (int i = start_idx; i < end_idx; ++i) {
384 HashtableEntry<oop, mtSymbol>** p = the_table()->bucket_addr(i);
385 HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
386 while (entry != NULL) {
387 assert(!entry->is_shared(), "CDS not used for the StringTable");
388
389 if (is_alive->do_object_b(string_object_no_keepalive(entry))) {
390 if (f != NULL) {
391 f->do_oop(entry->literal_addr());
392 }
393 p = entry->next_addr();
394 } else {
395 *p = entry->next();
396 context->free_entry(entry);
397 }
398 context->_num_processed++;
399 entry = *p;
400 }
401 }
402 }
403
404 void StringTable::oops_do(OopClosure* f) {
405 buckets_oops_do(f, 0, the_table()->table_size());
406 }
407
408 void StringTable::possibly_parallel_oops_do(OopClosure* f) {
409 const int limit = the_table()->table_size();
410
411 for (;;) {
412 // Grab next set of buckets to scan
413 int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize;
414 if (start_idx >= limit) {
415 // End of table
416 break;
417 }
418
419 int end_idx = MIN2(limit, start_idx + ClaimChunkSize);
420 buckets_oops_do(f, start_idx, end_idx);
421 }
422 }
423
424 // This verification is part of Universe::verify() and needs to be quick.
425 // See StringTable::verify_and_compare() below for exhaustive verification.
426 void StringTable::verify() {
427 for (int i = 0; i < the_table()->table_size(); ++i) {
428 HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
429 for ( ; p != NULL; p = p->next()) {
430 oop s = string_object_no_keepalive(p);
431 guarantee(s != NULL, "interned string is NULL");
432 unsigned int h = hash_string(s);
433 guarantee(p->hash() == h, "broken hash in string table entry");
434 guarantee(the_table()->hash_to_index(h) == i,
435 "wrong index in string table");
436 }
437 }
438 }
439
440 void StringTable::dump(outputStream* st, bool verbose) {
441 if (!verbose) {
442 the_table()->print_table_statistics(st, "StringTable");
443 } else {
444 Thread* THREAD = Thread::current();
445 st->print_cr("VERSION: 1.1");
446 for (int i = 0; i < the_table()->table_size(); ++i) {
447 HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
448 for ( ; p != NULL; p = p->next()) {
449 oop s = string_object_no_keepalive(p);
450 typeArrayOop value = java_lang_String::value_no_keepalive(s);
451 int length = java_lang_String::length(s);
452 bool is_latin1 = java_lang_String::is_latin1(s);
453
454 if (length <= 0) {
455 st->print("%d: ", length);
456 } else {
457 ResourceMark rm(THREAD);
458 int utf8_length = length;
459 char* utf8_string;
460
461 if (!is_latin1) {
462 jchar* chars = value->char_at_addr(0);
463 utf8_string = UNICODE::as_utf8(chars, utf8_length);
464 } else {
465 jbyte* bytes = value->byte_at_addr(0);
466 utf8_string = UNICODE::as_utf8(bytes, utf8_length);
467 }
468
469 st->print("%d: ", utf8_length);
470 HashtableTextDump::put_utf8(st, utf8_string, utf8_length);
471 }
472 st->cr();
473 }
474 }
475 }
476 }
477
478 StringTable::VerifyRetTypes StringTable::compare_entries(
479 int bkt1, int e_cnt1,
480 HashtableEntry<oop, mtSymbol>* e_ptr1,
481 int bkt2, int e_cnt2,
482 HashtableEntry<oop, mtSymbol>* e_ptr2) {
483 // These entries are sanity checked by verify_and_compare_entries()
484 // before this function is called.
485 oop str1 = string_object_no_keepalive(e_ptr1);
486 oop str2 = string_object_no_keepalive(e_ptr2);
487
488 if (str1 == str2) {
489 tty->print_cr("ERROR: identical oop values (0x" PTR_FORMAT ") "
490 "in entry @ bucket[%d][%d] and entry @ bucket[%d][%d]",
491 p2i(str1), bkt1, e_cnt1, bkt2, e_cnt2);
492 return _verify_fail_continue;
493 }
494
495 if (java_lang_String::equals(str1, str2)) {
496 tty->print_cr("ERROR: identical String values in entry @ "
497 "bucket[%d][%d] and entry @ bucket[%d][%d]",
498 bkt1, e_cnt1, bkt2, e_cnt2);
499 return _verify_fail_continue;
500 }
501
502 return _verify_pass;
503 }
504
505 StringTable::VerifyRetTypes StringTable::verify_entry(int bkt, int e_cnt,
506 HashtableEntry<oop, mtSymbol>* e_ptr,
507 StringTable::VerifyMesgModes mesg_mode) {
508
509 VerifyRetTypes ret = _verify_pass; // be optimistic
510
511 oop str = string_object_no_keepalive(e_ptr);
512 if (str == NULL) {
513 if (mesg_mode == _verify_with_mesgs) {
514 tty->print_cr("ERROR: NULL oop value in entry @ bucket[%d][%d]", bkt,
515 e_cnt);
516 }
517 // NULL oop means no more verifications are possible
518 return _verify_fail_done;
519 }
520
521 if (str->klass() != SystemDictionary::String_klass()) {
522 if (mesg_mode == _verify_with_mesgs) {
523 tty->print_cr("ERROR: oop is not a String in entry @ bucket[%d][%d]",
524 bkt, e_cnt);
525 }
526 // not a String means no more verifications are possible
527 return _verify_fail_done;
528 }
529
530 unsigned int h = hash_string(str);
531 if (e_ptr->hash() != h) {
665 VMThread::execute(&dumper);
666 }
667
668 int StringtableDCmd::num_arguments() {
669 ResourceMark rm;
670 StringtableDCmd* dcmd = new StringtableDCmd(NULL, false);
671 if (dcmd != NULL) {
672 DCmdMark mark(dcmd);
673 return dcmd->_dcmdparser.num_arguments();
674 } else {
675 return 0;
676 }
677 }
678
679 #if INCLUDE_CDS_JAVA_HEAP
680 // Sharing
681 oop StringTable::create_archived_string(oop s, Thread* THREAD) {
682 assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
683
684 oop new_s = NULL;
685 typeArrayOop v = java_lang_String::value_no_keepalive(s);
686 typeArrayOop new_v = (typeArrayOop)MetaspaceShared::archive_heap_object(v, THREAD);
687 if (new_v == NULL) {
688 return NULL;
689 }
690 new_s = MetaspaceShared::archive_heap_object(s, THREAD);
691 if (new_s == NULL) {
692 return NULL;
693 }
694
695 // adjust the pointer to the 'value' field in the new String oop
696 java_lang_String::set_value_raw(new_s, new_v);
697 return new_s;
698 }
699
700 bool StringTable::copy_shared_string(GrowableArray<MemRegion> *string_space,
701 CompactStringTableWriter* writer) {
702 assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
703
704 Thread* THREAD = Thread::current();
705 G1CollectedHeap::heap()->begin_archive_alloc_range();
706 for (int i = 0; i < the_table()->table_size(); ++i) {
707 HashtableEntry<oop, mtSymbol>* bucket = the_table()->bucket(i);
708 for ( ; bucket != NULL; bucket = bucket->next()) {
709 oop s = string_object_no_keepalive(bucket);
710 unsigned int hash = java_lang_String::hash_code(s);
711 if (hash == 0) {
712 continue;
713 }
714
715 java_lang_String::set_hash(s, hash);
716 oop new_s = create_archived_string(s, THREAD);
717 if (new_s == NULL) {
718 continue;
719 }
720
721 // set the archived string in bucket
722 set_string_object(bucket, new_s);
723
724 // add to the compact table
725 writer->add(hash, new_s);
726 }
727 }
728
729 G1CollectedHeap::heap()->end_archive_alloc_range(string_space, os::vm_allocation_granularity());
730 return true;
731 }
732
733 void StringTable::write_to_archive(GrowableArray<MemRegion> *string_space) {
734 assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
735
736 _shared_table.reset();
737 int num_buckets = the_table()->number_of_entries() /
738 SharedSymbolTableBucketSize;
739 // calculation of num_buckets can result in zero buckets, we need at least one
740 CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1,
741 &MetaspaceShared::stats()->string);
742
744 if (copy_shared_string(string_space, &writer)) {
745 writer.dump(&_shared_table);
746 }
747 }
748
749 void StringTable::serialize(SerializeClosure* soc) {
750 _shared_table.set_type(CompactHashtable<oop, char>::_string_table);
751 _shared_table.serialize(soc);
752
753 if (soc->writing()) {
754 _shared_table.reset(); // Sanity. Make sure we don't use the shared table at dump time
755 } else if (!_shared_string_mapped) {
756 _shared_table.reset();
757 }
758 }
759
760 void StringTable::shared_oops_do(OopClosure* f) {
761 _shared_table.oops_do(f);
762 }
763 #endif //INCLUDE_CDS_JAVA_HEAP
|