< prev index next >
src/hotspot/share/classfile/compactHashtable.hpp
Print this page
@@ -27,11 +27,18 @@
#include "oops/array.hpp"
#include "oops/symbol.hpp"
#include "utilities/hashtable.hpp"
-template <class T, class N> 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;
// Stats for symbol tables in the CDS archive
@@ -106,37 +113,17 @@
// This is called at dump-time only
CompactHashtableWriter(int num_buckets, CompactHashtableStats* stats);
~CompactHashtableWriter();
void add(unsigned int hash, u4 value);
- void add(u4 value) {
- add((unsigned int)value, value);
- }
private:
void allocate_table();
void dump_table(NumberSeq* summary);
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<Symbol*, char> *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<oop, char> *cht);
};
#define REGULAR_BUCKET_TYPE 0
#define VALUE_ONLY_BUCKET_TYPE 1
#define TABLEEND_BUCKET_TYPE 3
@@ -146,12 +133,11 @@
#define BUCKET_TYPE(info) (((info) & ~BUCKET_OFFSET_MASK) >> BUCKET_TYPE_SHIFT)
#define BUCKET_INFO(offset, type) (((type) << BUCKET_TYPE_SHIFT) | ((offset) & BUCKET_OFFSET_MASK))
/////////////////////////////////////////////////////////////////////////////
//
-// 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
// cost per entry.
//
@@ -223,60 +209,93 @@
_entry_count = entry_count;
_buckets = buckets;
_entries = entries;
}
- template <class I> inline void iterate(const I& iterator);
-
bool exists(u4 value);
// For reading from/writing to the CDS archive
void serialize(SerializeClosure* soc);
inline bool empty() {
return (_entry_count == 0);
}
};
-template <class T, class N> 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<Symbol*, char>* 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<oop, char>* 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 <class ITER>
+ 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;
+ }
+ }
+ }
}
};
////////////////////////////////////////////////////////////////////////
//
< prev index next >