8295013: OopStorage should derive from CHeapObjBase

Reviewed-by: stefank, tschatzl
This commit is contained in:
Kim Barrett 2022-10-11 23:17:31 +00:00
parent 3a980b972f
commit 94a9b048af
5 changed files with 179 additions and 177 deletions

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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; const size_t initial_active_array_size = 8;
static Mutex* make_oopstorage_mutex(const char* storage_name, 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); 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) : OopStorage::OopStorage(const char* name, MEMFLAGS memflags) :
_name(os::strdup(name)), _name(os::strdup(name)),
_active_array(ActiveArray::create(initial_active_array_size, memflags)), _active_array(ActiveArray::create(initial_active_array_size, memflags)),

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 // interactions for this protocol. Similarly, see the allocate() function for
// a discussion of allocation. // a discussion of allocation.
class OopStorage { class OopStorage : public CHeapObjBase {
public: public:
explicit OopStorage(const char* name, MEMFLAGS memflags); static OopStorage* create(const char* name, MEMFLAGS memflags);
~OopStorage(); ~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. // These count and usage accessors are racy unless at a safepoint.
// The number of allocated and not yet released entries. // 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. // Flag indicating this storage object is a candidate for empty block deletion.
volatile bool _needs_cleanup; volatile bool _needs_cleanup;
// Clients construct via "create" factory function.
OopStorage(const char* name, MEMFLAGS memflags);
NONCOPYABLE(OopStorage);
bool try_add_block(); bool try_add_block();
Block* block_for_allocation(); Block* block_for_allocation();
void log_block_transition(Block* block, const char* new_state) const; void log_block_transition(Block* block, const char* new_state) const;

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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) { OopStorage* OopStorageSet::create_strong(const char* name, MEMFLAGS memflags) {
static uint registered_strong = 0; static uint registered_strong = 0;
assert(registered_strong < strong_count, "More registered strong storages than slots"); 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; _storages[strong_start + registered_strong++] = storage;
return 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) { OopStorage* OopStorageSet::create_weak(const char* name, MEMFLAGS memflags) {
static uint registered_weak = 0; static uint registered_weak = 0;
assert(registered_weak < weak_count, "More registered strong storages than slots"); 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; _storages[weak_start + registered_weak++] = storage;
return storage; return storage;
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 { class OopStorageTest : public ::testing::Test {
OopStorage* _storage;
public: public:
OopStorageTest(); OopStorageTest();
~OopStorageTest(); ~OopStorageTest();
OopStorage _storage; OopStorage& storage() const { return *_storage; }
class CountingIterateClosure; class CountingIterateClosure;
template<bool is_const> class VM_CountAtSafepoint; template<bool is_const> class VM_CountAtSafepoint;
}; };
OopStorageTest::OopStorageTest() : OopStorageTest::OopStorageTest() :
_storage("Test Storage", mtGC) _storage(OopStorage::create("Test Storage", mtGC))
{ } { }
OopStorageTest::~OopStorageTest() { OopStorageTest::~OopStorageTest() {
clear_list(TestAccess::allocation_list(_storage)); clear_list(TestAccess::allocation_list(storage()));
delete _storage;
} }
class OopStorageTestWithAllocation : public OopStorageTest { class OopStorageTestWithAllocation : public OopStorageTest {
@ -200,9 +203,9 @@ public:
OopStorageTestWithAllocation::OopStorageTestWithAllocation() { OopStorageTestWithAllocation::OopStorageTestWithAllocation() {
for (size_t i = 0; i < _max_entries; ++i) { for (size_t i = 0; i < _max_entries; ++i) {
_entries[i] = _storage.allocate(); _entries[i] = storage().allocate();
EXPECT_TRUE(_entries[i] != NULL); 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) { TEST_VM_F(OopStorageTest, allocate_one) {
EXPECT_EQ(0u, active_count(_storage)); EXPECT_EQ(0u, active_count(storage()));
EXPECT_TRUE(is_list_empty(TestAccess::allocation_list(_storage))); EXPECT_TRUE(is_list_empty(TestAccess::allocation_list(storage())));
oop* ptr = _storage.allocate(); oop* ptr = storage().allocate();
EXPECT_TRUE(ptr != NULL); 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, active_count(storage()));
EXPECT_EQ(1u, _storage.block_count()); EXPECT_EQ(1u, storage().block_count());
EXPECT_EQ(1u, list_length(TestAccess::allocation_list(_storage))); 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_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_empty(*block));
EXPECT_FALSE(TestAccess::block_is_full(*block)); EXPECT_FALSE(TestAccess::block_is_full(*block));
EXPECT_EQ(1u, TestAccess::block_allocation_count(*block)); EXPECT_EQ(1u, TestAccess::block_allocation_count(*block));
release_entry(_storage, ptr); release_entry(storage(), ptr);
EXPECT_EQ(0u, _storage.allocation_count()); EXPECT_EQ(0u, storage().allocation_count());
EXPECT_EQ(1u, active_count(_storage)); EXPECT_EQ(1u, active_count(storage()));
EXPECT_EQ(1u, _storage.block_count()); EXPECT_EQ(1u, storage().block_count());
EXPECT_EQ(1u, list_length(TestAccess::allocation_list(_storage))); 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, new_block);
EXPECT_EQ(block, active_head(_storage)); EXPECT_EQ(block, active_head(storage()));
EXPECT_TRUE(TestAccess::block_is_empty(*block)); EXPECT_TRUE(TestAccess::block_is_empty(*block));
EXPECT_FALSE(TestAccess::block_is_full(*block)); EXPECT_FALSE(TestAccess::block_is_full(*block));
EXPECT_EQ(0u, TestAccess::block_allocation_count(*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; static const size_t max_entries = 1000;
oop* entries[max_entries]; 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, active_count(storage()));
EXPECT_EQ(0u, _storage.block_count()); EXPECT_EQ(0u, storage().block_count());
EXPECT_TRUE(is_list_empty(allocation_list)); EXPECT_TRUE(is_list_empty(allocation_list));
size_t allocated = 0; size_t allocated = 0;
for ( ; allocated < max_entries; ++allocated) { for ( ; allocated < max_entries; ++allocated) {
EXPECT_EQ(allocated, _storage.allocation_count()); EXPECT_EQ(allocated, storage().allocation_count());
if (active_count(_storage) != 0) { if (active_count(storage()) != 0) {
EXPECT_EQ(1u, active_count(_storage)); EXPECT_EQ(1u, active_count(storage()));
EXPECT_EQ(1u, _storage.block_count()); EXPECT_EQ(1u, storage().block_count());
const OopBlock& block = *TestAccess::active_array(_storage).at(0); const OopBlock& block = *TestAccess::active_array(storage()).at(0);
EXPECT_EQ(allocated, TestAccess::block_allocation_count(block)); EXPECT_EQ(allocated, TestAccess::block_allocation_count(block));
if (TestAccess::block_is_full(block)) { if (TestAccess::block_is_full(block)) {
break; break;
@ -295,22 +298,22 @@ TEST_VM_F(OopStorageTest, allocation_count) {
EXPECT_EQ(&block, allocation_list.chead()); EXPECT_EQ(&block, allocation_list.chead());
} }
} }
entries[allocated] = _storage.allocate(); entries[allocated] = storage().allocate();
} }
EXPECT_EQ(allocated, _storage.allocation_count()); EXPECT_EQ(allocated, storage().allocation_count());
EXPECT_EQ(1u, active_count(_storage)); EXPECT_EQ(1u, active_count(storage()));
EXPECT_EQ(1u, _storage.block_count()); EXPECT_EQ(1u, storage().block_count());
EXPECT_TRUE(is_list_empty(allocation_list)); 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_TRUE(TestAccess::block_is_full(block));
EXPECT_EQ(allocated, TestAccess::block_allocation_count(block)); EXPECT_EQ(allocated, TestAccess::block_allocation_count(block));
for (size_t i = 0; i < allocated; ++i) { for (size_t i = 0; i < allocated; ++i) {
release_entry(_storage, entries[i]); release_entry(storage(), entries[i]);
size_t remaining = allocated - (i + 1); size_t remaining = allocated - (i + 1);
EXPECT_EQ(remaining, TestAccess::block_allocation_count(block)); 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)); EXPECT_FALSE(is_list_empty(allocation_list));
} }
} }
@ -319,40 +322,40 @@ TEST_VM_F(OopStorageTest, allocate_many) {
static const size_t max_entries = 1000; static const size_t max_entries = 1000;
oop* entries[max_entries]; 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); ASSERT_TRUE(entries[0] != NULL);
EXPECT_EQ(1u, active_count(_storage)); EXPECT_EQ(1u, active_count(storage()));
EXPECT_EQ(1u, _storage.block_count()); EXPECT_EQ(1u, storage().block_count());
EXPECT_EQ(1u, list_length(allocation_list)); 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(1u, TestAccess::block_allocation_count(*block));
EXPECT_EQ(block, allocation_list.chead()); EXPECT_EQ(block, allocation_list.chead());
for (size_t i = 1; i < max_entries; ++i) { for (size_t i = 1; i < max_entries; ++i) {
entries[i] = _storage.allocate(); entries[i] = storage().allocate();
EXPECT_EQ(i + 1, _storage.allocation_count()); EXPECT_EQ(i + 1, storage().allocation_count());
ASSERT_TRUE(entries[i] != NULL); ASSERT_TRUE(entries[i] != NULL);
EXPECT_EQ(0u, empty_block_count(_storage)); EXPECT_EQ(0u, empty_block_count(storage()));
if (block == NULL) { if (block == NULL) {
ASSERT_FALSE(is_list_empty(allocation_list)); ASSERT_FALSE(is_list_empty(allocation_list));
EXPECT_EQ(1u, list_length(allocation_list)); EXPECT_EQ(1u, list_length(allocation_list));
block = allocation_list.chead(); block = allocation_list.chead();
EXPECT_EQ(1u, TestAccess::block_allocation_count(*block)); 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)) { } else if (TestAccess::block_is_full(*block)) {
EXPECT_TRUE(is_list_empty(allocation_list)); EXPECT_TRUE(is_list_empty(allocation_list));
block = NULL; block = NULL;
} else { } else {
EXPECT_FALSE(is_list_empty(allocation_list)); EXPECT_FALSE(is_list_empty(allocation_list));
EXPECT_EQ(block, allocation_list.chead()); 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_NE(0u, TestAccess::block_allocation_count(*block));
EXPECT_FALSE(is_list_empty(allocation_list)); EXPECT_FALSE(is_list_empty(allocation_list));
EXPECT_EQ(block, allocation_list.chead()); 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) { for (size_t i = 0; i < max_entries; ++i) {
release_entry(_storage, entries[i]); release_entry(storage(), entries[i]);
EXPECT_TRUE(is_allocation_list_sorted(_storage)); EXPECT_TRUE(is_allocation_list_sorted(storage()));
EXPECT_EQ(max_entries - (i + 1), total_allocation_count(_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()), list_length(allocation_list));
EXPECT_EQ(active_count(_storage), _storage.block_count()); EXPECT_EQ(active_count(storage()), storage().block_count());
EXPECT_EQ(active_count(_storage), empty_block_count(_storage)); EXPECT_EQ(active_count(storage()), empty_block_count(storage()));
for (const OopBlock* block = allocation_list.chead(); for (const OopBlock* block = allocation_list.chead();
block != NULL; block != NULL;
block = allocation_list.next(*block)) { block = allocation_list.next(*block)) {
@ -383,29 +386,29 @@ TEST_VM_F(OopStorageTestWithAllocation, random_release) {
static const size_t step = 11; static const size_t step = 11;
ASSERT_NE(0u, _max_entries % step); // max_entries and step are mutually prime 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)); EXPECT_GE(1u, list_length(allocation_list));
// Release all entries in "random" order. // Release all entries in "random" order.
size_t released = 0; size_t released = 0;
for (size_t i = 0; released < _max_entries; i = (i + step) % _max_entries) { for (size_t i = 0; released < _max_entries; i = (i + step) % _max_entries) {
if (_entries[i] != NULL) { if (_entries[i] != NULL) {
release_entry(_storage, _entries[i]); release_entry(storage(), _entries[i]);
_entries[i] = NULL; _entries[i] = NULL;
++released; ++released;
EXPECT_EQ(_max_entries - released, total_allocation_count(_storage)); EXPECT_EQ(_max_entries - released, total_allocation_count(storage()));
EXPECT_TRUE(is_allocation_list_sorted(_storage)); EXPECT_TRUE(is_allocation_list_sorted(storage()));
} }
} }
EXPECT_EQ(active_count(_storage), list_length(allocation_list)); EXPECT_EQ(active_count(storage()), list_length(allocation_list));
EXPECT_EQ(active_count(_storage), _storage.block_count()); EXPECT_EQ(active_count(storage()), storage().block_count());
EXPECT_EQ(0u, total_allocation_count(_storage)); EXPECT_EQ(0u, total_allocation_count(storage()));
EXPECT_EQ(list_length(allocation_list), empty_block_count(_storage)); EXPECT_EQ(list_length(allocation_list), empty_block_count(storage()));
} }
TEST_VM_F(OopStorageTestWithAllocation, random_allocate_release) { 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; static const size_t allocate_step = 5;
ASSERT_NE(0u, _max_entries % release_step); // max_entries and step are mutually prime 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)); EXPECT_GE(1u, list_length(allocation_list));
// Release all entries in "random" order, "randomly" interspersed // Release all entries in "random" order, "randomly" interspersed
@ -426,25 +429,25 @@ TEST_VM_F(OopStorageTestWithAllocation, random_allocate_release) {
size_t total_released = 0; size_t total_released = 0;
for (size_t i = 0; released < _max_entries; i = (i + release_step) % _max_entries) { for (size_t i = 0; released < _max_entries; i = (i + release_step) % _max_entries) {
if (_entries[i] != NULL) { if (_entries[i] != NULL) {
release_entry(_storage, _entries[i]); release_entry(storage(), _entries[i]);
_entries[i] = NULL; _entries[i] = NULL;
++released; ++released;
++total_released; ++total_released;
EXPECT_EQ(_max_entries - released, total_allocation_count(_storage)); EXPECT_EQ(_max_entries - released, total_allocation_count(storage()));
EXPECT_TRUE(is_allocation_list_sorted(_storage)); EXPECT_TRUE(is_allocation_list_sorted(storage()));
if (total_released % allocate_step == 0) { if (total_released % allocate_step == 0) {
_entries[i] = _storage.allocate(); _entries[i] = storage().allocate();
--released; --released;
EXPECT_EQ(_max_entries - released, total_allocation_count(_storage)); EXPECT_EQ(_max_entries - released, total_allocation_count(storage()));
EXPECT_TRUE(is_allocation_list_sorted(_storage)); EXPECT_TRUE(is_allocation_list_sorted(storage()));
} }
} }
} }
EXPECT_EQ(active_count(_storage), list_length(allocation_list)); EXPECT_EQ(active_count(storage()), list_length(allocation_list));
EXPECT_EQ(active_count(_storage), _storage.block_count()); EXPECT_EQ(active_count(storage()), storage().block_count());
EXPECT_EQ(0u, total_allocation_count(_storage)); EXPECT_EQ(0u, total_allocation_count(storage()));
EXPECT_EQ(list_length(allocation_list), empty_block_count(_storage)); EXPECT_EQ(list_length(allocation_list), empty_block_count(storage()));
} }
template<bool sorted> template<bool sorted>
@ -462,16 +465,16 @@ public:
QuickSort::sort(to_release, nrelease, PointerCompare(), false); QuickSort::sort(to_release, nrelease, PointerCompare(), false);
} }
_storage.release(to_release, nrelease); storage().release(to_release, nrelease);
EXPECT_EQ(_max_entries - nrelease, _storage.allocation_count()); EXPECT_EQ(_max_entries - nrelease, storage().allocation_count());
for (size_t i = 0; i < nrelease; ++i) { for (size_t i = 0; i < nrelease; ++i) {
release_entry(_storage, _entries[2 * i + 1], false); release_entry(storage(), _entries[2 * i + 1], false);
EXPECT_EQ(_max_entries - nrelease - (i + 1), _storage.allocation_count()); 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); FREE_C_HEAP_ARRAY(oop*, to_release);
} }
@ -494,25 +497,25 @@ TEST_VM_F(OopStorageTest, bulk_allocation) {
static const size_t zero = 0; static const size_t zero = 0;
oop* entries[max_entries] = {}; 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()));
size_t allocated = _storage.allocate(entries, max_entries); size_t allocated = storage().allocate(entries, max_entries);
ASSERT_NE(allocated, zero); ASSERT_NE(allocated, zero);
// ASSERT_LE would ODR-use the OopStorage constant. // ASSERT_LE would ODR-use the OopStorage constant.
size_t bulk_allocate_limit = OopStorage::bulk_allocate_limit; size_t bulk_allocate_limit = OopStorage::bulk_allocate_limit;
ASSERT_LE(allocated, bulk_allocate_limit); ASSERT_LE(allocated, bulk_allocate_limit);
ASSERT_LE(allocated, max_entries); ASSERT_LE(allocated, max_entries);
for (size_t i = 0; i < allocated; ++i) { 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) { for (size_t i = allocated; i < max_entries; ++i) {
EXPECT_EQ(NULL, entries[i]); EXPECT_EQ(NULL, entries[i]);
} }
_storage.release(entries, allocated); storage().release(entries, allocated);
EXPECT_EQ(0u, _storage.allocation_count()); EXPECT_EQ(0u, storage().allocation_count());
for (size_t i = 0; i < allocated; ++i) { 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); char* mem = NEW_C_HEAP_ARRAY(char, 1000, mtInternal);
oop* ptr = reinterpret_cast<oop*>(align_down(mem + 250, sizeof(oop))); oop* ptr = reinterpret_cast<oop*>(align_down(mem + 250, sizeof(oop)));
// Predicate returns false for some malloc'ed block. // 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); FREE_C_HEAP_ARRAY(char, mem);
} }
@ -530,7 +533,7 @@ TEST_VM_F(OopStorageTest, invalid_pointer) {
oop obj; oop obj;
oop* ptr = &obj; oop* ptr = &obj;
// Predicate returns false for some "random" location. // 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 #endif // DISABLE_GARBAGE_ALLOCATION_STATUS_TESTS
@ -594,7 +597,7 @@ TEST_VM_F(OopStorageTest, simple_iterate) {
size_t entries_with_values = 0; size_t entries_with_values = 0;
for (size_t i = 0; i < max_entries; i += 10) { for (size_t i = 0; i < max_entries; i += 10) {
for ( ; allocated < i; ++allocated) { for ( ; allocated < i; ++allocated) {
entries[allocated] = _storage.allocate(); entries[allocated] = storage().allocate();
ASSERT_TRUE(entries[allocated] != NULL); ASSERT_TRUE(entries[allocated] != NULL);
if ((allocated % 3) != 0) { if ((allocated % 3) != 0) {
*entries[allocated] = dummy_oop; *entries[allocated] = dummy_oop;
@ -604,7 +607,7 @@ TEST_VM_F(OopStorageTest, simple_iterate) {
{ {
CountingIterateClosure cl; CountingIterateClosure cl;
VM_CountAtSafepoint<false> op(&_storage, &cl); VM_CountAtSafepoint<false> op(&storage(), &cl);
{ {
ThreadInVMfromNative invm(JavaThread::current()); ThreadInVMfromNative invm(JavaThread::current());
VMThread::execute(&op); VMThread::execute(&op);
@ -617,7 +620,7 @@ TEST_VM_F(OopStorageTest, simple_iterate) {
{ {
CountingIterateClosure cl; CountingIterateClosure cl;
VM_CountAtSafepoint<true> op(&_storage, &cl); VM_CountAtSafepoint<true> op(&storage(), &cl);
{ {
ThreadInVMfromNative invm(JavaThread::current()); ThreadInVMfromNative invm(JavaThread::current());
VMThread::execute(&op); VMThread::execute(&op);
@ -630,9 +633,9 @@ TEST_VM_F(OopStorageTest, simple_iterate) {
} }
while (allocated > 0) { 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 { class OopStorageTestIteration : public OopStorageTestWithAllocation {
@ -651,17 +654,17 @@ public:
memset(_states, 0, sizeof(_states)); memset(_states, 0, sizeof(_states));
size_t initial_release = 0; 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); ASSERT_GT(_max_entries, initial_release);
release_entry(_storage, _entries[initial_release]); release_entry(storage(), _entries[initial_release]);
_states[0][initial_release] = mark_released; _states[0][initial_release] = mark_released;
} }
for (size_t i = initial_release; i < _max_entries; i += 3) { 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; _states[0][i] = mark_released;
} }
process_deferred_updates(_storage); process_deferred_updates(storage());
} }
class VerifyState; class VerifyState;
@ -831,7 +834,7 @@ private:
TEST_VM_F(OopStorageTestIteration, iterate_safepoint) { TEST_VM_F(OopStorageTestIteration, iterate_safepoint) {
VerifyState vstate(mark_non_const, _entries, _states); VerifyState vstate(mark_non_const, _entries, _states);
VM_Verify<false> op(&_storage, &vstate); VM_Verify<false> op(&storage(), &vstate);
{ {
ThreadInVMfromNative invm(JavaThread::current()); ThreadInVMfromNative invm(JavaThread::current());
VMThread::execute(&op); VMThread::execute(&op);
@ -842,7 +845,7 @@ TEST_VM_F(OopStorageTestIteration, iterate_safepoint) {
TEST_VM_F(OopStorageTestIteration, const_iterate_safepoint) { TEST_VM_F(OopStorageTestIteration, const_iterate_safepoint) {
VerifyState vstate(mark_const, _entries, _states); VerifyState vstate(mark_const, _entries, _states);
VM_Verify<true> op(&_storage, &vstate); VM_Verify<true> op(&storage(), &vstate);
{ {
ThreadInVMfromNative invm(JavaThread::current()); ThreadInVMfromNative invm(JavaThread::current());
VMThread::execute(&op); VMThread::execute(&op);
@ -853,7 +856,7 @@ TEST_VM_F(OopStorageTestIteration, const_iterate_safepoint) {
TEST_VM_F(OopStorageTestIteration, oops_do) { TEST_VM_F(OopStorageTestIteration, oops_do) {
VerifyState vstate(mark_non_const, _entries, _states); VerifyState vstate(mark_non_const, _entries, _states);
VM_VerifyUsingOopsDo op(&_storage, &vstate); VM_VerifyUsingOopsDo op(&storage(), &vstate);
{ {
ThreadInVMfromNative invm(JavaThread::current()); ThreadInVMfromNative invm(JavaThread::current());
VMThread::execute(&op); VMThread::execute(&op);
@ -946,7 +949,7 @@ private:
TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_iterate) { TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_iterate) {
VerifyState vstate(mark_non_const, _entries, _states); VerifyState vstate(mark_non_const, _entries, _states);
Task<false, false> task("test", &_storage, &vstate); Task<false, false> task("test", &storage(), &vstate);
VM_ParStateVerify op(workers(), &task); VM_ParStateVerify op(workers(), &task);
{ {
ThreadInVMfromNative invm(JavaThread::current()); 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) { TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_const_iterate) {
VerifyState vstate(mark_const, _entries, _states); VerifyState vstate(mark_const, _entries, _states);
Task<false, true> task("test", &_storage, &vstate); Task<false, true> task("test", &storage(), &vstate);
VM_ParStateVerify op(workers(), &task); VM_ParStateVerify op(workers(), &task);
{ {
ThreadInVMfromNative invm(JavaThread::current()); 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) { TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_oops_do) {
VerifyState vstate(mark_non_const, _entries, _states); VerifyState vstate(mark_non_const, _entries, _states);
TaskUsingOopsDo<false, false> task("test", &_storage, &vstate); TaskUsingOopsDo<false, false> task("test", &storage(), &vstate);
VM_ParStateVerify op(workers(), &task); VM_ParStateVerify op(workers(), &task);
{ {
ThreadInVMfromNative invm(JavaThread::current()); 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) { TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_const_oops_do) {
VerifyState vstate(mark_const, _entries, _states); VerifyState vstate(mark_const, _entries, _states);
TaskUsingOopsDo<false, true> task("test", &_storage, &vstate); TaskUsingOopsDo<false, true> task("test", &storage(), &vstate);
VM_ParStateVerify op(workers(), &task); VM_ParStateVerify op(workers(), &task);
{ {
ThreadInVMfromNative invm(JavaThread::current()); 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) { TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_iterate) {
VerifyState vstate(mark_non_const, _entries, _states); VerifyState vstate(mark_non_const, _entries, _states);
Task<true, false> task("test", &_storage, &vstate); Task<true, false> task("test", &storage(), &vstate);
workers()->run_task(&task); workers()->run_task(&task);
vstate.check(); vstate.check();
} }
TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_const_iterate) { TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_const_iterate) {
VerifyState vstate(mark_const, _entries, _states); VerifyState vstate(mark_const, _entries, _states);
Task<true, true> task("test", &_storage, &vstate); Task<true, true> task("test", &storage(), &vstate);
workers()->run_task(&task); workers()->run_task(&task);
vstate.check(); vstate.check();
} }
TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_oops_do) { TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_oops_do) {
VerifyState vstate(mark_non_const, _entries, _states); VerifyState vstate(mark_non_const, _entries, _states);
TaskUsingOopsDo<true, false> task("test", &_storage, &vstate); TaskUsingOopsDo<true, false> task("test", &storage(), &vstate);
workers()->run_task(&task); workers()->run_task(&task);
vstate.check(); vstate.check();
} }
TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_const_oops_do) { TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_const_oops_do) {
VerifyState vstate(mark_const, _entries, _states); VerifyState vstate(mark_const, _entries, _states);
TaskUsingOopsDo<true, true> task("test", &_storage, &vstate); TaskUsingOopsDo<true, true> task("test", &storage(), &vstate);
workers()->run_task(&task); workers()->run_task(&task);
vstate.check(); vstate.check();
} }
TEST_VM_F(OopStorageTestWithAllocation, delete_empty_blocks) { TEST_VM_F(OopStorageTestWithAllocation, delete_empty_blocks) {
size_t initial_active_size = active_count(_storage); size_t initial_active_size = active_count(storage());
EXPECT_EQ(initial_active_size, _storage.block_count()); EXPECT_EQ(initial_active_size, storage().block_count());
ASSERT_LE(3u, initial_active_size); // Need at least 3 blocks for test 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); 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, active_count(storage()));
EXPECT_EQ(initial_active_size, _storage.block_count()); EXPECT_EQ(initial_active_size, storage().block_count());
EXPECT_EQ(3u, empty_block_count(_storage)); EXPECT_EQ(3u, empty_block_count(storage()));
{ {
ThreadInVMfromNative invm(JavaThread::current()); ThreadInVMfromNative invm(JavaThread::current());
while (_storage.delete_empty_blocks()) {} while (storage().delete_empty_blocks()) {}
} }
EXPECT_EQ(0u, empty_block_count(_storage)); EXPECT_EQ(0u, empty_block_count(storage()));
EXPECT_EQ(initial_active_size - 3, active_count(_storage)); EXPECT_EQ(initial_active_size - 3, active_count(storage()));
EXPECT_EQ(initial_active_size - 3, _storage.block_count()); EXPECT_EQ(initial_active_size - 3, storage().block_count());
} }
TEST_VM_F(OopStorageTestWithAllocation, allocation_status) { TEST_VM_F(OopStorageTestWithAllocation, allocation_status) {
oop* retained = _entries[200]; oop* retained = _entries[200];
oop* released = _entries[300]; oop* released = _entries[300];
oop* garbage = reinterpret_cast<oop*>(1024 * 1024); oop* garbage = reinterpret_cast<oop*>(1024 * 1024);
release_entry(_storage, released); release_entry(storage(), released);
EXPECT_EQ(OopStorage::ALLOCATED_ENTRY, _storage.allocation_status(retained)); EXPECT_EQ(OopStorage::ALLOCATED_ENTRY, storage().allocation_status(retained));
EXPECT_EQ(OopStorage::UNALLOCATED_ENTRY, _storage.allocation_status(released)); EXPECT_EQ(OopStorage::UNALLOCATED_ENTRY, storage().allocation_status(released));
EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(garbage)); EXPECT_EQ(OopStorage::INVALID_ENTRY, storage().allocation_status(garbage));
for (size_t i = 0; i < _max_entries; ++i) { for (size_t i = 0; i < _max_entries; ++i) {
if ((_entries[i] != retained) && (_entries[i] != released)) { if ((_entries[i] != retained) && (_entries[i] != released)) {
// Leave deferred release updates to block deletion. // Leave deferred release updates to block deletion.
release_entry(_storage, _entries[i], false); release_entry(storage(), _entries[i], false);
} }
} }
{ {
ThreadInVMfromNative invm(JavaThread::current()); 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::ALLOCATED_ENTRY, storage().allocation_status(retained));
EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(released)); EXPECT_EQ(OopStorage::INVALID_ENTRY, storage().allocation_status(released));
EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(garbage)); EXPECT_EQ(OopStorage::INVALID_ENTRY, storage().allocation_status(garbage));
} }
TEST_VM_F(OopStorageTest, usage_info) { TEST_VM_F(OopStorageTest, usage_info) {
@ -1069,24 +1072,24 @@ TEST_VM_F(OopStorageTest, usage_info) {
oop* entries[1000]; oop* entries[1000];
size_t allocated = 0; 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. // 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) { while (storage().block_count() < goal_blocks) {
size_t this_count = _storage.block_count(); size_t this_count = storage().block_count();
while (_storage.block_count() == this_count) { while (storage().block_count() == this_count) {
ASSERT_GT(ARRAY_SIZE(entries), allocated); ASSERT_GT(ARRAY_SIZE(entries), allocated);
entries[allocated] = _storage.allocate(); entries[allocated] = storage().allocate();
ASSERT_TRUE(entries[allocated] != NULL); ASSERT_TRUE(entries[allocated] != NULL);
++allocated; ++allocated;
} }
EXPECT_NE(0u, _storage.block_count()); EXPECT_NE(0u, storage().block_count());
EXPECT_NE(0u, _storage.total_memory_usage()); EXPECT_NE(0u, storage().total_memory_usage());
} }
EXPECT_LT(TestAccess::memory_per_block() * _storage.block_count(), EXPECT_LT(TestAccess::memory_per_block() * storage().block_count(),
_storage.total_memory_usage()); storage().total_memory_usage());
} }
#ifndef PRODUCT #ifndef PRODUCT
@ -1095,22 +1098,22 @@ TEST_VM_F(OopStorageTestWithAllocation, print_storage) {
// Release the first 1/2 // Release the first 1/2
for (size_t i = 0; i < (_max_entries / 2); ++i) { for (size_t i = 0; i < (_max_entries / 2); ++i) {
// Deferred updates don't affect print output. // Deferred updates don't affect print output.
release_entry(_storage, _entries[i], false); release_entry(storage(), _entries[i], false);
_entries[i] = NULL; _entries[i] = NULL;
} }
// Release every other remaining // Release every other remaining
for (size_t i = _max_entries / 2; i < _max_entries; i += 2) { for (size_t i = _max_entries / 2; i < _max_entries; i += 2) {
// Deferred updates don't affect print output. // Deferred updates don't affect print output.
release_entry(_storage, _entries[i], false); release_entry(storage(), _entries[i], false);
_entries[i] = NULL; _entries[i] = NULL;
} }
size_t expected_entries = _max_entries / 4; 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 entries_per_block = BitsPerWord;
size_t expected_blocks = (_max_entries + entries_per_block - 1) / entries_per_block; 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); 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_entries,
expected_blocks, expected_blocks,
expected_usage, expected_usage,
_storage.total_memory_usage()); storage().total_memory_usage());
stringStream st; stringStream st;
_storage.print_on(&st); storage().print_on(&st);
EXPECT_STREQ(expected_st.as_string(), st.as_string()); EXPECT_STREQ(expected_st.as_string(), st.as_string());
} }
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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; const size_t _storage_entries = 1000000;
class OopStorageParIterPerf : public ::testing::Test { class OopStorageParIterPerf : public ::testing::Test {
OopStorage* _storage;
public: public:
OopStorageParIterPerf(); OopStorageParIterPerf();
~OopStorageParIterPerf(); ~OopStorageParIterPerf();
@ -62,13 +64,13 @@ public:
class Task; class Task;
class Closure; class Closure;
OopStorage& storage() const { return *_storage; }
Tickspan run_task(Task* task, uint nthreads); Tickspan run_task(Task* task, uint nthreads);
void show_task(const Task* task, Tickspan duration, uint nthreads); void show_task(const Task* task, Tickspan duration, uint nthreads);
void run_test(uint nthreads); void run_test(uint nthreads);
static WorkerThreads* _workers; static WorkerThreads* _workers;
OopStorage _storage;
oop* _entries[_storage_entries]; oop* _entries[_storage_entries];
}; };
@ -85,16 +87,17 @@ WorkerThreads* OopStorageParIterPerf::workers() const {
} }
OopStorageParIterPerf::OopStorageParIterPerf() : OopStorageParIterPerf::OopStorageParIterPerf() :
_storage("Test Storage", mtGC) _storage(OopStorage::create("Test Storage", mtGC))
{ {
for (size_t i = 0; i < _storage_entries; ++i) { 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()); _num_workers = MIN2(_max_workers, (uint)os::processor_count());
} }
OopStorageParIterPerf::~OopStorageParIterPerf() { OopStorageParIterPerf::~OopStorageParIterPerf() {
_storage.release(_entries, ARRAY_SIZE(_entries)); storage().release(_entries, ARRAY_SIZE(_entries));
delete _storage;
} }
class OopStorageParIterPerf::VM_ParStateTime : public VM_GTestExecuteAtSafepoint { class OopStorageParIterPerf::VM_ParStateTime : public VM_GTestExecuteAtSafepoint {
@ -177,7 +180,7 @@ void OopStorageParIterPerf::run_test(uint nthreads) {
if (nthreads <= _num_workers) { if (nthreads <= _num_workers) {
SCOPED_TRACE(err_msg("Running test with %u threads", nthreads).buffer()); SCOPED_TRACE(err_msg("Running test with %u threads", nthreads).buffer());
Closure closure; Closure closure;
Task task(&_storage, &closure, nthreads); Task task(&storage(), &closure, nthreads);
Tickspan t = run_task(&task, nthreads); Tickspan t = run_task(&task, nthreads);
show_task(&task, t, nthreads); show_task(&task, t, nthreads);
} }