bool SimpleCompactHashtable::exists(u4 value) { assert(!DumpSharedSpaces, "run-time only"); if (_entry_count == 0) { return false; } unsigned int hash = (unsigned int)value; 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) { return (entry[0] == value); } else { u4*entry_max = _entries + BUCKET_OFFSET(_buckets[index + 1]); while (entry <entry_max) { if (entry[1] == value) { return true; } entry += 2; } return false; } }
inline void SimpleCompactHashtable::iterate(const I& iterator) { assert(!DumpSharedSpaces, "run-time only"); 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) { iterator.do_value(_base_address, entry[0]); } else { u4*entry_max = _entries + BUCKET_OFFSET(_buckets[i + 1]); while (entry < entry_max) { iterator.do_value(_base_address, entry[1]); entry += 2; } } } }
template <class T, class N> void CompactHashtable<T, N>::symbols_do(SymbolClosure *cl) { assert(!DumpSharedSpaces, "run-time only"); for (juint i = 0; i < _bucket_count; i ++) { juint bucket_info = _buckets[i]; juint bucket_offset = BUCKET_OFFSET(bucket_info); int bucket_type = BUCKET_TYPE(bucket_info); juint* bucket = _buckets + bucket_offset; juint* bucket_end = _buckets; Symbol* sym; if (bucket_type == COMPACT_BUCKET_TYPE) { sym = (Symbol*)((void*)(_base_address + bucket[0])); cl->do_symbol(&sym); } else { bucket_end += BUCKET_OFFSET(_buckets[i + 1]); while (bucket < bucket_end) { sym = (Symbol*)((void*)(_base_address + bucket[1])); cl->do_symbol(&sym); bucket += 2; } } } }
///////////////////////////////////////////////////////////// // // The CompactHashtable implementation // template <class T, class N> const char* CompactHashtable<T, N>::init(const char* buffer) { assert(!DumpSharedSpaces, "run-time only"); juint*p = (juint*)buffer; juint upper = *p++; juint lower = *p++; _base_address = uintx(jlong_from(upper, lower)); _entry_count = *p++; _bucket_count = *p++; _buckets = p; _table_end_offset = BUCKET_OFFSET(p[_bucket_count]); // located at the end of the bucket_info table juint *end = _buckets + _table_end_offset; return (const char*)end; }
template <class T, class N> void CompactHashtable<T, N>::oops_do(OopClosure* f) { assert(!DumpSharedSpaces, "run-time only"); assert(_type == _string_table || _bucket_count == 0, "sanity"); for (juint i = 0; i < _bucket_count; i ++) { juint bucket_info = _buckets[i]; juint bucket_offset = BUCKET_OFFSET(bucket_info); int bucket_type = BUCKET_TYPE(bucket_info); juint* bucket = _buckets + bucket_offset; juint* bucket_end = _buckets; narrowOop o; if (bucket_type == COMPACT_BUCKET_TYPE) { o = (narrowOop)bucket[0]; f->do_oop(&o); } else { bucket_end += BUCKET_OFFSET(_buckets[i + 1]); while (bucket < bucket_end) { o = (narrowOop)bucket[1]; f->do_oop(&o); bucket += 2; } } } }