< prev index next >

src/hotspot/share/classfile/symbolTable.hpp

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -24,27 +24,15 @@
 
 #ifndef SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
 #define SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
 
 #include "memory/allocation.hpp"
+#include "memory/padded.hpp"
 #include "oops/symbol.hpp"
+#include "utilities/concurrentHashTable.hpp"
 #include "utilities/hashtable.hpp"
 
-// The symbol table holds all Symbol*s and corresponding interned strings.
-// Symbol*s and literal strings should be canonicalized.
-//
-// The interned strings are created lazily.
-//
-// It is implemented as an open hash table with a fixed number of buckets.
-//
-// %note:
-//  - symbolTableEntrys are allocated in blocks to reduce the space overhead.
-
-class BoolObjectClosure;
-class outputStream;
-class SerializeClosure;
-
 // TempNewSymbol acts as a handle class in a handle/body idiom and is
 // responsible for proper resource management of the body (which is a Symbol*).
 // The body is resource managed by a reference counting scheme.
 // TempNewSymbol can therefore be used to properly hold a newly created or referenced
 // Symbol* temporarily in scope.

@@ -57,11 +45,11 @@
 // symbol table and add to the symbol's reference count.
 // probe() and lookup_only() will increment the refcount if symbol is found.
 class TempNewSymbol : public StackObj {
   Symbol* _temp;
 
- public:
+public:
   TempNewSymbol() : _temp(NULL) {}
 
   // Conversion from a Symbol* to a TempNewSymbol.
   // Does not increment the current reference count.
   TempNewSymbol(Symbol *s) : _temp(s) {}

@@ -95,178 +83,180 @@
   bool    operator == (Symbol* o) const          { return _temp == o; }
   operator Symbol*()                             { return _temp; }
 };
 
 template <class T, class N> class CompactHashtable;
+class CompactSymbolTableWriter;
+class SerializeClosure;
+
+class SymbolTableConfig;
+typedef ConcurrentHashTable<Symbol*,
+                              SymbolTableConfig, mtSymbol> SymbolTableHash;
 
-class SymbolTable : public RehashableHashtable<Symbol*, mtSymbol> {
+class SymbolTableCreateEntry;
+
+class SymbolTable : public CHeapObj<mtSymbol> {
   friend class VMStructs;
+  friend class Symbol;
   friend class ClassFileParser;
+  friend class SymbolTableConfig;
+  friend class SymbolTableCreateEntry;
 
 private:
+  static void delete_symbol(Symbol* sym);
+  void grow(JavaThread* jt);
+  void clean_dead_entries(JavaThread* jt);
+
   // The symbol table
   static SymbolTable* _the_table;
+  // Shared symbol table.
+  static CompactHashtable<Symbol*, char> _shared_table;
+  static volatile bool _lookup_shared_first;
+  static volatile bool _alt_hash;
+
+  // For statistics
+  volatile size_t _symbols_removed;
+  volatile size_t _symbols_counted;
 
+  SymbolTableHash* _local_table;
+  size_t _current_size;
+  volatile bool _has_work;
   // Set if one bucket is out of balance due to hash algorithm deficiency
-  static bool _needs_rehashing;
-  static bool _lookup_shared_first;
+  volatile bool _needs_rehashing;
 
-  // For statistics
-  static int _symbols_removed;
-  static int _symbols_counted;
+  volatile size_t _items_count;
+  volatile size_t _uncleaned_items_count;
 
-  // shared symbol table.
-  static CompactHashtable<Symbol*, char> _shared_table;
+  double get_load_factor();
+  double get_dead_factor();
 
-  Symbol* allocate_symbol(const u1* name, int len, bool c_heap, TRAPS); // Assumes no characters larger than 0x7F
+  void check_concurrent_work();
+  void trigger_concurrent_work();
+
+  static void item_added();
+  static void item_removed();
+  static void set_item_clean_count(size_t ncl);
+  static void mark_item_clean_count();
+
+  SymbolTable();
+
+  Symbol* allocate_symbol(const char* name, int len, bool c_heap, TRAPS); // Assumes no characters larger than 0x7F
+  Symbol* do_lookup(const char* name, int len, uintx hash);
+  Symbol* do_add_if_needed(const char* name, int len, uintx hash, bool heap, TRAPS);
 
   // Adding elements
-  Symbol* basic_add(int index, u1* name, int len, unsigned int hashValue,
-                    bool c_heap, TRAPS);
-  bool basic_add(ClassLoaderData* loader_data,
-                 const constantPoolHandle& cp, int names_count,
-                 const char** names, int* lengths, int* cp_indices,
-                 unsigned int* hashValues, TRAPS);
+  static void add(ClassLoaderData* loader_data,
+                  const constantPoolHandle& cp, int names_count,
+                  const char** names, int* lengths, int* cp_indices,
+                  unsigned int* hashValues, TRAPS);
 
   static void new_symbols(ClassLoaderData* loader_data,
                           const constantPoolHandle& cp, int names_count,
                           const char** name, int* lengths,
                           int* cp_indices, unsigned int* hashValues,
                           TRAPS) {
     add(loader_data, cp, names_count, name, lengths, cp_indices, hashValues, THREAD);
   }
 
   static Symbol* lookup_shared(const char* name, int len, unsigned int hash);
-  Symbol* lookup_dynamic(int index, const char* name, int len, unsigned int hash);
-  Symbol* lookup(int index, const char* name, int len, unsigned int hash);
-
-  SymbolTable()
-    : RehashableHashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>)) {}
-
-  SymbolTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
-    : RehashableHashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>), t,
-                number_of_entries) {}
+  Symbol* lookup_dynamic(const char* name, int len, unsigned int hash);
+  Symbol* lookup_common(const char* name, int len, unsigned int hash);
 
   // Arena for permanent symbols (null class loader) that are never unloaded
   static Arena*  _arena;
   static Arena* arena() { return _arena; }  // called for statistics
 
   static void initialize_symbols(int arena_alloc_size = 0);
 
-  static volatile int _parallel_claimed_idx;
+  void concurrent_work(JavaThread* jt);
+  void print_table_statistics(outputStream* st, const char* table_name);
+
+  void try_rehash_table();
+  bool do_rehash();
 
-  typedef SymbolTable::BucketUnlinkContext BucketUnlinkContext;
-  // Release any dead symbols. Unlinked bucket entries are collected in the given
-  // context to be freed later.
-  // This allows multiple threads to work on the table at once.
-  static void buckets_unlink(int start_idx, int end_idx, BucketUnlinkContext* context);
 public:
+  // The symbol table
+  static SymbolTable* the_table() { return _the_table; }
+  size_t table_size(Thread* thread = NULL);
+
   enum {
     symbol_alloc_batch_size = 8,
     // Pick initial size based on java -version size measurements
-    symbol_alloc_arena_size = 360*K
+    symbol_alloc_arena_size = 360*K // TODO (revisit)
   };
 
-  // The symbol table
-  static SymbolTable* the_table() { return _the_table; }
-
-  // Size of one bucket in the string table.  Used when checking for rollover.
-  static uint bucket_size() { return sizeof(HashtableBucket<mtSymbol>); }
-
   static void create_table() {
     assert(_the_table == NULL, "One symbol table allowed.");
     _the_table = new SymbolTable();
     initialize_symbols(symbol_alloc_arena_size);
   }
 
-  static unsigned int hash_symbol(const char* s, int len);
-  static unsigned int hash_shared_symbol(const char* s, int len);
+  static void unlink() {
+    do_check_concurrent_work();
+  }
+  static void do_check_concurrent_work();
+  static void do_concurrent_work(JavaThread* jt);
+  static bool has_work() { return the_table()->_has_work; }
 
+  // Probing
   static Symbol* lookup(const char* name, int len, TRAPS);
   // lookup only, won't add. Also calculate hash.
   static Symbol* lookup_only(const char* name, int len, unsigned int& hash);
   // Only copy to C string to be added if lookup failed.
   static Symbol* lookup(const Symbol* sym, int begin, int end, TRAPS);
-
-  static void release(Symbol* sym);
-
-  // Look up the address of the literal in the SymbolTable for this Symbol*
-  static Symbol** lookup_symbol_addr(Symbol* sym);
-
   // jchar (UTF16) version of lookups
   static Symbol* lookup_unicode(const jchar* name, int len, TRAPS);
   static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash);
-
-  static void add(ClassLoaderData* loader_data,
-                  const constantPoolHandle& cp, int names_count,
-                  const char** names, int* lengths, int* cp_indices,
-                  unsigned int* hashValues, TRAPS);
-
-  // Release any dead symbols
-  static void unlink() {
-    int processed = 0;
-    int removed = 0;
-    unlink(&processed, &removed);
-  }
-  static void unlink(int* processed, int* removed);
-  // Release any dead symbols, possibly parallel version
-  static void possibly_parallel_unlink(int* processed, int* removed);
-
-  // iterate over symbols
-  static void symbols_do(SymbolClosure *cl);
-  static void metaspace_pointers_do(MetaspaceClosure* it);
+  // Needed for preloading classes in signatures when compiling.
+  // Returns the symbol is already present in symbol table, otherwise
+  // NULL.  NO ALLOCATION IS GUARANTEED!
+  static Symbol* probe(const char* name, int len) {
+    unsigned int ignore_hash;
+    return lookup_only(name, len, ignore_hash);
+  }
+  static Symbol* probe_unicode(const jchar* name, int len) {
+    unsigned int ignore_hash;
+    return lookup_only_unicode(name, len, ignore_hash);
+  }
 
   // Symbol creation
   static Symbol* new_symbol(const char* utf8_buffer, int length, TRAPS) {
     assert(utf8_buffer != NULL, "just checking");
     return lookup(utf8_buffer, length, THREAD);
   }
-  static Symbol*       new_symbol(const char* name, TRAPS) {
+  static Symbol* new_symbol(const char* name, TRAPS) {
     return new_symbol(name, (int)strlen(name), THREAD);
   }
-  static Symbol*       new_symbol(const Symbol* sym, int begin, int end, TRAPS) {
+  static Symbol* new_symbol(const Symbol* sym, int begin, int end, TRAPS) {
     assert(begin <= end && end <= sym->utf8_length(), "just checking");
     return lookup(sym, begin, end, THREAD);
   }
-
   // Create a symbol in the arena for symbols that are not deleted
   static Symbol* new_permanent_symbol(const char* name, TRAPS);
 
-  // Symbol lookup
-  static Symbol* lookup(int index, const char* name, int len, TRAPS);
+  // Rehash the string table if it gets out of balance
+  static void rehash_table();
+  static bool needs_rehashing()
+    { return SymbolTable::the_table()->_needs_rehashing; }
 
-  // Needed for preloading classes in signatures when compiling.
-  // Returns the symbol is already present in symbol table, otherwise
-  // NULL.  NO ALLOCATION IS GUARANTEED!
-  static Symbol* probe(const char* name, int len) {
-    unsigned int ignore_hash;
-    return lookup_only(name, len, ignore_hash);
-  }
-  static Symbol* probe_unicode(const jchar* name, int len) {
-    unsigned int ignore_hash;
-    return lookup_only_unicode(name, len, ignore_hash);
-  }
+  // Heap dumper and CDS
+  static void symbols_do(SymbolClosure *cl);
 
-  // Histogram
-  static void print_histogram()     PRODUCT_RETURN;
-  static void print()     PRODUCT_RETURN;
+  // Sharing
+private:
+  static void copy_shared_symbol_table(CompactSymbolTableWriter* ch_table);
+public:
+  static void write_to_archive() NOT_CDS_RETURN;
+  static void serialize(SerializeClosure* soc) NOT_CDS_RETURN;
+  static void metaspace_pointers_do(MetaspaceClosure* it);
 
+  // Jcmd
+  static void dump(outputStream* st, bool verbose=false);
   // Debugging
   static void verify();
-  static void dump(outputStream* st, bool verbose=false);
   static void read(const char* filename, TRAPS);
 
-  // Sharing
-  static void write_to_archive();
-  static void serialize(SerializeClosure* soc);
-  static u4 encode_shared(Symbol* sym);
-  static Symbol* decode_shared(u4 offset);
-
-  // Rehash the symbol table if it gets out of balance
-  static void rehash_table();
-  static bool needs_rehashing()         { return _needs_rehashing; }
-  // Parallel chunked scanning
-  static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; }
-  static int parallel_claimed_index()        { return _parallel_claimed_idx; }
+  // Histogram
+  static void print_histogram() PRODUCT_RETURN;
 };
 
 #endif // SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
< prev index next >