hotspot/src/share/vm/classfile/compactHashtable.hpp
changeset 37995 92aec042a43b
parent 35868 bf29f15cdf30
child 39713 29ece76096cb
equal deleted inserted replaced
37994:1a816b464178 37995:92aec042a43b
     1 /*
     1 /*
     2  * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    29 #include "classfile/symbolTable.hpp"
    29 #include "classfile/symbolTable.hpp"
    30 #include "oops/symbol.hpp"
    30 #include "oops/symbol.hpp"
    31 #include "services/diagnosticCommand.hpp"
    31 #include "services/diagnosticCommand.hpp"
    32 #include "utilities/hashtable.hpp"
    32 #include "utilities/hashtable.hpp"
    33 
    33 
       
    34 template <class T, class N> class CompactHashtable;
    34 class NumberSeq;
    35 class NumberSeq;
       
    36 class SimpleCompactHashtable;
       
    37 class SerializeClosure;
    35 
    38 
    36 // Stats for symbol tables in the CDS archive
    39 // Stats for symbol tables in the CDS archive
    37 class CompactHashtableStats VALUE_OBJ_CLASS_SPEC {
    40 class CompactHashtableStats VALUE_OBJ_CLASS_SPEC {
    38 public:
    41 public:
    39   int hashentry_count;
    42   int hashentry_count;
    68 // Buckets without entry are skipped from the table. Their offsets are
    71 // Buckets without entry are skipped from the table. Their offsets are
    69 // still written out for faster lookup.
    72 // still written out for faster lookup.
    70 //
    73 //
    71 class CompactHashtableWriter: public StackObj {
    74 class CompactHashtableWriter: public StackObj {
    72 public:
    75 public:
    73   class Entry: public CHeapObj<mtSymbol> {
    76   class Entry VALUE_OBJ_CLASS_SPEC {
    74     Entry* _next;
       
    75     unsigned int _hash;
    77     unsigned int _hash;
    76     void* _literal;
    78     u4 _value;
    77 
    79 
    78   public:
    80   public:
    79     Entry(unsigned int hash, Symbol *symbol) : _next(NULL), _hash(hash), _literal(symbol) {}
    81     Entry() {}
    80     Entry(unsigned int hash, oop string)     : _next(NULL), _hash(hash), _literal(string) {}
    82     Entry(unsigned int hash, u4 val) : _hash(hash), _value(val) {}
    81 
    83 
    82     void *value() {
    84     u4 value() {
    83       return _literal;
    85       return _value;
    84     }
       
    85     Symbol *symbol() {
       
    86       return (Symbol*)_literal;
       
    87     }
       
    88     oop string() {
       
    89       return (oop)_literal;
       
    90     }
    86     }
    91     unsigned int hash() {
    87     unsigned int hash() {
    92       return _hash;
    88       return _hash;
    93     }
    89     }
    94     Entry *next()           {return _next;}
    90 
    95     void set_next(Entry *p) {_next = p;}
    91     bool operator==(const CompactHashtableWriter::Entry& other) {
       
    92       return (_value == other._value && _hash == other._hash);
       
    93     }
    96   }; // class CompactHashtableWriter::Entry
    94   }; // class CompactHashtableWriter::Entry
    97 
    95 
    98 private:
    96 private:
    99   static int number_of_buckets(int num_entries);
       
   100 
       
   101   int _type;
       
   102   int _num_entries;
    97   int _num_entries;
   103   int _num_buckets;
    98   int _num_buckets;
   104   juint* _bucket_sizes;
    99   int _num_empty_buckets;
   105   Entry** _buckets;
   100   int _num_value_only_buckets;
   106   int _required_bytes;
   101   int _num_other_buckets;
       
   102   GrowableArray<Entry>** _buckets;
   107   CompactHashtableStats* _stats;
   103   CompactHashtableStats* _stats;
       
   104   Array<u4>* _compact_buckets;
       
   105   Array<u4>* _compact_entries;
   108 
   106 
   109 public:
   107 public:
   110   // This is called at dump-time only
   108   // This is called at dump-time only
   111   CompactHashtableWriter(int table_type, int num_entries, CompactHashtableStats* stats);
   109   CompactHashtableWriter(int num_buckets, CompactHashtableStats* stats);
   112   ~CompactHashtableWriter();
   110   ~CompactHashtableWriter();
   113 
   111 
   114   int get_required_bytes() {
   112   void add(unsigned int hash, u4 value);
   115     return _required_bytes;
   113   void add(u4 value) {
   116   }
   114     add((unsigned int)value, value);
   117 
   115   }
   118   inline void add(unsigned int hash, Symbol* symbol);
       
   119   inline void add(unsigned int hash, oop string);
       
   120 
   116 
   121 private:
   117 private:
   122   void add(unsigned int hash, Entry* entry);
   118   void allocate_table();
   123   juint* dump_table(juint* p, juint** first_bucket, NumberSeq* summary);
   119   void dump_table(NumberSeq* summary);
   124   juint* dump_buckets(juint* table, juint* p, NumberSeq* summary);
   120 
   125 
   121 public:
   126 public:
   122   void dump(SimpleCompactHashtable *cht, const char* table_name);
   127   void dump(char** top, char* end);
       
   128   const char* table_name();
   123   const char* table_name();
   129 };
   124 };
   130 
   125 
       
   126 class CompactSymbolTableWriter: public CompactHashtableWriter {
       
   127 public:
       
   128   CompactSymbolTableWriter(int num_buckets, CompactHashtableStats* stats) :
       
   129     CompactHashtableWriter(num_buckets, stats) {}
       
   130   void add(unsigned int hash, Symbol *symbol);
       
   131   void dump(CompactHashtable<Symbol*, char> *cht);
       
   132 };
       
   133 
       
   134 class CompactStringTableWriter: public CompactHashtableWriter {
       
   135 public:
       
   136   CompactStringTableWriter(int num_entries, CompactHashtableStats* stats) :
       
   137     CompactHashtableWriter(num_entries, stats) {}
       
   138   void add(unsigned int hash, oop string);
       
   139   void dump(CompactHashtable<oop, char> *cht);
       
   140 };
       
   141 
   131 #define REGULAR_BUCKET_TYPE       0
   142 #define REGULAR_BUCKET_TYPE       0
   132 #define COMPACT_BUCKET_TYPE       1
   143 #define VALUE_ONLY_BUCKET_TYPE    1
   133 #define TABLEEND_BUCKET_TYPE      3
   144 #define TABLEEND_BUCKET_TYPE      3
   134 #define BUCKET_OFFSET_MASK        0x3FFFFFFF
   145 #define BUCKET_OFFSET_MASK        0x3FFFFFFF
   135 #define BUCKET_OFFSET(info)       ((info) & BUCKET_OFFSET_MASK)
   146 #define BUCKET_OFFSET(info)       ((info) & BUCKET_OFFSET_MASK)
   136 #define BUCKET_TYPE_SHIFT         30
   147 #define BUCKET_TYPE_SHIFT         30
   137 #define BUCKET_TYPE(info)         (((info) & ~BUCKET_OFFSET_MASK) >> BUCKET_TYPE_SHIFT)
   148 #define BUCKET_TYPE(info)         (((info) & ~BUCKET_OFFSET_MASK) >> BUCKET_TYPE_SHIFT)
   144 //
   155 //
   145 // Because these tables are read-only (no entries can be added/deleted) at run-time
   156 // Because these tables are read-only (no entries can be added/deleted) at run-time
   146 // and tend to have large number of entries, we try to minimize the footprint
   157 // and tend to have large number of entries, we try to minimize the footprint
   147 // cost per entry.
   158 // cost per entry.
   148 //
   159 //
   149 // Layout of compact table in the shared archive:
   160 // The CompactHashtable is split into two arrays
   150 //
   161 //
   151 //   uintx base_address;
   162 //   u4 buckets[num_buckets+1]; // bit[31,30]: type; bit[29-0]: offset
   152 //   juint num_entries;
   163 //   u4 entries[<variable size>]
   153 //   juint num_buckets;
   164 //
   154 //   juint bucket_infos[num_buckets+1]; // bit[31,30]: type; bit[29-0]: offset
   165 // The size of buckets[] is 'num_buckets + 1'. Each entry of
   155 //   juint table[]
   166 // buckets[] is a 32-bit encoding of the bucket type and bucket offset,
   156 //
       
   157 // -----------------------------------
       
   158 // | base_address  | num_entries     |
       
   159 // |---------------------------------|
       
   160 // | num_buckets   | bucket_info0    |
       
   161 // |---------------------------------|
       
   162 // | bucket_info1  | bucket_info2    |
       
   163 // | bucket_info3    ...             |
       
   164 // | ....          | table_end_info  |
       
   165 // |---------------------------------|
       
   166 // | entry0                          |
       
   167 // | entry1                          |
       
   168 // | entry2                          |
       
   169 // |                                 |
       
   170 // | ...                             |
       
   171 // -----------------------------------
       
   172 //
       
   173 // The size of the bucket_info table is 'num_buckets + 1'. Each entry of the
       
   174 // bucket_info table is a 32-bit encoding of the bucket type and bucket offset,
       
   175 // with the type in the left-most 2-bit and offset in the remaining 30-bit.
   167 // with the type in the left-most 2-bit and offset in the remaining 30-bit.
   176 // The last entry is a special type. It contains the offset of the last
   168 // The last entry is a special type. It contains the end of the last
   177 // bucket end. We use that information when traversing the compact table.
   169 // bucket.
   178 //
   170 //
   179 // There are two types of buckets, regular buckets and compact buckets. The
   171 // There are two types of buckets, regular buckets and value_only buckets. The
   180 // compact buckets have '01' in their highest 2-bit, and regular buckets have
   172 // value_only buckets have '01' in their highest 2-bit, and regular buckets have
   181 // '00' in their highest 2-bit.
   173 // '00' in their highest 2-bit.
   182 //
   174 //
   183 // For normal buckets, each entry is 8 bytes in the table[]:
   175 // For normal buckets, each entry is 8 bytes in the entries[]:
   184 //   juint hash;    /* symbol/string hash */
   176 //   u4 hash;    /* symbol/string hash */
   185 //   union {
   177 //   union {
   186 //     juint offset;  /* Symbol* sym = (Symbol*)(base_address + offset) */
   178 //     u4 offset;  /* Symbol* sym = (Symbol*)(base_address + offset) */
   187 //     narrowOop str; /* String narrowOop encoding */
   179 //     narrowOop str; /* String narrowOop encoding */
   188 //   }
   180 //   }
   189 //
   181 //
   190 //
   182 //
   191 // For compact buckets, each entry has only the 4-byte 'offset' in the table[].
   183 // For value_only buckets, each entry has only the 4-byte 'offset' in the entries[].
       
   184 //
       
   185 // Example -- note that the second bucket is a VALUE_ONLY_BUCKET_TYPE so the hash code
       
   186 //            is skipped.
       
   187 // buckets[0, 4, 5, ....]
       
   188 //         |  |  |
       
   189 //         |  |  +---+
       
   190 //         |  |      |
       
   191 //         |  +----+ |
       
   192 //         v       v v
       
   193 // entries[H,O,H,O,O,H,O,H,O.....]
   192 //
   194 //
   193 // See CompactHashtable::lookup() for how the table is searched at runtime.
   195 // See CompactHashtable::lookup() for how the table is searched at runtime.
   194 // See CompactHashtableWriter::dump() for how the table is written at CDS
   196 // See CompactHashtableWriter::dump() for how the table is written at CDS
   195 // dump time.
   197 // dump time.
   196 //
   198 //
   197 template <class T, class N> class CompactHashtable VALUE_OBJ_CLASS_SPEC {
   199 class SimpleCompactHashtable VALUE_OBJ_CLASS_SPEC {
       
   200 protected:
       
   201   address  _base_address;
       
   202   u4  _bucket_count;
       
   203   u4  _entry_count;
       
   204   u4* _buckets;
       
   205   u4* _entries;
       
   206 
       
   207 public:
       
   208   SimpleCompactHashtable() {
       
   209     _entry_count = 0;
       
   210     _bucket_count = 0;
       
   211     _buckets = 0;
       
   212     _entries = 0;
       
   213   }
       
   214 
       
   215   void reset() {
       
   216     _bucket_count = 0;
       
   217     _entry_count = 0;
       
   218     _buckets = 0;
       
   219     _entries = 0;
       
   220   }
       
   221 
       
   222   void init(address base_address, u4 entry_count, u4 bucket_count, u4* buckets, u4* entries) {
       
   223     _base_address = base_address;
       
   224     _bucket_count = bucket_count;
       
   225     _entry_count = entry_count;
       
   226     _buckets = buckets;
       
   227     _entries = entries;
       
   228   }
       
   229 
       
   230   template <class I> inline void iterate(const I& iterator);
       
   231 
       
   232   bool exists(u4 value);
       
   233 
       
   234   // For reading from/writing to the CDS archive
       
   235   void serialize(SerializeClosure* soc);
       
   236 };
       
   237 
       
   238 template <class T, class N> class CompactHashtable : public SimpleCompactHashtable {
   198   friend class VMStructs;
   239   friend class VMStructs;
   199 
   240 
   200  public:
   241 public:
   201   enum CompactHashtableType {
   242   enum CompactHashtableType {
   202     _symbol_table = 0,
   243     _symbol_table = 0,
   203     _string_table = 1
   244     _string_table = 1
   204   };
   245   };
   205 
   246 
   206 private:
   247 private:
   207   CompactHashtableType _type;
   248   u4 _type;
   208   uintx  _base_address;
   249 
   209   juint  _entry_count;
   250   inline Symbol* decode_entry(CompactHashtable<Symbol*, char>* const t,
   210   juint  _bucket_count;
   251                               u4 offset, const char* name, int len);
   211   juint  _table_end_offset;
   252 
   212   juint* _buckets;
   253   inline oop decode_entry(CompactHashtable<oop, char>* const t,
   213 
   254                           u4 offset, const char* name, int len);
   214   inline Symbol* lookup_entry(CompactHashtable<Symbol*, char>* const t,
   255 public:
   215                               juint* addr, const char* name, int len);
   256   CompactHashtable() : SimpleCompactHashtable() {}
   216 
   257 
   217   inline oop lookup_entry(CompactHashtable<oop, char>* const t,
   258   void set_type(CompactHashtableType type) {
   218                           juint* addr, const char* name, int len);
   259     _type = (u4)type;
   219 public:
       
   220   CompactHashtable() {
       
   221     _entry_count = 0;
       
   222     _bucket_count = 0;
       
   223     _table_end_offset = 0;
       
   224     _buckets = 0;
       
   225   }
       
   226   const char* init(CompactHashtableType type, const char *buffer);
       
   227 
       
   228   void reset() {
       
   229     _entry_count = 0;
       
   230     _bucket_count = 0;
       
   231     _table_end_offset = 0;
       
   232     _buckets = 0;
       
   233   }
   260   }
   234 
   261 
   235   // Lookup an entry from the compact table
   262   // Lookup an entry from the compact table
   236   inline T lookup(const N* name, unsigned int hash, int len);
   263   inline T lookup(const N* name, unsigned int hash, int len);
   237 
   264 
   238   // iterate over symbols
   265   // iterate over symbols
   239   void symbols_do(SymbolClosure *cl);
   266   void symbols_do(SymbolClosure *cl);
   240 
   267 
   241   // iterate over strings
   268   // iterate over strings
   242   void oops_do(OopClosure* f);
   269   void oops_do(OopClosure* f);
       
   270 
       
   271   // For reading from/writing to the CDS archive
       
   272   void serialize(SerializeClosure* soc);
   243 };
   273 };
   244 
   274 
   245 ////////////////////////////////////////////////////////////////////////
   275 ////////////////////////////////////////////////////////////////////////
   246 //
   276 //
   247 // Read/Write the contents of a hashtable textual dump (created by
   277 // Read/Write the contents of a hashtable textual dump (created by
   291     const char* p   = _p;
   321     const char* p   = _p;
   292     const char* end = _end;
   322     const char* end = _end;
   293     u8 n = 0;
   323     u8 n = 0;
   294 
   324 
   295     while (p < end) {
   325     while (p < end) {
   296       char c = *p ++;
   326       char c = *p++;
   297       if ('0' <= c && c <= '9') {
   327       if ('0' <= c && c <= '9') {
   298         n = n * 10 + (c - '0');
   328         n = n * 10 + (c - '0');
   299         if (n > (u8)INT_MAX) {
   329         if (n > (u8)INT_MAX) {
   300           corrupted(_p, "Num overflow");
   330           corrupted(_p, "Num overflow");
   301         }
   331         }