From 94a9b048afef789e5c604201b61b86ace5c9af67 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 11 Oct 2022 23:17:31 +0000 Subject: [PATCH] 8295013: OopStorage should derive from CHeapObjBase Reviewed-by: stefank, tschatzl --- src/hotspot/share/gc/shared/oopStorage.cpp | 15 +- src/hotspot/share/gc/shared/oopStorage.hpp | 13 +- src/hotspot/share/gc/shared/oopStorageSet.cpp | 6 +- .../gtest/gc/shared/test_oopStorage.cpp | 307 +++++++++--------- .../gc/shared/test_oopStorage_parperf.cpp | 15 +- 5 files changed, 179 insertions(+), 177 deletions(-) diff --git a/src/hotspot/share/gc/shared/oopStorage.cpp b/src/hotspot/share/gc/shared/oopStorage.cpp index 177647c6c5d..a541657497c 100644 --- a/src/hotspot/share/gc/shared/oopStorage.cpp +++ b/src/hotspot/share/gc/shared/oopStorage.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ -805,6 +805,10 @@ void OopStorage::release(const oop* const* ptrs, size_t size) { } } +OopStorage* OopStorage::create(const char* name, MEMFLAGS memflags) { + return new (memflags) OopStorage(name, memflags); +} + const size_t initial_active_array_size = 8; static Mutex* make_oopstorage_mutex(const char* storage_name, @@ -815,15 +819,6 @@ static Mutex* make_oopstorage_mutex(const char* storage_name, return new PaddedMutex(rank, name); } -void* OopStorage::operator new(size_t size, MEMFLAGS memflags) { - assert(size >= sizeof(OopStorage), "precondition"); - return NEW_C_HEAP_ARRAY(char, size, memflags); -} - -void OopStorage::operator delete(void* obj, MEMFLAGS /* memflags */) { - FREE_C_HEAP_ARRAY(char, obj); -} - OopStorage::OopStorage(const char* name, MEMFLAGS memflags) : _name(os::strdup(name)), _active_array(ActiveArray::create(initial_active_array_size, memflags)), diff --git a/src/hotspot/share/gc/shared/oopStorage.hpp b/src/hotspot/share/gc/shared/oopStorage.hpp index 9c1804f35ce..d40e5a49cda 100644 --- a/src/hotspot/share/gc/shared/oopStorage.hpp +++ b/src/hotspot/share/gc/shared/oopStorage.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ -72,14 +72,11 @@ class outputStream; // interactions for this protocol. Similarly, see the allocate() function for // a discussion of allocation. -class OopStorage { +class OopStorage : public CHeapObjBase { public: - explicit OopStorage(const char* name, MEMFLAGS memflags); + static OopStorage* create(const char* name, MEMFLAGS memflags); ~OopStorage(); - void* operator new(size_t size, MEMFLAGS memflags); - void operator delete(void* obj, MEMFLAGS memflags); - // These count and usage accessors are racy unless at a safepoint. // The number of allocated and not yet released entries. @@ -282,6 +279,10 @@ private: // Flag indicating this storage object is a candidate for empty block deletion. volatile bool _needs_cleanup; + // Clients construct via "create" factory function. + OopStorage(const char* name, MEMFLAGS memflags); + NONCOPYABLE(OopStorage); + bool try_add_block(); Block* block_for_allocation(); void log_block_transition(Block* block, const char* new_state) const; diff --git a/src/hotspot/share/gc/shared/oopStorageSet.cpp b/src/hotspot/share/gc/shared/oopStorageSet.cpp index d97d8cc7eeb..78da4988e21 100644 --- a/src/hotspot/share/gc/shared/oopStorageSet.cpp +++ b/src/hotspot/share/gc/shared/oopStorageSet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -34,7 +34,7 @@ OopStorage* OopStorageSet::_storages[all_count] = {}; OopStorage* OopStorageSet::create_strong(const char* name, MEMFLAGS memflags) { static uint registered_strong = 0; assert(registered_strong < strong_count, "More registered strong storages than slots"); - OopStorage* storage = new (memflags) OopStorage(name, memflags); + OopStorage* storage = OopStorage::create(name, memflags); _storages[strong_start + registered_strong++] = storage; return storage; } @@ -42,7 +42,7 @@ OopStorage* OopStorageSet::create_strong(const char* name, MEMFLAGS memflags) { OopStorage* OopStorageSet::create_weak(const char* name, MEMFLAGS memflags) { static uint registered_weak = 0; assert(registered_weak < weak_count, "More registered strong storages than slots"); - OopStorage* storage = new (memflags) OopStorage(name, memflags); + OopStorage* storage = OopStorage::create(name, memflags); _storages[weak_start + registered_weak++] = storage; return storage; } diff --git a/test/hotspot/gtest/gc/shared/test_oopStorage.cpp b/test/hotspot/gtest/gc/shared/test_oopStorage.cpp index 85a1c098aa9..36fc603e995 100644 --- a/test/hotspot/gtest/gc/shared/test_oopStorage.cpp +++ b/test/hotspot/gtest/gc/shared/test_oopStorage.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ -172,22 +172,25 @@ static OopBlock* active_head(const OopStorage& storage) { } class OopStorageTest : public ::testing::Test { + OopStorage* _storage; + public: OopStorageTest(); ~OopStorageTest(); - OopStorage _storage; + OopStorage& storage() const { return *_storage; } class CountingIterateClosure; template class VM_CountAtSafepoint; }; OopStorageTest::OopStorageTest() : - _storage("Test Storage", mtGC) + _storage(OopStorage::create("Test Storage", mtGC)) { } OopStorageTest::~OopStorageTest() { - clear_list(TestAccess::allocation_list(_storage)); + clear_list(TestAccess::allocation_list(storage())); + delete _storage; } class OopStorageTestWithAllocation : public OopStorageTest { @@ -200,9 +203,9 @@ public: OopStorageTestWithAllocation::OopStorageTestWithAllocation() { for (size_t i = 0; i < _max_entries; ++i) { - _entries[i] = _storage.allocate(); + _entries[i] = storage().allocate(); EXPECT_TRUE(_entries[i] != NULL); - EXPECT_EQ(i + 1, _storage.allocation_count()); + EXPECT_EQ(i + 1, storage().allocation_count()); } }; @@ -233,38 +236,38 @@ static size_t total_allocation_count(const OopStorage& storage) { } TEST_VM_F(OopStorageTest, allocate_one) { - EXPECT_EQ(0u, active_count(_storage)); - EXPECT_TRUE(is_list_empty(TestAccess::allocation_list(_storage))); + EXPECT_EQ(0u, active_count(storage())); + EXPECT_TRUE(is_list_empty(TestAccess::allocation_list(storage()))); - oop* ptr = _storage.allocate(); + oop* ptr = storage().allocate(); EXPECT_TRUE(ptr != NULL); - EXPECT_EQ(1u, _storage.allocation_count()); + EXPECT_EQ(1u, storage().allocation_count()); - EXPECT_EQ(1u, active_count(_storage)); - EXPECT_EQ(1u, _storage.block_count()); - EXPECT_EQ(1u, list_length(TestAccess::allocation_list(_storage))); + EXPECT_EQ(1u, active_count(storage())); + EXPECT_EQ(1u, storage().block_count()); + EXPECT_EQ(1u, list_length(TestAccess::allocation_list(storage()))); - EXPECT_EQ(0u, empty_block_count(_storage)); + EXPECT_EQ(0u, empty_block_count(storage())); - const OopBlock* block = TestAccess::allocation_list(_storage).chead(); + const OopBlock* block = TestAccess::allocation_list(storage()).chead(); EXPECT_NE(block, (OopBlock*)NULL); - EXPECT_EQ(block, active_head(_storage)); + EXPECT_EQ(block, active_head(storage())); EXPECT_FALSE(TestAccess::block_is_empty(*block)); EXPECT_FALSE(TestAccess::block_is_full(*block)); EXPECT_EQ(1u, TestAccess::block_allocation_count(*block)); - release_entry(_storage, ptr); - EXPECT_EQ(0u, _storage.allocation_count()); + release_entry(storage(), ptr); + EXPECT_EQ(0u, storage().allocation_count()); - EXPECT_EQ(1u, active_count(_storage)); - EXPECT_EQ(1u, _storage.block_count()); - EXPECT_EQ(1u, list_length(TestAccess::allocation_list(_storage))); + EXPECT_EQ(1u, active_count(storage())); + EXPECT_EQ(1u, storage().block_count()); + EXPECT_EQ(1u, list_length(TestAccess::allocation_list(storage()))); - EXPECT_EQ(1u, empty_block_count(_storage)); + EXPECT_EQ(1u, empty_block_count(storage())); - const OopBlock* new_block = TestAccess::allocation_list(_storage).chead(); + const OopBlock* new_block = TestAccess::allocation_list(storage()).chead(); EXPECT_EQ(block, new_block); - EXPECT_EQ(block, active_head(_storage)); + EXPECT_EQ(block, active_head(storage())); EXPECT_TRUE(TestAccess::block_is_empty(*block)); EXPECT_FALSE(TestAccess::block_is_full(*block)); EXPECT_EQ(0u, TestAccess::block_allocation_count(*block)); @@ -274,19 +277,19 @@ TEST_VM_F(OopStorageTest, allocation_count) { static const size_t max_entries = 1000; oop* entries[max_entries]; - AllocationList& allocation_list = TestAccess::allocation_list(_storage); + AllocationList& allocation_list = TestAccess::allocation_list(storage()); - EXPECT_EQ(0u, active_count(_storage)); - EXPECT_EQ(0u, _storage.block_count()); + EXPECT_EQ(0u, active_count(storage())); + EXPECT_EQ(0u, storage().block_count()); EXPECT_TRUE(is_list_empty(allocation_list)); size_t allocated = 0; for ( ; allocated < max_entries; ++allocated) { - EXPECT_EQ(allocated, _storage.allocation_count()); - if (active_count(_storage) != 0) { - EXPECT_EQ(1u, active_count(_storage)); - EXPECT_EQ(1u, _storage.block_count()); - const OopBlock& block = *TestAccess::active_array(_storage).at(0); + EXPECT_EQ(allocated, storage().allocation_count()); + if (active_count(storage()) != 0) { + EXPECT_EQ(1u, active_count(storage())); + EXPECT_EQ(1u, storage().block_count()); + const OopBlock& block = *TestAccess::active_array(storage()).at(0); EXPECT_EQ(allocated, TestAccess::block_allocation_count(block)); if (TestAccess::block_is_full(block)) { break; @@ -295,22 +298,22 @@ TEST_VM_F(OopStorageTest, allocation_count) { EXPECT_EQ(&block, allocation_list.chead()); } } - entries[allocated] = _storage.allocate(); + entries[allocated] = storage().allocate(); } - EXPECT_EQ(allocated, _storage.allocation_count()); - EXPECT_EQ(1u, active_count(_storage)); - EXPECT_EQ(1u, _storage.block_count()); + EXPECT_EQ(allocated, storage().allocation_count()); + EXPECT_EQ(1u, active_count(storage())); + EXPECT_EQ(1u, storage().block_count()); EXPECT_TRUE(is_list_empty(allocation_list)); - const OopBlock& block = *TestAccess::active_array(_storage).at(0); + const OopBlock& block = *TestAccess::active_array(storage()).at(0); EXPECT_TRUE(TestAccess::block_is_full(block)); EXPECT_EQ(allocated, TestAccess::block_allocation_count(block)); for (size_t i = 0; i < allocated; ++i) { - release_entry(_storage, entries[i]); + release_entry(storage(), entries[i]); size_t remaining = allocated - (i + 1); EXPECT_EQ(remaining, TestAccess::block_allocation_count(block)); - EXPECT_EQ(remaining, _storage.allocation_count()); + EXPECT_EQ(remaining, storage().allocation_count()); EXPECT_FALSE(is_list_empty(allocation_list)); } } @@ -319,40 +322,40 @@ TEST_VM_F(OopStorageTest, allocate_many) { static const size_t max_entries = 1000; oop* entries[max_entries]; - AllocationList& allocation_list = TestAccess::allocation_list(_storage); + AllocationList& allocation_list = TestAccess::allocation_list(storage()); - EXPECT_EQ(0u, empty_block_count(_storage)); + EXPECT_EQ(0u, empty_block_count(storage())); - entries[0] = _storage.allocate(); + entries[0] = storage().allocate(); ASSERT_TRUE(entries[0] != NULL); - EXPECT_EQ(1u, active_count(_storage)); - EXPECT_EQ(1u, _storage.block_count()); + EXPECT_EQ(1u, active_count(storage())); + EXPECT_EQ(1u, storage().block_count()); EXPECT_EQ(1u, list_length(allocation_list)); - EXPECT_EQ(0u, empty_block_count(_storage)); + EXPECT_EQ(0u, empty_block_count(storage())); - const OopBlock* block = TestAccess::active_array(_storage).at(0); + const OopBlock* block = TestAccess::active_array(storage()).at(0); EXPECT_EQ(1u, TestAccess::block_allocation_count(*block)); EXPECT_EQ(block, allocation_list.chead()); for (size_t i = 1; i < max_entries; ++i) { - entries[i] = _storage.allocate(); - EXPECT_EQ(i + 1, _storage.allocation_count()); + entries[i] = storage().allocate(); + EXPECT_EQ(i + 1, storage().allocation_count()); ASSERT_TRUE(entries[i] != NULL); - EXPECT_EQ(0u, empty_block_count(_storage)); + EXPECT_EQ(0u, empty_block_count(storage())); if (block == NULL) { ASSERT_FALSE(is_list_empty(allocation_list)); EXPECT_EQ(1u, list_length(allocation_list)); block = allocation_list.chead(); EXPECT_EQ(1u, TestAccess::block_allocation_count(*block)); - EXPECT_EQ(block, active_head(_storage)); + EXPECT_EQ(block, active_head(storage())); } else if (TestAccess::block_is_full(*block)) { EXPECT_TRUE(is_list_empty(allocation_list)); block = NULL; } else { EXPECT_FALSE(is_list_empty(allocation_list)); EXPECT_EQ(block, allocation_list.chead()); - EXPECT_EQ(block, active_head(_storage)); + EXPECT_EQ(block, active_head(storage())); } } @@ -360,18 +363,18 @@ TEST_VM_F(OopStorageTest, allocate_many) { EXPECT_NE(0u, TestAccess::block_allocation_count(*block)); EXPECT_FALSE(is_list_empty(allocation_list)); EXPECT_EQ(block, allocation_list.chead()); - EXPECT_EQ(block, active_head(_storage)); + EXPECT_EQ(block, active_head(storage())); } for (size_t i = 0; i < max_entries; ++i) { - release_entry(_storage, entries[i]); - EXPECT_TRUE(is_allocation_list_sorted(_storage)); - EXPECT_EQ(max_entries - (i + 1), total_allocation_count(_storage)); + release_entry(storage(), entries[i]); + EXPECT_TRUE(is_allocation_list_sorted(storage())); + EXPECT_EQ(max_entries - (i + 1), total_allocation_count(storage())); } - EXPECT_EQ(active_count(_storage), list_length(allocation_list)); - EXPECT_EQ(active_count(_storage), _storage.block_count()); - EXPECT_EQ(active_count(_storage), empty_block_count(_storage)); + EXPECT_EQ(active_count(storage()), list_length(allocation_list)); + EXPECT_EQ(active_count(storage()), storage().block_count()); + EXPECT_EQ(active_count(storage()), empty_block_count(storage())); for (const OopBlock* block = allocation_list.chead(); block != NULL; block = allocation_list.next(*block)) { @@ -383,29 +386,29 @@ TEST_VM_F(OopStorageTestWithAllocation, random_release) { static const size_t step = 11; ASSERT_NE(0u, _max_entries % step); // max_entries and step are mutually prime - EXPECT_EQ(0u, empty_block_count(_storage)); + EXPECT_EQ(0u, empty_block_count(storage())); - AllocationList& allocation_list = TestAccess::allocation_list(_storage); + AllocationList& allocation_list = TestAccess::allocation_list(storage()); - EXPECT_EQ(_max_entries, total_allocation_count(_storage)); + EXPECT_EQ(_max_entries, total_allocation_count(storage())); EXPECT_GE(1u, list_length(allocation_list)); // Release all entries in "random" order. size_t released = 0; for (size_t i = 0; released < _max_entries; i = (i + step) % _max_entries) { if (_entries[i] != NULL) { - release_entry(_storage, _entries[i]); + release_entry(storage(), _entries[i]); _entries[i] = NULL; ++released; - EXPECT_EQ(_max_entries - released, total_allocation_count(_storage)); - EXPECT_TRUE(is_allocation_list_sorted(_storage)); + EXPECT_EQ(_max_entries - released, total_allocation_count(storage())); + EXPECT_TRUE(is_allocation_list_sorted(storage())); } } - EXPECT_EQ(active_count(_storage), list_length(allocation_list)); - EXPECT_EQ(active_count(_storage), _storage.block_count()); - EXPECT_EQ(0u, total_allocation_count(_storage)); - EXPECT_EQ(list_length(allocation_list), empty_block_count(_storage)); + EXPECT_EQ(active_count(storage()), list_length(allocation_list)); + EXPECT_EQ(active_count(storage()), storage().block_count()); + EXPECT_EQ(0u, total_allocation_count(storage())); + EXPECT_EQ(list_length(allocation_list), empty_block_count(storage())); } TEST_VM_F(OopStorageTestWithAllocation, random_allocate_release) { @@ -413,11 +416,11 @@ TEST_VM_F(OopStorageTestWithAllocation, random_allocate_release) { static const size_t allocate_step = 5; ASSERT_NE(0u, _max_entries % release_step); // max_entries and step are mutually prime - EXPECT_EQ(0u, empty_block_count(_storage)); + EXPECT_EQ(0u, empty_block_count(storage())); - AllocationList& allocation_list = TestAccess::allocation_list(_storage); + AllocationList& allocation_list = TestAccess::allocation_list(storage()); - EXPECT_EQ(_max_entries, total_allocation_count(_storage)); + EXPECT_EQ(_max_entries, total_allocation_count(storage())); EXPECT_GE(1u, list_length(allocation_list)); // Release all entries in "random" order, "randomly" interspersed @@ -426,25 +429,25 @@ TEST_VM_F(OopStorageTestWithAllocation, random_allocate_release) { size_t total_released = 0; for (size_t i = 0; released < _max_entries; i = (i + release_step) % _max_entries) { if (_entries[i] != NULL) { - release_entry(_storage, _entries[i]); + release_entry(storage(), _entries[i]); _entries[i] = NULL; ++released; ++total_released; - EXPECT_EQ(_max_entries - released, total_allocation_count(_storage)); - EXPECT_TRUE(is_allocation_list_sorted(_storage)); + EXPECT_EQ(_max_entries - released, total_allocation_count(storage())); + EXPECT_TRUE(is_allocation_list_sorted(storage())); if (total_released % allocate_step == 0) { - _entries[i] = _storage.allocate(); + _entries[i] = storage().allocate(); --released; - EXPECT_EQ(_max_entries - released, total_allocation_count(_storage)); - EXPECT_TRUE(is_allocation_list_sorted(_storage)); + EXPECT_EQ(_max_entries - released, total_allocation_count(storage())); + EXPECT_TRUE(is_allocation_list_sorted(storage())); } } } - EXPECT_EQ(active_count(_storage), list_length(allocation_list)); - EXPECT_EQ(active_count(_storage), _storage.block_count()); - EXPECT_EQ(0u, total_allocation_count(_storage)); - EXPECT_EQ(list_length(allocation_list), empty_block_count(_storage)); + EXPECT_EQ(active_count(storage()), list_length(allocation_list)); + EXPECT_EQ(active_count(storage()), storage().block_count()); + EXPECT_EQ(0u, total_allocation_count(storage())); + EXPECT_EQ(list_length(allocation_list), empty_block_count(storage())); } template @@ -462,16 +465,16 @@ public: QuickSort::sort(to_release, nrelease, PointerCompare(), false); } - _storage.release(to_release, nrelease); - EXPECT_EQ(_max_entries - nrelease, _storage.allocation_count()); + storage().release(to_release, nrelease); + EXPECT_EQ(_max_entries - nrelease, storage().allocation_count()); for (size_t i = 0; i < nrelease; ++i) { - release_entry(_storage, _entries[2 * i + 1], false); - EXPECT_EQ(_max_entries - nrelease - (i + 1), _storage.allocation_count()); + release_entry(storage(), _entries[2 * i + 1], false); + EXPECT_EQ(_max_entries - nrelease - (i + 1), storage().allocation_count()); } - EXPECT_TRUE(process_deferred_updates(_storage)); + EXPECT_TRUE(process_deferred_updates(storage())); - EXPECT_EQ(_storage.block_count(), empty_block_count(_storage)); + EXPECT_EQ(storage().block_count(), empty_block_count(storage())); FREE_C_HEAP_ARRAY(oop*, to_release); } @@ -494,25 +497,25 @@ TEST_VM_F(OopStorageTest, bulk_allocation) { static const size_t zero = 0; oop* entries[max_entries] = {}; - AllocationList& allocation_list = TestAccess::allocation_list(_storage); + AllocationList& allocation_list = TestAccess::allocation_list(storage()); - EXPECT_EQ(0u, empty_block_count(_storage)); - size_t allocated = _storage.allocate(entries, max_entries); + EXPECT_EQ(0u, empty_block_count(storage())); + size_t allocated = storage().allocate(entries, max_entries); ASSERT_NE(allocated, zero); // ASSERT_LE would ODR-use the OopStorage constant. size_t bulk_allocate_limit = OopStorage::bulk_allocate_limit; ASSERT_LE(allocated, bulk_allocate_limit); ASSERT_LE(allocated, max_entries); for (size_t i = 0; i < allocated; ++i) { - EXPECT_EQ(OopStorage::ALLOCATED_ENTRY, _storage.allocation_status(entries[i])); + EXPECT_EQ(OopStorage::ALLOCATED_ENTRY, storage().allocation_status(entries[i])); } for (size_t i = allocated; i < max_entries; ++i) { EXPECT_EQ(NULL, entries[i]); } - _storage.release(entries, allocated); - EXPECT_EQ(0u, _storage.allocation_count()); + storage().release(entries, allocated); + EXPECT_EQ(0u, storage().allocation_count()); for (size_t i = 0; i < allocated; ++i) { - EXPECT_EQ(OopStorage::UNALLOCATED_ENTRY, _storage.allocation_status(entries[i])); + EXPECT_EQ(OopStorage::UNALLOCATED_ENTRY, storage().allocation_status(entries[i])); } } @@ -522,7 +525,7 @@ TEST_VM_F(OopStorageTest, invalid_pointer) { char* mem = NEW_C_HEAP_ARRAY(char, 1000, mtInternal); oop* ptr = reinterpret_cast(align_down(mem + 250, sizeof(oop))); // Predicate returns false for some malloc'ed block. - EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(ptr)); + EXPECT_EQ(OopStorage::INVALID_ENTRY, storage().allocation_status(ptr)); FREE_C_HEAP_ARRAY(char, mem); } @@ -530,7 +533,7 @@ TEST_VM_F(OopStorageTest, invalid_pointer) { oop obj; oop* ptr = &obj; // Predicate returns false for some "random" location. - EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(ptr)); + EXPECT_EQ(OopStorage::INVALID_ENTRY, storage().allocation_status(ptr)); } } #endif // DISABLE_GARBAGE_ALLOCATION_STATUS_TESTS @@ -594,7 +597,7 @@ TEST_VM_F(OopStorageTest, simple_iterate) { size_t entries_with_values = 0; for (size_t i = 0; i < max_entries; i += 10) { for ( ; allocated < i; ++allocated) { - entries[allocated] = _storage.allocate(); + entries[allocated] = storage().allocate(); ASSERT_TRUE(entries[allocated] != NULL); if ((allocated % 3) != 0) { *entries[allocated] = dummy_oop; @@ -604,7 +607,7 @@ TEST_VM_F(OopStorageTest, simple_iterate) { { CountingIterateClosure cl; - VM_CountAtSafepoint op(&_storage, &cl); + VM_CountAtSafepoint op(&storage(), &cl); { ThreadInVMfromNative invm(JavaThread::current()); VMThread::execute(&op); @@ -617,7 +620,7 @@ TEST_VM_F(OopStorageTest, simple_iterate) { { CountingIterateClosure cl; - VM_CountAtSafepoint op(&_storage, &cl); + VM_CountAtSafepoint op(&storage(), &cl); { ThreadInVMfromNative invm(JavaThread::current()); VMThread::execute(&op); @@ -630,9 +633,9 @@ TEST_VM_F(OopStorageTest, simple_iterate) { } while (allocated > 0) { - release_entry(_storage, entries[--allocated], false); + release_entry(storage(), entries[--allocated], false); } - process_deferred_updates(_storage); + process_deferred_updates(storage()); } class OopStorageTestIteration : public OopStorageTestWithAllocation { @@ -651,17 +654,17 @@ public: memset(_states, 0, sizeof(_states)); size_t initial_release = 0; - for ( ; empty_block_count(_storage) < 2; ++initial_release) { + for ( ; empty_block_count(storage()) < 2; ++initial_release) { ASSERT_GT(_max_entries, initial_release); - release_entry(_storage, _entries[initial_release]); + release_entry(storage(), _entries[initial_release]); _states[0][initial_release] = mark_released; } for (size_t i = initial_release; i < _max_entries; i += 3) { - release_entry(_storage, _entries[i], false); + release_entry(storage(), _entries[i], false); _states[0][i] = mark_released; } - process_deferred_updates(_storage); + process_deferred_updates(storage()); } class VerifyState; @@ -831,7 +834,7 @@ private: TEST_VM_F(OopStorageTestIteration, iterate_safepoint) { VerifyState vstate(mark_non_const, _entries, _states); - VM_Verify op(&_storage, &vstate); + VM_Verify op(&storage(), &vstate); { ThreadInVMfromNative invm(JavaThread::current()); VMThread::execute(&op); @@ -842,7 +845,7 @@ TEST_VM_F(OopStorageTestIteration, iterate_safepoint) { TEST_VM_F(OopStorageTestIteration, const_iterate_safepoint) { VerifyState vstate(mark_const, _entries, _states); - VM_Verify op(&_storage, &vstate); + VM_Verify op(&storage(), &vstate); { ThreadInVMfromNative invm(JavaThread::current()); VMThread::execute(&op); @@ -853,7 +856,7 @@ TEST_VM_F(OopStorageTestIteration, const_iterate_safepoint) { TEST_VM_F(OopStorageTestIteration, oops_do) { VerifyState vstate(mark_non_const, _entries, _states); - VM_VerifyUsingOopsDo op(&_storage, &vstate); + VM_VerifyUsingOopsDo op(&storage(), &vstate); { ThreadInVMfromNative invm(JavaThread::current()); VMThread::execute(&op); @@ -946,7 +949,7 @@ private: TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_iterate) { VerifyState vstate(mark_non_const, _entries, _states); - Task task("test", &_storage, &vstate); + Task task("test", &storage(), &vstate); VM_ParStateVerify op(workers(), &task); { ThreadInVMfromNative invm(JavaThread::current()); @@ -957,7 +960,7 @@ TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_iterate) { TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_const_iterate) { VerifyState vstate(mark_const, _entries, _states); - Task task("test", &_storage, &vstate); + Task task("test", &storage(), &vstate); VM_ParStateVerify op(workers(), &task); { ThreadInVMfromNative invm(JavaThread::current()); @@ -968,7 +971,7 @@ TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_const_iterate) { TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_oops_do) { VerifyState vstate(mark_non_const, _entries, _states); - TaskUsingOopsDo task("test", &_storage, &vstate); + TaskUsingOopsDo task("test", &storage(), &vstate); VM_ParStateVerify op(workers(), &task); { ThreadInVMfromNative invm(JavaThread::current()); @@ -979,7 +982,7 @@ TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_oops_do) { TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_const_oops_do) { VerifyState vstate(mark_const, _entries, _states); - TaskUsingOopsDo task("test", &_storage, &vstate); + TaskUsingOopsDo task("test", &storage(), &vstate); VM_ParStateVerify op(workers(), &task); { ThreadInVMfromNative invm(JavaThread::current()); @@ -990,78 +993,78 @@ TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_const_oops_do) { TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_iterate) { VerifyState vstate(mark_non_const, _entries, _states); - Task task("test", &_storage, &vstate); + Task task("test", &storage(), &vstate); workers()->run_task(&task); vstate.check(); } TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_const_iterate) { VerifyState vstate(mark_const, _entries, _states); - Task task("test", &_storage, &vstate); + Task task("test", &storage(), &vstate); workers()->run_task(&task); vstate.check(); } TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_oops_do) { VerifyState vstate(mark_non_const, _entries, _states); - TaskUsingOopsDo task("test", &_storage, &vstate); + TaskUsingOopsDo task("test", &storage(), &vstate); workers()->run_task(&task); vstate.check(); } TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_const_oops_do) { VerifyState vstate(mark_const, _entries, _states); - TaskUsingOopsDo task("test", &_storage, &vstate); + TaskUsingOopsDo task("test", &storage(), &vstate); workers()->run_task(&task); vstate.check(); } TEST_VM_F(OopStorageTestWithAllocation, delete_empty_blocks) { - size_t initial_active_size = active_count(_storage); - EXPECT_EQ(initial_active_size, _storage.block_count()); + size_t initial_active_size = active_count(storage()); + EXPECT_EQ(initial_active_size, storage().block_count()); ASSERT_LE(3u, initial_active_size); // Need at least 3 blocks for test - for (size_t i = 0; empty_block_count(_storage) < 3; ++i) { + for (size_t i = 0; empty_block_count(storage()) < 3; ++i) { ASSERT_GT(_max_entries, i); - release_entry(_storage, _entries[i]); + release_entry(storage(), _entries[i]); } - EXPECT_EQ(initial_active_size, active_count(_storage)); - EXPECT_EQ(initial_active_size, _storage.block_count()); - EXPECT_EQ(3u, empty_block_count(_storage)); + EXPECT_EQ(initial_active_size, active_count(storage())); + EXPECT_EQ(initial_active_size, storage().block_count()); + EXPECT_EQ(3u, empty_block_count(storage())); { ThreadInVMfromNative invm(JavaThread::current()); - while (_storage.delete_empty_blocks()) {} + while (storage().delete_empty_blocks()) {} } - EXPECT_EQ(0u, empty_block_count(_storage)); - EXPECT_EQ(initial_active_size - 3, active_count(_storage)); - EXPECT_EQ(initial_active_size - 3, _storage.block_count()); + EXPECT_EQ(0u, empty_block_count(storage())); + EXPECT_EQ(initial_active_size - 3, active_count(storage())); + EXPECT_EQ(initial_active_size - 3, storage().block_count()); } TEST_VM_F(OopStorageTestWithAllocation, allocation_status) { oop* retained = _entries[200]; oop* released = _entries[300]; oop* garbage = reinterpret_cast(1024 * 1024); - release_entry(_storage, released); + release_entry(storage(), released); - EXPECT_EQ(OopStorage::ALLOCATED_ENTRY, _storage.allocation_status(retained)); - EXPECT_EQ(OopStorage::UNALLOCATED_ENTRY, _storage.allocation_status(released)); - EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(garbage)); + EXPECT_EQ(OopStorage::ALLOCATED_ENTRY, storage().allocation_status(retained)); + EXPECT_EQ(OopStorage::UNALLOCATED_ENTRY, storage().allocation_status(released)); + EXPECT_EQ(OopStorage::INVALID_ENTRY, storage().allocation_status(garbage)); for (size_t i = 0; i < _max_entries; ++i) { if ((_entries[i] != retained) && (_entries[i] != released)) { // Leave deferred release updates to block deletion. - release_entry(_storage, _entries[i], false); + release_entry(storage(), _entries[i], false); } } { ThreadInVMfromNative invm(JavaThread::current()); - while (_storage.delete_empty_blocks()) {} + while (storage().delete_empty_blocks()) {} } - EXPECT_EQ(OopStorage::ALLOCATED_ENTRY, _storage.allocation_status(retained)); - EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(released)); - EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(garbage)); + EXPECT_EQ(OopStorage::ALLOCATED_ENTRY, storage().allocation_status(retained)); + EXPECT_EQ(OopStorage::INVALID_ENTRY, storage().allocation_status(released)); + EXPECT_EQ(OopStorage::INVALID_ENTRY, storage().allocation_status(garbage)); } TEST_VM_F(OopStorageTest, usage_info) { @@ -1069,24 +1072,24 @@ TEST_VM_F(OopStorageTest, usage_info) { oop* entries[1000]; size_t allocated = 0; - EXPECT_EQ(0u, _storage.block_count()); + EXPECT_EQ(0u, storage().block_count()); // There is non-block overhead, so always some usage. - EXPECT_LT(0u, _storage.total_memory_usage()); + EXPECT_LT(0u, storage().total_memory_usage()); - while (_storage.block_count() < goal_blocks) { - size_t this_count = _storage.block_count(); - while (_storage.block_count() == this_count) { + while (storage().block_count() < goal_blocks) { + size_t this_count = storage().block_count(); + while (storage().block_count() == this_count) { ASSERT_GT(ARRAY_SIZE(entries), allocated); - entries[allocated] = _storage.allocate(); + entries[allocated] = storage().allocate(); ASSERT_TRUE(entries[allocated] != NULL); ++allocated; } - EXPECT_NE(0u, _storage.block_count()); - EXPECT_NE(0u, _storage.total_memory_usage()); + EXPECT_NE(0u, storage().block_count()); + EXPECT_NE(0u, storage().total_memory_usage()); } - EXPECT_LT(TestAccess::memory_per_block() * _storage.block_count(), - _storage.total_memory_usage()); + EXPECT_LT(TestAccess::memory_per_block() * storage().block_count(), + storage().total_memory_usage()); } #ifndef PRODUCT @@ -1095,22 +1098,22 @@ TEST_VM_F(OopStorageTestWithAllocation, print_storage) { // Release the first 1/2 for (size_t i = 0; i < (_max_entries / 2); ++i) { // Deferred updates don't affect print output. - release_entry(_storage, _entries[i], false); + release_entry(storage(), _entries[i], false); _entries[i] = NULL; } // Release every other remaining for (size_t i = _max_entries / 2; i < _max_entries; i += 2) { // Deferred updates don't affect print output. - release_entry(_storage, _entries[i], false); + release_entry(storage(), _entries[i], false); _entries[i] = NULL; } size_t expected_entries = _max_entries / 4; - EXPECT_EQ(expected_entries, _storage.allocation_count()); + EXPECT_EQ(expected_entries, storage().allocation_count()); size_t entries_per_block = BitsPerWord; size_t expected_blocks = (_max_entries + entries_per_block - 1) / entries_per_block; - EXPECT_EQ(expected_blocks, _storage.block_count()); + EXPECT_EQ(expected_blocks, storage().block_count()); double expected_usage = (100.0 * expected_entries) / (expected_blocks * entries_per_block); @@ -1123,9 +1126,9 @@ TEST_VM_F(OopStorageTestWithAllocation, print_storage) { expected_entries, expected_blocks, expected_usage, - _storage.total_memory_usage()); + storage().total_memory_usage()); stringStream st; - _storage.print_on(&st); + storage().print_on(&st); EXPECT_STREQ(expected_st.as_string(), st.as_string()); } } diff --git a/test/hotspot/gtest/gc/shared/test_oopStorage_parperf.cpp b/test/hotspot/gtest/gc/shared/test_oopStorage_parperf.cpp index 9e8716291b3..905859af80b 100644 --- a/test/hotspot/gtest/gc/shared/test_oopStorage_parperf.cpp +++ b/test/hotspot/gtest/gc/shared/test_oopStorage_parperf.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ -52,6 +52,8 @@ static uint _num_workers = 0; const size_t _storage_entries = 1000000; class OopStorageParIterPerf : public ::testing::Test { + OopStorage* _storage; + public: OopStorageParIterPerf(); ~OopStorageParIterPerf(); @@ -62,13 +64,13 @@ public: class Task; class Closure; + OopStorage& storage() const { return *_storage; } Tickspan run_task(Task* task, uint nthreads); void show_task(const Task* task, Tickspan duration, uint nthreads); void run_test(uint nthreads); static WorkerThreads* _workers; - OopStorage _storage; oop* _entries[_storage_entries]; }; @@ -85,16 +87,17 @@ WorkerThreads* OopStorageParIterPerf::workers() const { } OopStorageParIterPerf::OopStorageParIterPerf() : - _storage("Test Storage", mtGC) + _storage(OopStorage::create("Test Storage", mtGC)) { for (size_t i = 0; i < _storage_entries; ++i) { - _entries[i] = _storage.allocate(); + _entries[i] = storage().allocate(); } _num_workers = MIN2(_max_workers, (uint)os::processor_count()); } OopStorageParIterPerf::~OopStorageParIterPerf() { - _storage.release(_entries, ARRAY_SIZE(_entries)); + storage().release(_entries, ARRAY_SIZE(_entries)); + delete _storage; } class OopStorageParIterPerf::VM_ParStateTime : public VM_GTestExecuteAtSafepoint { @@ -177,7 +180,7 @@ void OopStorageParIterPerf::run_test(uint nthreads) { if (nthreads <= _num_workers) { SCOPED_TRACE(err_msg("Running test with %u threads", nthreads).buffer()); Closure closure; - Task task(&_storage, &closure, nthreads); + Task task(&storage(), &closure, nthreads); Tickspan t = run_task(&task, nthreads); show_task(&task, t, nthreads); }