Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/classfile/symbolTable.hpp
32285 views
/*1* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP25#define SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP2627#include "memory/allocation.inline.hpp"28#include "oops/symbol.hpp"29#include "utilities/hashtable.hpp"3031// The symbol table holds all Symbol*s and corresponding interned strings.32// Symbol*s and literal strings should be canonicalized.33//34// The interned strings are created lazily.35//36// It is implemented as an open hash table with a fixed number of buckets.37//38// %note:39// - symbolTableEntrys are allocated in blocks to reduce the space overhead.4041class BoolObjectClosure;42class outputStream;434445// Class to hold a newly created or referenced Symbol* temporarily in scope.46// new_symbol() and lookup() will create a Symbol* if not already in the47// symbol table and add to the symbol's reference count.48// probe() and lookup_only() will increment the refcount if symbol is found.49class TempNewSymbol : public StackObj {50Symbol* _temp;5152public:53TempNewSymbol() : _temp(NULL) {}54// Creating or looking up a symbol increments the symbol's reference count55TempNewSymbol(Symbol *s) : _temp(s) {}5657// Operator= increments reference count.58void operator=(const TempNewSymbol &s) {59//clear(); //FIXME60_temp = s._temp;61if (_temp !=NULL) _temp->increment_refcount();62}6364// Decrement reference counter so it can go away if it's unique65void clear() { if (_temp != NULL) _temp->decrement_refcount(); _temp = NULL; }6667~TempNewSymbol() { clear(); }6869// Operators so they can be used like Symbols70Symbol* operator -> () const { return _temp; }71bool operator == (Symbol* o) const { return _temp == o; }72// Sneaky conversion function73operator Symbol*() { return _temp; }74};7576class SymbolTable : public RehashableHashtable<Symbol*, mtSymbol> {77friend class VMStructs;78friend class ClassFileParser;7980private:81// The symbol table82static SymbolTable* _the_table;8384// Set if one bucket is out of balance due to hash algorithm deficiency85static bool _needs_rehashing;8687// For statistics88static int _symbols_removed;89static int _symbols_counted;9091Symbol* allocate_symbol(const u1* name, int len, bool c_heap, TRAPS); // Assumes no characters larger than 0x7F9293// Adding elements94Symbol* basic_add(int index, u1* name, int len, unsigned int hashValue,95bool c_heap, TRAPS);96bool basic_add(ClassLoaderData* loader_data,97constantPoolHandle cp, int names_count,98const char** names, int* lengths, int* cp_indices,99unsigned int* hashValues, TRAPS);100101static void new_symbols(ClassLoaderData* loader_data,102constantPoolHandle cp, int names_count,103const char** name, int* lengths,104int* cp_indices, unsigned int* hashValues,105TRAPS) {106add(loader_data, cp, names_count, name, lengths, cp_indices, hashValues, THREAD);107}108109Symbol* lookup(int index, const char* name, int len, unsigned int hash);110111SymbolTable()112: RehashableHashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>)) {}113114SymbolTable(HashtableBucket<mtSymbol>* t, int number_of_entries)115: RehashableHashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>), t,116number_of_entries) {}117118// Arena for permanent symbols (null class loader) that are never unloaded119static Arena* _arena;120static Arena* arena() { return _arena; } // called for statistics121122static void initialize_symbols(int arena_alloc_size = 0);123124static volatile int _parallel_claimed_idx;125126typedef SymbolTable::BucketUnlinkContext BucketUnlinkContext;127// Release any dead symbols. Unlinked bucket entries are collected in the given128// context to be freed later.129// This allows multiple threads to work on the table at once.130static void buckets_unlink(int start_idx, int end_idx, BucketUnlinkContext* context, size_t* memory_total);131public:132enum {133symbol_alloc_batch_size = 8,134// Pick initial size based on java -version size measurements135symbol_alloc_arena_size = 360*K136};137138// The symbol table139static SymbolTable* the_table() { return _the_table; }140141// Size of one bucket in the string table. Used when checking for rollover.142static uint bucket_size() { return sizeof(HashtableBucket<mtSymbol>); }143144static void create_table() {145assert(_the_table == NULL, "One symbol table allowed.");146_the_table = new SymbolTable();147initialize_symbols(symbol_alloc_arena_size);148}149150static void create_table(HashtableBucket<mtSymbol>* t, int length,151int number_of_entries) {152assert(_the_table == NULL, "One symbol table allowed.");153154// If CDS archive used a different symbol table size, use that size instead155// which is better than giving an error.156SymbolTableSize = length/bucket_size();157158_the_table = new SymbolTable(t, number_of_entries);159// if CDS give symbol table a default arena size since most symbols160// are already allocated in the shared misc section.161initialize_symbols();162}163164static unsigned int hash_symbol(const char* s, int len);165166static Symbol* lookup(const char* name, int len, TRAPS);167// lookup only, won't add. Also calculate hash.168static Symbol* lookup_only(const char* name, int len, unsigned int& hash);169// Only copy to C string to be added if lookup failed.170static Symbol* lookup(const Symbol* sym, int begin, int end, TRAPS);171172static void release(Symbol* sym);173174// Look up the address of the literal in the SymbolTable for this Symbol*175static Symbol** lookup_symbol_addr(Symbol* sym);176177// jchar (utf16) version of lookups178static Symbol* lookup_unicode(const jchar* name, int len, TRAPS);179static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash);180181static void add(ClassLoaderData* loader_data,182constantPoolHandle cp, int names_count,183const char** names, int* lengths, int* cp_indices,184unsigned int* hashValues, TRAPS);185186// Release any dead symbols187static void unlink() {188int processed = 0;189int removed = 0;190unlink(&processed, &removed);191}192static void unlink(int* processed, int* removed);193// Release any dead symbols, possibly parallel version194static void possibly_parallel_unlink(int* processed, int* removed);195196// iterate over symbols197static void symbols_do(SymbolClosure *cl);198199// Symbol creation200static Symbol* new_symbol(const char* utf8_buffer, int length, TRAPS) {201assert(utf8_buffer != NULL, "just checking");202return lookup(utf8_buffer, length, THREAD);203}204static Symbol* new_symbol(const char* name, TRAPS) {205return new_symbol(name, (int)strlen(name), THREAD);206}207static Symbol* new_symbol(const Symbol* sym, int begin, int end, TRAPS) {208assert(begin <= end && end <= sym->utf8_length(), "just checking");209return lookup(sym, begin, end, THREAD);210}211212// Create a symbol in the arena for symbols that are not deleted213static Symbol* new_permanent_symbol(const char* name, TRAPS);214215// Symbol lookup216static Symbol* lookup(int index, const char* name, int len, TRAPS);217218// Needed for preloading classes in signatures when compiling.219// Returns the symbol is already present in symbol table, otherwise220// NULL. NO ALLOCATION IS GUARANTEED!221static Symbol* probe(const char* name, int len) {222unsigned int ignore_hash;223return lookup_only(name, len, ignore_hash);224}225static Symbol* probe_unicode(const jchar* name, int len) {226unsigned int ignore_hash;227return lookup_only_unicode(name, len, ignore_hash);228}229230// Histogram231static void print_histogram() PRODUCT_RETURN;232static void print() PRODUCT_RETURN;233234// Debugging235static void verify();236static void dump(outputStream* st);237238// Sharing239static void copy_buckets(char** top, char*end) {240the_table()->Hashtable<Symbol*, mtSymbol>::copy_buckets(top, end);241}242static void copy_table(char** top, char*end) {243the_table()->Hashtable<Symbol*, mtSymbol>::copy_table(top, end);244}245static void reverse(void* boundary = NULL) {246the_table()->Hashtable<Symbol*, mtSymbol>::reverse(boundary);247}248249// Rehash the symbol table if it gets out of balance250static void rehash_table();251static bool needs_rehashing() { return _needs_rehashing; }252// Parallel chunked scanning253static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; }254static int parallel_claimed_index() { return _parallel_claimed_idx; }255};256257class StringTable : public RehashableHashtable<oop, mtSymbol> {258friend class VMStructs;259260private:261// The string table262static StringTable* _the_table;263264// Set if one bucket is out of balance due to hash algorithm deficiency265static bool _needs_rehashing;266267// Claimed high water mark for parallel chunked scanning268static volatile int _parallel_claimed_idx;269270static oop intern(Handle string_or_null, jchar* chars, int length, TRAPS);271oop basic_add(int index, Handle string_or_null, jchar* name, int len,272unsigned int hashValue, TRAPS);273274oop lookup(int index, jchar* chars, int length, unsigned int hashValue);275276// Apply the give oop closure to the entries to the buckets277// in the range [start_idx, end_idx).278static void buckets_oops_do(OopClosure* f, int start_idx, int end_idx);279280typedef StringTable::BucketUnlinkContext BucketUnlinkContext;281// Unlink or apply the give oop closure to the entries to the buckets282// in the range [start_idx, end_idx). Unlinked bucket entries are collected in the given283// context to be freed later.284// This allows multiple threads to work on the table at once.285static void buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, BucketUnlinkContext* context);286287StringTable() : RehashableHashtable<oop, mtSymbol>((int)StringTableSize,288sizeof (HashtableEntry<oop, mtSymbol>)) {}289290StringTable(HashtableBucket<mtSymbol>* t, int number_of_entries)291: RehashableHashtable<oop, mtSymbol>((int)StringTableSize, sizeof (HashtableEntry<oop, mtSymbol>), t,292number_of_entries) {}293public:294// The string table295static StringTable* the_table() { return _the_table; }296297// Size of one bucket in the string table. Used when checking for rollover.298static uint bucket_size() { return sizeof(HashtableBucket<mtSymbol>); }299300static void create_table() {301assert(_the_table == NULL, "One string table allowed.");302_the_table = new StringTable();303}304305// GC support306// Delete pointers to otherwise-unreachable objects.307static void unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f) {308int processed = 0;309int removed = 0;310unlink_or_oops_do(cl, f, &processed, &removed);311}312static void unlink(BoolObjectClosure* cl) {313int processed = 0;314int removed = 0;315unlink_or_oops_do(cl, NULL, &processed, &removed);316}317static void unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f, int* processed, int* removed);318static void unlink(BoolObjectClosure* cl, int* processed, int* removed) {319unlink_or_oops_do(cl, NULL, processed, removed);320}321// Serially invoke "f->do_oop" on the locations of all oops in the table.322static void oops_do(OopClosure* f);323324// Possibly parallel versions of the above325static void possibly_parallel_unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f, int* processed, int* removed);326static void possibly_parallel_unlink(BoolObjectClosure* cl, int* processed, int* removed) {327possibly_parallel_unlink_or_oops_do(cl, NULL, processed, removed);328}329static void possibly_parallel_oops_do(OopClosure* f);330static void possibly_parallel_oops_do_shenandoah(OopClosure* f);331332// Hashing algorithm, used as the hash value used by the333// StringTable for bucket selection and comparison (stored in the334// HashtableEntry structures). This is used in the String.intern() method.335static unsigned int hash_string(const jchar* s, int len);336337// Internal test.338static void test_alt_hash() PRODUCT_RETURN;339340// Probing341static oop lookup(Symbol* symbol);342static oop lookup(jchar* chars, int length);343344// Interning345static oop intern(Symbol* symbol, TRAPS);346static oop intern(oop string, TRAPS);347static oop intern(const char *utf8_string, TRAPS);348349// Debugging350static void verify();351static void dump(outputStream* st);352353enum VerifyMesgModes {354_verify_quietly = 0,355_verify_with_mesgs = 1356};357358enum VerifyRetTypes {359_verify_pass = 0,360_verify_fail_continue = 1,361_verify_fail_done = 2362};363364static VerifyRetTypes compare_entries(int bkt1, int e_cnt1,365HashtableEntry<oop, mtSymbol>* e_ptr1,366int bkt2, int e_cnt2,367HashtableEntry<oop, mtSymbol>* e_ptr2);368static VerifyRetTypes verify_entry(int bkt, int e_cnt,369HashtableEntry<oop, mtSymbol>* e_ptr,370VerifyMesgModes mesg_mode);371static int verify_and_compare_entries();372373// Sharing374static void copy_buckets(char** top, char*end) {375the_table()->Hashtable<oop, mtSymbol>::copy_buckets(top, end);376}377static void copy_table(char** top, char*end) {378the_table()->Hashtable<oop, mtSymbol>::copy_table(top, end);379}380static void reverse() {381the_table()->Hashtable<oop, mtSymbol>::reverse();382}383384// Rehash the symbol table if it gets out of balance385static void rehash_table();386static bool needs_rehashing() { return _needs_rehashing; }387388// Parallel chunked scanning389static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; }390static int parallel_claimed_index() { return _parallel_claimed_idx; }391};392#endif // SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP393394395