--- a/test/hotspot/gtest/gc/shared/test_oopStorage.cpp Thu May 03 14:13:20 2018 -0700
+++ b/test/hotspot/gtest/gc/shared/test_oopStorage.cpp Thu May 03 17:36:50 2018 -0400
@@ -53,9 +53,10 @@
public:
typedef OopStorage::Block Block;
typedef OopStorage::BlockList BlockList;
+ typedef OopStorage::BlockArray BlockArray;
- static BlockList& active_list(OopStorage& storage) {
- return storage._active_list;
+ static BlockArray& active_array(const OopStorage& storage) {
+ return *storage._active_array;
}
static BlockList& allocate_list(OopStorage& storage) {
@@ -96,20 +97,25 @@
static size_t memory_per_block() {
return Block::allocation_size();
}
+
+ static void block_array_set_block_count(BlockArray* blocks, size_t count) {
+ blocks->_block_count = count;
+ }
};
typedef OopStorage::TestAccess TestAccess;
-// --- FIXME: Should be just Block, but that collides with opto Block
-// when building with precompiled headers. There really should be
-// an opto namespace.
+
+// The "Oop" prefix is to avoid collision with similar opto names when
+// building with precompiled headers, or for consistency with that
+// workaround. There really should be an opto namespace.
typedef TestAccess::Block OopBlock;
-// --- FIXME: Similarly, this typedef collides with opto BlockList.
-// typedef TestAccess::BlockList BlockList;
+typedef TestAccess::BlockList OopBlockList;
+typedef TestAccess::BlockArray OopBlockArray;
// Using EXPECT_EQ can't use NULL directly. Otherwise AIX build breaks.
const OopBlock* const NULL_BLOCK = NULL;
-static size_t list_length(const TestAccess::BlockList& list) {
+static size_t list_length(const OopBlockList& list) {
size_t result = 0;
for (const OopBlock* block = list.chead();
block != NULL;
@@ -119,7 +125,7 @@
return result;
}
-static void clear_list(TestAccess::BlockList& list) {
+static void clear_list(OopBlockList& list) {
OopBlock* next;
for (OopBlock* block = list.head(); block != NULL; block = next) {
next = list.next(*block);
@@ -127,7 +133,7 @@
}
}
-static bool is_list_empty(const TestAccess::BlockList& list) {
+static bool is_list_empty(const OopBlockList& list) {
return list.chead() == NULL;
}
@@ -149,7 +155,7 @@
}
static size_t empty_block_count(const OopStorage& storage) {
- const TestAccess::BlockList& list = TestAccess::allocate_list(storage);
+ const OopBlockList& list = TestAccess::allocate_list(storage);
size_t count = 0;
for (const OopBlock* block = list.ctail();
(block != NULL) && block->is_empty();
@@ -158,6 +164,20 @@
return count;
}
+static size_t active_count(const OopStorage& storage) {
+ return TestAccess::active_array(storage).block_count();
+}
+
+static OopBlock* active_head(const OopStorage& storage) {
+ OopBlockArray& ba = TestAccess::active_array(storage);
+ size_t count = ba.block_count();
+ if (count == 0) {
+ return NULL;
+ } else {
+ return ba.at(count - 1);
+ }
+}
+
class OopStorageTest : public ::testing::Test {
public:
OopStorageTest();
@@ -188,7 +208,6 @@
OopStorageTest::~OopStorageTest() {
clear_list(TestAccess::allocate_list(_storage));
- clear_list(TestAccess::active_list(_storage));
}
class OopStorageTestWithAllocation : public OopStorageTest {
@@ -227,7 +246,7 @@
static bool is_allocate_list_sorted(const OopStorage& storage) {
// The allocate_list isn't strictly sorted. Rather, all empty
// blocks are segregated to the end of the list.
- const TestAccess::BlockList& list = TestAccess::allocate_list(storage);
+ const OopBlockList& list = TestAccess::allocate_list(storage);
const OopBlock* block = list.ctail();
for ( ; (block != NULL) && block->is_empty(); block = list.prev(*block)) {}
for ( ; block != NULL; block = list.prev(*block)) {
@@ -238,25 +257,25 @@
return true;
}
-static size_t total_allocation_count(const TestAccess::BlockList& list) {
+static size_t total_allocation_count(const OopStorage& storage) {
size_t total_count = 0;
- for (const OopBlock* block = list.chead();
- block != NULL;
- block = list.next(*block)) {
- total_count += TestAccess::block_allocation_count(*block);
+ const OopBlockArray& ba = TestAccess::active_array(storage);
+ size_t limit = active_count(storage);
+ for (size_t i = 0; i < limit; ++i) {
+ total_count += TestAccess::block_allocation_count(*ba.at(i));
}
return total_count;
}
TEST_VM_F(OopStorageTest, allocate_one) {
- EXPECT_TRUE(is_list_empty(TestAccess::active_list(_storage)));
+ EXPECT_EQ(0u, active_count(_storage));
EXPECT_TRUE(is_list_empty(TestAccess::allocate_list(_storage)));
oop* ptr = _storage.allocate();
EXPECT_TRUE(ptr != NULL);
EXPECT_EQ(1u, _storage.allocation_count());
- EXPECT_EQ(1u, list_length(TestAccess::active_list(_storage)));
+ EXPECT_EQ(1u, active_count(_storage));
EXPECT_EQ(1u, _storage.block_count());
EXPECT_EQ(1u, list_length(TestAccess::allocate_list(_storage)));
@@ -264,7 +283,7 @@
const OopBlock* block = TestAccess::allocate_list(_storage).chead();
EXPECT_NE(block, (OopBlock*)NULL);
- EXPECT_EQ(block, (TestAccess::active_list(_storage).chead()));
+ 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));
@@ -272,7 +291,7 @@
release_entry(_storage, ptr);
EXPECT_EQ(0u, _storage.allocation_count());
- EXPECT_EQ(1u, list_length(TestAccess::active_list(_storage)));
+ EXPECT_EQ(1u, active_count(_storage));
EXPECT_EQ(1u, _storage.block_count());
EXPECT_EQ(1u, list_length(TestAccess::allocate_list(_storage)));
@@ -280,7 +299,7 @@
const OopBlock* new_block = TestAccess::allocate_list(_storage).chead();
EXPECT_EQ(block, new_block);
- EXPECT_EQ(block, (TestAccess::active_list(_storage).chead()));
+ 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));
@@ -290,20 +309,19 @@
static const size_t max_entries = 1000;
oop* entries[max_entries];
- TestAccess::BlockList& active_list = TestAccess::active_list(_storage);
- TestAccess::BlockList& allocate_list = TestAccess::allocate_list(_storage);
+ OopBlockList& allocate_list = TestAccess::allocate_list(_storage);
- EXPECT_TRUE(is_list_empty(active_list));
+ EXPECT_EQ(0u, active_count(_storage));
EXPECT_EQ(0u, _storage.block_count());
EXPECT_TRUE(is_list_empty(allocate_list));
size_t allocated = 0;
for ( ; allocated < max_entries; ++allocated) {
EXPECT_EQ(allocated, _storage.allocation_count());
- if (!is_list_empty(active_list)) {
- EXPECT_EQ(1u, list_length(active_list));
+ if (active_count(_storage) != 0) {
+ EXPECT_EQ(1u, active_count(_storage));
EXPECT_EQ(1u, _storage.block_count());
- const OopBlock& block = *active_list.chead();
+ const OopBlock& block = *TestAccess::active_array(_storage).at(0);
EXPECT_EQ(allocated, TestAccess::block_allocation_count(block));
if (TestAccess::block_is_full(block)) {
break;
@@ -316,10 +334,10 @@
}
EXPECT_EQ(allocated, _storage.allocation_count());
- EXPECT_EQ(1u, list_length(active_list));
+ EXPECT_EQ(1u, active_count(_storage));
EXPECT_EQ(1u, _storage.block_count());
EXPECT_TRUE(is_list_empty(allocate_list));
- const OopBlock& block = *active_list.chead();
+ const OopBlock& block = *TestAccess::active_array(_storage).at(0);
EXPECT_TRUE(TestAccess::block_is_full(block));
EXPECT_EQ(allocated, TestAccess::block_allocation_count(block));
@@ -336,19 +354,18 @@
static const size_t max_entries = 1000;
oop* entries[max_entries];
- TestAccess::BlockList& active_list = TestAccess::active_list(_storage);
- TestAccess::BlockList& allocate_list = TestAccess::allocate_list(_storage);
+ OopBlockList& allocate_list = TestAccess::allocate_list(_storage);
EXPECT_EQ(0u, empty_block_count(_storage));
entries[0] = _storage.allocate();
ASSERT_TRUE(entries[0] != NULL);
- EXPECT_EQ(1u, list_length(active_list));
+ EXPECT_EQ(1u, active_count(_storage));
EXPECT_EQ(1u, _storage.block_count());
EXPECT_EQ(1u, list_length(allocate_list));
EXPECT_EQ(0u, empty_block_count(_storage));
- const OopBlock* block = active_list.chead();
+ const OopBlock* block = TestAccess::active_array(_storage).at(0);
EXPECT_EQ(1u, TestAccess::block_allocation_count(*block));
EXPECT_EQ(block, allocate_list.chead());
@@ -363,14 +380,14 @@
EXPECT_EQ(1u, list_length(allocate_list));
block = allocate_list.chead();
EXPECT_EQ(1u, TestAccess::block_allocation_count(*block));
- EXPECT_EQ(block, active_list.chead());
+ EXPECT_EQ(block, active_head(_storage));
} else if (TestAccess::block_is_full(*block)) {
EXPECT_TRUE(is_list_empty(allocate_list));
block = NULL;
} else {
EXPECT_FALSE(is_list_empty(allocate_list));
EXPECT_EQ(block, allocate_list.chead());
- EXPECT_EQ(block, active_list.chead());
+ EXPECT_EQ(block, active_head(_storage));
}
}
@@ -378,20 +395,18 @@
EXPECT_NE(0u, TestAccess::block_allocation_count(*block));
EXPECT_FALSE(is_list_empty(allocate_list));
EXPECT_EQ(block, allocate_list.chead());
- EXPECT_EQ(block, active_list.chead());
+ EXPECT_EQ(block, active_head(_storage));
}
- size_t active_count = list_length(active_list);
-
for (size_t i = 0; i < max_entries; ++i) {
release_entry(_storage, entries[i]);
EXPECT_TRUE(is_allocate_list_sorted(_storage));
- EXPECT_EQ(max_entries - (i + 1), total_allocation_count(active_list));
+ EXPECT_EQ(max_entries - (i + 1), total_allocation_count(_storage));
}
- EXPECT_EQ(list_length(active_list), list_length(allocate_list));
- EXPECT_EQ(list_length(active_list), _storage.block_count());
- EXPECT_EQ(list_length(active_list), empty_block_count(_storage));
+ EXPECT_EQ(active_count(_storage), list_length(allocate_list));
+ EXPECT_EQ(active_count(_storage), _storage.block_count());
+ EXPECT_EQ(active_count(_storage), empty_block_count(_storage));
for (const OopBlock* block = allocate_list.chead();
block != NULL;
block = allocate_list.next(*block)) {
@@ -405,10 +420,9 @@
EXPECT_EQ(0u, empty_block_count(_storage));
- TestAccess::BlockList& active_list = TestAccess::active_list(_storage);
- TestAccess::BlockList& allocate_list = TestAccess::allocate_list(_storage);
+ OopBlockList& allocate_list = TestAccess::allocate_list(_storage);
- EXPECT_EQ(_max_entries, total_allocation_count(active_list));
+ EXPECT_EQ(_max_entries, total_allocation_count(_storage));
EXPECT_GE(1u, list_length(allocate_list));
// Release all entries in "random" order.
@@ -418,14 +432,14 @@
release_entry(_storage, _entries[i]);
_entries[i] = NULL;
++released;
- EXPECT_EQ(_max_entries - released, total_allocation_count(active_list));
+ EXPECT_EQ(_max_entries - released, total_allocation_count(_storage));
EXPECT_TRUE(is_allocate_list_sorted(_storage));
}
}
- EXPECT_EQ(list_length(active_list), list_length(allocate_list));
- EXPECT_EQ(list_length(active_list), _storage.block_count());
- EXPECT_EQ(0u, total_allocation_count(active_list));
+ EXPECT_EQ(active_count(_storage), list_length(allocate_list));
+ EXPECT_EQ(active_count(_storage), _storage.block_count());
+ EXPECT_EQ(0u, total_allocation_count(_storage));
EXPECT_EQ(list_length(allocate_list), empty_block_count(_storage));
}
@@ -436,10 +450,9 @@
EXPECT_EQ(0u, empty_block_count(_storage));
- TestAccess::BlockList& active_list = TestAccess::active_list(_storage);
- TestAccess::BlockList& allocate_list = TestAccess::allocate_list(_storage);
+ OopBlockList& allocate_list = TestAccess::allocate_list(_storage);
- EXPECT_EQ(_max_entries, total_allocation_count(active_list));
+ EXPECT_EQ(_max_entries, total_allocation_count(_storage));
EXPECT_GE(1u, list_length(allocate_list));
// Release all entries in "random" order, "randomly" interspersed
@@ -452,20 +465,20 @@
_entries[i] = NULL;
++released;
++total_released;
- EXPECT_EQ(_max_entries - released, total_allocation_count(active_list));
+ EXPECT_EQ(_max_entries - released, total_allocation_count(_storage));
EXPECT_TRUE(is_allocate_list_sorted(_storage));
if (total_released % allocate_step == 0) {
_entries[i] = _storage.allocate();
--released;
- EXPECT_EQ(_max_entries - released, total_allocation_count(active_list));
+ EXPECT_EQ(_max_entries - released, total_allocation_count(_storage));
EXPECT_TRUE(is_allocate_list_sorted(_storage));
}
}
}
- EXPECT_EQ(list_length(active_list), list_length(allocate_list));
- EXPECT_EQ(list_length(active_list), _storage.block_count());
- EXPECT_EQ(0u, total_allocation_count(active_list));
+ EXPECT_EQ(active_count(_storage), list_length(allocate_list));
+ EXPECT_EQ(active_count(_storage), _storage.block_count());
+ EXPECT_EQ(0u, total_allocation_count(_storage));
EXPECT_EQ(list_length(allocate_list), empty_block_count(_storage));
}
@@ -1015,9 +1028,7 @@
}
TEST_VM_F(OopStorageTestWithAllocation, delete_empty_blocks_safepoint) {
- TestAccess::BlockList& active_list = TestAccess::active_list(_storage);
-
- size_t initial_active_size = list_length(active_list);
+ 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
@@ -1026,7 +1037,7 @@
release_entry(_storage, _entries[i]);
}
- EXPECT_EQ(initial_active_size, list_length(active_list));
+ EXPECT_EQ(initial_active_size, active_count(_storage));
EXPECT_EQ(initial_active_size, _storage.block_count());
EXPECT_EQ(3u, empty_block_count(_storage));
@@ -1036,14 +1047,12 @@
VMThread::execute(&op);
}
EXPECT_EQ(0u, empty_block_count(_storage));
- EXPECT_EQ(initial_active_size - 3, list_length(active_list));
+ EXPECT_EQ(initial_active_size - 3, active_count(_storage));
EXPECT_EQ(initial_active_size - 3, _storage.block_count());
}
TEST_VM_F(OopStorageTestWithAllocation, delete_empty_blocks_concurrent) {
- TestAccess::BlockList& active_list = TestAccess::active_list(_storage);
-
- size_t initial_active_size = list_length(active_list);
+ 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
@@ -1052,13 +1061,13 @@
release_entry(_storage, _entries[i]);
}
- EXPECT_EQ(initial_active_size, list_length(active_list));
+ EXPECT_EQ(initial_active_size, active_count(_storage));
EXPECT_EQ(initial_active_size, _storage.block_count());
EXPECT_EQ(3u, empty_block_count(_storage));
_storage.delete_empty_blocks_concurrent();
EXPECT_EQ(0u, empty_block_count(_storage));
- EXPECT_EQ(initial_active_size - 3, list_length(active_list));
+ EXPECT_EQ(initial_active_size - 3, active_count(_storage));
EXPECT_EQ(initial_active_size - 3, _storage.block_count());
}
@@ -1161,23 +1170,21 @@
#endif // !PRODUCT
-//////////////////////////////////////////////////////////////////////////////
-// Unit tests for block lists
-
-class OopStorageBlockListTest : public ::testing::Test {
-public:
- OopStorageBlockListTest() {
+class OopStorageBlockCollectionTest : public ::testing::Test {
+protected:
+ OopStorageBlockCollectionTest() {
for (size_t i = 0; i < nvalues; ++i) {
values[i] = OopBlock::new_block(pseudo_owner());
}
}
- ~OopStorageBlockListTest() {
+ ~OopStorageBlockCollectionTest() {
for (size_t i = 0; i < nvalues; ++i) {
OopBlock::delete_block(*values[i]);
}
}
+public:
static const size_t nvalues = 10;
OopBlock* values[nvalues];
@@ -1190,11 +1197,13 @@
}
};
-const size_t OopStorageBlockListTest::nvalues;
-const void* const OopStorageBlockListTest::_pseudo_owner[] = {};
+const size_t OopStorageBlockCollectionTest::nvalues;
+const void* const OopStorageBlockCollectionTest::_pseudo_owner[] = {};
+
+class OopStorageBlockListTest : public OopStorageBlockCollectionTest {};
TEST_F(OopStorageBlockListTest, empty_list) {
- TestAccess::BlockList list(&OopBlock::get_active_entry);
+ OopBlockList list(&OopBlock::get_allocate_entry);
EXPECT_TRUE(is_list_empty(list));
EXPECT_EQ(NULL_BLOCK, list.head());
@@ -1203,7 +1212,7 @@
}
TEST_F(OopStorageBlockListTest, push_back) {
- TestAccess::BlockList list(&OopBlock::get_active_entry);
+ OopBlockList list(&OopBlock::get_allocate_entry);
for (size_t i = 0; i < nvalues; ++i) {
list.push_back(*values[i]);
@@ -1233,7 +1242,7 @@
}
TEST_F(OopStorageBlockListTest, push_front) {
- TestAccess::BlockList list(&OopBlock::get_active_entry);
+ OopBlockList list(&OopBlock::get_allocate_entry);
for (size_t i = 0; i < nvalues; ++i) {
list.push_front(*values[i]);
@@ -1264,7 +1273,7 @@
class OopStorageBlockListTestWithList : public OopStorageBlockListTest {
public:
- OopStorageBlockListTestWithList() : list(&OopBlock::get_active_entry) {
+ OopStorageBlockListTestWithList() : list(&OopBlock::get_allocate_entry) {
for (size_t i = 0; i < nvalues; ++i) {
list.push_back(*values[i]);
}
@@ -1274,7 +1283,7 @@
clear_list(list);
}
- TestAccess::BlockList list;
+ OopBlockList list;
};
TEST_F(OopStorageBlockListTestWithList, unlink_front) {
@@ -1336,7 +1345,7 @@
}
TEST_F(OopStorageBlockListTest, single) {
- TestAccess::BlockList list(&OopBlock::get_active_entry);
+ OopBlockList list(&OopBlock::get_allocate_entry);
list.push_back(*values[0]);
EXPECT_EQ(NULL_BLOCK, list.next(*values[0]));
@@ -1351,31 +1360,79 @@
EXPECT_EQ(NULL_BLOCK, list.ctail());
}
-TEST_F(OopStorageBlockListTestWithList, two_lists) {
- TestAccess::BlockList list2(&OopBlock::get_allocate_entry);
- for (size_t i = 0; i < nvalues; ++i) {
- list2.push_front(*values[i]);
+class OopStorageBlockArrayTest : public OopStorageBlockCollectionTest {};
+
+TEST_F(OopStorageBlockArrayTest, empty_array) {
+ OopBlockArray* a = OopBlockArray::create(nvalues);
+
+ EXPECT_EQ(nvalues, a->size());
+ EXPECT_EQ(0u, a->block_count_acquire());
+ TestAccess::block_array_set_block_count(a, 2);
+ EXPECT_EQ(2u, a->block_count_acquire());
+ TestAccess::block_array_set_block_count(a, 0);
+ a->increment_refcount();
+ a->increment_refcount();
+ EXPECT_FALSE(a->decrement_refcount());
+ EXPECT_TRUE(a->decrement_refcount());
+
+ OopBlockArray::destroy(a);
+}
+
+TEST_F(OopStorageBlockArrayTest, push) {
+ OopBlockArray* a = OopBlockArray::create(nvalues - 1);
+
+ for (size_t i = 0; i < nvalues - 1; ++i) {
+ EXPECT_TRUE(a->push(values[i]));
+ EXPECT_EQ(i + 1, a->block_count_acquire());
+ EXPECT_EQ(values[i], a->at(i));
+ }
+ EXPECT_FALSE(a->push(values[nvalues - 1]));
+
+ TestAccess::block_array_set_block_count(a, 0);
+ OopBlockArray::destroy(a);
+}
+
+class OopStorageBlockArrayTestWithArray : public OopStorageBlockArrayTest {
+public:
+ OopStorageBlockArrayTestWithArray() : a(OopBlockArray::create(nvalues)) {
+ for (size_t i = 0; i < nvalues; ++i) {
+ a->push(values[i]);
+ }
}
- const OopBlock* active_block = list.chead();
- const OopBlock* allocate_block = list2.ctail();
- for (size_t i = 0; i < nvalues; ++i) {
- EXPECT_EQ(active_block, allocate_block);
- active_block = list.next(*active_block);
- allocate_block = list2.prev(*allocate_block);
+ ~OopStorageBlockArrayTestWithArray() {
+ TestAccess::block_array_set_block_count(a, 0);
+ OopBlockArray::destroy(a);
}
- EXPECT_EQ(NULL_BLOCK, active_block);
- EXPECT_EQ(NULL_BLOCK, allocate_block);
+
+ OopBlockArray* a;
+};
+
+TEST_F(OopStorageBlockArrayTestWithArray, remove0) {
+ a->remove(values[0]);
+ EXPECT_EQ(nvalues - 1, a->block_count_acquire());
+ EXPECT_EQ(values[nvalues - 1], a->at(0));
+ for (size_t i = 1; i < nvalues - 1; ++i) {
+ EXPECT_EQ(values[i], a->at(i));
+ }
+}
- for (size_t i = 0; i < nvalues; ++i) {
- list2.unlink(*values[i]);
+TEST_F(OopStorageBlockArrayTestWithArray, remove3) {
+ a->remove(values[3]);
+ EXPECT_EQ(nvalues - 1, a->block_count_acquire());
+ for (size_t i = 0; i < 3; ++i) {
+ EXPECT_EQ(values[i], a->at(i));
}
- EXPECT_TRUE(is_list_empty(list2));
+ EXPECT_EQ(values[nvalues - 1], a->at(3));
+ for (size_t i = 4; i < nvalues - 1; ++i) {
+ EXPECT_EQ(values[i], a->at(i));
+ }
+}
- active_block = list.chead();
- for (size_t i = 0; i < nvalues; ++i) {
- EXPECT_EQ(active_block, values[i]);
- active_block = list.next(*active_block);
+TEST_F(OopStorageBlockArrayTestWithArray, remove_last) {
+ a->remove(values[nvalues - 1]);
+ EXPECT_EQ(nvalues - 1, a->block_count_acquire());
+ for (size_t i = 0; i < nvalues - 1; ++i) {
+ EXPECT_EQ(values[i], a->at(i));
}
- EXPECT_EQ(NULL_BLOCK, active_block);
}