1 /* 2 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 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 #ifndef SHARE_VM_CLASSFILE_STRINGTABLE_HPP 26 #define SHARE_VM_CLASSFILE_STRINGTABLE_HPP 27 28 #include "memory/allocation.hpp" 29 #include "utilities/hashtable.hpp" 30 31 template <class T, class N> class CompactHashtable; 32 class CompactStringTableWriter; 33 class FileMapInfo; 34 class SerializeClosure; 35 36 class StringTable : public RehashableHashtable<oop, mtSymbol> { 37 friend class VMStructs; 38 friend class Symbol; 39 40 private: 41 // The string table 42 static StringTable* _the_table; 43 44 // Shared string table 45 static CompactHashtable<oop, char> _shared_table; 46 static bool _shared_string_mapped; 47 48 // Set if one bucket is out of balance due to hash algorithm deficiency 49 static bool _needs_rehashing; 50 51 // Claimed high water mark for parallel chunked scanning 52 static volatile int _parallel_claimed_idx; 53 54 static oop intern(Handle string_or_null, jchar* chars, int length, TRAPS); 55 oop basic_add(int index, Handle string_or_null, jchar* name, int len, 56 unsigned int hashValue, TRAPS); 57 58 oop lookup_in_main_table(int index, jchar* chars, int length, unsigned int hashValue); 59 static oop lookup_shared(jchar* name, int len, unsigned int hash); 60 61 // Apply the give oop closure to the entries to the buckets 62 // in the range [start_idx, end_idx). 63 static void buckets_oops_do(OopClosure* f, int start_idx, int end_idx); 64 65 typedef StringTable::BucketUnlinkContext BucketUnlinkContext; 66 // Unlink or apply the give oop closure to the entries to the buckets 67 // in the range [start_idx, end_idx). Unlinked bucket entries are collected in the given 68 // context to be freed later. 69 // This allows multiple threads to work on the table at once. 70 static void buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, BucketUnlinkContext* context); 71 72 // Hashing algorithm, used as the hash value used by the 73 // StringTable for bucket selection and comparison (stored in the 74 // HashtableEntry structures). This is used in the String.intern() method. 75 static unsigned int hash_string(const jchar* s, int len); 76 static unsigned int hash_string(oop string); 77 static unsigned int alt_hash_string(const jchar* s, int len); 78 79 // Accessors for the string roots in the hashtable entries. 80 // Use string_object_no_keepalive() only when the value is not returned 81 // outside of a scope where a thread transition is possible. 82 static oop string_object(HashtableEntry<oop, mtSymbol>* entry); 83 static oop string_object_no_keepalive(HashtableEntry<oop, mtSymbol>* entry); 84 static void set_string_object(HashtableEntry<oop, mtSymbol>* entry, oop string); 85 86 StringTable() : RehashableHashtable<oop, mtSymbol>((int)StringTableSize, 87 sizeof (HashtableEntry<oop, mtSymbol>)) {} 88 89 StringTable(HashtableBucket<mtSymbol>* t, int number_of_entries) 90 : RehashableHashtable<oop, mtSymbol>((int)StringTableSize, sizeof (HashtableEntry<oop, mtSymbol>), t, 91 number_of_entries) {} 92 public: 93 // The string table 94 static StringTable* the_table() { return _the_table; } 95 96 // Size of one bucket in the string table. Used when checking for rollover. 97 static uint bucket_size() { return sizeof(HashtableBucket<mtSymbol>); } 98 99 static void create_table() { 100 assert(_the_table == NULL, "One string table allowed."); 101 _the_table = new StringTable(); 102 } 103 104 // GC support 105 // Delete pointers to otherwise-unreachable objects. 106 static void unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f) { 107 int processed = 0; 108 int removed = 0; 109 unlink_or_oops_do(cl, f, &processed, &removed); 110 } 111 static void unlink(BoolObjectClosure* cl) { 112 int processed = 0; 113 int removed = 0; 114 unlink_or_oops_do(cl, NULL, &processed, &removed); 115 } 116 static void unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f, int* processed, int* removed); 117 static void unlink(BoolObjectClosure* cl, int* processed, int* removed) { 118 unlink_or_oops_do(cl, NULL, processed, removed); 119 } 120 // Serially invoke "f->do_oop" on the locations of all oops in the table. 121 static void oops_do(OopClosure* f); 122 123 // Possibly parallel versions of the above 124 static void possibly_parallel_unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f, int* processed, int* removed); 125 static void possibly_parallel_unlink(BoolObjectClosure* cl, int* processed, int* removed) { 126 possibly_parallel_unlink_or_oops_do(cl, NULL, processed, removed); 127 } 128 static void possibly_parallel_oops_do(OopClosure* f); 129 130 // Internal test. 131 static void test_alt_hash() PRODUCT_RETURN; 132 133 // Probing 134 static oop lookup(Symbol* symbol); 135 static oop lookup(jchar* chars, int length); 136 137 // Interning 138 static oop intern(Symbol* symbol, TRAPS); 139 static oop intern(oop string, TRAPS); 140 static oop intern(const char *utf8_string, TRAPS); 141 142 // Debugging 143 static void verify(); 144 static void dump(outputStream* st, bool verbose=false); 145 146 enum VerifyMesgModes { 147 _verify_quietly = 0, 148 _verify_with_mesgs = 1 149 }; 150 151 enum VerifyRetTypes { 152 _verify_pass = 0, 153 _verify_fail_continue = 1, 154 _verify_fail_done = 2 155 }; 156 157 static VerifyRetTypes compare_entries(int bkt1, int e_cnt1, 158 HashtableEntry<oop, mtSymbol>* e_ptr1, 159 int bkt2, int e_cnt2, 160 HashtableEntry<oop, mtSymbol>* e_ptr2); 161 static VerifyRetTypes verify_entry(int bkt, int e_cnt, 162 HashtableEntry<oop, mtSymbol>* e_ptr, 163 VerifyMesgModes mesg_mode); 164 static int verify_and_compare_entries(); 165 166 // Sharing 167 static void set_shared_string_mapped() { _shared_string_mapped = true; } 168 static bool shared_string_mapped() { return _shared_string_mapped; } 169 static void shared_oops_do(OopClosure* f) NOT_CDS_JAVA_HEAP_RETURN; 170 static bool copy_shared_string(GrowableArray<MemRegion> *string_space, 171 CompactStringTableWriter* ch_table) NOT_CDS_JAVA_HEAP_RETURN_(false); 172 static oop create_archived_string(oop s, Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN_(NULL); 173 static void write_to_archive(GrowableArray<MemRegion> *string_space) NOT_CDS_JAVA_HEAP_RETURN; 174 static void serialize(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN; 175 176 // Rehash the symbol table if it gets out of balance 177 static void rehash_table(); 178 static bool needs_rehashing() { return _needs_rehashing; } 179 180 // Parallel chunked scanning 181 static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; } 182 static int parallel_claimed_index() { return _parallel_claimed_idx; } 183 }; 184 #endif // SHARE_VM_CLASSFILE_STRINGTABLE_HPP