73 public:
74 StableMemoryChecker(const void* region, jint size) {
75 _region = (address) region;
76 _size = size;
77 sample(_save_buf);
78 }
79
80 bool verify() {
81 u1 check_buf[sizeof(_save_buf)];
82 int check_size = sample(check_buf);
83 return (0 == memcmp(_save_buf, check_buf, check_size));
84 }
85
86 void set_region(const void* region) { _region = (address) region; }
87 };
88 #endif
89
90
91 // --------------------------------------------------------------------------
92 StringTable* StringTable::_the_table = NULL;
93 bool StringTable::_ignore_shared_strings = false;
94 bool StringTable::_needs_rehashing = false;
95
96 volatile int StringTable::_parallel_claimed_idx = 0;
97
98 CompactHashtable<oop, char> StringTable::_shared_table;
99
100 // Pick hashing algorithm
101 unsigned int StringTable::hash_string(const jchar* s, int len) {
102 return use_alternate_hashcode() ? alt_hash_string(s, len) :
103 java_lang_String::hash_code(s, len);
104 }
105
106 unsigned int StringTable::alt_hash_string(const jchar* s, int len) {
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);
661 _dcmdparser.add_dcmd_option(&_verbose);
662 }
663
664 void StringtableDCmd::execute(DCmdSource source, TRAPS) {
665 VM_DumpHashtable dumper(output(), VM_DumpHashtable::DumpStrings,
666 _verbose.value());
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 // Sharing
682 bool StringTable::copy_shared_string(GrowableArray<MemRegion> *string_space,
683 CompactStringTableWriter* writer) {
684 #if INCLUDE_CDS && INCLUDE_ALL_GCS && defined(_LP64) && !defined(_WINDOWS)
685 assert(UseG1GC, "Only support G1 GC");
686 assert(UseCompressedOops && UseCompressedClassPointers,
687 "Only support UseCompressedOops and UseCompressedClassPointers enabled");
688
689 Thread* THREAD = Thread::current();
690 G1CollectedHeap::heap()->begin_archive_alloc_range();
691 for (int i = 0; i < the_table()->table_size(); ++i) {
692 HashtableEntry<oop, mtSymbol>* bucket = the_table()->bucket(i);
693 for ( ; bucket != NULL; bucket = bucket->next()) {
694 oop s = bucket->literal();
695 unsigned int hash = java_lang_String::hash_code(s);
696 if (hash == 0) {
697 continue;
698 }
699
700 // allocate the new 'value' array first
701 typeArrayOop v = java_lang_String::value(s);
702 int v_len = v->size();
703 typeArrayOop new_v;
704 if (G1CollectedHeap::heap()->is_archive_alloc_too_large(v_len)) {
705 continue; // skip the current String. The 'value' array is too large to handle
706 } else {
707 new_v = (typeArrayOop)G1CollectedHeap::heap()->archive_mem_allocate(v_len);
708 if (new_v == NULL) {
709 return false; // allocation failed
710 }
711 }
712 // now allocate the new String object
713 int s_len = s->size();
714 oop new_s = (oop)G1CollectedHeap::heap()->archive_mem_allocate(s_len);
715 if (new_s == NULL) {
716 return false;
717 }
718
719 s->identity_hash();
720 v->identity_hash();
721
722 // copy the objects' data
723 Copy::aligned_disjoint_words((HeapWord*)s, (HeapWord*)new_s, s_len);
724 Copy::aligned_disjoint_words((HeapWord*)v, (HeapWord*)new_v, v_len);
725
726 // adjust the pointer to the 'value' field in the new String oop. Also pre-compute and set the
727 // 'hash' field. That avoids "write" to the shared strings at runtime by the deduplication process.
728 java_lang_String::set_value_raw(new_s, new_v);
729 if (java_lang_String::hash(new_s) == 0) {
730 java_lang_String::set_hash(new_s, hash);
731 }
732
733 // add to the compact table
734 writer->add(hash, new_s);
735
736 MetaspaceShared::relocate_klass_ptr(new_s);
737 MetaspaceShared::relocate_klass_ptr(new_v);
738 }
739 }
740
741 G1CollectedHeap::heap()->end_archive_alloc_range(string_space, os::vm_allocation_granularity());
742 assert(string_space->length() <= 2, "sanity");
743 #endif
744 return true;
745 }
746
747 void StringTable::write_to_archive(GrowableArray<MemRegion> *string_space) {
748 #if INCLUDE_CDS
749 _shared_table.reset();
750 if (!(UseG1GC && UseCompressedOops && UseCompressedClassPointers)) {
751 log_info(cds)(
752 "Shared strings are excluded from the archive as UseG1GC, "
753 "UseCompressedOops and UseCompressedClassPointers are required."
754 "Current settings: UseG1GC=%s, UseCompressedOops=%s, UseCompressedClassPointers=%s.",
755 BOOL_TO_STR(UseG1GC), BOOL_TO_STR(UseCompressedOops),
756 BOOL_TO_STR(UseCompressedClassPointers));
757 } else {
758 int num_buckets = the_table()->number_of_entries() /
759 SharedSymbolTableBucketSize;
760 // calculation of num_buckets can result in zero buckets, we need at least one
761 CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1,
762 &MetaspaceShared::stats()->string);
763
764 // Copy the interned strings into the "string space" within the java heap
765 if (copy_shared_string(string_space, &writer)) {
766 writer.dump(&_shared_table);
767 }
768 }
769 #endif
770 }
771
772 void StringTable::serialize(SerializeClosure* soc) {
773 #if INCLUDE_CDS && defined(_LP64) && !defined(_WINDOWS)
774 _shared_table.set_type(CompactHashtable<oop, char>::_string_table);
775 _shared_table.serialize(soc);
776
777 if (soc->writing()) {
778 _shared_table.reset(); // Sanity. Make sure we don't use the shared table at dump time
779 } else if (_ignore_shared_strings) {
780 _shared_table.reset();
781 }
782 #endif
783 }
784
785 void StringTable::shared_oops_do(OopClosure* f) {
786 #if INCLUDE_CDS && defined(_LP64) && !defined(_WINDOWS)
787 _shared_table.oops_do(f);
788 #endif
789 }
790
|
73 public:
74 StableMemoryChecker(const void* region, jint size) {
75 _region = (address) region;
76 _size = size;
77 sample(_save_buf);
78 }
79
80 bool verify() {
81 u1 check_buf[sizeof(_save_buf)];
82 int check_size = sample(check_buf);
83 return (0 == memcmp(_save_buf, check_buf, check_size));
84 }
85
86 void set_region(const void* region) { _region = (address) region; }
87 };
88 #endif
89
90
91 // --------------------------------------------------------------------------
92 StringTable* StringTable::_the_table = NULL;
93 bool StringTable::_shared_string_mapped = false;
94 bool StringTable::_needs_rehashing = false;
95
96 volatile int StringTable::_parallel_claimed_idx = 0;
97
98 CompactHashtable<oop, char> StringTable::_shared_table;
99
100 // Pick hashing algorithm
101 unsigned int StringTable::hash_string(const jchar* s, int len) {
102 return use_alternate_hashcode() ? alt_hash_string(s, len) :
103 java_lang_String::hash_code(s, len);
104 }
105
106 unsigned int StringTable::alt_hash_string(const jchar* s, int len) {
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);
661 _dcmdparser.add_dcmd_option(&_verbose);
662 }
663
664 void StringtableDCmd::execute(DCmdSource source, TRAPS) {
665 VM_DumpHashtable dumper(output(), VM_DumpHashtable::DumpStrings,
666 _verbose.value());
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 assert(string_space->length() <= 2, "sanity");
733 return true;
734 }
735
736 void StringTable::write_to_archive(GrowableArray<MemRegion> *string_space) {
737 assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
738
739 _shared_table.reset();
740 int num_buckets = the_table()->number_of_entries() /
741 SharedSymbolTableBucketSize;
742 // calculation of num_buckets can result in zero buckets, we need at least one
743 CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1,
744 &MetaspaceShared::stats()->string);
745
746 // Copy the interned strings into the "string space" within the java heap
747 if (copy_shared_string(string_space, &writer)) {
748 writer.dump(&_shared_table);
749 }
750 }
751
752 void StringTable::serialize(SerializeClosure* soc) {
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 (!_shared_string_mapped) {
759 _shared_table.reset();
760 }
761 }
762
763 void StringTable::shared_oops_do(OopClosure* f) {
764 _shared_table.oops_do(f);
765 }
766 #endif //INCLUDE_CDS_JAVA_HEAP
767
|