--- old/src/hotspot/share/classfile/compactHashtable.hpp 2018-09-18 21:27:53.477217783 -0700 +++ new/src/hotspot/share/classfile/compactHashtable.hpp 2018-09-18 21:27:53.217207768 -0700 @@ -29,7 +29,14 @@ #include "oops/symbol.hpp" #include "utilities/hashtable.hpp" -template class CompactHashtable; + +template < + typename K, + typename V, + V (*DECODE)(address base_address, u4 offset), + bool (*EQUALS)(V value, K key, int len) + > +class CompactHashtable; class NumberSeq; class SimpleCompactHashtable; class SerializeClosure; @@ -108,9 +115,6 @@ ~CompactHashtableWriter(); void add(unsigned int hash, u4 value); - void add(u4 value) { - add((unsigned int)value, value); - } private: void allocate_table(); @@ -118,23 +122,6 @@ public: void dump(SimpleCompactHashtable *cht, const char* table_name); - const char* table_name(); -}; - -class CompactSymbolTableWriter: public CompactHashtableWriter { -public: - CompactSymbolTableWriter(int num_buckets, CompactHashtableStats* stats) : - CompactHashtableWriter(num_buckets, stats) {} - void add(unsigned int hash, Symbol *symbol); - void dump(CompactHashtable *cht); -}; - -class CompactStringTableWriter: public CompactHashtableWriter { -public: - CompactStringTableWriter(int num_entries, CompactHashtableStats* stats) : - CompactHashtableWriter(num_entries, stats) {} - void add(unsigned int hash, oop string); - void dump(CompactHashtable *cht); }; #define REGULAR_BUCKET_TYPE 0 @@ -148,8 +135,7 @@ ///////////////////////////////////////////////////////////////////////////// // -// CompactHashtable is used to stored the CDS archive's symbol/string table. Used -// at runtime only to access the compact table from the archive. +// CompactHashtable is used to store the CDS archive's symbol/string tables. // // Because these tables are read-only (no entries can be added/deleted) at run-time // and tend to have large number of entries, we try to minimize the footprint @@ -225,10 +211,6 @@ _entries = entries; } - template inline void iterate(const I& iterator); - - bool exists(u4 value); - // For reading from/writing to the CDS archive void serialize(SerializeClosure* soc); @@ -237,44 +219,74 @@ } }; -template class CompactHashtable : public SimpleCompactHashtable { +template < + typename K, + typename V, + V (*DECODE)(address base_address, u4 offset), + bool (*EQUALS)(V value, K key, int len) + > +class CompactHashtable : public SimpleCompactHashtable { friend class VMStructs; -public: - enum CompactHashtableType { - _symbol_table = 0, - _string_table = 1 - }; - -private: - u4 _type; - - inline Symbol* decode_entry(CompactHashtable* const t, - u4 offset, const char* name, int len); + V decode(u4 offset) const { + return DECODE(_base_address, offset); + } - inline oop decode_entry(CompactHashtable* const t, - u4 offset, const char* name, int len); public: CompactHashtable() : SimpleCompactHashtable() {} - void set_type(CompactHashtableType type) { - _type = (u4)type; + // Lookup a value V from the compact table using key K + inline V lookup(K key, unsigned int hash, int len) const { + if (_entry_count > 0) { + int index = hash % _bucket_count; + u4 bucket_info = _buckets[index]; + u4 bucket_offset = BUCKET_OFFSET(bucket_info); + int bucket_type = BUCKET_TYPE(bucket_info); + u4* entry = _entries + bucket_offset; + + if (bucket_type == VALUE_ONLY_BUCKET_TYPE) { + V value = decode(entry[0]); + if (EQUALS(value, key, len)) { + return value; + } + } else { + // This is a regular bucket, which has more than one + // entries. Each entry is a pair of entry (hash, offset). + // Seek until the end of the bucket. + u4* entry_max = _entries + BUCKET_OFFSET(_buckets[index + 1]); + while (entry < entry_max) { + unsigned int h = (unsigned int)(entry[0]); + if (h == hash) { + V value = decode(entry[1]); + if (EQUALS(value, key, len)) { + return value; + } + } + entry += 2; + } + } + } + return NULL; } - // Lookup an entry from the compact table - inline T lookup(const N* name, unsigned int hash, int len); - - // iterate over symbols - void symbols_do(SymbolClosure *cl); - - // iterate over strings - void oops_do(OopClosure* f); - - // For reading from/writing to the CDS archive - void serialize(SerializeClosure* soc); - - uintx base_address() { - return (uintx) _base_address; + template + inline void iterate(ITER* iter) const { + for (u4 i = 0; i < _bucket_count; i++) { + u4 bucket_info = _buckets[i]; + u4 bucket_offset = BUCKET_OFFSET(bucket_info); + int bucket_type = BUCKET_TYPE(bucket_info); + u4* entry = _entries + bucket_offset; + + if (bucket_type == VALUE_ONLY_BUCKET_TYPE) { + iter->do_value(decode(entry[0])); + } else { + u4*entry_max = _entries + BUCKET_OFFSET(_buckets[i + 1]); + while (entry < entry_max) { + iter->do_value(decode(entry[1])); + entry += 2; + } + } + } } };