# HG changeset patch # User anoll # Date 1393830254 -3600 # Node ID 0f438571f27837b89ec122203ecec10a129d19ee # Parent 1c9f21f3fbf419cac77597bbb07e45d62a576ae6 8035946: Use ResourceHashtable for dependency checking Summary: Use ResourceHashtable for dependency checking and delete GenericHashtable Reviewed-by: kvn, coleenp diff -r 1c9f21f3fbf4 -r 0f438571f278 hotspot/src/share/vm/code/dependencies.cpp --- a/hotspot/src/share/vm/code/dependencies.cpp Fri Feb 28 09:30:20 2014 -0800 +++ b/hotspot/src/share/vm/code/dependencies.cpp Mon Mar 03 08:04:14 2014 +0100 @@ -725,13 +725,13 @@ } // ----------------- DependencySignature -------------------------------------- -bool DependencySignature::equals(DependencySignature* sig) const { - if ((type() != sig->type()) || (args_count() != sig->args_count())) { +bool DependencySignature::equals(DependencySignature const& s1, DependencySignature const& s2) { + if ((s1.type() != s2.type()) || (s1.args_count() != s2.args_count())) { return false; } - for (int i = 0; i < sig->args_count(); i++) { - if (arg(i) != sig->arg(i)) { + for (int i = 0; i < s1.args_count(); i++) { + if (s1.arg(i) != s2.arg(i)) { return false; } } diff -r 1c9f21f3fbf4 -r 0f438571f278 hotspot/src/share/vm/code/dependencies.hpp --- a/hotspot/src/share/vm/code/dependencies.hpp Fri Feb 28 09:30:20 2014 -0800 +++ b/hotspot/src/share/vm/code/dependencies.hpp Mon Mar 03 08:04:14 2014 +0100 @@ -527,7 +527,7 @@ }; -class DependencySignature : public GenericHashtableEntry { +class DependencySignature : public ResourceObj { private: int _args_count; uintptr_t _argument_hash[Dependencies::max_arg_count]; @@ -542,12 +542,13 @@ } } - bool equals(DependencySignature* sig) const; - uintptr_t key() const { return _argument_hash[0] >> 2; } + static bool equals(DependencySignature const& s1, DependencySignature const& s2); + static unsigned hash (DependencySignature const& s1) { return s1.arg(0) >> 2; } int args_count() const { return _args_count; } uintptr_t arg(int idx) const { return _argument_hash[idx]; } Dependencies::DepType type() const { return _type; } + }; diff -r 1c9f21f3fbf4 -r 0f438571f278 hotspot/src/share/vm/code/nmethod.cpp --- a/hotspot/src/share/vm/code/nmethod.cpp Fri Feb 28 09:30:20 2014 -0800 +++ b/hotspot/src/share/vm/code/nmethod.cpp Mon Mar 03 08:04:14 2014 +0100 @@ -39,6 +39,7 @@ #include "prims/jvmtiImpl.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/sweeper.hpp" +#include "utilities/resourceHash.hpp" #include "utilities/dtrace.hpp" #include "utilities/events.hpp" #include "utilities/xmlstream.hpp" @@ -2135,7 +2136,11 @@ // Turn off dependency tracing while actually testing dependencies. NOT_PRODUCT( FlagSetting fs(TraceDependencies, false) ); - GenericHashtable* table = new GenericHashtable(11027); + typedef ResourceHashtable DepTable; + + DepTable* table = new DepTable(); + // Iterate over live nmethods and check dependencies of all nmethods that are not // marked for deoptimization. A particular dependency is only checked once. for(nmethod* nm = CodeCache::alive_nmethod(CodeCache::first()); nm != NULL; nm = CodeCache::alive_nmethod(CodeCache::next(nm))) { @@ -2143,9 +2148,10 @@ for (Dependencies::DepStream deps(nm); deps.next(); ) { // Construct abstraction of a dependency. DependencySignature* current_sig = new DependencySignature(deps); - // Determine if 'deps' is already checked. table->add() returns - // 'true' if the dependency was added (i.e., was not in the hashtable). - if (table->add(current_sig)) { + + // Determine if dependency is already checked. table->put(...) returns + // 'true' if the dependency is added (i.e., was not in the hashtable). + if (table->put(*current_sig, 1)) { if (deps.check_dependency() != NULL) { // Dependency checking failed. Print out information about the failed // dependency and finally fail with an assert. We can fail here, since diff -r 1c9f21f3fbf4 -r 0f438571f278 hotspot/src/share/vm/utilities/hashtable.cpp --- a/hotspot/src/share/vm/utilities/hashtable.cpp Fri Feb 28 09:30:20 2014 -0800 +++ b/hotspot/src/share/vm/utilities/hashtable.cpp Mon Mar 03 08:04:14 2014 +0100 @@ -25,7 +25,6 @@ #include "precompiled.hpp" #include "classfile/altHashing.hpp" #include "classfile/javaClasses.hpp" -#include "code/dependencies.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "memory/resourceArea.hpp" @@ -353,116 +352,6 @@ #endif -template GenericHashtable::GenericHashtable(int size, bool C_heap, MEMFLAGS memflag) { - assert(size > 0, " Invalid hashtable size"); - _size = size; - _C_heap = C_heap; - _memflag = memflag; - // Perform subtype-specific resource allocation - _items = (C_heap) ? NEW_C_HEAP_ARRAY(T*, size, memflag) : NEW_RESOURCE_ARRAY(T*, size); - memset(_items, 0, sizeof(T*) * size); - - DEBUG_ONLY(_num_items = 0;) -} - -template GenericHashtable::~GenericHashtable() { - if (on_C_heap()) { - // Check backing array - for (int i = 0; i < size(); i++) { - T* item = head(i); - // Delete all items in linked list - while (item != NULL) { - T* next_item = item->next(); - delete item; - DEBUG_ONLY(_num_items--); - item = next_item; - } - } - FREE_C_HEAP_ARRAY(T*, _items, _memflag); - _items = NULL; - assert (_num_items == 0, "Not all memory released"); - } -} - -/** - * Return a pointer to the item 'I' that is stored in the hashtable for - * which match_item->equals(I) == true. If no such item is found, NULL - * is returned. - */ -template T* GenericHashtable::contains(T* match_item) { - if (match_item != NULL) { - int idx = index(match_item); - return contains_impl(match_item, idx); - } - return NULL; -} - -/** - * Add item to the hashtable. Return 'true' if the item was added - * and false otherwise. - */ -template bool GenericHashtable::add(T* item) { - if (item != NULL) { - int idx = index(item); - T* found_item = contains_impl(item, idx); - if (found_item == NULL) { - T* list_head = head(idx); - item->set_next(list_head); - item->set_prev(NULL); - - if (list_head != NULL) { - list_head->set_prev(item); - } - set_head(item, idx); - DEBUG_ONLY(_num_items++); - return true; - } - } - return false; -} - -/** - * Removes an item 'I' from the hashtable, if present. 'I' is removed, if - * match_item->equals(I) == true. Removing an item from the hashtable does - * not free memory. - */ -template T* GenericHashtable::remove(T* match_item) { - if (match_item != NULL) { - int idx = index(match_item); - T* found_item = contains_impl(match_item, idx); - if (found_item != NULL) { - // Remove item from linked list - T* prev = found_item->prev(); - T* next = found_item->next(); - if (prev != NULL) { - prev->set_next(next); - } else { - set_head(next, idx); - } - if (next != NULL) { - next->set_prev(prev); - } - - DEBUG_ONLY(_num_items--); - return found_item; - } - } - return NULL; -} - - -template T* GenericHashtable::contains_impl(T* item, int idx) { - T* current_item = head(idx); - while (current_item != NULL) { - if (current_item->equals(item)) { - return current_item; - } - current_item = current_item->next(); - } - return NULL; -} - - // Explicitly instantiate these types template class Hashtable; template class Hashtable; @@ -482,5 +371,3 @@ template class BasicHashtable; template class BasicHashtable; template class BasicHashtable; - -template class GenericHashtable; diff -r 1c9f21f3fbf4 -r 0f438571f278 hotspot/src/share/vm/utilities/hashtable.hpp --- a/hotspot/src/share/vm/utilities/hashtable.hpp Fri Feb 28 09:30:20 2014 -0800 +++ b/hotspot/src/share/vm/utilities/hashtable.hpp Mon Mar 03 08:04:14 2014 +0100 @@ -327,86 +327,4 @@ } }; - -/* - * Usage of GenericHashtable: - * - * class X : public GenericHashtableEntry { - * - * // Implement virtual functions in class X - * bool equals(X* sig) const; - * uintptr_t hash() const; - * }; - * - * void foo() { - * GenericHashtable* table = new GenericHashtable(11027, false); - * - * X* elem = new X(); - * table->add(elem); - * table->contains(elem); - * } - * - * You can choose other allocation types as well. For example, to store the hashtable to a - * particular region (CHeapObj) simply replace ResourceObj with the desired type: - * - * class X : public GenericHashtableEntry > { ... }; - * - * To make the destructor (and remove) of the hashtable work: - * 1) override the delete operator of X - * 2) provide a destructor of the X - * - * You may also find it convenient to override the new operator. - * - * If you use this templates do not forget to add an explicit initialization - * (at the end of hashtable.cpp). - * - * template class GenericHashtable; - */ -template class GenericHashtableEntry : public M { - private: - T* _next; - T* _prev; - public: - // Must be implemented by subclass. - virtual uintptr_t key() const = 0; - virtual bool equals(T* other) const = 0; - - T* next() const { return _next; } - T* prev() const { return _prev; } - void set_next(T* item) { _next = item; } - void set_prev(T* item) { _prev = item; } - - // Constructor and destructor - GenericHashtableEntry() : _next(NULL), _prev(NULL) { }; - virtual ~GenericHashtableEntry() {}; -}; - -template class GenericHashtable : public M { - private: - T** _items; - int _size; - bool _C_heap; - MEMFLAGS _memflag; - - // Accessor methods - T* head (int idx) const { return _items[idx]; } - void set_head(T* item, int idx) { _items[idx] = item; } - int index (T* item) { assert(item != NULL, "missing null check"); return item->key() % size(); } - - // Helper function - T* contains_impl(T* item, int idx); - - DEBUG_ONLY(int _num_items;) - public: - GenericHashtable(int size, bool C_heap = false, MEMFLAGS memflag = mtNone); - ~GenericHashtable(); - T* contains(T* match_item); - T* remove (T* match_item); - bool add (T* item); - - - bool on_C_heap() const { return _C_heap; } - int size() const { return _size; } -}; - #endif // SHARE_VM_UTILITIES_HASHTABLE_HPP diff -r 1c9f21f3fbf4 -r 0f438571f278 hotspot/src/share/vm/utilities/resourceHash.hpp --- a/hotspot/src/share/vm/utilities/resourceHash.hpp Fri Feb 28 09:30:20 2014 -0800 +++ b/hotspot/src/share/vm/utilities/resourceHash.hpp Mon Mar 03 08:04:14 2014 +0100 @@ -105,14 +105,20 @@ } } - // Inserts or replaces a value in the table - void put(K const& key, V const& value) { + /** + * Inserts or replaces a value in the table. + * @return: true: if a new item is added + * false: if the item already existed and the value is updated + */ + bool put(K const& key, V const& value) { unsigned hv = HASH(key); Node** ptr = lookup_node(hv, key); if (*ptr != NULL) { (*ptr)->_value = value; + return false; } else { *ptr = new Node(hv, key, value); + return true; } }