symbolTable.hpp revision 3602:da91efe96a93
1/*
2 * Copyright (c) 1997, 2012, 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_SYMBOLTABLE_HPP
26#define SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
27
28#include "memory/allocation.inline.hpp"
29#include "oops/symbol.hpp"
30#include "utilities/hashtable.hpp"
31
32// The symbol table holds all Symbol*s and corresponding interned strings.
33// Symbol*s and literal strings should be canonicalized.
34//
35// The interned strings are created lazily.
36//
37// It is implemented as an open hash table with a fixed number of buckets.
38//
39// %note:
40//  - symbolTableEntrys are allocated in blocks to reduce the space overhead.
41
42class BoolObjectClosure;
43class outputStream;
44
45
46// Class to hold a newly created or referenced Symbol* temporarily in scope.
47// new_symbol() and lookup() will create a Symbol* if not already in the
48// symbol table and add to the symbol's reference count.
49// probe() and lookup_only() will increment the refcount if symbol is found.
50class TempNewSymbol : public StackObj {
51  Symbol* _temp;
52
53 public:
54  TempNewSymbol() : _temp(NULL) {}
55  // Creating or looking up a symbol increments the symbol's reference count
56  TempNewSymbol(Symbol *s) : _temp(s) {}
57
58  // Operator= increments reference count.
59  void operator=(const TempNewSymbol &s) {
60    //clear();  //FIXME
61    _temp = s._temp;
62    if (_temp !=NULL) _temp->increment_refcount();
63  }
64
65  // Decrement reference counter so it can go away if it's unique
66  void clear() { if (_temp != NULL)  _temp->decrement_refcount();  _temp = NULL; }
67
68  ~TempNewSymbol() { clear(); }
69
70  // Operators so they can be used like Symbols
71  Symbol* operator -> () const                   { return _temp; }
72  bool    operator == (Symbol* o) const          { return _temp == o; }
73  // Sneaky conversion function
74  operator Symbol*()                             { return _temp; }
75};
76
77class SymbolTable : public Hashtable<Symbol*, mtSymbol> {
78  friend class VMStructs;
79  friend class ClassFileParser;
80
81private:
82  // The symbol table
83  static SymbolTable* _the_table;
84
85  // Set if one bucket is out of balance due to hash algorithm deficiency
86  static bool _needs_rehashing;
87
88  // For statistics
89  static int symbols_removed;
90  static int symbols_counted;
91
92  Symbol* allocate_symbol(const u1* name, int len, bool c_heap, TRAPS); // Assumes no characters larger than 0x7F
93
94  // Adding elements
95  Symbol* basic_add(int index, u1* name, int len, unsigned int hashValue,
96                    bool c_heap, TRAPS);
97  bool basic_add(ClassLoaderData* loader_data,
98                 constantPoolHandle cp, int names_count,
99                 const char** names, int* lengths, int* cp_indices,
100                 unsigned int* hashValues, TRAPS);
101
102  static void new_symbols(ClassLoaderData* loader_data,
103                          constantPoolHandle cp, int names_count,
104                          const char** name, int* lengths,
105                          int* cp_indices, unsigned int* hashValues,
106                          TRAPS) {
107    add(loader_data, cp, names_count, name, lengths, cp_indices, hashValues, THREAD);
108  }
109
110  // Table size
111  enum {
112    symbol_table_size = 20011
113  };
114
115  Symbol* lookup(int index, const char* name, int len, unsigned int hash);
116
117  SymbolTable()
118    : Hashtable<Symbol*, mtSymbol>(symbol_table_size, sizeof (HashtableEntry<Symbol*, mtSymbol>)) {}
119
120  SymbolTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
121    : Hashtable<Symbol*, mtSymbol>(symbol_table_size, sizeof (HashtableEntry<Symbol*, mtSymbol>), t,
122                number_of_entries) {}
123
124  // Arena for permanent symbols (null class loader) that are never unloaded
125  static Arena*  _arena;
126  static Arena* arena() { return _arena; }  // called for statistics
127
128  static void initialize_symbols(int arena_alloc_size = 0);
129public:
130  enum {
131    symbol_alloc_batch_size = 8,
132    // Pick initial size based on java -version size measurements
133    symbol_alloc_arena_size = 360*K
134  };
135
136  // The symbol table
137  static SymbolTable* the_table() { return _the_table; }
138
139  static void create_table() {
140    assert(_the_table == NULL, "One symbol table allowed.");
141    _the_table = new SymbolTable();
142    initialize_symbols(symbol_alloc_arena_size);
143  }
144
145  static void create_table(HashtableBucket<mtSymbol>* t, int length,
146                           int number_of_entries) {
147    assert(_the_table == NULL, "One symbol table allowed.");
148    assert(length == symbol_table_size * sizeof(HashtableBucket<mtSymbol>),
149           "bad shared symbol size.");
150    _the_table = new SymbolTable(t, number_of_entries);
151    // if CDS give symbol table a default arena size since most symbols
152    // are already allocated in the shared misc section.
153    initialize_symbols();
154  }
155
156  static unsigned int hash_symbol(const char* s, int len);
157
158  static Symbol* lookup(const char* name, int len, TRAPS);
159  // lookup only, won't add. Also calculate hash.
160  static Symbol* lookup_only(const char* name, int len, unsigned int& hash);
161  // Only copy to C string to be added if lookup failed.
162  static Symbol* lookup(const Symbol* sym, int begin, int end, TRAPS);
163
164  static void release(Symbol* sym);
165
166  // Look up the address of the literal in the SymbolTable for this Symbol*
167  static Symbol** lookup_symbol_addr(Symbol* sym);
168
169  // jchar (utf16) version of lookups
170  static Symbol* lookup_unicode(const jchar* name, int len, TRAPS);
171  static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash);
172
173  static void add(ClassLoaderData* loader_data,
174                  constantPoolHandle cp, int names_count,
175                  const char** names, int* lengths, int* cp_indices,
176                  unsigned int* hashValues, TRAPS);
177
178  // Release any dead symbols
179  static void unlink();
180
181  // iterate over symbols
182  static void symbols_do(SymbolClosure *cl);
183
184  // Symbol creation
185  static Symbol* new_symbol(const char* utf8_buffer, int length, TRAPS) {
186    assert(utf8_buffer != NULL, "just checking");
187    return lookup(utf8_buffer, length, THREAD);
188  }
189  static Symbol*       new_symbol(const char* name, TRAPS) {
190    return new_symbol(name, (int)strlen(name), THREAD);
191  }
192  static Symbol*       new_symbol(const Symbol* sym, int begin, int end, TRAPS) {
193    assert(begin <= end && end <= sym->utf8_length(), "just checking");
194    return lookup(sym, begin, end, THREAD);
195  }
196
197  // Create a symbol in the arena for symbols that are not deleted
198  static Symbol* new_permanent_symbol(const char* name, TRAPS);
199
200  // Symbol lookup
201  static Symbol* lookup(int index, const char* name, int len, TRAPS);
202
203  // Needed for preloading classes in signatures when compiling.
204  // Returns the symbol is already present in symbol table, otherwise
205  // NULL.  NO ALLOCATION IS GUARANTEED!
206  static Symbol* probe(const char* name, int len) {
207    unsigned int ignore_hash;
208    return lookup_only(name, len, ignore_hash);
209  }
210  static Symbol* probe_unicode(const jchar* name, int len) {
211    unsigned int ignore_hash;
212    return lookup_only_unicode(name, len, ignore_hash);
213  }
214
215  // Histogram
216  static void print_histogram()     PRODUCT_RETURN;
217  static void print()     PRODUCT_RETURN;
218
219  // Debugging
220  static void verify();
221  static void dump(outputStream* st);
222
223  // Sharing
224  static void copy_buckets(char** top, char*end) {
225    the_table()->Hashtable<Symbol*, mtSymbol>::copy_buckets(top, end);
226  }
227  static void copy_table(char** top, char*end) {
228    the_table()->Hashtable<Symbol*, mtSymbol>::copy_table(top, end);
229  }
230  static void reverse(void* boundary = NULL) {
231    the_table()->Hashtable<Symbol*, mtSymbol>::reverse(boundary);
232  }
233
234  // Rehash the symbol table if it gets out of balance
235  static void rehash_table();
236  static bool needs_rehashing()         { return _needs_rehashing; }
237};
238
239class StringTable : public Hashtable<oop, mtSymbol> {
240  friend class VMStructs;
241
242private:
243  // The string table
244  static StringTable* _the_table;
245
246  // Set if one bucket is out of balance due to hash algorithm deficiency
247  static bool _needs_rehashing;
248
249  static oop intern(Handle string_or_null, jchar* chars, int length, TRAPS);
250  oop basic_add(int index, Handle string_or_null, jchar* name, int len,
251                unsigned int hashValue, TRAPS);
252
253  oop lookup(int index, jchar* chars, int length, unsigned int hashValue);
254
255  StringTable() : Hashtable<oop, mtSymbol>((int)StringTableSize,
256                              sizeof (HashtableEntry<oop, mtSymbol>)) {}
257
258  StringTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
259    : Hashtable<oop, mtSymbol>((int)StringTableSize, sizeof (HashtableEntry<oop, mtSymbol>), t,
260                     number_of_entries) {}
261public:
262  // The string table
263  static StringTable* the_table() { return _the_table; }
264
265  static void create_table() {
266    assert(_the_table == NULL, "One string table allowed.");
267    _the_table = new StringTable();
268  }
269
270  static void create_table(HashtableBucket<mtSymbol>* t, int length,
271                           int number_of_entries) {
272    assert(_the_table == NULL, "One string table allowed.");
273    assert((size_t)length == StringTableSize * sizeof(HashtableBucket<mtSymbol>),
274           "bad shared string size.");
275    _the_table = new StringTable(t, number_of_entries);
276  }
277
278  // GC support
279  //   Delete pointers to otherwise-unreachable objects.
280  static void unlink(BoolObjectClosure* cl);
281
282  // Invoke "f->do_oop" on the locations of all oops in the table.
283  static void oops_do(OopClosure* f);
284
285  // Hashing algorithm, used as the hash value used by the
286  //     StringTable for bucket selection and comparison (stored in the
287  //     HashtableEntry structures).  This is used in the String.intern() method.
288  static unsigned int hash_string(const jchar* s, int len);
289
290  // Internal test.
291  static void test_alt_hash() PRODUCT_RETURN;
292
293  // Probing
294  static oop lookup(Symbol* symbol);
295
296  // Interning
297  static oop intern(Symbol* symbol, TRAPS);
298  static oop intern(oop string, TRAPS);
299  static oop intern(const char *utf8_string, TRAPS);
300
301  // Debugging
302  static void verify();
303  static void dump(outputStream* st);
304
305  // Sharing
306  static void copy_buckets(char** top, char*end) {
307    the_table()->Hashtable<oop, mtSymbol>::copy_buckets(top, end);
308  }
309  static void copy_table(char** top, char*end) {
310    the_table()->Hashtable<oop, mtSymbol>::copy_table(top, end);
311  }
312  static void reverse() {
313    the_table()->Hashtable<oop, mtSymbol>::reverse();
314  }
315
316  // Rehash the symbol table if it gets out of balance
317  static void rehash_table();
318  static bool needs_rehashing() { return _needs_rehashing; }
319};
320#endif // SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
321