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 oop string = string_object_no_keepalive(l);
156 if (java_lang_String::equals(string, name, len)) {
157 return string_object(l);
158 }
159 }
160 }
161 // If the bucket size is too deep check if this hash code is insufficient.
162 if (count >= rehash_count && !needs_rehashing()) {
163 _needs_rehashing = check_rehash_table(count);
164 }
165 return NULL;
166 }
167
168
169 oop StringTable::basic_add(int index_arg, Handle string, jchar* name,
170 int len, unsigned int hashValue_arg, TRAPS) {
171
172 assert(java_lang_String::equals(string(), name, len),
173 "string must be properly initialized");
174 // Cannot hit a safepoint in this function because the "this" pointer can move.
175 NoSafepointVerifier nsv;
176
177 // Check if the symbol table has been rehashed, if so, need to recalculate
192 // No need to lookup the shared table from here since the caller (intern()) already did
193 oop test = lookup_in_main_table(index, name, len, hashValue); // calls lookup(u1*, int)
194 if (test != NULL) {
195 // Entry already added
196 return test;
197 }
198
199 HashtableEntry<oop, mtSymbol>* entry = new_entry(hashValue, string());
200 add_entry(index, entry);
201 return string();
202 }
203
204
205 oop StringTable::lookup(Symbol* symbol) {
206 ResourceMark rm;
207 int length;
208 jchar* chars = symbol->as_unicode(length);
209 return lookup(chars, length);
210 }
211
212 oop StringTable::lookup(jchar* name, int len) {
213 // shared table always uses java_lang_String::hash_code
214 unsigned int hash = java_lang_String::hash_code(name, len);
215 oop string = lookup_shared(name, len, hash);
216 if (string != NULL) {
217 return string;
218 }
219 if (use_alternate_hashcode()) {
220 hash = alt_hash_string(name, len);
221 }
222 int index = the_table()->hash_to_index(hash);
223 string = the_table()->lookup_in_main_table(index, name, len, hash);
224
225 return string;
226 }
227
228 oop StringTable::intern(Handle string_or_null, jchar* name,
229 int len, TRAPS) {
230 // shared table always uses java_lang_String::hash_code
231 unsigned int hashValue = java_lang_String::hash_code(name, len);
232 oop found_string = lookup_shared(name, len, hashValue);
233 if (found_string != NULL) {
234 return found_string;
235 }
236 if (use_alternate_hashcode()) {
237 hashValue = alt_hash_string(name, len);
238 }
239 int index = the_table()->hash_to_index(hashValue);
240 found_string = the_table()->lookup_in_main_table(index, name, len, hashValue);
241
242 // Found
243 if (found_string != NULL) {
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 return added_or_found;
280 }
281
282 oop StringTable::intern(Symbol* symbol, TRAPS) {
283 if (symbol == NULL) return NULL;
284 ResourceMark rm(THREAD);
285 int length;
286 jchar* chars = symbol->as_unicode(length);
287 Handle string;
288 oop result = intern(string, chars, length, CHECK_NULL);
289 return result;
290 }
291
292
293 oop StringTable::intern(oop string, TRAPS)
294 {
295 if (string == NULL) return NULL;
296 ResourceMark rm(THREAD);
297 int length;
298 Handle h_string (THREAD, string);
367 }
368 }
369
370 void StringTable::buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, BucketUnlinkContext* context) {
371 const int limit = the_table()->table_size();
372
373 assert(0 <= start_idx && start_idx <= limit,
374 "start_idx (%d) is out of bounds", start_idx);
375 assert(0 <= end_idx && end_idx <= limit,
376 "end_idx (%d) is out of bounds", end_idx);
377 assert(start_idx <= end_idx,
378 "Index ordering: start_idx=%d, end_idx=%d",
379 start_idx, end_idx);
380
381 for (int i = start_idx; i < end_idx; ++i) {
382 HashtableEntry<oop, mtSymbol>** p = the_table()->bucket_addr(i);
383 HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
384 while (entry != NULL) {
385 assert(!entry->is_shared(), "CDS not used for the StringTable");
386
387 if (is_alive->do_object_b(string_object_no_keepalive(entry))) {
388 if (f != NULL) {
389 f->do_oop(entry->literal_addr());
390 }
391 p = entry->next_addr();
392 } else {
393 *p = entry->next();
394 context->free_entry(entry);
395 }
396 context->_num_processed++;
397 entry = *p;
398 }
399 }
400 }
401
402 void StringTable::oops_do(OopClosure* f) {
403 buckets_oops_do(f, 0, the_table()->table_size());
404 }
405
406 void StringTable::possibly_parallel_oops_do(OopClosure* f) {
407 const int limit = the_table()->table_size();
408
409 for (;;) {
410 // Grab next set of buckets to scan
411 int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize;
412 if (start_idx >= limit) {
413 // End of table
414 break;
415 }
416
417 int end_idx = MIN2(limit, start_idx + ClaimChunkSize);
418 buckets_oops_do(f, start_idx, end_idx);
419 }
420 }
421
422 // This verification is part of Universe::verify() and needs to be quick.
423 // See StringTable::verify_and_compare() below for exhaustive verification.
424 void StringTable::verify() {
425 for (int i = 0; i < the_table()->table_size(); ++i) {
426 HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
427 for ( ; p != NULL; p = p->next()) {
428 oop s = string_object_no_keepalive(p);
429 guarantee(s != NULL, "interned string is NULL");
430 unsigned int h = hash_string(s);
431 guarantee(p->hash() == h, "broken hash in string table entry");
432 guarantee(the_table()->hash_to_index(h) == i,
433 "wrong index in string table");
434 }
435 }
436 }
437
438 void StringTable::dump(outputStream* st, bool verbose) {
439 if (!verbose) {
440 the_table()->print_table_statistics(st, "StringTable");
441 } else {
442 Thread* THREAD = Thread::current();
443 st->print_cr("VERSION: 1.1");
444 for (int i = 0; i < the_table()->table_size(); ++i) {
445 HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
446 for ( ; p != NULL; p = p->next()) {
447 oop s = string_object_no_keepalive(p);
448 typeArrayOop value = java_lang_String::value_no_keepalive(s);
449 int length = java_lang_String::length(s);
450 bool is_latin1 = java_lang_String::is_latin1(s);
451
452 if (length <= 0) {
453 st->print("%d: ", length);
454 } else {
455 ResourceMark rm(THREAD);
456 int utf8_length = length;
457 char* utf8_string;
458
459 if (!is_latin1) {
460 jchar* chars = value->char_at_addr(0);
461 utf8_string = UNICODE::as_utf8(chars, utf8_length);
462 } else {
463 jbyte* bytes = value->byte_at_addr(0);
464 utf8_string = UNICODE::as_utf8(bytes, utf8_length);
465 }
466
467 st->print("%d: ", utf8_length);
468 HashtableTextDump::put_utf8(st, utf8_string, utf8_length);
469 }
470 st->cr();
471 }
472 }
473 }
474 }
475
476 StringTable::VerifyRetTypes StringTable::compare_entries(
477 int bkt1, int e_cnt1,
478 HashtableEntry<oop, mtSymbol>* e_ptr1,
479 int bkt2, int e_cnt2,
480 HashtableEntry<oop, mtSymbol>* e_ptr2) {
481 // These entries are sanity checked by verify_and_compare_entries()
482 // before this function is called.
483 oop str1 = string_object_no_keepalive(e_ptr1);
484 oop str2 = string_object_no_keepalive(e_ptr2);
485
486 if (str1 == str2) {
487 tty->print_cr("ERROR: identical oop values (0x" PTR_FORMAT ") "
488 "in entry @ bucket[%d][%d] and entry @ bucket[%d][%d]",
489 p2i(str1), bkt1, e_cnt1, bkt2, e_cnt2);
490 return _verify_fail_continue;
491 }
492
493 if (java_lang_String::equals(str1, str2)) {
494 tty->print_cr("ERROR: identical String values in entry @ "
495 "bucket[%d][%d] and entry @ bucket[%d][%d]",
496 bkt1, e_cnt1, bkt2, e_cnt2);
497 return _verify_fail_continue;
498 }
499
500 return _verify_pass;
501 }
502
503 StringTable::VerifyRetTypes StringTable::verify_entry(int bkt, int e_cnt,
504 HashtableEntry<oop, mtSymbol>* e_ptr,
505 StringTable::VerifyMesgModes mesg_mode) {
506
507 VerifyRetTypes ret = _verify_pass; // be optimistic
508
509 oop str = string_object_no_keepalive(e_ptr);
510 if (str == NULL) {
511 if (mesg_mode == _verify_with_mesgs) {
512 tty->print_cr("ERROR: NULL oop value in entry @ bucket[%d][%d]", bkt,
513 e_cnt);
514 }
515 // NULL oop means no more verifications are possible
516 return _verify_fail_done;
517 }
518
519 if (str->klass() != SystemDictionary::String_klass()) {
520 if (mesg_mode == _verify_with_mesgs) {
521 tty->print_cr("ERROR: oop is not a String in entry @ bucket[%d][%d]",
522 bkt, e_cnt);
523 }
524 // not a String means no more verifications are possible
525 return _verify_fail_done;
526 }
527
528 unsigned int h = hash_string(str);
529 if (e_ptr->hash() != h) {
663 VMThread::execute(&dumper);
664 }
665
666 int StringtableDCmd::num_arguments() {
667 ResourceMark rm;
668 StringtableDCmd* dcmd = new StringtableDCmd(NULL, false);
669 if (dcmd != NULL) {
670 DCmdMark mark(dcmd);
671 return dcmd->_dcmdparser.num_arguments();
672 } else {
673 return 0;
674 }
675 }
676
677 #if INCLUDE_CDS_JAVA_HEAP
678 // Sharing
679 oop StringTable::create_archived_string(oop s, Thread* THREAD) {
680 assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
681
682 oop new_s = NULL;
683 typeArrayOop v = java_lang_String::value_no_keepalive(s);
684 typeArrayOop new_v = (typeArrayOop)MetaspaceShared::archive_heap_object(v, THREAD);
685 if (new_v == NULL) {
686 return NULL;
687 }
688 new_s = MetaspaceShared::archive_heap_object(s, THREAD);
689 if (new_s == NULL) {
690 return NULL;
691 }
692
693 // adjust the pointer to the 'value' field in the new String oop
694 java_lang_String::set_value_raw(new_s, new_v);
695 return new_s;
696 }
697
698 bool StringTable::copy_shared_string(GrowableArray<MemRegion> *string_space,
699 CompactStringTableWriter* writer) {
700 assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
701
702 Thread* THREAD = Thread::current();
703 G1CollectedHeap::heap()->begin_archive_alloc_range();
704 for (int i = 0; i < the_table()->table_size(); ++i) {
705 HashtableEntry<oop, mtSymbol>* bucket = the_table()->bucket(i);
706 for ( ; bucket != NULL; bucket = bucket->next()) {
707 oop s = string_object_no_keepalive(bucket);
708 unsigned int hash = java_lang_String::hash_code(s);
709 if (hash == 0) {
710 continue;
711 }
712
713 java_lang_String::set_hash(s, hash);
714 oop new_s = create_archived_string(s, THREAD);
715 if (new_s == NULL) {
716 continue;
717 }
718
719 // set the archived string in bucket
720 set_string_object(bucket, new_s);
721
722 // add to the compact table
723 writer->add(hash, new_s);
724 }
725 }
726
727 G1CollectedHeap::heap()->end_archive_alloc_range(string_space, os::vm_allocation_granularity());
728 return true;
729 }
730
731 void StringTable::write_to_archive(GrowableArray<MemRegion> *string_space) {
732 assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
733
734 _shared_table.reset();
735 int num_buckets = the_table()->number_of_entries() /
736 SharedSymbolTableBucketSize;
737 // calculation of num_buckets can result in zero buckets, we need at least one
738 CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1,
739 &MetaspaceShared::stats()->string);
740
742 if (copy_shared_string(string_space, &writer)) {
743 writer.dump(&_shared_table);
744 }
745 }
746
747 void StringTable::serialize(SerializeClosure* soc) {
748 _shared_table.set_type(CompactHashtable<oop, char>::_string_table);
749 _shared_table.serialize(soc);
750
751 if (soc->writing()) {
752 _shared_table.reset(); // Sanity. Make sure we don't use the shared table at dump time
753 } else if (!_shared_string_mapped) {
754 _shared_table.reset();
755 }
756 }
757
758 void StringTable::shared_oops_do(OopClosure* f) {
759 _shared_table.oops_do(f);
760 }
761 #endif //INCLUDE_CDS_JAVA_HEAP
|