src/share/vm/classfile/symbolTable.hpp

Tue, 17 Oct 2017 12:58:25 +0800

author
aoqi
date
Tue, 17 Oct 2017 12:58:25 +0800
changeset 7994
04ff2f6cd0eb
parent 7535
7ae4e26cb1e0
child 8856
ac27a9c85bea
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2013, 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
aoqi@0 127 // Release any dead symbols
aoqi@0 128 static void buckets_unlink(int start_idx, int end_idx, int* processed, int* removed, size_t* memory_total);
aoqi@0 129 public:
aoqi@0 130 enum {
aoqi@0 131 symbol_alloc_batch_size = 8,
aoqi@0 132 // Pick initial size based on java -version size measurements
aoqi@0 133 symbol_alloc_arena_size = 360*K
aoqi@0 134 };
aoqi@0 135
aoqi@0 136 // The symbol table
aoqi@0 137 static SymbolTable* the_table() { return _the_table; }
aoqi@0 138
aoqi@0 139 // Size of one bucket in the string table. Used when checking for rollover.
aoqi@0 140 static uint bucket_size() { return sizeof(HashtableBucket<mtSymbol>); }
aoqi@0 141
aoqi@0 142 static void create_table() {
aoqi@0 143 assert(_the_table == NULL, "One symbol table allowed.");
aoqi@0 144 _the_table = new SymbolTable();
aoqi@0 145 initialize_symbols(symbol_alloc_arena_size);
aoqi@0 146 }
aoqi@0 147
aoqi@0 148 static void create_table(HashtableBucket<mtSymbol>* t, int length,
aoqi@0 149 int number_of_entries) {
aoqi@0 150 assert(_the_table == NULL, "One symbol table allowed.");
aoqi@0 151
aoqi@0 152 // If CDS archive used a different symbol table size, use that size instead
aoqi@0 153 // which is better than giving an error.
aoqi@0 154 SymbolTableSize = length/bucket_size();
aoqi@0 155
aoqi@0 156 _the_table = new SymbolTable(t, number_of_entries);
aoqi@0 157 // if CDS give symbol table a default arena size since most symbols
aoqi@0 158 // are already allocated in the shared misc section.
aoqi@0 159 initialize_symbols();
aoqi@0 160 }
aoqi@0 161
aoqi@0 162 static unsigned int hash_symbol(const char* s, int len);
aoqi@0 163
aoqi@0 164 static Symbol* lookup(const char* name, int len, TRAPS);
aoqi@0 165 // lookup only, won't add. Also calculate hash.
aoqi@0 166 static Symbol* lookup_only(const char* name, int len, unsigned int& hash);
aoqi@0 167 // Only copy to C string to be added if lookup failed.
aoqi@0 168 static Symbol* lookup(const Symbol* sym, int begin, int end, TRAPS);
aoqi@0 169
aoqi@0 170 static void release(Symbol* sym);
aoqi@0 171
aoqi@0 172 // Look up the address of the literal in the SymbolTable for this Symbol*
aoqi@0 173 static Symbol** lookup_symbol_addr(Symbol* sym);
aoqi@0 174
aoqi@0 175 // jchar (utf16) version of lookups
aoqi@0 176 static Symbol* lookup_unicode(const jchar* name, int len, TRAPS);
aoqi@0 177 static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash);
aoqi@0 178
aoqi@0 179 static void add(ClassLoaderData* loader_data,
aoqi@0 180 constantPoolHandle cp, int names_count,
aoqi@0 181 const char** names, int* lengths, int* cp_indices,
aoqi@0 182 unsigned int* hashValues, TRAPS);
aoqi@0 183
aoqi@0 184 // Release any dead symbols
aoqi@0 185 static void unlink() {
aoqi@0 186 int processed = 0;
aoqi@0 187 int removed = 0;
aoqi@0 188 unlink(&processed, &removed);
aoqi@0 189 }
aoqi@0 190 static void unlink(int* processed, int* removed);
aoqi@0 191 // Release any dead symbols, possibly parallel version
aoqi@0 192 static void possibly_parallel_unlink(int* processed, int* removed);
aoqi@0 193
aoqi@0 194 // iterate over symbols
aoqi@0 195 static void symbols_do(SymbolClosure *cl);
aoqi@0 196
aoqi@0 197 // Symbol creation
aoqi@0 198 static Symbol* new_symbol(const char* utf8_buffer, int length, TRAPS) {
aoqi@0 199 assert(utf8_buffer != NULL, "just checking");
aoqi@0 200 return lookup(utf8_buffer, length, THREAD);
aoqi@0 201 }
aoqi@0 202 static Symbol* new_symbol(const char* name, TRAPS) {
aoqi@0 203 return new_symbol(name, (int)strlen(name), THREAD);
aoqi@0 204 }
aoqi@0 205 static Symbol* new_symbol(const Symbol* sym, int begin, int end, TRAPS) {
aoqi@0 206 assert(begin <= end && end <= sym->utf8_length(), "just checking");
aoqi@0 207 return lookup(sym, begin, end, THREAD);
aoqi@0 208 }
aoqi@0 209
aoqi@0 210 // Create a symbol in the arena for symbols that are not deleted
aoqi@0 211 static Symbol* new_permanent_symbol(const char* name, TRAPS);
aoqi@0 212
aoqi@0 213 // Symbol lookup
aoqi@0 214 static Symbol* lookup(int index, const char* name, int len, TRAPS);
aoqi@0 215
aoqi@0 216 // Needed for preloading classes in signatures when compiling.
aoqi@0 217 // Returns the symbol is already present in symbol table, otherwise
aoqi@0 218 // NULL. NO ALLOCATION IS GUARANTEED!
aoqi@0 219 static Symbol* probe(const char* name, int len) {
aoqi@0 220 unsigned int ignore_hash;
aoqi@0 221 return lookup_only(name, len, ignore_hash);
aoqi@0 222 }
aoqi@0 223 static Symbol* probe_unicode(const jchar* name, int len) {
aoqi@0 224 unsigned int ignore_hash;
aoqi@0 225 return lookup_only_unicode(name, len, ignore_hash);
aoqi@0 226 }
aoqi@0 227
aoqi@0 228 // Histogram
aoqi@0 229 static void print_histogram() PRODUCT_RETURN;
aoqi@0 230 static void print() PRODUCT_RETURN;
aoqi@0 231
aoqi@0 232 // Debugging
aoqi@0 233 static void verify();
aoqi@0 234 static void dump(outputStream* st);
aoqi@0 235
aoqi@0 236 // Sharing
aoqi@0 237 static void copy_buckets(char** top, char*end) {
aoqi@0 238 the_table()->Hashtable<Symbol*, mtSymbol>::copy_buckets(top, end);
aoqi@0 239 }
aoqi@0 240 static void copy_table(char** top, char*end) {
aoqi@0 241 the_table()->Hashtable<Symbol*, mtSymbol>::copy_table(top, end);
aoqi@0 242 }
aoqi@0 243 static void reverse(void* boundary = NULL) {
aoqi@0 244 the_table()->Hashtable<Symbol*, mtSymbol>::reverse(boundary);
aoqi@0 245 }
aoqi@0 246
aoqi@0 247 // Rehash the symbol table if it gets out of balance
aoqi@0 248 static void rehash_table();
aoqi@0 249 static bool needs_rehashing() { return _needs_rehashing; }
aoqi@0 250 // Parallel chunked scanning
aoqi@0 251 static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; }
aoqi@0 252 static int parallel_claimed_index() { return _parallel_claimed_idx; }
aoqi@0 253 };
aoqi@0 254
mgerdin@7207 255 class StringTable : public RehashableHashtable<oop, mtSymbol> {
aoqi@0 256 friend class VMStructs;
aoqi@0 257
aoqi@0 258 private:
aoqi@0 259 // The string table
aoqi@0 260 static StringTable* _the_table;
aoqi@0 261
aoqi@0 262 // Set if one bucket is out of balance due to hash algorithm deficiency
aoqi@0 263 static bool _needs_rehashing;
aoqi@0 264
aoqi@0 265 // Claimed high water mark for parallel chunked scanning
aoqi@0 266 static volatile int _parallel_claimed_idx;
aoqi@0 267
aoqi@0 268 static oop intern(Handle string_or_null, jchar* chars, int length, TRAPS);
aoqi@0 269 oop basic_add(int index, Handle string_or_null, jchar* name, int len,
aoqi@0 270 unsigned int hashValue, TRAPS);
aoqi@0 271
aoqi@0 272 oop lookup(int index, jchar* chars, int length, unsigned int hashValue);
aoqi@0 273
aoqi@0 274 // Apply the give oop closure to the entries to the buckets
aoqi@0 275 // in the range [start_idx, end_idx).
aoqi@0 276 static void buckets_oops_do(OopClosure* f, int start_idx, int end_idx);
aoqi@0 277 // Unlink or 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_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, int* processed, int* removed);
aoqi@0 280
mgerdin@7207 281 StringTable() : RehashableHashtable<oop, mtSymbol>((int)StringTableSize,
aoqi@0 282 sizeof (HashtableEntry<oop, mtSymbol>)) {}
aoqi@0 283
aoqi@0 284 StringTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
mgerdin@7207 285 : RehashableHashtable<oop, mtSymbol>((int)StringTableSize, sizeof (HashtableEntry<oop, mtSymbol>), t,
aoqi@0 286 number_of_entries) {}
aoqi@0 287 public:
aoqi@0 288 // The string table
aoqi@0 289 static StringTable* the_table() { return _the_table; }
aoqi@0 290
aoqi@0 291 // Size of one bucket in the string table. Used when checking for rollover.
aoqi@0 292 static uint bucket_size() { return sizeof(HashtableBucket<mtSymbol>); }
aoqi@0 293
aoqi@0 294 static void create_table() {
aoqi@0 295 assert(_the_table == NULL, "One string table allowed.");
aoqi@0 296 _the_table = new StringTable();
aoqi@0 297 }
aoqi@0 298
aoqi@0 299 // GC support
aoqi@0 300 // Delete pointers to otherwise-unreachable objects.
aoqi@0 301 static void unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f) {
aoqi@0 302 int processed = 0;
aoqi@0 303 int removed = 0;
aoqi@0 304 unlink_or_oops_do(cl, f, &processed, &removed);
aoqi@0 305 }
aoqi@0 306 static void unlink(BoolObjectClosure* cl) {
aoqi@0 307 int processed = 0;
aoqi@0 308 int removed = 0;
aoqi@0 309 unlink_or_oops_do(cl, NULL, &processed, &removed);
aoqi@0 310 }
aoqi@0 311 static void unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f, int* processed, int* removed);
aoqi@0 312 static void unlink(BoolObjectClosure* cl, int* processed, int* removed) {
aoqi@0 313 unlink_or_oops_do(cl, NULL, processed, removed);
aoqi@0 314 }
aoqi@0 315 // Serially invoke "f->do_oop" on the locations of all oops in the table.
aoqi@0 316 static void oops_do(OopClosure* f);
aoqi@0 317
aoqi@0 318 // Possibly parallel versions of the above
aoqi@0 319 static void possibly_parallel_unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f, int* processed, int* removed);
aoqi@0 320 static void possibly_parallel_unlink(BoolObjectClosure* cl, int* processed, int* removed) {
aoqi@0 321 possibly_parallel_unlink_or_oops_do(cl, NULL, processed, removed);
aoqi@0 322 }
aoqi@0 323 static void possibly_parallel_oops_do(OopClosure* f);
aoqi@0 324
aoqi@0 325 // Hashing algorithm, used as the hash value used by the
aoqi@0 326 // StringTable for bucket selection and comparison (stored in the
aoqi@0 327 // HashtableEntry structures). This is used in the String.intern() method.
aoqi@0 328 static unsigned int hash_string(const jchar* s, int len);
aoqi@0 329
aoqi@0 330 // Internal test.
aoqi@0 331 static void test_alt_hash() PRODUCT_RETURN;
aoqi@0 332
aoqi@0 333 // Probing
aoqi@0 334 static oop lookup(Symbol* symbol);
aoqi@0 335 static oop lookup(jchar* chars, int length);
aoqi@0 336
aoqi@0 337 // Interning
aoqi@0 338 static oop intern(Symbol* symbol, TRAPS);
aoqi@0 339 static oop intern(oop string, TRAPS);
aoqi@0 340 static oop intern(const char *utf8_string, TRAPS);
aoqi@0 341
aoqi@0 342 // Debugging
aoqi@0 343 static void verify();
aoqi@0 344 static void dump(outputStream* st);
aoqi@0 345
aoqi@0 346 enum VerifyMesgModes {
aoqi@0 347 _verify_quietly = 0,
aoqi@0 348 _verify_with_mesgs = 1
aoqi@0 349 };
aoqi@0 350
aoqi@0 351 enum VerifyRetTypes {
aoqi@0 352 _verify_pass = 0,
aoqi@0 353 _verify_fail_continue = 1,
aoqi@0 354 _verify_fail_done = 2
aoqi@0 355 };
aoqi@0 356
aoqi@0 357 static VerifyRetTypes compare_entries(int bkt1, int e_cnt1,
aoqi@0 358 HashtableEntry<oop, mtSymbol>* e_ptr1,
aoqi@0 359 int bkt2, int e_cnt2,
aoqi@0 360 HashtableEntry<oop, mtSymbol>* e_ptr2);
aoqi@0 361 static VerifyRetTypes verify_entry(int bkt, int e_cnt,
aoqi@0 362 HashtableEntry<oop, mtSymbol>* e_ptr,
aoqi@0 363 VerifyMesgModes mesg_mode);
aoqi@0 364 static int verify_and_compare_entries();
aoqi@0 365
aoqi@0 366 // Sharing
aoqi@0 367 static void copy_buckets(char** top, char*end) {
aoqi@0 368 the_table()->Hashtable<oop, mtSymbol>::copy_buckets(top, end);
aoqi@0 369 }
aoqi@0 370 static void copy_table(char** top, char*end) {
aoqi@0 371 the_table()->Hashtable<oop, mtSymbol>::copy_table(top, end);
aoqi@0 372 }
aoqi@0 373 static void reverse() {
aoqi@0 374 the_table()->Hashtable<oop, mtSymbol>::reverse();
aoqi@0 375 }
aoqi@0 376
aoqi@0 377 // Rehash the symbol table if it gets out of balance
aoqi@0 378 static void rehash_table();
aoqi@0 379 static bool needs_rehashing() { return _needs_rehashing; }
aoqi@0 380
aoqi@0 381 // Parallel chunked scanning
aoqi@0 382 static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; }
aoqi@0 383 static int parallel_claimed_index() { return _parallel_claimed_idx; }
aoqi@0 384 };
aoqi@0 385 #endif // SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP

mercurial