8338929: Make Metaspace::deallocate space-aware

Reviewed-by: coleenp, adinn
This commit is contained in:
Thomas Stuefe 2024-08-27 15:46:10 +00:00
parent fa4ff78bd4
commit daf26178be
6 changed files with 54 additions and 24 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -130,9 +130,10 @@ MetaWord* ClassLoaderMetaspace::expand_and_allocate(size_t word_size, Metaspace:
// Prematurely returns a metaspace allocation to the _block_freelists
// because it is not needed anymore.
void ClassLoaderMetaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) {
void ClassLoaderMetaspace::deallocate(MetaWord* ptr, size_t word_size) {
MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
if (Metaspace::using_class_space() && is_class) {
const bool is_class = Metaspace::using_class_space() && Metaspace::is_in_class_space(ptr);
if (is_class) {
class_space_arena()->deallocate(ptr, word_size);
} else {
non_class_space_arena()->deallocate(ptr, word_size);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -92,7 +92,7 @@ public:
// Prematurely returns a metaspace allocation to the _block_freelists
// because it is not needed anymore.
void deallocate(MetaWord* ptr, size_t word_size, bool is_class);
void deallocate(MetaWord* ptr, size_t word_size);
// Update statistics. This walks all in-use chunks.
void add_to_statistics(metaspace::ClmsStats* out) const;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -54,7 +54,7 @@ class MetadataFactory : AllStatic {
assert(loader_data != nullptr, "shouldn't pass null");
assert(!data->is_shared(), "cannot deallocate array in shared spaces");
int size = data->size();
loader_data->metaspace_non_null()->deallocate((MetaWord*)data, size, false);
loader_data->metaspace_non_null()->deallocate((MetaWord*)data, size);
}
}
@ -68,7 +68,6 @@ class MetadataFactory : AllStatic {
assert(!md->on_stack(), "can't deallocate things on stack");
assert(!md->is_shared(), "cannot deallocate if in shared spaces");
md->deallocate_contents(loader_data);
bool is_klass = md->is_klass();
// Call the destructor. This is currently used for MethodData which has a member
// that needs to be destructed to release resources. Most Metadata derived classes have noop
// destructors and/or cleanup using deallocate_contents.
@ -76,7 +75,7 @@ class MetadataFactory : AllStatic {
// or volatile so we can call the destructor of the type T points to.
using U = std::remove_cv_t<T>;
md->~U();
loader_data->metaspace_non_null()->deallocate((MetaWord*)md, size, is_klass);
loader_data->metaspace_non_null()->deallocate((MetaWord*)md, size);
}
}
};

View File

@ -538,6 +538,8 @@ void MetaspaceGC::compute_new_size() {
////// Metaspace methods /////
const MetaspaceTracer* Metaspace::_tracer = nullptr;
const void* Metaspace::_class_space_start = nullptr;
const void* Metaspace::_class_space_end = nullptr;
bool Metaspace::initialized() {
return metaspace::MetaspaceContext::context_nonclass() != nullptr
@ -570,6 +572,8 @@ void Metaspace::initialize_class_space(ReservedSpace rs) {
"wrong alignment");
MetaspaceContext::initialize_class_space_context(rs);
_class_space_start = rs.base();
_class_space_end = rs.end();
}
// Returns true if class space has been setup (initialize_class_space).
@ -979,17 +983,15 @@ void Metaspace::purge(bool classes_unloaded) {
MetaspaceCriticalAllocation::process();
}
bool Metaspace::contains(const void* ptr) {
if (MetaspaceShared::is_in_shared_metaspace(ptr)) {
return true;
}
return contains_non_shared(ptr);
// Returns true if pointer points into one of the metaspace regions, or
// into the class space.
bool Metaspace::is_in_shared_metaspace(const void* ptr) {
return MetaspaceShared::is_in_shared_metaspace(ptr);
}
bool Metaspace::contains_non_shared(const void* ptr) {
if (using_class_space() && VirtualSpaceList::vslist_class()->contains((MetaWord*)ptr)) {
return true;
}
// Returns true if pointer points into one of the non-class-space metaspace regions.
bool Metaspace::is_in_nonclass_metaspace(const void* ptr) {
return VirtualSpaceList::vslist_nonclass()->contains((MetaWord*)ptr);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2021 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -64,6 +64,10 @@ private:
static const MetaspaceTracer* _tracer;
// For quick pointer testing: extent of class space; nullptr if no class space.
static const void* _class_space_start;
static const void* _class_space_end;
static bool _initialized;
public:
@ -113,8 +117,32 @@ public:
static MetaWord* allocate(ClassLoaderData* loader_data, size_t word_size,
MetaspaceObj::Type type);
static bool contains(const void* ptr);
static bool contains_non_shared(const void* ptr);
// Returns true if the pointer points into class space, non-class metaspace, or the
// metadata portion of the CDS archive.
static bool contains(const void* ptr) {
return is_in_shared_metaspace(ptr) || // in cds
is_in_class_space(ptr) || // in class space
is_in_nonclass_metaspace(ptr); // in one of the non-class regions?
}
// Returns true if the pointer points into class space or into non-class metaspace
static bool contains_non_shared(const void* ptr) {
return is_in_class_space(ptr) || // in class space
is_in_nonclass_metaspace(ptr); // in one of the non-class regions?
}
// Returns true if pointer points into the CDS klass region.
static bool is_in_shared_metaspace(const void* ptr);
// Returns true if pointer points into one of the non-class-space metaspace regions.
static bool is_in_nonclass_metaspace(const void* ptr);
// Returns true if pointer points into class space, false if it doesn't or if
// there is no class space. Class space is a contiguous region, which is why
// two address comparisons are enough.
static inline bool is_in_class_space(const void* ptr) {
return ptr < _class_space_end && ptr >= _class_space_start;
}
// Free empty virtualspaces
static void purge(bool classes_unloaded);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -67,7 +67,7 @@ TEST_VM(metaspace, misc_max_alloc_size) {
ASSERT_NOT_NULL(p);
}
// And also, successfully deallocate it.
cld->metaspace_non_null()->deallocate(p, sz, in_class_space);
cld->metaspace_non_null()->deallocate(p, sz);
}
}