< prev index next >

src/share/vm/gc/g1/g1CodeCacheRemSet.cpp

Print this page
rev 11782 : 8164230: Convert TestCodeCacheRemSet_test to GTest
Reviewed-by: duke

@@ -23,70 +23,26 @@
  */
 
 #include "precompiled.hpp"
 #include "code/codeCache.hpp"
 #include "code/nmethod.hpp"
+#include "gc/g1/g1CodeRootSetTable.hpp"
 #include "gc/g1/g1CodeCacheRemSet.hpp"
 #include "gc/g1/heapRegion.hpp"
 #include "memory/heap.hpp"
 #include "memory/iterator.hpp"
 #include "oops/oop.inline.hpp"
 #include "utilities/hashtable.inline.hpp"
 #include "utilities/stack.inline.hpp"
 
-class CodeRootSetTable : public Hashtable<nmethod*, mtGC> {
-  friend class G1CodeRootSetTest;
-  typedef HashtableEntry<nmethod*, mtGC> Entry;
+G1CodeRootSetTable* volatile G1CodeRootSetTable::_purge_list = NULL;
 
-  static CodeRootSetTable* volatile _purge_list;
-
-  CodeRootSetTable* _purge_next;
-
-  unsigned int compute_hash(nmethod* nm) {
-    uintptr_t hash = (uintptr_t)nm;
-    return hash ^ (hash >> 7); // code heap blocks are 128byte aligned
-  }
-
-  void remove_entry(Entry* e, Entry* previous);
-  Entry* new_entry(nmethod* nm);
-
- public:
-  CodeRootSetTable(int size) : Hashtable<nmethod*, mtGC>(size, sizeof(Entry)), _purge_next(NULL) {}
-  ~CodeRootSetTable();
-
-  // Needs to be protected locks
-  bool add(nmethod* nm);
-  bool remove(nmethod* nm);
-
-  // Can be called without locking
-  bool contains(nmethod* nm);
-
-  int entry_size() const { return BasicHashtable<mtGC>::entry_size(); }
-
-  void copy_to(CodeRootSetTable* new_table);
-  void nmethods_do(CodeBlobClosure* blk);
-
-  template<typename CB>
-  int remove_if(CB& should_remove);
-
-  static void purge_list_append(CodeRootSetTable* tbl);
-  static void purge();
-
-  static size_t static_mem_size() {
-    return sizeof(_purge_list);
-  }
-
-  size_t mem_size();
-};
-
-CodeRootSetTable* volatile CodeRootSetTable::_purge_list = NULL;
-
-size_t CodeRootSetTable::mem_size() {
-  return sizeof(CodeRootSetTable) + (entry_size() * number_of_entries()) + (sizeof(HashtableBucket<mtGC>) * table_size());
+size_t G1CodeRootSetTable::mem_size() {
+  return sizeof(G1CodeRootSetTable) + (entry_size() * number_of_entries()) + (sizeof(HashtableBucket<mtGC>) * table_size());
 }
 
-CodeRootSetTable::Entry* CodeRootSetTable::new_entry(nmethod* nm) {
+G1CodeRootSetTable::Entry* G1CodeRootSetTable::new_entry(nmethod* nm) {
   unsigned int hash = compute_hash(nm);
   Entry* entry = (Entry*) new_entry_free_list();
   if (entry == NULL) {
     entry = (Entry*) NEW_C_HEAP_ARRAY2(char, entry_size(), mtGC, CURRENT_PC);
   }

@@ -94,11 +50,11 @@
   entry->set_hash(hash);
   entry->set_literal(nm);
   return entry;
 }
 
-void CodeRootSetTable::remove_entry(Entry* e, Entry* previous) {
+void G1CodeRootSetTable::remove_entry(Entry* e, Entry* previous) {
   int index = hash_to_index(e->hash());
   assert((e == bucket(index)) == (previous == NULL), "if e is the first entry then previous should be null");
 
   if (previous == NULL) {
     set_entry(index, e->next());

@@ -106,11 +62,11 @@
     previous->set_next(e->next());
   }
   free_entry(e);
 }
 
-CodeRootSetTable::~CodeRootSetTable() {
+G1CodeRootSetTable::~G1CodeRootSetTable() {
   for (int index = 0; index < table_size(); ++index) {
     for (Entry* e = bucket(index); e != NULL; ) {
       Entry* to_remove = e;
       // read next before freeing.
       e = e->next();

@@ -123,31 +79,31 @@
   for (BasicHashtableEntry<mtGC>* e = new_entry_free_list(); e != NULL; e = new_entry_free_list()) {
     FREE_C_HEAP_ARRAY(char, e);
   }
 }
 
-bool CodeRootSetTable::add(nmethod* nm) {
+bool G1CodeRootSetTable::add(nmethod* nm) {
   if (!contains(nm)) {
     Entry* e = new_entry(nm);
     int index = hash_to_index(e->hash());
     add_entry(index, e);
     return true;
   }
   return false;
 }
 
-bool CodeRootSetTable::contains(nmethod* nm) {
+bool G1CodeRootSetTable::contains(nmethod* nm) {
   int index = hash_to_index(compute_hash(nm));
   for (Entry* e = bucket(index); e != NULL; e = e->next()) {
     if (e->literal() == nm) {
       return true;
     }
   }
   return false;
 }
 
-bool CodeRootSetTable::remove(nmethod* nm) {
+bool G1CodeRootSetTable::remove(nmethod* nm) {
   int index = hash_to_index(compute_hash(nm));
   Entry* previous = NULL;
   for (Entry* e = bucket(index); e != NULL; previous = e, e = e->next()) {
     if (e->literal() == nm) {
       remove_entry(e, previous);

@@ -155,29 +111,29 @@
     }
   }
   return false;
 }
 
-void CodeRootSetTable::copy_to(CodeRootSetTable* new_table) {
+void G1CodeRootSetTable::copy_to(G1CodeRootSetTable* new_table) {
   for (int index = 0; index < table_size(); ++index) {
     for (Entry* e = bucket(index); e != NULL; e = e->next()) {
       new_table->add(e->literal());
     }
   }
   new_table->copy_freelist(this);
 }
 
-void CodeRootSetTable::nmethods_do(CodeBlobClosure* blk) {
+void G1CodeRootSetTable::nmethods_do(CodeBlobClosure* blk) {
   for (int index = 0; index < table_size(); ++index) {
     for (Entry* e = bucket(index); e != NULL; e = e->next()) {
       blk->do_code_blob(e->literal());
     }
   }
 }
 
 template<typename CB>
-int CodeRootSetTable::remove_if(CB& should_remove) {
+int G1CodeRootSetTable::remove_if(CB& should_remove) {
   int num_removed = 0;
   for (int index = 0; index < table_size(); ++index) {
     Entry* previous = NULL;
     Entry* e = bucket(index);
     while (e != NULL) {

@@ -196,56 +152,56 @@
 
 G1CodeRootSet::~G1CodeRootSet() {
   delete _table;
 }
 
-CodeRootSetTable* G1CodeRootSet::load_acquire_table() {
-  return (CodeRootSetTable*) OrderAccess::load_ptr_acquire(&_table);
+G1CodeRootSetTable* G1CodeRootSet::load_acquire_table() {
+  return (G1CodeRootSetTable*) OrderAccess::load_ptr_acquire(&_table);
 }
 
 void G1CodeRootSet::allocate_small_table() {
-  CodeRootSetTable* temp = new CodeRootSetTable(SmallSize);
+  G1CodeRootSetTable* temp = new G1CodeRootSetTable(SmallSize);
 
   OrderAccess::release_store_ptr(&_table, temp);
 }
 
-void CodeRootSetTable::purge_list_append(CodeRootSetTable* table) {
+void G1CodeRootSetTable::purge_list_append(G1CodeRootSetTable* table) {
   for (;;) {
     table->_purge_next = _purge_list;
-    CodeRootSetTable* old = (CodeRootSetTable*) Atomic::cmpxchg_ptr(table, &_purge_list, table->_purge_next);
+    G1CodeRootSetTable* old = (G1CodeRootSetTable*) Atomic::cmpxchg_ptr(table, &_purge_list, table->_purge_next);
     if (old == table->_purge_next) {
       break;
     }
   }
 }
 
-void CodeRootSetTable::purge() {
-  CodeRootSetTable* table = _purge_list;
+void G1CodeRootSetTable::purge() {
+  G1CodeRootSetTable* table = _purge_list;
   _purge_list = NULL;
   while (table != NULL) {
-    CodeRootSetTable* to_purge = table;
+    G1CodeRootSetTable* to_purge = table;
     table = table->_purge_next;
     delete to_purge;
   }
 }
 
 void G1CodeRootSet::move_to_large() {
-  CodeRootSetTable* temp = new CodeRootSetTable(LargeSize);
+  G1CodeRootSetTable* temp = new G1CodeRootSetTable(LargeSize);
 
   _table->copy_to(temp);
 
-  CodeRootSetTable::purge_list_append(_table);
+  G1CodeRootSetTable::purge_list_append(_table);
 
   OrderAccess::release_store_ptr(&_table, temp);
 }
 
 void G1CodeRootSet::purge() {
-  CodeRootSetTable::purge();
+  G1CodeRootSetTable::purge();
 }
 
 size_t G1CodeRootSet::static_mem_size() {
-  return CodeRootSetTable::static_mem_size();
+  return G1CodeRootSetTable::static_mem_size();
 }
 
 void G1CodeRootSet::add(nmethod* method) {
   bool added = false;
   if (is_empty()) {

@@ -276,11 +232,11 @@
          (_length == (size_t)_table->number_of_entries()), "sizes should match");
   return removed;
 }
 
 bool G1CodeRootSet::contains(nmethod* method) {
-  CodeRootSetTable* table = load_acquire_table(); // contains() may be called outside of lock, so ensure mem sync.
+  G1CodeRootSetTable* table = load_acquire_table(); // contains() may be called outside of lock, so ensure mem sync.
   if (table != NULL) {
     return table->contains(method);
   }
   return false;
 }

@@ -346,69 +302,5 @@
   }
   if (_length == 0) {
     clear();
   }
 }
-
-#ifndef PRODUCT
-
-class G1CodeRootSetTest {
- public:
-  static void test() {
-    {
-      G1CodeRootSet set1;
-      assert(set1.is_empty(), "Code root set must be initially empty but is not.");
-
-      assert(G1CodeRootSet::static_mem_size() == sizeof(void*),
-             "The code root set's static memory usage is incorrect, " SIZE_FORMAT " bytes", G1CodeRootSet::static_mem_size());
-
-      set1.add((nmethod*)1);
-      assert(set1.length() == 1, "Added exactly one element, but set contains "
-             SIZE_FORMAT " elements", set1.length());
-
-      const size_t num_to_add = (size_t)G1CodeRootSet::Threshold + 1;
-
-      for (size_t i = 1; i <= num_to_add; i++) {
-        set1.add((nmethod*)1);
-      }
-      assert(set1.length() == 1,
-             "Duplicate detection should not have increased the set size but "
-             "is " SIZE_FORMAT, set1.length());
-
-      for (size_t i = 2; i <= num_to_add; i++) {
-        set1.add((nmethod*)(uintptr_t)(i));
-      }
-      assert(set1.length() == num_to_add,
-             "After adding in total " SIZE_FORMAT " distinct code roots, they "
-             "need to be in the set, but there are only " SIZE_FORMAT,
-             num_to_add, set1.length());
-
-      assert(CodeRootSetTable::_purge_list != NULL, "should have grown to large hashtable");
-
-      size_t num_popped = 0;
-      for (size_t i = 1; i <= num_to_add; i++) {
-        bool removed = set1.remove((nmethod*)i);
-        if (removed) {
-          num_popped += 1;
-        } else {
-          break;
-        }
-      }
-      assert(num_popped == num_to_add,
-             "Managed to pop " SIZE_FORMAT " code roots, but only " SIZE_FORMAT " "
-             "were added", num_popped, num_to_add);
-      assert(CodeRootSetTable::_purge_list != NULL, "should have grown to large hashtable");
-
-      G1CodeRootSet::purge();
-
-      assert(CodeRootSetTable::_purge_list == NULL, "should have purged old small tables");
-
-    }
-
-  }
-};
-
-void TestCodeCacheRemSet_test() {
-  G1CodeRootSetTest::test();
-}
-
-#endif
< prev index next >