mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-14 04:15:04 +00:00
8371341: ZGC: Improve gtest interoperability with instrumented builds (ASAN)
Reviewed-by: stefank, eosterlund
This commit is contained in:
parent
a8b35bf5a6
commit
4e4cced710
@ -33,6 +33,7 @@
|
||||
using ZVirtualMemoryRegistry = ZRangeRegistry<ZVirtualMemory>;
|
||||
|
||||
class ZVirtualMemoryReserver {
|
||||
friend class ZTest;
|
||||
friend class ZMapperTest;
|
||||
friend class ZVirtualMemoryManagerTest;
|
||||
|
||||
|
||||
@ -28,9 +28,10 @@
|
||||
#include "gc/z/zGlobals.hpp"
|
||||
#include "gc/z/zHeap.hpp"
|
||||
#include "gc/z/zPage.inline.hpp"
|
||||
#include "gc/z/zRangeRegistry.inline.hpp"
|
||||
#include "gc/z/zVirtualMemory.inline.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "unittest.hpp"
|
||||
#include "zunittest.hpp"
|
||||
|
||||
using namespace testing;
|
||||
|
||||
@ -40,35 +41,21 @@ using namespace testing;
|
||||
|
||||
#define CAPTURE(expression) CAPTURE1(expression)
|
||||
|
||||
class ZForwardingTest : public Test {
|
||||
class ZForwardingTest : public ZTest {
|
||||
public:
|
||||
// Setup and tear down
|
||||
ZHeap* _old_heap;
|
||||
ZGenerationOld* _old_old;
|
||||
ZGenerationYoung* _old_young;
|
||||
char* _reserved;
|
||||
static size_t _page_offset;
|
||||
|
||||
char* reserve_page_memory() {
|
||||
// Probe for a free 2MB region inside the usable address range.
|
||||
// Inspired by ZVirtualMemoryManager::reserve_contiguous.
|
||||
const size_t unused = ZAddressOffsetMax - ZGranuleSize;
|
||||
const size_t increment = MAX2(align_up(unused / 100, ZGranuleSize), ZGranuleSize);
|
||||
|
||||
for (uintptr_t start = 0; start + ZGranuleSize <= ZAddressOffsetMax; start += increment) {
|
||||
char* const reserved = os::attempt_reserve_memory_at((char*)ZAddressHeapBase + start, ZGranuleSize, mtTest);
|
||||
if (reserved != nullptr) {
|
||||
// Success
|
||||
return reserved;
|
||||
}
|
||||
}
|
||||
|
||||
// Failed
|
||||
return nullptr;
|
||||
}
|
||||
ZAddressReserver _zaddress_reserver;
|
||||
zoffset _page_offset;
|
||||
|
||||
virtual void SetUp() {
|
||||
ZGlobalsPointers::initialize();
|
||||
// Only run test on supported Windows versions
|
||||
if (!is_os_supported()) {
|
||||
GTEST_SKIP() << "OS not supported";
|
||||
}
|
||||
|
||||
_old_heap = ZHeap::_heap;
|
||||
ZHeap::_heap = (ZHeap*)os::malloc(sizeof(ZHeap), mtTest);
|
||||
|
||||
@ -84,36 +71,34 @@ public:
|
||||
ZGeneration::_old->_seqnum = 1;
|
||||
ZGeneration::_young->_seqnum = 2;
|
||||
|
||||
// Preconditions for reserve_free_granule()
|
||||
ASSERT_NE(ZAddressHeapBase, 0u);
|
||||
ASSERT_NE(ZAddressOffsetMax, 0u);
|
||||
ASSERT_NE(ZGranuleSize, 0u);
|
||||
_zaddress_reserver.SetUp(ZGranuleSize);
|
||||
_page_offset = _zaddress_reserver.registry()->peek_low_address();
|
||||
|
||||
_reserved = nullptr;
|
||||
if (_page_offset == zoffset::invalid) {
|
||||
GTEST_SKIP() << "Unable to reserve memory";
|
||||
}
|
||||
|
||||
// Find a suitable address for the testing page
|
||||
char* reserved = reserve_page_memory();
|
||||
|
||||
ASSERT_NE(reserved, nullptr) << "Failed to reserve the page granule. Test needs tweaking";
|
||||
ASSERT_GE(reserved, (char*)ZAddressHeapBase);
|
||||
ASSERT_LT(reserved, (char*)ZAddressHeapBase + ZAddressOffsetMax);
|
||||
|
||||
_reserved = reserved;
|
||||
|
||||
os::commit_memory((char*)_reserved, ZGranuleSize, false /* executable */);
|
||||
|
||||
_page_offset = uintptr_t(_reserved) - ZAddressHeapBase;
|
||||
char* const addr = (char*)untype(ZOffset::address_unsafe(_page_offset));
|
||||
os::commit_memory(addr, ZGranuleSize, /* executable */ false);
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
if (!is_os_supported()) {
|
||||
// Test skipped, nothing to cleanup
|
||||
return;
|
||||
}
|
||||
|
||||
os::free(ZHeap::_heap);
|
||||
ZHeap::_heap = _old_heap;
|
||||
ZGeneration::_old = _old_old;
|
||||
ZGeneration::_young = _old_young;
|
||||
if (_reserved != nullptr) {
|
||||
os::uncommit_memory((char*)_reserved, ZGranuleSize, false /* executable */);
|
||||
os::release_memory((char*)_reserved, ZGranuleSize);
|
||||
|
||||
if (_page_offset != zoffset::invalid) {
|
||||
char* const addr = (char*)untype(ZOffset::address_unsafe(_page_offset));
|
||||
os::uncommit_memory(addr, ZGranuleSize, false /* executable */);
|
||||
}
|
||||
|
||||
_zaddress_reserver.TearDown();
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
@ -219,7 +204,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
static void test(void (*function)(ZForwarding*), uint32_t size) {
|
||||
void test(void (*function)(ZForwarding*), uint32_t size) {
|
||||
// Create page
|
||||
const ZVirtualMemory vmem(zoffset(_page_offset), ZPageSizeSmall);
|
||||
ZPage page(ZPageType::small, ZPageAge::eden, vmem, 0u);
|
||||
@ -257,7 +242,7 @@ public:
|
||||
}
|
||||
|
||||
// Run the given function with a few different input values.
|
||||
static void test(void (*function)(ZForwarding*)) {
|
||||
void test(void (*function)(ZForwarding*)) {
|
||||
test(function, 1);
|
||||
test(function, 2);
|
||||
test(function, 3);
|
||||
@ -285,5 +270,3 @@ TEST_VM_F(ZForwardingTest, find_full) {
|
||||
TEST_VM_F(ZForwardingTest, find_every_other) {
|
||||
test(&ZForwardingTest::find_every_other);
|
||||
}
|
||||
|
||||
size_t ZForwardingTest::_page_offset;
|
||||
|
||||
@ -34,8 +34,9 @@ using namespace testing;
|
||||
|
||||
class ZMapperTest : public ZTest {
|
||||
private:
|
||||
static constexpr size_t ReservationSize = 32 * M;
|
||||
static constexpr size_t ReservationSize = 3 * ZGranuleSize;
|
||||
|
||||
ZAddressReserver _zaddress_reserver;
|
||||
ZVirtualMemoryReserver* _reserver;
|
||||
ZVirtualMemoryRegistry* _registry;
|
||||
|
||||
@ -46,9 +47,14 @@ public:
|
||||
GTEST_SKIP() << "OS not supported";
|
||||
}
|
||||
|
||||
_reserver = (ZVirtualMemoryReserver*)os::malloc(sizeof(ZVirtualMemoryManager), mtTest);
|
||||
_reserver = ::new (_reserver) ZVirtualMemoryReserver(ReservationSize);
|
||||
_registry = &_reserver->_registry;
|
||||
_zaddress_reserver.SetUp(ReservationSize);
|
||||
_reserver = _zaddress_reserver.reserver();
|
||||
_registry = _zaddress_reserver.registry();
|
||||
|
||||
if (_reserver->reserved() < ReservationSize || !_registry->is_contiguous()) {
|
||||
GTEST_SKIP() << "Fixture failed to reserve adequate memory, reserved "
|
||||
<< (_reserver->reserved() >> ZGranuleSizeShift) << " * ZGranuleSize";
|
||||
}
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
@ -58,9 +64,9 @@ public:
|
||||
}
|
||||
|
||||
// Best-effort cleanup
|
||||
_reserver->unreserve_all();
|
||||
_reserver->~ZVirtualMemoryReserver();
|
||||
os::free(_reserver);
|
||||
_registry = nullptr;
|
||||
_reserver = nullptr;
|
||||
_zaddress_reserver.TearDown();
|
||||
}
|
||||
|
||||
void test_unreserve() {
|
||||
|
||||
@ -56,6 +56,7 @@ class ZVirtualMemoryManagerTest : public ZTest {
|
||||
private:
|
||||
static constexpr size_t ReservationSize = 32 * M;
|
||||
|
||||
ZAddressReserver _zaddress_reserver;
|
||||
ZVirtualMemoryReserver* _reserver;
|
||||
ZVirtualMemoryRegistry* _registry;
|
||||
|
||||
@ -66,9 +67,14 @@ public:
|
||||
GTEST_SKIP() << "OS not supported";
|
||||
}
|
||||
|
||||
_reserver = (ZVirtualMemoryReserver*)os::malloc(sizeof(ZVirtualMemoryManager), mtTest);
|
||||
_reserver = ::new (_reserver) ZVirtualMemoryReserver(ReservationSize);
|
||||
_registry = &_reserver->_registry;
|
||||
_zaddress_reserver.SetUp(ReservationSize);
|
||||
_reserver = _zaddress_reserver.reserver();
|
||||
_registry = _zaddress_reserver.registry();
|
||||
|
||||
if (_reserver->reserved() < ReservationSize || !_registry->is_contiguous()) {
|
||||
GTEST_SKIP() << "Fixture failed to reserve adequate memory, reserved "
|
||||
<< (_reserver->reserved() >> ZGranuleSizeShift) << " * ZGranuleSize";
|
||||
}
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
@ -77,10 +83,9 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
// Best-effort cleanup
|
||||
_reserver->unreserve_all();
|
||||
_reserver->~ZVirtualMemoryReserver();
|
||||
os::free(_reserver);
|
||||
_registry = nullptr;
|
||||
_reserver = nullptr;
|
||||
_zaddress_reserver.TearDown();
|
||||
}
|
||||
|
||||
void test_reserve_discontiguous_and_coalesce() {
|
||||
@ -112,11 +117,6 @@ public:
|
||||
// to separate the fetched memory from the memory left in the manager. This
|
||||
// used to fail because the memory was already split into two placeholders.
|
||||
|
||||
if (_reserver->reserved() < 4 * ZGranuleSize || !_registry->is_contiguous()) {
|
||||
GTEST_SKIP() << "Fixture failed to reserve adequate memory, reserved "
|
||||
<< (_reserver->reserved() >> ZGranuleSizeShift) << " * ZGranuleSize";
|
||||
}
|
||||
|
||||
// Start at the offset we reserved.
|
||||
const zoffset base_offset = _registry->peek_low_address();
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include "gc/z/zNUMA.hpp"
|
||||
#include "gc/z/zRangeRegistry.hpp"
|
||||
#include "gc/z/zVirtualMemory.inline.hpp"
|
||||
#include "gc/z/zVirtualMemoryManager.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "unittest.hpp"
|
||||
|
||||
@ -60,6 +61,50 @@ public:
|
||||
};
|
||||
|
||||
class ZTest : public testing::Test {
|
||||
public:
|
||||
class ZAddressReserver {
|
||||
ZVirtualMemoryReserver* _reserver;
|
||||
bool _active;
|
||||
|
||||
public:
|
||||
ZAddressReserver()
|
||||
: _reserver(nullptr),
|
||||
_active(false) {}
|
||||
|
||||
~ZAddressReserver() {
|
||||
GTEST_EXPECT_FALSE(_active) << "ZAddressReserver deconstructed without calling TearDown";
|
||||
}
|
||||
|
||||
void SetUp(size_t reservation_size) {
|
||||
GTEST_EXPECT_TRUE(ZArguments::is_os_supported()) << "Should not use SetUp on unsupported systems";
|
||||
GTEST_EXPECT_FALSE(_active) << "SetUp called twice without a TearDown";
|
||||
_active = true;
|
||||
|
||||
_reserver = (ZVirtualMemoryReserver*)os::malloc(sizeof(ZVirtualMemoryManager), mtTest);
|
||||
_reserver = ::new (_reserver) ZVirtualMemoryReserver(reservation_size);
|
||||
}
|
||||
|
||||
void TearDown() {
|
||||
GTEST_EXPECT_TRUE(_active) << "TearDown called without a preceding SetUp";
|
||||
_active = false;
|
||||
|
||||
// Best-effort cleanup
|
||||
_reserver->unreserve_all();
|
||||
_reserver->~ZVirtualMemoryReserver();
|
||||
os::free(_reserver);
|
||||
}
|
||||
|
||||
ZVirtualMemoryReserver* reserver() {
|
||||
GTEST_EXPECT_TRUE(_active) << "Should only use HeapReserver while active";
|
||||
return _reserver;
|
||||
}
|
||||
|
||||
ZVirtualMemoryRegistry* registry() {
|
||||
GTEST_EXPECT_TRUE(_active) << "Should only use HeapReserver while active";
|
||||
return &_reserver->_registry;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
ZAddressOffsetMaxSetter _zaddress_offset_max_setter;
|
||||
unsigned int _rand_seed;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user