# HG changeset patch # User kzhaldyb # Date 1471868026 -10800 # Mon Aug 22 15:13:46 2016 +0300 # Node ID 4e4d5ee654e9017671c890295a499c84496e513a # Parent f37577c20a6bcad942dc58b61664d48097279015 8164230: Convert TestCodeCacheRemSet_test to GTest Reviewed-by: duke diff --git a/src/share/vm/gc/g1/g1CodeCacheRemSet.cpp b/src/share/vm/gc/g1/g1CodeCacheRemSet.cpp --- a/src/share/vm/gc/g1/g1CodeCacheRemSet.cpp +++ b/src/share/vm/gc/g1/g1CodeCacheRemSet.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "code/codeCache.hpp" #include "code/nmethod.hpp" +#include "gc/g1/g1CodeCacheRemSet.internal.hpp" #include "gc/g1/g1CodeCacheRemSet.hpp" #include "gc/g1/heapRegion.hpp" #include "memory/heap.hpp" @@ -33,51 +34,6 @@ #include "utilities/hashtable.inline.hpp" #include "utilities/stack.inline.hpp" -class CodeRootSetTable : public Hashtable { - friend class G1CodeRootSetTest; - typedef HashtableEntry Entry; - - 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(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::entry_size(); } - - void copy_to(CodeRootSetTable* new_table); - void nmethods_do(CodeBlobClosure* blk); - - template - 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() { @@ -348,67 +304,3 @@ 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 diff --git a/src/share/vm/gc/g1/g1CodeCacheRemSet.internal.hpp b/src/share/vm/gc/g1/g1CodeCacheRemSet.internal.hpp new file mode 100644 --- /dev/null +++ b/src/share/vm/gc/g1/g1CodeCacheRemSet.internal.hpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_VM_GC_G1_G1CODECACHEREMSET_INTERNAL_HPP +#define SHARE_VM_GC_G1_G1CODECACHEREMSET_INTERNAL_HPP + +class CodeRootSetTable : public Hashtable { + friend class G1CodeRootSetTest; + typedef HashtableEntry Entry; + + 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(size, sizeof(Entry)), _purge_next(NULL) {} + ~CodeRootSetTable(); + + // Needs to be protected by locks + bool add(nmethod* nm); + bool remove(nmethod* nm); + + // Can be called without locking + bool contains(nmethod* nm); + + int entry_size() const { return BasicHashtable::entry_size(); } + + void copy_to(CodeRootSetTable* new_table); + void nmethods_do(CodeBlobClosure* blk); + + template + 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(); +}; + +#endif /* SHARE_VM_GC_G1_G1CODECACHEREMSET_INTERNAL_HPP */ diff --git a/src/share/vm/utilities/internalVMTests.cpp b/src/share/vm/utilities/internalVMTests.cpp --- a/src/share/vm/utilities/internalVMTests.cpp +++ b/src/share/vm/utilities/internalVMTests.cpp @@ -92,7 +92,6 @@ run_unit_test(TestOldFreeSpaceCalculation_test); run_unit_test(TestG1BiasedArray_test); run_unit_test(TestBufferingOopClosure_test); - run_unit_test(TestCodeCacheRemSet_test); if (UseG1GC) { run_unit_test(FreeRegionList_test); run_unit_test(IHOP_test); diff --git a/test/native/gc/g1/test_g1CodeCacheRemSet.cpp b/test/native/gc/g1/test_g1CodeCacheRemSet.cpp new file mode 100644 --- /dev/null +++ b/test/native/gc/g1/test_g1CodeCacheRemSet.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "gc/g1/g1CodeCacheRemSet.internal.hpp" +#include "gc/g1/g1CodeCacheRemSet.hpp" +#include "unittest.hpp" + +class G1CodeRootSetTest : public ::testing::Test { + private: + G1CodeRootSet root_set; + + public: + + size_t getThreshold() { + return root_set.Threshold; + } + + CodeRootSetTable* getPurgeList() { + return CodeRootSetTable::_purge_list; + } + + G1CodeRootSet* getG1CodeRootSet() { + return &root_set; + } +}; + +TEST_VM_F(G1CodeRootSetTest, g1_code_cache_rem_set) { + G1CodeRootSet* root_set = getG1CodeRootSet(); + + ASSERT_TRUE(root_set->is_empty()) << "Code root set must be initially empty " + "but is not."; + + ASSERT_EQ(G1CodeRootSet::static_mem_size(), sizeof (void*)) << + "The code root set's static memory usage is incorrect, " + << G1CodeRootSet::static_mem_size() << " bytes"; + + root_set->add((nmethod*) 1); + ASSERT_EQ(root_set->length(), (size_t) 1) << "Added exactly one element, but" + " set contains " << root_set->length() << " elements"; + + const size_t num_to_add = (size_t) getThreshold() + 1; + + for (size_t i = 1; i <= num_to_add; i++) { + root_set->add((nmethod*) 1); + } + ASSERT_EQ(root_set->length(), (size_t) 1) + << "Duplicate detection should not have increased the set size but " + << "is " << root_set->length(); + + for (size_t i = 2; i <= num_to_add; i++) { + root_set->add((nmethod*) (uintptr_t) (i)); + } + + ASSERT_EQ(root_set->length(), num_to_add) + << "After adding in total " << num_to_add << " distinct code roots, " + "they need to be in the set, but there are only " << root_set->length(); + + ASSERT_NE(getPurgeList(), (CodeRootSetTable*) NULL) + << "should have grown to large hashtable"; + + size_t num_popped = 0; + for (size_t i = 1; i <= num_to_add; i++) { + bool removed = root_set->remove((nmethod*) i); + if (removed) { + num_popped += 1; + } else { + break; + } + } + ASSERT_EQ(num_popped, num_to_add) + << "Managed to pop " << num_popped << " code roots, but only " + << num_to_add << " were added"; + ASSERT_NE(getPurgeList(), (CodeRootSetTable*) NULL) + << "should have grown to large hashtable"; + + G1CodeRootSet::purge(); + + ASSERT_EQ(getPurgeList(), (CodeRootSetTable*) NULL) + << "should have purged old small tables"; +}