7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
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.hpp"
32 #include "gc/shared/oopStorage.inline.hpp"
33 #include "gc/shared/oopStorageParState.inline.hpp"
34 #include "logging/log.hpp"
35 #include "logging/logStream.hpp"
36 #include "memory/allocation.inline.hpp"
37 #include "memory/filemap.hpp"
38 #include "memory/metaspaceShared.inline.hpp"
39 #include "memory/resourceArea.hpp"
40 #include "memory/universe.hpp"
41 #include "oops/access.inline.hpp"
42 #include "oops/oop.inline.hpp"
43 #include "oops/typeArrayOop.inline.hpp"
44 #include "oops/weakHandle.inline.hpp"
45 #include "runtime/atomic.hpp"
46 #include "runtime/handles.inline.hpp"
47 #include "runtime/mutexLocker.hpp"
48 #include "runtime/safepointVerifiers.hpp"
49 #include "runtime/timerTrace.hpp"
50 #include "runtime/interfaceSupport.inline.hpp"
51 #include "services/diagnosticCommand.hpp"
52 #include "utilities/concurrentHashTable.inline.hpp"
53 #include "utilities/concurrentHashTableTasks.inline.hpp"
54 #include "utilities/macros.hpp"
55
56 // We prefer short chains of avg 2
57 #define PREF_AVG_LIST_LEN 2
58 // 2^24 is max size
59 #define END_SIZE 24
60 // If a chain gets to 32 something might be wrong
61 #define REHASH_LEN 32
62 // If we have as many dead items as 50% of the number of bucket
63 #define CLEAN_DEAD_HIGH_WATER_MARK 0.5
64
65 // --------------------------------------------------------------------------
66 StringTable* StringTable::_the_table = NULL;
67 CompactHashtable<oop, char> StringTable::_shared_table;
68 volatile bool StringTable::_shared_string_mapped = false;
69 volatile bool StringTable::_alt_hash = false;
70
71 static juint murmur_seed = 0;
72
73 uintx hash_string(const jchar* s, int len, bool useAlt) {
74 return useAlt ?
75 AltHashing::murmur3_32(murmur_seed, s, len) :
76 java_lang_String::hash_code(s, len);
77 }
78
79 class StringTableConfig : public StringTableHash::BaseConfig {
80 private:
81 public:
82 static uintx get_hash(WeakHandle<vm_string_table_data> const& value,
83 bool* is_dead) {
84 EXCEPTION_MARK;
85 oop val_oop = value.peek();
86 if (val_oop == NULL) {
87 *is_dead = true;
761 _verbose.value());
762 VMThread::execute(&dumper);
763 }
764
765 int StringtableDCmd::num_arguments() {
766 ResourceMark rm;
767 StringtableDCmd* dcmd = new StringtableDCmd(NULL, false);
768 if (dcmd != NULL) {
769 DCmdMark mark(dcmd);
770 return dcmd->_dcmdparser.num_arguments();
771 } else {
772 return 0;
773 }
774 }
775
776 // Sharing
777 #if INCLUDE_CDS_JAVA_HEAP
778 oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) {
779 assert(hash == java_lang_String::hash_code(name, len),
780 "hash must be computed using java_lang_String::hash_code");
781 return _shared_table.lookup((const char*)name, hash, len);
782 }
783
784 oop StringTable::create_archived_string(oop s, Thread* THREAD) {
785 assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
786
787 if (MetaspaceShared::is_archive_object(s)) {
788 return s;
789 }
790
791 oop new_s = NULL;
792 typeArrayOop v = java_lang_String::value_no_keepalive(s);
793 typeArrayOop new_v =
794 (typeArrayOop)MetaspaceShared::archive_heap_object(v, THREAD);
795 if (new_v == NULL) {
796 return NULL;
797 }
798 new_s = MetaspaceShared::archive_heap_object(s, THREAD);
799 if (new_s == NULL) {
800 return NULL;
801 }
802
803 // adjust the pointer to the 'value' field in the new String oop
804 java_lang_String::set_value_raw(new_s, new_v);
805 return new_s;
806 }
807
808 struct CopyToArchive : StackObj {
809 CompactStringTableWriter* _writer;
810 CopyToArchive(CompactStringTableWriter* writer) : _writer(writer) {}
811 bool operator()(WeakHandle<vm_string_table_data>* val) {
812 oop s = val->peek();
813 if (s == NULL) {
814 return true;
815 }
816 unsigned int hash = java_lang_String::hash_code(s);
817 if (hash == 0) {
818 return true;
819 }
820
821 java_lang_String::set_hash(s, hash);
822 oop new_s = StringTable::create_archived_string(s, Thread::current());
823 if (new_s == NULL) {
824 return true;
825 }
826
827 val->replace(new_s);
832 };
833
834 void StringTable::copy_shared_string_table(CompactStringTableWriter* writer) {
835 assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
836
837 CopyToArchive copy(writer);
838 StringTable::the_table()->_local_table->do_scan(Thread::current(), copy);
839 }
840
841 void StringTable::write_to_archive() {
842 assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
843
844 _shared_table.reset();
845 int num_buckets = the_table()->_items_count / SharedSymbolTableBucketSize;
846 // calculation of num_buckets can result in zero buckets, we need at least one
847 CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1,
848 &MetaspaceShared::stats()->string);
849
850 // Copy the interned strings into the "string space" within the java heap
851 copy_shared_string_table(&writer);
852 writer.dump(&_shared_table);
853 }
854
855 void StringTable::serialize(SerializeClosure* soc) {
856 _shared_table.set_type(CompactHashtable<oop, char>::_string_table);
857 _shared_table.serialize(soc);
858
859 if (soc->writing()) {
860 // Sanity. Make sure we don't use the shared table at dump time
861 _shared_table.reset();
862 } else if (!_shared_string_mapped) {
863 _shared_table.reset();
864 }
865 }
866
867 void StringTable::shared_oops_do(OopClosure* f) {
868 _shared_table.oops_do(f);
869 }
870 #endif //INCLUDE_CDS_JAVA_HEAP
|
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
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.hpp"
28 #include "classfile/javaClasses.inline.hpp"
29 #include "classfile/stringTable.hpp"
30 #include "classfile/systemDictionary.hpp"
31 #include "gc/shared/collectedHeap.hpp"
32 #include "gc/shared/oopStorage.inline.hpp"
33 #include "gc/shared/oopStorageParState.inline.hpp"
34 #include "logging/log.hpp"
35 #include "logging/logStream.hpp"
36 #include "memory/allocation.inline.hpp"
37 #include "memory/filemap.hpp"
38 #include "memory/heapShared.inline.hpp"
39 #include "memory/metaspaceShared.inline.hpp"
40 #include "memory/resourceArea.hpp"
41 #include "memory/universe.hpp"
42 #include "oops/access.inline.hpp"
43 #include "oops/oop.inline.hpp"
44 #include "oops/typeArrayOop.inline.hpp"
45 #include "oops/weakHandle.inline.hpp"
46 #include "runtime/atomic.hpp"
47 #include "runtime/handles.inline.hpp"
48 #include "runtime/mutexLocker.hpp"
49 #include "runtime/safepointVerifiers.hpp"
50 #include "runtime/timerTrace.hpp"
51 #include "runtime/interfaceSupport.inline.hpp"
52 #include "services/diagnosticCommand.hpp"
53 #include "utilities/concurrentHashTable.inline.hpp"
54 #include "utilities/concurrentHashTableTasks.inline.hpp"
55 #include "utilities/macros.hpp"
56
57 // We prefer short chains of avg 2
58 #define PREF_AVG_LIST_LEN 2
59 // 2^24 is max size
60 #define END_SIZE 24
61 // If a chain gets to 32 something might be wrong
62 #define REHASH_LEN 32
63 // If we have as many dead items as 50% of the number of bucket
64 #define CLEAN_DEAD_HIGH_WATER_MARK 0.5
65
66 // --------------------------------------------------------------------------
67 inline oop read_string_from_compact_hashtable(address base_address, u4 offset) {
68 assert(sizeof(narrowOop) == sizeof(offset), "must be");
69 narrowOop v = (narrowOop)offset;
70 return HeapShared::decode_from_archive(v);
71 }
72
73 inline bool string_equals_compact_hashtable_entry(oop value, const jchar* key, int len) {
74 return java_lang_String::equals(value, (jchar*)key, len);
75 }
76
77 static CompactHashtable<
78 const jchar*, oop,
79 read_string_from_compact_hashtable,
80 string_equals_compact_hashtable_entry
81 > _shared_table;
82
83 // --------------------------------------------------------------------------
84 StringTable* StringTable::_the_table = NULL;
85 volatile bool StringTable::_shared_string_mapped = false;
86 volatile bool StringTable::_alt_hash = false;
87
88 static juint murmur_seed = 0;
89
90 uintx hash_string(const jchar* s, int len, bool useAlt) {
91 return useAlt ?
92 AltHashing::murmur3_32(murmur_seed, s, len) :
93 java_lang_String::hash_code(s, len);
94 }
95
96 class StringTableConfig : public StringTableHash::BaseConfig {
97 private:
98 public:
99 static uintx get_hash(WeakHandle<vm_string_table_data> const& value,
100 bool* is_dead) {
101 EXCEPTION_MARK;
102 oop val_oop = value.peek();
103 if (val_oop == NULL) {
104 *is_dead = true;
778 _verbose.value());
779 VMThread::execute(&dumper);
780 }
781
782 int StringtableDCmd::num_arguments() {
783 ResourceMark rm;
784 StringtableDCmd* dcmd = new StringtableDCmd(NULL, false);
785 if (dcmd != NULL) {
786 DCmdMark mark(dcmd);
787 return dcmd->_dcmdparser.num_arguments();
788 } else {
789 return 0;
790 }
791 }
792
793 // Sharing
794 #if INCLUDE_CDS_JAVA_HEAP
795 oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) {
796 assert(hash == java_lang_String::hash_code(name, len),
797 "hash must be computed using java_lang_String::hash_code");
798 return _shared_table.lookup(name, hash, len);
799 }
800
801 oop StringTable::create_archived_string(oop s, Thread* THREAD) {
802 assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
803
804 if (MetaspaceShared::is_archive_object(s)) {
805 return s;
806 }
807
808 oop new_s = NULL;
809 typeArrayOop v = java_lang_String::value_no_keepalive(s);
810 typeArrayOop new_v =
811 (typeArrayOop)MetaspaceShared::archive_heap_object(v, THREAD);
812 if (new_v == NULL) {
813 return NULL;
814 }
815 new_s = MetaspaceShared::archive_heap_object(s, THREAD);
816 if (new_s == NULL) {
817 return NULL;
818 }
819
820 // adjust the pointer to the 'value' field in the new String oop
821 java_lang_String::set_value_raw(new_s, new_v);
822 return new_s;
823 }
824
825 class CompactStringTableWriter: public CompactHashtableWriter {
826 public:
827 CompactStringTableWriter(int num_entries, CompactHashtableStats* stats) :
828 CompactHashtableWriter(num_entries, stats) {}
829 void add(unsigned int hash, oop string) {
830 CompactHashtableWriter::add(hash, CompressedOops::encode(string));
831 }
832 };
833
834 struct CopyToArchive : StackObj {
835 CompactStringTableWriter* _writer;
836 CopyToArchive(CompactStringTableWriter* writer) : _writer(writer) {}
837 bool operator()(WeakHandle<vm_string_table_data>* val) {
838 oop s = val->peek();
839 if (s == NULL) {
840 return true;
841 }
842 unsigned int hash = java_lang_String::hash_code(s);
843 if (hash == 0) {
844 return true;
845 }
846
847 java_lang_String::set_hash(s, hash);
848 oop new_s = StringTable::create_archived_string(s, Thread::current());
849 if (new_s == NULL) {
850 return true;
851 }
852
853 val->replace(new_s);
858 };
859
860 void StringTable::copy_shared_string_table(CompactStringTableWriter* writer) {
861 assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
862
863 CopyToArchive copy(writer);
864 StringTable::the_table()->_local_table->do_scan(Thread::current(), copy);
865 }
866
867 void StringTable::write_to_archive() {
868 assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
869
870 _shared_table.reset();
871 int num_buckets = the_table()->_items_count / SharedSymbolTableBucketSize;
872 // calculation of num_buckets can result in zero buckets, we need at least one
873 CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1,
874 &MetaspaceShared::stats()->string);
875
876 // Copy the interned strings into the "string space" within the java heap
877 copy_shared_string_table(&writer);
878 writer.dump(&_shared_table, "string");
879 }
880
881 void StringTable::serialize(SerializeClosure* soc) {
882 _shared_table.serialize(soc);
883
884 if (soc->writing()) {
885 // Sanity. Make sure we don't use the shared table at dump time
886 _shared_table.reset();
887 } else if (!_shared_string_mapped) {
888 _shared_table.reset();
889 }
890 }
891
892 class SharedStringIterator {
893 OopClosure* _oop_closure;
894 public:
895 SharedStringIterator(OopClosure* f) : _oop_closure(f) {}
896 void do_value(oop string) {
897 _oop_closure->do_oop(&string);
898 }
899 };
900
901 void StringTable::shared_oops_do(OopClosure* f) {
902 SharedStringIterator iter(f);
903 _shared_table.iterate(&iter);
904 }
905 #endif //INCLUDE_CDS_JAVA_HEAP
|