8295013: OopStorage should derive from CHeapObjBase
Reviewed-by: stefank, tschatzl
This commit is contained in:
parent
3a980b972f
commit
94a9b048af
@ -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)),
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user