/* * Copyright Amazon.com Inc. 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 "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahMarkBitMap.hpp" #include "gc/shenandoah/shenandoahMarkBitMap.inline.hpp" BEGIN_ALLOW_FORBIDDEN_FUNCTIONS #include END_ALLOW_FORBIDDEN_FUNCTIONS #include "memory/memRegion.hpp" #include "unittest.hpp" #include "utilities/ostream.hpp" #include "utilities/vmassert_reinstall.hpp" #include "utilities/vmassert_uninstall.hpp" // These tests will all be skipped (unless Shenandoah becomes the default // collector). To execute these tests, you must enable Shenandoah, which // is done with: // // % make exploded-test TEST="gtest:ShenandoahOld*" CONF=release TEST_OPTS="JAVA_OPTIONS=-XX:+UseShenandoahGC -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCMode=generational" // // Please note that these 'unit' tests are really integration tests and rely // on the JVM being initialized. These tests manipulate the state of the // collector in ways that are not compatible with a normal collection run. // If these tests take longer than the minimum time between gc intervals - // or, more likely, if you have them paused in a debugger longer than this // interval - you can expect trouble. These tests will also not run in a build // with asserts enabled because they use APIs that expect to run on a safepoint. #ifdef ASSERT #define SKIP_IF_NOT_SHENANDOAH() \ std::cout << "skipped (debug build)\n"; \ return; #else #define SKIP_IF_NOT_SHENANDOAH() \ if (!UseShenandoahGC) { \ std::cout << "skipped\n"; \ return; \ } #endif static bool _success; static size_t _assertion_failures; #define MarkBitMapAssertEqual(a, b) EXPECT_EQ((a), (b)); if ((a) != (b)) { _assertion_failures++; } #define MarkBitMapAssertTrue(a) EXPECT_TRUE((a)); if ((a) == 0) { _assertion_failures++; } class ShenandoahMarkBitMapTest: public ::testing::Test { protected: static void verify_bitmap_is_empty(HeapWord *start, size_t words_in_heap, ShenandoahMarkBitMap* mbm) { MarkBitMapAssertTrue(mbm->is_bitmap_clear_range(start, start + words_in_heap)); while (words_in_heap-- > 0) { MarkBitMapAssertTrue(!mbm->is_marked(start)); MarkBitMapAssertTrue(!mbm->is_marked_weak(start)); MarkBitMapAssertTrue(!mbm->is_marked_strong(start)); start++; } } static void verify_bitmap_is_weakly_marked(ShenandoahMarkBitMap* mbm, HeapWord* weakly_marked_addresses[], size_t weakly_marked_objects) { for (size_t i = 0; i < weakly_marked_objects; i++) { HeapWord* obj_addr = weakly_marked_addresses[i]; MarkBitMapAssertTrue(mbm->is_marked(obj_addr)); MarkBitMapAssertTrue(mbm->is_marked_weak(obj_addr)); } } static void verify_bitmap_is_strongly_marked(ShenandoahMarkBitMap* mbm, HeapWord* strongly_marked_addresses[], size_t strongly_marked_objects) { for (size_t i = 0; i < strongly_marked_objects; i++) { HeapWord* obj_addr = strongly_marked_addresses[i]; MarkBitMapAssertTrue(mbm->is_marked(obj_addr)); MarkBitMapAssertTrue(mbm->is_marked_strong(obj_addr)); } } static void verify_bitmap_all(ShenandoahMarkBitMap* mbm, HeapWord* all_marked_addresses[], bool is_weakly_marked_object[], bool is_strongly_marked_object[], size_t all_marked_objects, HeapWord* heap_memory, HeapWord* end_of_heap_memory) { HeapWord* last_marked_addr = &heap_memory[-1]; for (size_t i = 0; i < all_marked_objects; i++) { HeapWord* obj_addr = all_marked_addresses[i]; if (is_strongly_marked_object[i]) { MarkBitMapAssertTrue(mbm->is_marked(obj_addr)); MarkBitMapAssertTrue(mbm->is_marked_strong(obj_addr)); } if (is_weakly_marked_object[i]) { MarkBitMapAssertTrue(mbm->is_marked(obj_addr)); MarkBitMapAssertTrue(mbm->is_marked_weak(obj_addr)); } while (++last_marked_addr < obj_addr) { MarkBitMapAssertTrue(!mbm->is_marked(last_marked_addr)); MarkBitMapAssertTrue(!mbm->is_marked_strong(last_marked_addr)); MarkBitMapAssertTrue(!mbm->is_marked_weak(last_marked_addr)); } last_marked_addr = obj_addr; } while (++last_marked_addr < end_of_heap_memory) { MarkBitMapAssertTrue(!mbm->is_marked(last_marked_addr)); MarkBitMapAssertTrue(!mbm->is_marked_strong(last_marked_addr)); MarkBitMapAssertTrue(!mbm->is_marked_weak(last_marked_addr)); } HeapWord* next_marked = (HeapWord*) &heap_memory[0] - 1; for (size_t i = 0; i < all_marked_objects; i++) { next_marked = mbm->get_next_marked_addr(next_marked + 1, end_of_heap_memory); MarkBitMapAssertTrue(mbm->is_marked(next_marked)); MarkBitMapAssertEqual(next_marked, all_marked_addresses[i]); if (is_strongly_marked_object[i]) { MarkBitMapAssertTrue(mbm->is_marked_strong(next_marked)); } if (is_weakly_marked_object[i]) { MarkBitMapAssertTrue(mbm->is_marked_weak(next_marked)); } } // We expect no more marked addresses to be found. Should return limit. HeapWord* sentinel = mbm->get_next_marked_addr(next_marked + 1, end_of_heap_memory); MarkBitMapAssertEqual(sentinel, end_of_heap_memory); HeapWord* prev_marked = end_of_heap_memory + 1; for (int i = (int) all_marked_objects - 1; i >= 0; i--) { prev_marked = mbm->get_prev_marked_addr(&heap_memory[0], prev_marked - 1); MarkBitMapAssertEqual(prev_marked, all_marked_addresses[i]); MarkBitMapAssertTrue(mbm->is_marked(prev_marked)); if (is_strongly_marked_object[i]) { MarkBitMapAssertTrue(mbm->is_marked_strong(prev_marked)); } if (is_weakly_marked_object[i]) { MarkBitMapAssertTrue(mbm->is_marked_weak(prev_marked)); } } // We expect no more marked addresses to be found. should return prev_marked. sentinel = mbm->get_prev_marked_addr(&heap_memory[0], prev_marked - 1); MarkBitMapAssertEqual(sentinel, prev_marked); } public: static bool run_test() { ShenandoahHeap* heap = ShenandoahHeap::heap(); size_t test_heap_size = MIN2(32 * M, heap->max_capacity()); size_t heap_size_words = test_heap_size / HeapWordSize; HeapWord* my_heap_memory = heap->base(); HeapWord* end_of_my_heap = my_heap_memory + heap_size_words; MemRegion heap_descriptor(my_heap_memory, heap_size_words); _success = false; _assertion_failures = 0; size_t bitmap_page_size = UseLargePages ? os::large_page_size() : os::vm_page_size(); size_t bitmap_size_orig = ShenandoahMarkBitMap::compute_size(test_heap_size); size_t bitmap_size = align_up(bitmap_size_orig, bitmap_page_size); size_t bitmap_word_size = (bitmap_size + HeapWordSize - 1) / HeapWordSize; HeapWord* my_bitmap_memory = NEW_C_HEAP_ARRAY(HeapWord, bitmap_word_size, mtGC); MarkBitMapAssertTrue(my_bitmap_memory != nullptr); if (my_bitmap_memory == nullptr) { std::cout <<"Cannot run test because failed to allocate bitmap memory\n" << std::flush; return false; } MemRegion bitmap_descriptor(my_bitmap_memory, bitmap_size / HeapWordSize); ShenandoahMarkBitMap mbm(heap_descriptor, bitmap_descriptor); mbm.clear_range_large(heap_descriptor); verify_bitmap_is_empty((HeapWord*) my_heap_memory, heap_size_words, &mbm); HeapWord* weakly_marked_addresses[] = { (HeapWord*) &my_heap_memory[13], (HeapWord*) &my_heap_memory[14], (HeapWord*) &my_heap_memory[15], (HeapWord*) &my_heap_memory[16], (HeapWord*) &my_heap_memory[176], (HeapWord*) &my_heap_memory[240], (HeapWord*) &my_heap_memory[480], (HeapWord*) &my_heap_memory[1360], (HeapWord*) &my_heap_memory[1488], (HeapWord*) &my_heap_memory[2416], (HeapWord*) &my_heap_memory[5968], (HeapWord*) &my_heap_memory[8191], (HeapWord*) &my_heap_memory[8192], (HeapWord*) &my_heap_memory[8193] }; size_t weakly_marked_objects = sizeof(weakly_marked_addresses) / sizeof(HeapWord*); for (size_t i = 0; i < weakly_marked_objects; i++) { mbm.mark_weak(weakly_marked_addresses[i]); } HeapWord* next_marked = (HeapWord*) &my_heap_memory[0] - 1; for (size_t i = 0; i < weakly_marked_objects; i++) { next_marked = mbm.get_next_marked_addr(next_marked + 1, end_of_my_heap); MarkBitMapAssertEqual(next_marked, weakly_marked_addresses[i]); MarkBitMapAssertTrue(mbm.is_marked(next_marked)); MarkBitMapAssertTrue(mbm.is_marked_weak(next_marked)); MarkBitMapAssertTrue(!mbm.is_marked_strong(next_marked)); } // We expect no more marked addresses to be found. Should return limit. HeapWord* sentinel = mbm.get_next_marked_addr(next_marked + 1, end_of_my_heap); HeapWord* heap_limit = end_of_my_heap; MarkBitMapAssertEqual(sentinel, heap_limit); HeapWord* prev_marked = end_of_my_heap + 1;; for (int i = (int) weakly_marked_objects - 1; i >= 0; i--) { // to be renamed get_prev_marked_addr() prev_marked = mbm.get_prev_marked_addr(&my_heap_memory[0], prev_marked - 1); MarkBitMapAssertEqual(prev_marked, weakly_marked_addresses[i]); MarkBitMapAssertTrue(mbm.is_marked(prev_marked)); MarkBitMapAssertTrue(mbm.is_marked_weak(prev_marked)); MarkBitMapAssertTrue(!mbm.is_marked_strong(prev_marked)); } // We expect no more marked addresses to be found. should return prev_marked. sentinel = mbm.get_prev_marked_addr(&my_heap_memory[0], prev_marked - 1); // MarkBitMapAssertEqual(sentinel, prev_marked); MarkBitMapAssertEqual(sentinel, prev_marked); verify_bitmap_is_weakly_marked(&mbm, weakly_marked_addresses, weakly_marked_objects); HeapWord* strongly_marked_addresses[] = { (HeapWord*) &my_heap_memory[8], (HeapWord*) &my_heap_memory[24], (HeapWord*) &my_heap_memory[32], (HeapWord*) &my_heap_memory[56], (HeapWord*) &my_heap_memory[64], (HeapWord*) &my_heap_memory[168], (HeapWord*) &my_heap_memory[232], (HeapWord*) &my_heap_memory[248], (HeapWord*) &my_heap_memory[256], (HeapWord*) &my_heap_memory[257], (HeapWord*) &my_heap_memory[258], (HeapWord*) &my_heap_memory[259], (HeapWord*) &my_heap_memory[488], (HeapWord*) &my_heap_memory[1352], (HeapWord*) &my_heap_memory[1496], (HeapWord*) &my_heap_memory[2432], (HeapWord*) &my_heap_memory[5960] }; size_t strongly_marked_objects = sizeof(strongly_marked_addresses) / sizeof(HeapWord*); for (size_t i = 0; i < strongly_marked_objects; i++) { bool upgraded = false; mbm.mark_strong(strongly_marked_addresses[i], upgraded); MarkBitMapAssertTrue(!upgraded); } verify_bitmap_is_strongly_marked(&mbm, strongly_marked_addresses, strongly_marked_objects); HeapWord* upgraded_weakly_marked_addresses[] = { (HeapWord*) &my_heap_memory[240], (HeapWord*) &my_heap_memory[1360], }; size_t upgraded_weakly_marked_objects = sizeof(upgraded_weakly_marked_addresses) / sizeof(HeapWord *); for (size_t i = 0; i < upgraded_weakly_marked_objects; i++) { bool upgraded = false; mbm.mark_strong(upgraded_weakly_marked_addresses[i], upgraded); MarkBitMapAssertTrue(upgraded); } verify_bitmap_is_strongly_marked(&mbm, upgraded_weakly_marked_addresses, upgraded_weakly_marked_objects); HeapWord* all_marked_addresses[] = { (HeapWord*) &my_heap_memory[8], /* strongly marked */ (HeapWord*) &my_heap_memory[13], /* weakly marked */ (HeapWord*) &my_heap_memory[14], /* weakly marked */ (HeapWord*) &my_heap_memory[15], /* weakly marked */ (HeapWord*) &my_heap_memory[16], /* weakly marked */ (HeapWord*) &my_heap_memory[24], /* strongly marked */ (HeapWord*) &my_heap_memory[32], /* strongly marked */ (HeapWord*) &my_heap_memory[56], /* strongly marked */ (HeapWord*) &my_heap_memory[64], /* strongly marked */ (HeapWord*) &my_heap_memory[168], /* strongly marked */ (HeapWord*) &my_heap_memory[176], /* weakly marked */ (HeapWord*) &my_heap_memory[232], /* strongly marked */ (HeapWord*) &my_heap_memory[240], /* weakly marked upgraded to strongly marked */ (HeapWord*) &my_heap_memory[248], /* strongly marked */ (HeapWord*) &my_heap_memory[256], /* strongly marked */ (HeapWord*) &my_heap_memory[257], /* strongly marked */ (HeapWord*) &my_heap_memory[258], /* strongly marked */ (HeapWord*) &my_heap_memory[259], /* strongly marked */ (HeapWord*) &my_heap_memory[480], /* weakly marked */ (HeapWord*) &my_heap_memory[488], /* strongly marked */ (HeapWord*) &my_heap_memory[1352], /* strongly marked */ (HeapWord*) &my_heap_memory[1360], /* weakly marked upgraded to strongly marked */ (HeapWord*) &my_heap_memory[1488], /* weakly marked */ (HeapWord*) &my_heap_memory[1496], /* strongly marked */ (HeapWord*) &my_heap_memory[2416], /* weakly marked */ (HeapWord*) &my_heap_memory[2432], /* strongly marked */ (HeapWord*) &my_heap_memory[5960], /* strongly marked */ (HeapWord*) &my_heap_memory[5968], /* weakly marked */ (HeapWord*) &my_heap_memory[8191], /* weakly marked */ (HeapWord*) &my_heap_memory[8192], /* weakly marked */ (HeapWord*) &my_heap_memory[8193] /* weakly marked */ }; size_t all_marked_objects = sizeof(all_marked_addresses) / sizeof(HeapWord*); bool is_weakly_marked_object[] = { false, true, true, true, true, false, false, false, false, false, true, false, true, false, false, false, false, false, true, false, false, true, true, false, true, false, false, true, true, true, true }; bool is_strongly_marked_object[] = { true, false, false, false, false, true, true, true, true, true, false, true, true, true, true, true, true, true, false, true, true, true, false, true, false, true, true, false, false, false, false }; verify_bitmap_all(&mbm, all_marked_addresses, is_weakly_marked_object, is_strongly_marked_object, all_marked_objects, my_heap_memory, end_of_my_heap); MemRegion first_clear_region(&my_heap_memory[168], &my_heap_memory[256]); mbm.clear_range_large(first_clear_region); // Five objects are no longer marked HeapWord* all_marked_addresses_after_first_clear[] = { (HeapWord*) &my_heap_memory[8], /* strongly marked */ (HeapWord*) &my_heap_memory[13], /* weakly marked */ (HeapWord*) &my_heap_memory[14], /* weakly marked */ (HeapWord*) &my_heap_memory[15], /* weakly marked */ (HeapWord*) &my_heap_memory[16], /* weakly marked */ (HeapWord*) &my_heap_memory[24], /* strongly marked */ (HeapWord*) &my_heap_memory[32], /* strongly marked */ (HeapWord*) &my_heap_memory[56], /* strongly marked */ (HeapWord*) &my_heap_memory[64], /* strongly marked */ (HeapWord*) &my_heap_memory[256], /* strongly marked */ (HeapWord*) &my_heap_memory[257], /* strongly marked */ (HeapWord*) &my_heap_memory[258], /* strongly marked */ (HeapWord*) &my_heap_memory[259], /* strongly marked */ (HeapWord*) &my_heap_memory[480], /* weakly marked */ (HeapWord*) &my_heap_memory[488], /* strongly marked */ (HeapWord*) &my_heap_memory[1352], /* strongly marked */ (HeapWord*) &my_heap_memory[1360], /* weakly marked upgraded to strongly marked */ (HeapWord*) &my_heap_memory[1488], /* weakly marked */ (HeapWord*) &my_heap_memory[1496], /* strongly marked */ (HeapWord*) &my_heap_memory[2416], /* weakly marked */ (HeapWord*) &my_heap_memory[2432], /* strongly marked */ (HeapWord*) &my_heap_memory[5960], /* strongly marked */ (HeapWord*) &my_heap_memory[5968], /* weakly marked */ (HeapWord*) &my_heap_memory[8191], /* weakly marked */ (HeapWord*) &my_heap_memory[8192], /* weakly marked */ (HeapWord*) &my_heap_memory[8193] /* weakly marked */ }; size_t all_marked_objects_after_first_clear = sizeof(all_marked_addresses_after_first_clear) / sizeof(HeapWord*); bool is_weakly_marked_object_after_first_clear[] = { false, true, true, true, true, false, false, false, false, false, false, false, false, true, false, false, true, true, false, true, false, false, true, true, true, true }; bool is_strongly_marked_object_after_first_clear[] = { true, false, false, false, false, true, true, true, true, true, true, true, true, false, true, true, true, false, true, false, true, true, false, false, false, false }; verify_bitmap_all(&mbm, all_marked_addresses_after_first_clear, is_weakly_marked_object_after_first_clear, is_strongly_marked_object_after_first_clear, all_marked_objects_after_first_clear, my_heap_memory, end_of_my_heap); MemRegion second_clear_region(&my_heap_memory[1360], &my_heap_memory[2416]); mbm.clear_range_large(second_clear_region); // Five objects are no longer marked HeapWord* all_marked_addresses_after_2nd_clear[] = { (HeapWord*) &my_heap_memory[8], /* strongly marked */ (HeapWord*) &my_heap_memory[13], /* weakly marked */ (HeapWord*) &my_heap_memory[14], /* weakly marked */ (HeapWord*) &my_heap_memory[15], /* weakly marked */ (HeapWord*) &my_heap_memory[16], /* weakly marked */ (HeapWord*) &my_heap_memory[24], /* strongly marked */ (HeapWord*) &my_heap_memory[32], /* strongly marked */ (HeapWord*) &my_heap_memory[56], /* strongly marked */ (HeapWord*) &my_heap_memory[64], /* strongly marked */ (HeapWord*) &my_heap_memory[256], /* strongly marked */ (HeapWord*) &my_heap_memory[257], /* strongly marked */ (HeapWord*) &my_heap_memory[258], /* strongly marked */ (HeapWord*) &my_heap_memory[259], /* strongly marked */ (HeapWord*) &my_heap_memory[480], /* weakly marked */ (HeapWord*) &my_heap_memory[488], /* strongly marked */ (HeapWord*) &my_heap_memory[1352], /* strongly marked */ (HeapWord*) &my_heap_memory[2416], /* weakly marked */ (HeapWord*) &my_heap_memory[2432], /* strongly marked */ (HeapWord*) &my_heap_memory[5960], /* strongly marked */ (HeapWord*) &my_heap_memory[5968], /* weakly marked */ (HeapWord*) &my_heap_memory[8191], /* weakly marked */ (HeapWord*) &my_heap_memory[8192], /* weakly marked */ (HeapWord*) &my_heap_memory[8193] /* weakly marked */ }; size_t all_marked_objects_after_2nd_clear = sizeof(all_marked_addresses_after_2nd_clear) / sizeof(HeapWord*); bool is_weakly_marked_object_after_2nd_clear[] = { false, true, true, true, true, false, false, false, false, false, false, false, false, true, false, false, true, false, false, true, true, true, true }; bool is_strongly_marked_object_after_2nd_clear[] = { true, false, false, false, false, true, true, true, true, true, true, true, true, false, true, true, false, true, true, false, false, false, false }; verify_bitmap_all(&mbm, all_marked_addresses_after_2nd_clear, is_weakly_marked_object_after_2nd_clear, is_strongly_marked_object_after_2nd_clear, all_marked_objects_after_2nd_clear, my_heap_memory, end_of_my_heap); FREE_C_HEAP_ARRAY(HeapWord, my_bitmap_memory); _success = true; return true; } }; TEST_VM_F(ShenandoahMarkBitMapTest, minimum_test) { SKIP_IF_NOT_SHENANDOAH(); bool result = ShenandoahMarkBitMapTest::run_test(); ASSERT_EQ(result, true); ASSERT_EQ(_success, true); ASSERT_EQ(_assertion_failures, (size_t) 0); }