Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/utilities/hashtable.hpp
32285 views
/*1* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_VM_UTILITIES_HASHTABLE_HPP25#define SHARE_VM_UTILITIES_HASHTABLE_HPP2627#include "classfile/classLoaderData.hpp"28#include "memory/allocation.hpp"29#include "oops/oop.hpp"30#include "oops/symbol.hpp"31#include "runtime/handles.hpp"3233// This is a generic hashtable, designed to be used for the symbol34// and string tables.35//36// It is implemented as an open hash table with a fixed number of buckets.37//38// %note:39// - TableEntrys are allocated in blocks to reduce the space overhead.40414243template <MEMFLAGS F> class BasicHashtableEntry : public CHeapObj<F> {44friend class VMStructs;45private:46unsigned int _hash; // 32-bit hash for item4748// Link to next element in the linked list for this bucket. EXCEPT49// bit 0 set indicates that this entry is shared and must not be50// unlinked from the table. Bit 0 is set during the dumping of the51// archive. Since shared entries are immutable, _next fields in the52// shared entries will not change. New entries will always be53// unshared and since pointers are align, bit 0 will always remain 054// with no extra effort.55BasicHashtableEntry<F>* _next;5657// Windows IA64 compiler requires subclasses to be able to access these58protected:59// Entry objects should not be created, they should be taken from the60// free list with BasicHashtable.new_entry().61BasicHashtableEntry() { ShouldNotReachHere(); }62// Entry objects should not be destroyed. They should be placed on63// the free list instead with BasicHashtable.free_entry().64~BasicHashtableEntry() { ShouldNotReachHere(); }6566public:6768unsigned int hash() const { return _hash; }69void set_hash(unsigned int hash) { _hash = hash; }70unsigned int* hash_addr() { return &_hash; }7172static BasicHashtableEntry<F>* make_ptr(BasicHashtableEntry<F>* p) {73return (BasicHashtableEntry*)((intptr_t)p & -2);74}7576BasicHashtableEntry<F>* next() const {77return make_ptr(_next);78}7980void set_next(BasicHashtableEntry<F>* next) {81_next = next;82}8384BasicHashtableEntry<F>** next_addr() {85return &_next;86}8788bool is_shared() const {89return ((intptr_t)_next & 1) != 0;90}9192void set_shared() {93_next = (BasicHashtableEntry<F>*)((intptr_t)_next | 1);94}95};96979899template <class T, MEMFLAGS F> class HashtableEntry : public BasicHashtableEntry<F> {100friend class VMStructs;101private:102T _literal; // ref to item in table.103104public:105// Literal106T literal() const { return _literal; }107T* literal_addr() { return &_literal; }108void set_literal(T s) { _literal = s; }109110HashtableEntry* next() const {111return (HashtableEntry*)BasicHashtableEntry<F>::next();112}113HashtableEntry** next_addr() {114return (HashtableEntry**)BasicHashtableEntry<F>::next_addr();115}116};117118119120template <MEMFLAGS F> class HashtableBucket : public CHeapObj<F> {121friend class VMStructs;122private:123// Instance variable124BasicHashtableEntry<F>* _entry;125126public:127// Accessing128void clear() { _entry = NULL; }129130// The following methods use order access methods to avoid race131// conditions in multiprocessor systems.132BasicHashtableEntry<F>* get_entry() const;133void set_entry(BasicHashtableEntry<F>* l);134135// The following method is not MT-safe and must be done under lock.136BasicHashtableEntry<F>** entry_addr() { return &_entry; }137};138139140template <MEMFLAGS F> class BasicHashtable : public CHeapObj<F> {141friend class VMStructs;142143public:144BasicHashtable(int table_size, int entry_size);145BasicHashtable(int table_size, int entry_size,146HashtableBucket<F>* buckets, int number_of_entries);147148// Sharing support.149void copy_buckets(char** top, char* end);150void copy_table(char** top, char* end);151152// Bucket handling153int hash_to_index(unsigned int full_hash) {154int h = full_hash % _table_size;155assert(h >= 0 && h < _table_size, "Illegal hash value");156return h;157}158159// Reverse the order of elements in each of the buckets.160void reverse();161162private:163// Instance variables164int _table_size;165HashtableBucket<F>* _buckets;166BasicHashtableEntry<F>* volatile _free_list;167char* _first_free_entry;168char* _end_block;169int _entry_size;170volatile int _number_of_entries;171172protected:173174#ifdef ASSERT175int _lookup_count;176int _lookup_length;177void verify_lookup_length(double load);178#endif179180void initialize(int table_size, int entry_size, int number_of_entries);181182// Accessor183int entry_size() const { return _entry_size; }184185// The following method is MT-safe and may be used with caution.186BasicHashtableEntry<F>* bucket(int i);187188// The following method is not MT-safe and must be done under lock.189BasicHashtableEntry<F>** bucket_addr(int i) { return _buckets[i].entry_addr(); }190191// Attempt to get an entry from the free list192BasicHashtableEntry<F>* new_entry_free_list();193194// Table entry management195BasicHashtableEntry<F>* new_entry(unsigned int hashValue);196197// Used when moving the entry to another table198// Clean up links, but do not add to free_list199void unlink_entry(BasicHashtableEntry<F>* entry) {200entry->set_next(NULL);201--_number_of_entries;202}203204// Move over freelist and free block for allocation205void copy_freelist(BasicHashtable* src) {206_free_list = src->_free_list;207src->_free_list = NULL;208_first_free_entry = src->_first_free_entry;209src->_first_free_entry = NULL;210_end_block = src->_end_block;211src->_end_block = NULL;212}213214// Free the buckets in this hashtable215void free_buckets();216217// Helper data structure containing context for the bucket entry unlink process,218// storing the unlinked buckets in a linked list.219// Also avoids the need to pass around these four members as parameters everywhere.220struct BucketUnlinkContext {221int _num_processed;222int _num_removed;223// Head and tail pointers for the linked list of removed entries.224BasicHashtableEntry<F>* _removed_head;225BasicHashtableEntry<F>* _removed_tail;226227BucketUnlinkContext() : _num_processed(0), _num_removed(0), _removed_head(NULL), _removed_tail(NULL) {228}229230void free_entry(BasicHashtableEntry<F>* entry);231};232// Add of bucket entries linked together in the given context to the global free list. This method233// is mt-safe wrt. to other calls of this method.234void bulk_free_entries(BucketUnlinkContext* context);235public:236int table_size() { return _table_size; }237void set_entry(int index, BasicHashtableEntry<F>* entry);238239void add_entry(int index, BasicHashtableEntry<F>* entry);240241void free_entry(BasicHashtableEntry<F>* entry);242243int number_of_entries() { return _number_of_entries; }244245void verify() PRODUCT_RETURN;246};247248249template <class T, MEMFLAGS F> class Hashtable : public BasicHashtable<F> {250friend class VMStructs;251252public:253Hashtable(int table_size, int entry_size)254: BasicHashtable<F>(table_size, entry_size) { }255256Hashtable(int table_size, int entry_size,257HashtableBucket<F>* buckets, int number_of_entries)258: BasicHashtable<F>(table_size, entry_size, buckets, number_of_entries) { }259260// Debugging261void print() PRODUCT_RETURN;262263// Reverse the order of elements in each of the buckets. Hashtable264// entries which refer to objects at a lower address than 'boundary'265// are separated from those which refer to objects at higher266// addresses, and appear first in the list.267void reverse(void* boundary = NULL);268269protected:270271unsigned int compute_hash(Symbol* name) {272return (unsigned int) name->identity_hash();273}274275int index_for(Symbol* name) {276return this->hash_to_index(compute_hash(name));277}278279// Table entry management280HashtableEntry<T, F>* new_entry(unsigned int hashValue, T obj);281282// The following method is MT-safe and may be used with caution.283HashtableEntry<T, F>* bucket(int i) {284return (HashtableEntry<T, F>*)BasicHashtable<F>::bucket(i);285}286287// The following method is not MT-safe and must be done under lock.288HashtableEntry<T, F>** bucket_addr(int i) {289return (HashtableEntry<T, F>**)BasicHashtable<F>::bucket_addr(i);290}291292};293294template <class T, MEMFLAGS F> class RehashableHashtable : public Hashtable<T, F> {295protected:296297enum {298rehash_count = 100,299rehash_multiple = 60300};301302// Check that the table is unbalanced303bool check_rehash_table(int count);304305public:306RehashableHashtable(int table_size, int entry_size)307: Hashtable<T, F>(table_size, entry_size) { }308309RehashableHashtable(int table_size, int entry_size,310HashtableBucket<F>* buckets, int number_of_entries)311: Hashtable<T, F>(table_size, entry_size, buckets, number_of_entries) { }312313314// Function to move these elements into the new table.315void move_to(RehashableHashtable<T, F>* new_table);316static bool use_alternate_hashcode() { return _seed != 0; }317static juint seed() { return _seed; }318319static int literal_size(Symbol *symbol);320static int literal_size(oop oop);321322// The following two are currently not used, but are needed anyway because some323// C++ compilers (MacOS and Solaris) force the instantiation of324// Hashtable<ConstantPool*, mtClass>::dump_table() even though we never call this function325// in the VM code.326static int literal_size(ConstantPool *cp) {Unimplemented(); return 0;}327static int literal_size(Klass *k) {Unimplemented(); return 0;}328329void dump_table(outputStream* st, const char *table_name);330331private:332static juint _seed;333};334335336// Verions of hashtable where two handles are used to compute the index.337338template <class T, MEMFLAGS F> class TwoOopHashtable : public Hashtable<T, F> {339friend class VMStructs;340protected:341TwoOopHashtable(int table_size, int entry_size)342: Hashtable<T, F>(table_size, entry_size) {}343344TwoOopHashtable(int table_size, int entry_size, HashtableBucket<F>* t,345int number_of_entries)346: Hashtable<T, F>(table_size, entry_size, t, number_of_entries) {}347348public:349unsigned int compute_hash(Symbol* name, ClassLoaderData* loader_data) {350unsigned int name_hash = name->identity_hash();351// loader is null with CDS352assert(loader_data != NULL || UseSharedSpaces || DumpSharedSpaces,353"only allowed with shared spaces");354unsigned int loader_hash = loader_data == NULL ? 0 : loader_data->identity_hash();355return name_hash ^ loader_hash;356}357358int index_for(Symbol* name, ClassLoaderData* loader_data) {359return this->hash_to_index(compute_hash(name, loader_data));360}361};362363#endif // SHARE_VM_UTILITIES_HASHTABLE_HPP364365366