8035946: Use ResourceHashtable for dependency checking
authoranoll
Mon, 03 Mar 2014 08:04:14 +0100
changeset 23187 0f438571f278
parent 22930 1c9f21f3fbf4
child 23188 21757c31b2c9
8035946: Use ResourceHashtable for dependency checking Summary: Use ResourceHashtable for dependency checking and delete GenericHashtable Reviewed-by: kvn, coleenp
hotspot/src/share/vm/code/dependencies.cpp
hotspot/src/share/vm/code/dependencies.hpp
hotspot/src/share/vm/code/nmethod.cpp
hotspot/src/share/vm/utilities/hashtable.cpp
hotspot/src/share/vm/utilities/hashtable.hpp
hotspot/src/share/vm/utilities/resourceHash.hpp
--- 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;
     }
   }