8035946: Use ResourceHashtable for dependency checking
Summary: Use ResourceHashtable for dependency checking and delete GenericHashtable
Reviewed-by: kvn, coleenp
--- 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;
}
}
--- 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<DependencySignature, ResourceObj> {
+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; }
+
};
--- 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<DependencySignature, ResourceObj>* table = new GenericHashtable<DependencySignature, ResourceObj>(11027);
+ typedef ResourceHashtable<DependencySignature, int, &DependencySignature::hash,
+ &DependencySignature::equals, 11027> 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
--- 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<class T, class M> GenericHashtable<T, M>::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<class T, class M> GenericHashtable<T, M>::~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<class T, class F> T* GenericHashtable<T, F>::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<class T, class F> bool GenericHashtable<T, F>::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<class T, class F> T* GenericHashtable<T, F>::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<class T, class F> T* GenericHashtable<T, F>::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<ConstantPool*, mtClass>;
template class Hashtable<Symbol*, mtSymbol>;
@@ -482,5 +371,3 @@
template class BasicHashtable<mtSymbol>;
template class BasicHashtable<mtCode>;
template class BasicHashtable<mtInternal>;
-
-template class GenericHashtable<DependencySignature, ResourceObj>;
--- 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<X, ResourceObj> {
- *
- * // Implement virtual functions in class X
- * bool equals(X* sig) const;
- * uintptr_t hash() const;
- * };
- *
- * void foo() {
- * GenericHashtable<X, ResourceObj>* table = new GenericHashtable<X, ResourceObj>(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<type>) simply replace ResourceObj with the desired type:
- *
- * class X : public GenericHashtableEntry<X, CHeapObj<mtCode> > { ... };
- *
- * 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<X, ResourceObj>;
- */
-template <class T, class M> 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 T, class M> 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
--- 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;
}
}