--- old/src/hotspot/share/classfile/compactHashtable.hpp 2018-09-18 10:32:53.113623692 -0700 +++ new/src/hotspot/share/classfile/compactHashtable.hpp 2018-09-18 10:32:52.853613719 -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 stored 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,8 +211,6 @@ _entries = entries; } - template inline void iterate(const I& iterator); - bool exists(u4 value); // For reading from/writing to the CDS archive @@ -237,44 +221,79 @@ } }; -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 if_equals(const K key, int len, u4 offset) const { + V value = DECODE(_base_address, offset); + if (EQUALS(value, key, len)) { + return value; + } else { + return NULL; + } + } - 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 res = if_equals(key, len, entry[0]); + if (res != NULL) { + return res; + } + } 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 res = if_equals(key, len, entry[1]); + if (res != NULL) { + return res; + } + } + 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(_base_address, entry[0])); + } else { + u4*entry_max = _entries + BUCKET_OFFSET(_buckets[i + 1]); + while (entry < entry_max) { + iter->do_value(DECODE(_base_address, entry[1])); + entry += 2; + } + } + } } };