src/share/vm/classfile/symbolTable.hpp

Sat, 24 Oct 2020 16:43:47 +0800

author
aoqi
date
Sat, 24 Oct 2020 16:43:47 +0800
changeset 10015
eb7ce841ccec
parent 8856
ac27a9c85bea
permissions
-rw-r--r--

Merge

aoqi@0 1 /*
tschatzl@8766 2 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 *
aoqi@0 23 */
aoqi@0 24
aoqi@0 25 #ifndef SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
aoqi@0 26 #define SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
aoqi@0 27
aoqi@0 28 #include "memory/allocation.inline.hpp"
aoqi@0 29 #include "oops/symbol.hpp"
aoqi@0 30 #include "utilities/hashtable.hpp"
aoqi@0 31
aoqi@0 32 // The symbol table holds all Symbol*s and corresponding interned strings.
aoqi@0 33 // Symbol*s and literal strings should be canonicalized.
aoqi@0 34 //
aoqi@0 35 // The interned strings are created lazily.
aoqi@0 36 //
aoqi@0 37 // It is implemented as an open hash table with a fixed number of buckets.
aoqi@0 38 //
aoqi@0 39 // %note:
aoqi@0 40 // - symbolTableEntrys are allocated in blocks to reduce the space overhead.
aoqi@0 41
aoqi@0 42 class BoolObjectClosure;
aoqi@0 43 class outputStream;
aoqi@0 44
aoqi@0 45
aoqi@0 46 // Class to hold a newly created or referenced Symbol* temporarily in scope.
aoqi@0 47 // new_symbol() and lookup() will create a Symbol* if not already in the
aoqi@0 48 // symbol table and add to the symbol's reference count.
aoqi@0 49 // probe() and lookup_only() will increment the refcount if symbol is found.
aoqi@0 50 class TempNewSymbol : public StackObj {
aoqi@0 51 Symbol* _temp;
aoqi@0 52
aoqi@0 53 public:
aoqi@0 54 TempNewSymbol() : _temp(NULL) {}
aoqi@0 55 // Creating or looking up a symbol increments the symbol's reference count
aoqi@0 56 TempNewSymbol(Symbol *s) : _temp(s) {}
aoqi@0 57
aoqi@0 58 // Operator= increments reference count.
aoqi@0 59 void operator=(const TempNewSymbol &s) {
aoqi@0 60 //clear(); //FIXME
aoqi@0 61 _temp = s._temp;
aoqi@0 62 if (_temp !=NULL) _temp->increment_refcount();
aoqi@0 63 }
aoqi@0 64
aoqi@0 65 // Decrement reference counter so it can go away if it's unique
aoqi@0 66 void clear() { if (_temp != NULL) _temp->decrement_refcount(); _temp = NULL; }
aoqi@0 67
aoqi@0 68 ~TempNewSymbol() { clear(); }
aoqi@0 69
aoqi@0 70 // Operators so they can be used like Symbols
aoqi@0 71 Symbol* operator -> () const { return _temp; }
aoqi@0 72 bool operator == (Symbol* o) const { return _temp == o; }
aoqi@0 73 // Sneaky conversion function
aoqi@0 74 operator Symbol*() { return _temp; }
aoqi@0 75 };
aoqi@0 76
mgerdin@7207 77 class SymbolTable : public RehashableHashtable<Symbol*, mtSymbol> {
aoqi@0 78 friend class VMStructs;
aoqi@0 79 friend class ClassFileParser;
aoqi@0 80
aoqi@0 81 private:
aoqi@0 82 // The symbol table
aoqi@0 83 static SymbolTable* _the_table;
aoqi@0 84
aoqi@0 85 // Set if one bucket is out of balance due to hash algorithm deficiency
aoqi@0 86 static bool _needs_rehashing;
aoqi@0 87
aoqi@0 88 // For statistics
aoqi@0 89 static int _symbols_removed;
aoqi@0 90 static int _symbols_counted;
aoqi@0 91
aoqi@0 92 Symbol* allocate_symbol(const u1* name, int len, bool c_heap, TRAPS); // Assumes no characters larger than 0x7F
aoqi@0 93
aoqi@0 94 // Adding elements
aoqi@0 95 Symbol* basic_add(int index, u1* name, int len, unsigned int hashValue,
aoqi@0 96 bool c_heap, TRAPS);
aoqi@0 97 bool basic_add(ClassLoaderData* loader_data,
aoqi@0 98 constantPoolHandle cp, int names_count,
aoqi@0 99 const char** names, int* lengths, int* cp_indices,
aoqi@0 100 unsigned int* hashValues, TRAPS);
aoqi@0 101
aoqi@0 102 static void new_symbols(ClassLoaderData* loader_data,
aoqi@0 103 constantPoolHandle cp, int names_count,
aoqi@0 104 const char** name, int* lengths,
aoqi@0 105 int* cp_indices, unsigned int* hashValues,
aoqi@0 106 TRAPS) {
aoqi@0 107 add(loader_data, cp, names_count, name, lengths, cp_indices, hashValues, THREAD);
aoqi@0 108 }
aoqi@0 109
aoqi@0 110 Symbol* lookup(int index, const char* name, int len, unsigned int hash);
aoqi@0 111
aoqi@0 112 SymbolTable()
mgerdin@7207 113 : RehashableHashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>)) {}
aoqi@0 114
aoqi@0 115 SymbolTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
mgerdin@7207 116 : RehashableHashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>), t,
aoqi@0 117 number_of_entries) {}
aoqi@0 118
aoqi@0 119 // Arena for permanent symbols (null class loader) that are never unloaded
aoqi@0 120 static Arena* _arena;
aoqi@0 121 static Arena* arena() { return _arena; } // called for statistics
aoqi@0 122
aoqi@0 123 static void initialize_symbols(int arena_alloc_size = 0);
aoqi@0 124
aoqi@0 125 static volatile int _parallel_claimed_idx;
aoqi@0 126
tschatzl@8766 127 typedef SymbolTable::BucketUnlinkContext BucketUnlinkContext;
tschatzl@8766 128 // Release any dead symbols. Unlinked bucket entries are collected in the given
tschatzl@8766 129 // context to be freed later.
tschatzl@8766 130 // This allows multiple threads to work on the table at once.
tschatzl@8766 131 static void buckets_unlink(int start_idx, int end_idx, BucketUnlinkContext* context, size_t* memory_total);
aoqi@0 132 public:
aoqi@0 133 enum {
aoqi@0 134 symbol_alloc_batch_size = 8,
aoqi@0 135 // Pick initial size based on java -version size measurements
aoqi@0 136 symbol_alloc_arena_size = 360*K
aoqi@0 137 };
aoqi@0 138
aoqi@0 139 // The symbol table
aoqi@0 140 static SymbolTable* the_table() { return _the_table; }
aoqi@0 141
aoqi@0 142 // Size of one bucket in the string table. Used when checking for rollover.
aoqi@0 143 static uint bucket_size() { return sizeof(HashtableBucket<mtSymbol>); }
aoqi@0 144
aoqi@0 145 static void create_table() {
aoqi@0 146 assert(_the_table == NULL, "One symbol table allowed.");
aoqi@0 147 _the_table = new SymbolTable();
aoqi@0 148 initialize_symbols(symbol_alloc_arena_size);
aoqi@0 149 }
aoqi@0 150
aoqi@0 151 static void create_table(HashtableBucket<mtSymbol>* t, int length,
aoqi@0 152 int number_of_entries) {
aoqi@0 153 assert(_the_table == NULL, "One symbol table allowed.");
aoqi@0 154
aoqi@0 155 // If CDS archive used a different symbol table size, use that size instead
aoqi@0 156 // which is better than giving an error.
aoqi@0 157 SymbolTableSize = length/bucket_size();
aoqi@0 158
aoqi@0 159 _the_table = new SymbolTable(t, number_of_entries);
aoqi@0 160 // if CDS give symbol table a default arena size since most symbols
aoqi@0 161 // are already allocated in the shared misc section.
aoqi@0 162 initialize_symbols();
aoqi@0 163 }
aoqi@0 164
aoqi@0 165 static unsigned int hash_symbol(const char* s, int len);
aoqi@0 166
aoqi@0 167 static Symbol* lookup(const char* name, int len, TRAPS);
aoqi@0 168 // lookup only, won't add. Also calculate hash.
aoqi@0 169 static Symbol* lookup_only(const char* name, int len, unsigned int& hash);
aoqi@0 170 // Only copy to C string to be added if lookup failed.
aoqi@0 171 static Symbol* lookup(const Symbol* sym, int begin, int end, TRAPS);
aoqi@0 172
aoqi@0 173 static void release(Symbol* sym);
aoqi@0 174
aoqi@0 175 // Look up the address of the literal in the SymbolTable for this Symbol*
aoqi@0 176 static Symbol** lookup_symbol_addr(Symbol* sym);
aoqi@0 177
aoqi@0 178 // jchar (utf16) version of lookups
aoqi@0 179 static Symbol* lookup_unicode(const jchar* name, int len, TRAPS);
aoqi@0 180 static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash);
aoqi@0 181
aoqi@0 182 static void add(ClassLoaderData* loader_data,
aoqi@0 183 constantPoolHandle cp, int names_count,
aoqi@0 184 const char** names, int* lengths, int* cp_indices,
aoqi@0 185 unsigned int* hashValues, TRAPS);
aoqi@0 186
aoqi@0 187 // Release any dead symbols
aoqi@0 188 static void unlink() {
aoqi@0 189 int processed = 0;
aoqi@0 190 int removed = 0;
aoqi@0 191 unlink(&processed, &removed);
aoqi@0 192 }
aoqi@0 193 static void unlink(int* processed, int* removed);
aoqi@0 194 // Release any dead symbols, possibly parallel version
aoqi@0 195 static void possibly_parallel_unlink(int* processed, int* removed);
aoqi@0 196
aoqi@0 197 // iterate over symbols
aoqi@0 198 static void symbols_do(SymbolClosure *cl);
aoqi@0 199
aoqi@0 200 // Symbol creation
aoqi@0 201 static Symbol* new_symbol(const char* utf8_buffer, int length, TRAPS) {
aoqi@0 202 assert(utf8_buffer != NULL, "just checking");
aoqi@0 203 return lookup(utf8_buffer, length, THREAD);
aoqi@0 204 }
aoqi@0 205 static Symbol* new_symbol(const char* name, TRAPS) {
aoqi@0 206 return new_symbol(name, (int)strlen(name), THREAD);
aoqi@0 207 }
aoqi@0 208 static Symbol* new_symbol(const Symbol* sym, int begin, int end, TRAPS) {
aoqi@0 209 assert(begin <= end && end <= sym->utf8_length(), "just checking");
aoqi@0 210 return lookup(sym, begin, end, THREAD);
aoqi@0 211 }
aoqi@0 212
aoqi@0 213 // Create a symbol in the arena for symbols that are not deleted
aoqi@0 214 static Symbol* new_permanent_symbol(const char* name, TRAPS);
aoqi@0 215
aoqi@0 216 // Symbol lookup
aoqi@0 217 static Symbol* lookup(int index, const char* name, int len, TRAPS);
aoqi@0 218
aoqi@0 219 // Needed for preloading classes in signatures when compiling.
aoqi@0 220 // Returns the symbol is already present in symbol table, otherwise
aoqi@0 221 // NULL. NO ALLOCATION IS GUARANTEED!
aoqi@0 222 static Symbol* probe(const char* name, int len) {
aoqi@0 223 unsigned int ignore_hash;
aoqi@0 224 return lookup_only(name, len, ignore_hash);
aoqi@0 225 }
aoqi@0 226 static Symbol* probe_unicode(const jchar* name, int len) {
aoqi@0 227 unsigned int ignore_hash;
aoqi@0 228 return lookup_only_unicode(name, len, ignore_hash);
aoqi@0 229 }
aoqi@0 230
aoqi@0 231 // Histogram
aoqi@0 232 static void print_histogram() PRODUCT_RETURN;
aoqi@0 233 static void print() PRODUCT_RETURN;
aoqi@0 234
aoqi@0 235 // Debugging
aoqi@0 236 static void verify();
aoqi@0 237 static void dump(outputStream* st);
aoqi@0 238
aoqi@0 239 // Sharing
aoqi@0 240 static void copy_buckets(char** top, char*end) {
aoqi@0 241 the_table()->Hashtable<Symbol*, mtSymbol>::copy_buckets(top, end);
aoqi@0 242 }
aoqi@0 243 static void copy_table(char** top, char*end) {
aoqi@0 244 the_table()->Hashtable<Symbol*, mtSymbol>::copy_table(top, end);
aoqi@0 245 }
aoqi@0 246 static void reverse(void* boundary = NULL) {
aoqi@0 247 the_table()->Hashtable<Symbol*, mtSymbol>::reverse(boundary);
aoqi@0 248 }
aoqi@0 249
aoqi@0 250 // Rehash the symbol table if it gets out of balance
aoqi@0 251 static void rehash_table();
aoqi@0 252 static bool needs_rehashing() { return _needs_rehashing; }
aoqi@0 253 // Parallel chunked scanning
aoqi@0 254 static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; }
aoqi@0 255 static int parallel_claimed_index() { return _parallel_claimed_idx; }
aoqi@0 256 };
aoqi@0 257
mgerdin@7207 258 class StringTable : public RehashableHashtable<oop, mtSymbol> {
aoqi@0 259 friend class VMStructs;
aoqi@0 260
aoqi@0 261 private:
aoqi@0 262 // The string table
aoqi@0 263 static StringTable* _the_table;
aoqi@0 264
aoqi@0 265 // Set if one bucket is out of balance due to hash algorithm deficiency
aoqi@0 266 static bool _needs_rehashing;
aoqi@0 267
aoqi@0 268 // Claimed high water mark for parallel chunked scanning
aoqi@0 269 static volatile int _parallel_claimed_idx;
aoqi@0 270
aoqi@0 271 static oop intern(Handle string_or_null, jchar* chars, int length, TRAPS);
aoqi@0 272 oop basic_add(int index, Handle string_or_null, jchar* name, int len,
aoqi@0 273 unsigned int hashValue, TRAPS);
aoqi@0 274
aoqi@0 275 oop lookup(int index, jchar* chars, int length, unsigned int hashValue);
aoqi@0 276
aoqi@0 277 // Apply the give oop closure to the entries to the buckets
aoqi@0 278 // in the range [start_idx, end_idx).
aoqi@0 279 static void buckets_oops_do(OopClosure* f, int start_idx, int end_idx);
tschatzl@8766 280
tschatzl@8766 281 typedef StringTable::BucketUnlinkContext BucketUnlinkContext;
aoqi@0 282 // Unlink or apply the give oop closure to the entries to the buckets
tschatzl@8766 283 // in the range [start_idx, end_idx). Unlinked bucket entries are collected in the given
tschatzl@8766 284 // context to be freed later.
tschatzl@8766 285 // This allows multiple threads to work on the table at once.
tschatzl@8766 286 static void buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, BucketUnlinkContext* context);
aoqi@0 287
mgerdin@7207 288 StringTable() : RehashableHashtable<oop, mtSymbol>((int)StringTableSize,
aoqi@0 289 sizeof (HashtableEntry<oop, mtSymbol>)) {}
aoqi@0 290
aoqi@0 291 StringTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
mgerdin@7207 292 : RehashableHashtable<oop, mtSymbol>((int)StringTableSize, sizeof (HashtableEntry<oop, mtSymbol>), t,
aoqi@0 293 number_of_entries) {}
aoqi@0 294 public:
aoqi@0 295 // The string table
aoqi@0 296 static StringTable* the_table() { return _the_table; }
aoqi@0 297
aoqi@0 298 // Size of one bucket in the string table. Used when checking for rollover.
aoqi@0 299 static uint bucket_size() { return sizeof(HashtableBucket<mtSymbol>); }
aoqi@0 300
aoqi@0 301 static void create_table() {
aoqi@0 302 assert(_the_table == NULL, "One string table allowed.");
aoqi@0 303 _the_table = new StringTable();
aoqi@0 304 }
aoqi@0 305
aoqi@0 306 // GC support
aoqi@0 307 // Delete pointers to otherwise-unreachable objects.
aoqi@0 308 static void unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f) {
aoqi@0 309 int processed = 0;
aoqi@0 310 int removed = 0;
aoqi@0 311 unlink_or_oops_do(cl, f, &processed, &removed);
aoqi@0 312 }
aoqi@0 313 static void unlink(BoolObjectClosure* cl) {
aoqi@0 314 int processed = 0;
aoqi@0 315 int removed = 0;
aoqi@0 316 unlink_or_oops_do(cl, NULL, &processed, &removed);
aoqi@0 317 }
aoqi@0 318 static void unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f, int* processed, int* removed);
aoqi@0 319 static void unlink(BoolObjectClosure* cl, int* processed, int* removed) {
aoqi@0 320 unlink_or_oops_do(cl, NULL, processed, removed);
aoqi@0 321 }
aoqi@0 322 // Serially invoke "f->do_oop" on the locations of all oops in the table.
aoqi@0 323 static void oops_do(OopClosure* f);
aoqi@0 324
aoqi@0 325 // Possibly parallel versions of the above
aoqi@0 326 static void possibly_parallel_unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f, int* processed, int* removed);
aoqi@0 327 static void possibly_parallel_unlink(BoolObjectClosure* cl, int* processed, int* removed) {
aoqi@0 328 possibly_parallel_unlink_or_oops_do(cl, NULL, processed, removed);
aoqi@0 329 }
aoqi@0 330 static void possibly_parallel_oops_do(OopClosure* f);
aoqi@0 331
aoqi@0 332 // Hashing algorithm, used as the hash value used by the
aoqi@0 333 // StringTable for bucket selection and comparison (stored in the
aoqi@0 334 // HashtableEntry structures). This is used in the String.intern() method.
aoqi@0 335 static unsigned int hash_string(const jchar* s, int len);
aoqi@0 336
aoqi@0 337 // Internal test.
aoqi@0 338 static void test_alt_hash() PRODUCT_RETURN;
aoqi@0 339
aoqi@0 340 // Probing
aoqi@0 341 static oop lookup(Symbol* symbol);
aoqi@0 342 static oop lookup(jchar* chars, int length);
aoqi@0 343
aoqi@0 344 // Interning
aoqi@0 345 static oop intern(Symbol* symbol, TRAPS);
aoqi@0 346 static oop intern(oop string, TRAPS);
aoqi@0 347 static oop intern(const char *utf8_string, TRAPS);
aoqi@0 348
aoqi@0 349 // Debugging
aoqi@0 350 static void verify();
aoqi@0 351 static void dump(outputStream* st);
aoqi@0 352
aoqi@0 353 enum VerifyMesgModes {
aoqi@0 354 _verify_quietly = 0,
aoqi@0 355 _verify_with_mesgs = 1
aoqi@0 356 };
aoqi@0 357
aoqi@0 358 enum VerifyRetTypes {
aoqi@0 359 _verify_pass = 0,
aoqi@0 360 _verify_fail_continue = 1,
aoqi@0 361 _verify_fail_done = 2
aoqi@0 362 };
aoqi@0 363
aoqi@0 364 static VerifyRetTypes compare_entries(int bkt1, int e_cnt1,
aoqi@0 365 HashtableEntry<oop, mtSymbol>* e_ptr1,
aoqi@0 366 int bkt2, int e_cnt2,
aoqi@0 367 HashtableEntry<oop, mtSymbol>* e_ptr2);
aoqi@0 368 static VerifyRetTypes verify_entry(int bkt, int e_cnt,
aoqi@0 369 HashtableEntry<oop, mtSymbol>* e_ptr,
aoqi@0 370 VerifyMesgModes mesg_mode);
aoqi@0 371 static int verify_and_compare_entries();
aoqi@0 372
aoqi@0 373 // Sharing
aoqi@0 374 static void copy_buckets(char** top, char*end) {
aoqi@0 375 the_table()->Hashtable<oop, mtSymbol>::copy_buckets(top, end);
aoqi@0 376 }
aoqi@0 377 static void copy_table(char** top, char*end) {
aoqi@0 378 the_table()->Hashtable<oop, mtSymbol>::copy_table(top, end);
aoqi@0 379 }
aoqi@0 380 static void reverse() {
aoqi@0 381 the_table()->Hashtable<oop, mtSymbol>::reverse();
aoqi@0 382 }
aoqi@0 383
aoqi@0 384 // Rehash the symbol table if it gets out of balance
aoqi@0 385 static void rehash_table();
aoqi@0 386 static bool needs_rehashing() { return _needs_rehashing; }
aoqi@0 387
aoqi@0 388 // Parallel chunked scanning
aoqi@0 389 static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; }
aoqi@0 390 static int parallel_claimed_index() { return _parallel_claimed_idx; }
aoqi@0 391 };
aoqi@0 392 #endif // SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP

mercurial