| 1 | /* | 
|---|
| 2 | * Copyright (c) 1997, 2019, 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_CLASSFILE_SYMBOLTABLE_HPP | 
|---|
| 26 | #define SHARE_CLASSFILE_SYMBOLTABLE_HPP | 
|---|
| 27 |  | 
|---|
| 28 | #include "memory/allocation.hpp" | 
|---|
| 29 | #include "memory/padded.hpp" | 
|---|
| 30 | #include "oops/symbol.hpp" | 
|---|
| 31 | #include "utilities/tableStatistics.hpp" | 
|---|
| 32 |  | 
|---|
| 33 | class JavaThread; | 
|---|
| 34 |  | 
|---|
| 35 | // TempNewSymbol acts as a handle class in a handle/body idiom and is | 
|---|
| 36 | // responsible for proper resource management of the body (which is a Symbol*). | 
|---|
| 37 | // The body is resource managed by a reference counting scheme. | 
|---|
| 38 | // TempNewSymbol can therefore be used to properly hold a newly created or referenced | 
|---|
| 39 | // Symbol* temporarily in scope. | 
|---|
| 40 | // | 
|---|
| 41 | // Routines in SymbolTable will initialize the reference count of a Symbol* before | 
|---|
| 42 | // it becomes "managed" by TempNewSymbol instances. As a handle class, TempNewSymbol | 
|---|
| 43 | // needs to maintain proper reference counting in context of copy semantics. | 
|---|
| 44 | // | 
|---|
| 45 | // In SymbolTable, new_symbol() will create a Symbol* if not already in the | 
|---|
| 46 | // symbol table and add to the symbol's reference count. | 
|---|
| 47 | // probe() and lookup_only() will increment the refcount if symbol is found. | 
|---|
| 48 | class TempNewSymbol : public StackObj { | 
|---|
| 49 | Symbol* _temp; | 
|---|
| 50 |  | 
|---|
| 51 | public: | 
|---|
| 52 | TempNewSymbol() : _temp(NULL) {} | 
|---|
| 53 |  | 
|---|
| 54 | // Conversion from a Symbol* to a TempNewSymbol. | 
|---|
| 55 | // Does not increment the current reference count. | 
|---|
| 56 | TempNewSymbol(Symbol *s) : _temp(s) {} | 
|---|
| 57 |  | 
|---|
| 58 | // Copy constructor increments reference count. | 
|---|
| 59 | TempNewSymbol(const TempNewSymbol& rhs) : _temp(rhs._temp) { | 
|---|
| 60 | if (_temp != NULL) { | 
|---|
| 61 | _temp->increment_refcount(); | 
|---|
| 62 | } | 
|---|
| 63 | } | 
|---|
| 64 |  | 
|---|
| 65 | // Assignment operator uses a c++ trick called copy and swap idiom. | 
|---|
| 66 | // rhs is passed by value so within the scope of this method it is a copy. | 
|---|
| 67 | // At method exit it contains the former value of _temp, triggering the correct refcount | 
|---|
| 68 | // decrement upon destruction. | 
|---|
| 69 | void operator=(TempNewSymbol rhs) { | 
|---|
| 70 | Symbol* tmp = rhs._temp; | 
|---|
| 71 | rhs._temp = _temp; | 
|---|
| 72 | _temp = tmp; | 
|---|
| 73 | } | 
|---|
| 74 |  | 
|---|
| 75 | // Decrement reference counter so it can go away if it's unused | 
|---|
| 76 | ~TempNewSymbol() { | 
|---|
| 77 | if (_temp != NULL) { | 
|---|
| 78 | _temp->decrement_refcount(); | 
|---|
| 79 | } | 
|---|
| 80 | } | 
|---|
| 81 |  | 
|---|
| 82 | // Symbol* conversion operators | 
|---|
| 83 | Symbol* operator -> () const                   { return _temp; } | 
|---|
| 84 | bool    operator == (Symbol* o) const          { return _temp == o; } | 
|---|
| 85 | operator Symbol*()                             { return _temp; } | 
|---|
| 86 | }; | 
|---|
| 87 |  | 
|---|
| 88 | class CompactHashtableWriter; | 
|---|
| 89 | class SerializeClosure; | 
|---|
| 90 |  | 
|---|
| 91 | class SymbolTableConfig; | 
|---|
| 92 | class SymbolTableCreateEntry; | 
|---|
| 93 |  | 
|---|
| 94 | class constantPoolHandle; | 
|---|
| 95 | class SymbolClosure; | 
|---|
| 96 |  | 
|---|
| 97 | class SymbolTable : public AllStatic { | 
|---|
| 98 | friend class VMStructs; | 
|---|
| 99 | friend class Symbol; | 
|---|
| 100 | friend class ClassFileParser; | 
|---|
| 101 | friend class SymbolTableConfig; | 
|---|
| 102 | friend class SymbolTableCreateEntry; | 
|---|
| 103 |  | 
|---|
| 104 | private: | 
|---|
| 105 | static volatile bool _has_work; | 
|---|
| 106 |  | 
|---|
| 107 | // Set if one bucket is out of balance due to hash algorithm deficiency | 
|---|
| 108 | static volatile bool _needs_rehashing; | 
|---|
| 109 |  | 
|---|
| 110 | static void delete_symbol(Symbol* sym); | 
|---|
| 111 | static void grow(JavaThread* jt); | 
|---|
| 112 | static void clean_dead_entries(JavaThread* jt); | 
|---|
| 113 |  | 
|---|
| 114 | static double get_load_factor(); | 
|---|
| 115 |  | 
|---|
| 116 | static void check_concurrent_work(); | 
|---|
| 117 |  | 
|---|
| 118 | static void item_added(); | 
|---|
| 119 | static void item_removed(); | 
|---|
| 120 |  | 
|---|
| 121 | // For cleaning | 
|---|
| 122 | static void reset_has_items_to_clean(); | 
|---|
| 123 | static void mark_has_items_to_clean(); | 
|---|
| 124 | static bool has_items_to_clean(); | 
|---|
| 125 |  | 
|---|
| 126 | static Symbol* allocate_symbol(const char* name, int len, bool c_heap); // Assumes no characters larger than 0x7F | 
|---|
| 127 | static Symbol* do_lookup(const char* name, int len, uintx hash); | 
|---|
| 128 | static Symbol* do_add_if_needed(const char* name, int len, uintx hash, bool heap); | 
|---|
| 129 |  | 
|---|
| 130 | // lookup only, won't add. Also calculate hash. Used by the ClassfileParser. | 
|---|
| 131 | static Symbol* lookup_only(const char* name, int len, unsigned int& hash); | 
|---|
| 132 | static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash); | 
|---|
| 133 |  | 
|---|
| 134 | // Adding elements | 
|---|
| 135 | static void new_symbols(ClassLoaderData* loader_data, | 
|---|
| 136 | const constantPoolHandle& cp, int names_count, | 
|---|
| 137 | const char** name, int* lengths, | 
|---|
| 138 | int* cp_indices, unsigned int* hashValues); | 
|---|
| 139 |  | 
|---|
| 140 | static Symbol* lookup_shared(const char* name, int len, unsigned int hash) NOT_CDS_RETURN_(NULL); | 
|---|
| 141 | static Symbol* lookup_dynamic(const char* name, int len, unsigned int hash); | 
|---|
| 142 | static Symbol* lookup_common(const char* name, int len, unsigned int hash); | 
|---|
| 143 |  | 
|---|
| 144 | // Arena for permanent symbols (null class loader) that are never unloaded | 
|---|
| 145 | static Arena*  _arena; | 
|---|
| 146 | static Arena* arena() { return _arena; }  // called for statistics | 
|---|
| 147 |  | 
|---|
| 148 | static void print_table_statistics(outputStream* st, const char* table_name); | 
|---|
| 149 |  | 
|---|
| 150 | static void try_rehash_table(); | 
|---|
| 151 | static bool do_rehash(); | 
|---|
| 152 |  | 
|---|
| 153 | public: | 
|---|
| 154 | // The symbol table | 
|---|
| 155 | static size_t table_size(); | 
|---|
| 156 | static TableStatistics get_table_statistics(); | 
|---|
| 157 |  | 
|---|
| 158 | enum { | 
|---|
| 159 | symbol_alloc_batch_size = 8, | 
|---|
| 160 | // Pick initial size based on java -version size measurements | 
|---|
| 161 | symbol_alloc_arena_size = 360*K // TODO (revisit) | 
|---|
| 162 | }; | 
|---|
| 163 |  | 
|---|
| 164 | static void create_table(); | 
|---|
| 165 |  | 
|---|
| 166 | static void do_concurrent_work(JavaThread* jt); | 
|---|
| 167 | static bool has_work() { return _has_work; } | 
|---|
| 168 | static void trigger_cleanup(); | 
|---|
| 169 |  | 
|---|
| 170 | // Probing | 
|---|
| 171 | // Needed for preloading classes in signatures when compiling. | 
|---|
| 172 | // Returns the symbol is already present in symbol table, otherwise | 
|---|
| 173 | // NULL.  NO ALLOCATION IS GUARANTEED! | 
|---|
| 174 | static Symbol* probe(const char* name, int len) { | 
|---|
| 175 | unsigned int ignore_hash; | 
|---|
| 176 | return lookup_only(name, len, ignore_hash); | 
|---|
| 177 | } | 
|---|
| 178 | static Symbol* probe_unicode(const jchar* name, int len) { | 
|---|
| 179 | unsigned int ignore_hash; | 
|---|
| 180 | return lookup_only_unicode(name, len, ignore_hash); | 
|---|
| 181 | } | 
|---|
| 182 |  | 
|---|
| 183 | // Symbol lookup and create if not found. | 
|---|
| 184 | // jchar (UTF16) version of lookup | 
|---|
| 185 | static Symbol* new_symbol(const jchar* name, int len); | 
|---|
| 186 | // char (UTF8) versions | 
|---|
| 187 | static Symbol* new_symbol(const Symbol* sym, int begin, int end); | 
|---|
| 188 | static Symbol* new_symbol(const char* utf8_buffer, int length); | 
|---|
| 189 | static Symbol* new_symbol(const char* name) { | 
|---|
| 190 | return new_symbol(name, (int)strlen(name)); | 
|---|
| 191 | } | 
|---|
| 192 |  | 
|---|
| 193 | // Create a symbol in the arena for symbols that are not deleted | 
|---|
| 194 | static Symbol* new_permanent_symbol(const char* name); | 
|---|
| 195 |  | 
|---|
| 196 | // Rehash the string table if it gets out of balance | 
|---|
| 197 | static void rehash_table(); | 
|---|
| 198 | static bool needs_rehashing() { return _needs_rehashing; } | 
|---|
| 199 | static inline void update_needs_rehash(bool rehash) { | 
|---|
| 200 | if (rehash) { | 
|---|
| 201 | _needs_rehashing = true; | 
|---|
| 202 | } | 
|---|
| 203 | } | 
|---|
| 204 |  | 
|---|
| 205 | // Heap dumper and CDS | 
|---|
| 206 | static void symbols_do(SymbolClosure *cl); | 
|---|
| 207 |  | 
|---|
| 208 | // Sharing | 
|---|
| 209 | private: | 
|---|
| 210 | static void copy_shared_symbol_table(CompactHashtableWriter* ch_table); | 
|---|
| 211 | public: | 
|---|
| 212 | static size_t estimate_size_for_archive() NOT_CDS_RETURN_(0); | 
|---|
| 213 | static void write_to_archive(bool is_static_archive = true) NOT_CDS_RETURN; | 
|---|
| 214 | static void (SerializeClosure* soc, | 
|---|
| 215 | bool is_static_archive = true) NOT_CDS_RETURN; | 
|---|
| 216 | static void metaspace_pointers_do(MetaspaceClosure* it); | 
|---|
| 217 |  | 
|---|
| 218 | // Jcmd | 
|---|
| 219 | static void dump(outputStream* st, bool verbose=false); | 
|---|
| 220 | // Debugging | 
|---|
| 221 | static void verify(); | 
|---|
| 222 |  | 
|---|
| 223 | // Histogram | 
|---|
| 224 | static void print_histogram() PRODUCT_RETURN; | 
|---|
| 225 | }; | 
|---|
| 226 |  | 
|---|
| 227 | #endif // SHARE_CLASSFILE_SYMBOLTABLE_HPP | 
|---|
| 228 |  | 
|---|