mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-27 07:10:45 +00:00
8381993: Simplify MetaspaceClosure handling of Array and GrowableArray
Reviewed-by: coleenp, matsaave
This commit is contained in:
parent
76a44b3e03
commit
f97effa484
@ -37,19 +37,6 @@
|
||||
#include "utilities/macros.hpp"
|
||||
#include "utilities/resizableHashTable.hpp"
|
||||
|
||||
// This macro just check for the existence of a member with the name "metaspace_pointers_do". If the
|
||||
// parameter list is not (MetaspaceClosure* it), you will get a compilation error.
|
||||
#define HAS_METASPACE_POINTERS_DO(T) HasMetaspacePointersDo<T>::value
|
||||
|
||||
template<typename T>
|
||||
class HasMetaspacePointersDo {
|
||||
template<typename U> static void* test(decltype(&U::metaspace_pointers_do));
|
||||
template<typename> static int test(...);
|
||||
using test_type = decltype(test<T>(nullptr));
|
||||
public:
|
||||
static constexpr bool value = std::is_pointer_v<test_type>;
|
||||
};
|
||||
|
||||
// class MetaspaceClosure --
|
||||
//
|
||||
// This class is used for iterating the class metadata objects. It
|
||||
@ -98,7 +85,6 @@ public:
|
||||
// only in the Metadata class.
|
||||
//
|
||||
// To work around the lack of a vtable, we use the Ref class with templates
|
||||
// (see MSORef, OtherArrayRef, MSOArrayRef, and MSOPointerArrayRef)
|
||||
// so that we can statically discover the type of a object. The use of Ref
|
||||
// depends on the fact that:
|
||||
//
|
||||
@ -194,15 +180,6 @@ private:
|
||||
return obj->size_in_heapwords();
|
||||
}
|
||||
|
||||
static MetaspaceClosureType as_type(MetaspaceClosureType t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
static MetaspaceClosureType as_type(MetaspaceObj::Type msotype) {
|
||||
precond(msotype < MetaspaceObj::_number_of_types);
|
||||
return (MetaspaceClosureType)msotype;
|
||||
}
|
||||
|
||||
// MSORef -- iterate an instance of T, where T::metaspace_pointers_do() exists.
|
||||
template <class T> class MSORef : public Ref {
|
||||
T** _mpp;
|
||||
@ -210,99 +187,22 @@ private:
|
||||
return strip_tags(*_mpp);
|
||||
}
|
||||
protected:
|
||||
virtual void** mpp() const {
|
||||
virtual void** mpp() const override {
|
||||
return (void**)_mpp;
|
||||
}
|
||||
|
||||
public:
|
||||
MSORef(T** mpp, Writability w) : Ref(w), _mpp(mpp) {}
|
||||
|
||||
virtual bool is_read_only_by_default() const { return T::is_read_only_by_default(); }
|
||||
virtual bool not_null() const { return dereference() != nullptr; }
|
||||
virtual int size() const { return get_size(dereference()); }
|
||||
virtual MetaspaceClosureType type() const { return as_type(dereference()->type()); }
|
||||
|
||||
virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
|
||||
virtual bool is_read_only_by_default() const override { return T::is_read_only_by_default(); }
|
||||
virtual bool not_null() const override { return dereference() != nullptr; }
|
||||
virtual int size() const override { return get_size(dereference()); }
|
||||
virtual MetaspaceClosureType type() const override { return as_type(dereference()->type()); }
|
||||
virtual void metaspace_pointers_do(MetaspaceClosure *it) const override {
|
||||
dereference()->metaspace_pointers_do(it);
|
||||
}
|
||||
};
|
||||
|
||||
//---------------------
|
||||
// Support for Array<T>
|
||||
//---------------------
|
||||
|
||||
// Abstract base class for MSOArrayRef, MSOPointerArrayRef and OtherArrayRef.
|
||||
// These are used for iterating Array<T>.
|
||||
template <class T> class ArrayRef : public Ref {
|
||||
Array<T>** _mpp;
|
||||
protected:
|
||||
Array<T>* dereference() const {
|
||||
return strip_tags(*_mpp);
|
||||
}
|
||||
virtual void** mpp() const {
|
||||
return (void**)_mpp;
|
||||
}
|
||||
|
||||
ArrayRef(Array<T>** mpp, Writability w) : Ref(w), _mpp(mpp) {}
|
||||
|
||||
// all Arrays are read-only by default
|
||||
virtual bool is_read_only_by_default() const { return true; }
|
||||
virtual bool not_null() const { return dereference() != nullptr; }
|
||||
virtual int size() const { return dereference()->size(); }
|
||||
virtual MetaspaceClosureType type() const { return as_type(MetaspaceObj::array_type(sizeof(T))); }
|
||||
};
|
||||
|
||||
// OtherArrayRef -- iterate an instance of Array<T>, where T does NOT have metaspace_pointer_do().
|
||||
// T can be a primitive type, such as int, or a structure. However, we do not scan
|
||||
// the fields inside T, so you should not embed any pointers inside T.
|
||||
template <class T> class OtherArrayRef : public ArrayRef<T> {
|
||||
public:
|
||||
OtherArrayRef(Array<T>** mpp, Writability w) : ArrayRef<T>(mpp, w) {}
|
||||
|
||||
virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
|
||||
Array<T>* array = ArrayRef<T>::dereference();
|
||||
log_trace(aot)("Iter(OtherArray): %p [%d]", array, array->length());
|
||||
}
|
||||
};
|
||||
|
||||
// MSOArrayRef -- iterate an instance of Array<T>, where T has metaspace_pointer_do().
|
||||
// We recursively call T::metaspace_pointers_do() for each element in this array.
|
||||
template <class T> class MSOArrayRef : public ArrayRef<T> {
|
||||
public:
|
||||
MSOArrayRef(Array<T>** mpp, Writability w) : ArrayRef<T>(mpp, w) {}
|
||||
|
||||
virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
|
||||
metaspace_pointers_do_at_impl(it, ArrayRef<T>::dereference());
|
||||
}
|
||||
private:
|
||||
void metaspace_pointers_do_at_impl(MetaspaceClosure *it, Array<T>* array) const {
|
||||
log_trace(aot)("Iter(MSOArray): %p [%d]", array, array->length());
|
||||
for (int i = 0; i < array->length(); i++) {
|
||||
T* elm = array->adr_at(i);
|
||||
elm->metaspace_pointers_do(it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// MSOPointerArrayRef -- iterate an instance of Array<T*>, where T has metaspace_pointer_do().
|
||||
// We recursively call MetaspaceClosure::push() for each pointer in this array.
|
||||
template <class T> class MSOPointerArrayRef : public ArrayRef<T*> {
|
||||
public:
|
||||
MSOPointerArrayRef(Array<T*>** mpp, Writability w) : ArrayRef<T*>(mpp, w) {}
|
||||
|
||||
virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
|
||||
metaspace_pointers_do_at_impl(it, ArrayRef<T*>::dereference());
|
||||
}
|
||||
private:
|
||||
void metaspace_pointers_do_at_impl(MetaspaceClosure *it, Array<T*>* array) const {
|
||||
log_trace(aot)("Iter(MSOPointerArray): %p [%d]", array, array->length());
|
||||
for (int i = 0; i < array->length(); i++) {
|
||||
T** mpp = array->adr_at(i);
|
||||
it->push(mpp);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------
|
||||
// Support for GrowableArray<T>
|
||||
//--------------------------------
|
||||
@ -314,28 +214,27 @@ private:
|
||||
return *_mpp;
|
||||
}
|
||||
|
||||
public:
|
||||
GrowableArrayRef(GrowableArray<T>** mpp, Writability w) : Ref(w), _mpp(mpp) {}
|
||||
|
||||
virtual void** mpp() const {
|
||||
protected:
|
||||
virtual void** mpp() const override {
|
||||
return (void**)_mpp;
|
||||
}
|
||||
|
||||
virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
|
||||
public:
|
||||
GrowableArrayRef(GrowableArray<T>** mpp, Writability w) : Ref(w), _mpp(mpp) {}
|
||||
|
||||
virtual bool is_read_only_by_default() const override { return false; }
|
||||
virtual bool not_null() const override { return dereference() != nullptr; }
|
||||
virtual int size() const override { return (int)heap_word_size(sizeof(*dereference())); }
|
||||
virtual MetaspaceClosureType type() const override { return MetaspaceClosureType::GrowableArrayType; }
|
||||
virtual void metaspace_pointers_do(MetaspaceClosure *it) const override {
|
||||
GrowableArray<T>* array = dereference();
|
||||
log_trace(aot)("Iter(GrowableArray): %p [%d]", array, array->length());
|
||||
array->assert_on_C_heap();
|
||||
it->push_c_array(array->data_addr(), array->capacity());
|
||||
}
|
||||
|
||||
virtual bool is_read_only_by_default() const { return false; }
|
||||
virtual bool not_null() const { return dereference() != nullptr; }
|
||||
virtual int size() const { return (int)heap_word_size(sizeof(*dereference())); }
|
||||
virtual MetaspaceClosureType type() const { return MetaspaceClosureType::GrowableArrayType; }
|
||||
};
|
||||
|
||||
// Abstract base class for MSOCArrayRef, MSOPointerCArrayRef and OtherCArrayRef.
|
||||
// These are used for iterating the buffer held by GrowableArray<T>.
|
||||
// For iterating the buffer held by GrowableArray<T>.
|
||||
template <class T> class CArrayRef : public Ref {
|
||||
T** _mpp;
|
||||
int _num_elems; // Number of elements
|
||||
@ -344,83 +243,57 @@ private:
|
||||
return _num_elems * sizeof(T);
|
||||
}
|
||||
|
||||
protected:
|
||||
// C pointer arrays don't support tagged pointers.
|
||||
// Gives you back the GrowableArray::_data
|
||||
T* dereference() const {
|
||||
return *_mpp;
|
||||
}
|
||||
virtual void** mpp() const {
|
||||
return (void**)_mpp;
|
||||
}
|
||||
|
||||
int num_elems() const {
|
||||
return _num_elems;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void** mpp() const override {
|
||||
return (void**)_mpp;
|
||||
}
|
||||
|
||||
public:
|
||||
CArrayRef(T** mpp, int num_elems, Writability w)
|
||||
: Ref(w), _mpp(mpp), _num_elems(num_elems) {
|
||||
assert(is_aligned(byte_size(), BytesPerWord), "must be");
|
||||
}
|
||||
|
||||
virtual bool is_read_only_by_default() const { return false; }
|
||||
virtual bool not_null() const { return dereference() != nullptr; }
|
||||
virtual int size() const { return (int)heap_word_size(byte_size()); }
|
||||
virtual MetaspaceClosureType type() const { return MetaspaceClosureType::CArrayType; }
|
||||
};
|
||||
|
||||
// OtherCArrayRef -- iterate a C array of type T, where T does NOT have metaspace_pointer_do().
|
||||
// T can be a primitive type, such as int, or a structure. However, we do not scan
|
||||
// the fields inside T, so you should not embed any pointers inside T.
|
||||
template <class T> class OtherCArrayRef : public CArrayRef<T> {
|
||||
public:
|
||||
OtherCArrayRef(T** mpp, int num_elems, Writability w) : CArrayRef<T>(mpp, num_elems, w) {}
|
||||
|
||||
virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
|
||||
T* array = CArrayRef<T>::dereference();
|
||||
log_trace(aot)("Iter(OtherCArray): %p [%d]", array, CArrayRef<T>::num_elems());
|
||||
virtual bool is_read_only_by_default() const override { return false; }
|
||||
virtual bool not_null() const override { precond(dereference() != nullptr); return true; }
|
||||
virtual int size() const override { return (int)heap_word_size(byte_size()); }
|
||||
virtual MetaspaceClosureType type() const override { return MetaspaceClosureType::CArrayType; }
|
||||
virtual void metaspace_pointers_do(MetaspaceClosure *it) const override {
|
||||
metaspace_pointers_do_impl<T>(it, dereference());
|
||||
}
|
||||
};
|
||||
|
||||
// MSOCArrayRef<T> -- iterate a C array of type T, where T has metaspace_pointer_do().
|
||||
// We recursively call T::metaspace_pointers_do() for each element in this array.
|
||||
// This is for supporting GrowableArray<T>.
|
||||
//
|
||||
// E.g., PackageEntry* _pkg_entry_pointers[2]; // a buffer that has 2 PackageEntry objects
|
||||
// ...
|
||||
// it->push(&_pkg_entry_pointers, 2);
|
||||
// /* calls _pkg_entry_pointers[0].metaspace_pointers_do(it); */
|
||||
// /* calls _pkg_entry_pointers[1].metaspace_pointers_do(it); */
|
||||
template <class T> class MSOCArrayRef : public CArrayRef<T> {
|
||||
public:
|
||||
MSOCArrayRef(T** mpp, int num_elems, Writability w) : CArrayRef<T>(mpp, num_elems, w) {}
|
||||
private:
|
||||
// E.g., GrowableArray<int>
|
||||
template <typename U, ENABLE_IF(!std::is_pointer<U>::value && !HAS_METASPACE_POINTERS_DO(U))>
|
||||
void metaspace_pointers_do_impl(MetaspaceClosure* it, T* array) const {
|
||||
log_trace(aot)("Iter(OtherCArray): %p [%d]", array, num_elems());
|
||||
}
|
||||
|
||||
virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
|
||||
T* array = CArrayRef<T>::dereference();
|
||||
log_trace(aot)("Iter(MSOCArray): %p [%d]", array, CArrayRef<T>::num_elems());
|
||||
for (int i = 0; i < CArrayRef<T>::num_elems(); i++) {
|
||||
// E.g., GrowableArray<Annotation>
|
||||
template <typename U, ENABLE_IF(!std::is_pointer<U>::value && HAS_METASPACE_POINTERS_DO(U))>
|
||||
void metaspace_pointers_do_impl(MetaspaceClosure* it, T* array) const {
|
||||
log_trace(aot)("Iter(MSOCArray): %p [%d]", array, num_elems());
|
||||
for (int i = 0; i < num_elems(); i++) {
|
||||
T* elm = array + i;
|
||||
elm->metaspace_pointers_do(it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// MSOPointerCArrayRef<T> -- iterate a C array of type T*, where T has metaspace_pointer_do().
|
||||
// We recursively call MetaspaceClosure::push() for each pointer in this array.
|
||||
// This is for supporting GrowableArray<T*>.
|
||||
//
|
||||
// E.g., PackageEntry** _pkg_entry_pointers[2]; // a buffer that has 2 PackageEntry pointers
|
||||
// ...
|
||||
// it->push(&_pkg_entry_pointers, 2);
|
||||
// /* calls _pkg_entry_pointers[0]->metaspace_pointers_do(it); */
|
||||
// /* calls _pkg_entry_pointers[1]->metaspace_pointers_do(it); */
|
||||
template <class T> class MSOPointerCArrayRef : public CArrayRef<T*> {
|
||||
public:
|
||||
MSOPointerCArrayRef(T*** mpp, int num_elems, Writability w) : CArrayRef<T*>(mpp, num_elems, w) {}
|
||||
|
||||
virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
|
||||
T** array = CArrayRef<T*>::dereference();
|
||||
log_trace(aot)("Iter(MSOPointerCArray): %p [%d]", array, CArrayRef<T*>::num_elems());
|
||||
for (int i = 0; i < CArrayRef<T*>::num_elems(); i++) {
|
||||
T** mpp = array + i;
|
||||
// E.g., GrowableArray<Klass*>
|
||||
template <typename U, ENABLE_IF(std::is_pointer<U>::value && HAS_METASPACE_POINTERS_DO(typename std::remove_pointer<U>::type))>
|
||||
void metaspace_pointers_do_impl(MetaspaceClosure* it, T* array) const {
|
||||
log_trace(aot)("Iter(MSOPointerCArray): %p [%d]", array, num_elems());
|
||||
for (int i = 0; i < num_elems(); i++) {
|
||||
T* mpp = array + i;
|
||||
it->push(mpp);
|
||||
}
|
||||
}
|
||||
@ -462,17 +335,12 @@ public:
|
||||
//
|
||||
// MetaspaceClosure* it = ...;
|
||||
// Klass* o = ...; it->push(&o); => MSORef
|
||||
// Array<int>* a1 = ...; it->push(&a1); => OtherArrayRef
|
||||
// Array<Annotation>* a2 = ...; it->push(&a2); => MSOArrayRef
|
||||
// Array<Klass*>* a3 = ...; it->push(&a3); => MSOPointerArrayRef
|
||||
// Array<Array<Klass*>*>* a4 = ...; it->push(&a4); => MSOPointerArrayRef
|
||||
// Array<Annotation*>* a5 = ...; it->push(&a5); => MSOPointerArrayRef
|
||||
//
|
||||
// GrowableArrays have a separate "C array" buffer, so they are scanned in two steps:
|
||||
//
|
||||
// GrowableArray<jlong>* ga1 = ...; it->push(&ga1); => GrowableArrayRef => OtherCArrayRef
|
||||
// GrowableArray<Annotation>* ga2 = ...; it->push(&ga2); => GrowableArrayRef => MSOCArrayRef
|
||||
// GrowableArray<Klass*>* ga3 = ...; it->push(&ga3); => GrowableArrayRef => MSOPointerCArrayRef
|
||||
// GrowableArray<jlong>* ga1 = ...; it->push(&ga1); => GrowableArrayRef => CArrayRef<jlong>
|
||||
// GrowableArray<Annotation>* ga2 = ...; it->push(&ga2); => GrowableArrayRef => CArrayRef<Annotation>
|
||||
// GrowableArray<Klass*>* ga3 = ...; it->push(&ga3); => GrowableArrayRef => CArrayRef<Klass*>
|
||||
//
|
||||
// Note that the following will fail to compile:
|
||||
//
|
||||
@ -487,43 +355,15 @@ public:
|
||||
push_with_ref<MSORef<T>>(mpp, w);
|
||||
}
|
||||
|
||||
// --- Array<T>
|
||||
template <typename T, ENABLE_IF(!HAS_METASPACE_POINTERS_DO(T))>
|
||||
void push(Array<T>** mpp, Writability w = _default) {
|
||||
push_with_ref<OtherArrayRef<T>>(mpp, w);
|
||||
}
|
||||
|
||||
template <typename T, ENABLE_IF(HAS_METASPACE_POINTERS_DO(T))>
|
||||
void push(Array<T>** mpp, Writability w = _default) {
|
||||
push_with_ref<MSOArrayRef<T>>(mpp, w);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void push(Array<T*>** mpp, Writability w = _default) {
|
||||
static_assert(HAS_METASPACE_POINTERS_DO(T), "Do not push Arrays of arbitrary pointer types");
|
||||
push_with_ref<MSOPointerArrayRef<T>>(mpp, w);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void push(GrowableArray<T>** mpp, Writability w = _default) {
|
||||
push_with_ref<GrowableArrayRef<T>>(mpp, w);
|
||||
}
|
||||
|
||||
// --- The buffer of GrowableArray<T>
|
||||
template <typename T, ENABLE_IF(!HAS_METASPACE_POINTERS_DO(T))>
|
||||
void push_c_array(T** mpp, int num_elems, Writability w = _default) {
|
||||
push_impl(new OtherCArrayRef<T>(mpp, num_elems, w));
|
||||
}
|
||||
|
||||
template <typename T, ENABLE_IF(HAS_METASPACE_POINTERS_DO(T))>
|
||||
void push_c_array(T** mpp, int num_elems, Writability w = _default) {
|
||||
push_impl(new MSOCArrayRef<T>(mpp, num_elems, w));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void push_c_array(T*** mpp, int num_elems, Writability w = _default) {
|
||||
static_assert(HAS_METASPACE_POINTERS_DO(T), "Do not push C arrays of arbitrary pointer types");
|
||||
push_impl(new MSOPointerCArrayRef<T>(mpp, num_elems, w));
|
||||
void push_c_array(T** mpp, int num_elems, Writability w = _default) {
|
||||
push_impl(new CArrayRef<T>(mpp, num_elems, w));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#define SHARE_MEMORY_METASPACECLOSURETYPE_HPP
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
#include "metaprogramming/enableIf.hpp"
|
||||
|
||||
// MetaspaceClosure is able to iterate on MetaspaceObjs, plus the following classes
|
||||
#define METASPACE_CLOSURE_TYPES_DO(f) \
|
||||
@ -42,5 +43,29 @@ enum class MetaspaceClosureType : int {
|
||||
_number_of_types
|
||||
};
|
||||
|
||||
inline MetaspaceClosureType as_type(MetaspaceClosureType t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
inline MetaspaceClosureType as_type(MetaspaceObj::Type msotype) {
|
||||
precond(msotype < MetaspaceObj::_number_of_types);
|
||||
return (MetaspaceClosureType)msotype;
|
||||
}
|
||||
|
||||
// This macro checks for the existence of a member with the name metaspace_pointers_do
|
||||
#define HAS_METASPACE_POINTERS_DO(T) HasMetaspacePointersDo<T>::value
|
||||
|
||||
template<typename T>
|
||||
class HasMetaspacePointersDo {
|
||||
template<typename U> static void* test(decltype(&U::metaspace_pointers_do));
|
||||
template<typename> static int test(...);
|
||||
|
||||
// - If the first template matches, test_type will be void*
|
||||
// - If the first template doesn't match, test<T> will match second template,
|
||||
// and test_type will be int
|
||||
using test_type = decltype(test<T>(nullptr));
|
||||
public:
|
||||
static constexpr bool value = std::is_pointer_v<test_type>;
|
||||
};
|
||||
|
||||
#endif // SHARE_MEMORY_METASPACECLOSURETYPE_HPP
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
#ifndef SHARE_OOPS_ARRAY_HPP
|
||||
#define SHARE_OOPS_ARRAY_HPP
|
||||
|
||||
#include "memory/metaspaceClosureType.hpp"
|
||||
#include "runtime/atomicAccess.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/exceptions.hpp"
|
||||
@ -159,8 +160,48 @@ protected:
|
||||
st->print("Array<T>(" PTR_FORMAT ")", p2i(this));
|
||||
}
|
||||
|
||||
// This function does nothing. The iteration of the elements are done inside metaspaceClosure.hpp
|
||||
void metaspace_pointers_do(MetaspaceClosure* it) {}
|
||||
MetaspaceClosureType type() const { return as_type(MetaspaceObj::array_type(sizeof(T))); }
|
||||
|
||||
static bool is_read_only_by_default() {
|
||||
return is_read_only_by_default_impl<T>();
|
||||
}
|
||||
|
||||
private:
|
||||
// Elements are neither pointers nor metadata objects => no need to relocate, so put the array
|
||||
// in read-only region by default.
|
||||
template <typename U, ENABLE_IF(!std::is_pointer<U>::value && !HAS_METASPACE_POINTERS_DO(U))>
|
||||
static bool is_read_only_by_default_impl() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// The opposite of the above => the array may contain relocatable pointers, so put it
|
||||
// in read-write region by default.
|
||||
template <typename U, ENABLE_IF(std::is_pointer<U>::value || HAS_METASPACE_POINTERS_DO(U))>
|
||||
static bool is_read_only_by_default_impl() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
void metaspace_pointers_do(MetaspaceClosure* it) {
|
||||
metaspace_pointers_do_impl<T>(it);
|
||||
}
|
||||
|
||||
private:
|
||||
// E.g., Array<int>
|
||||
template <typename U, ENABLE_IF(!std::is_pointer<U>::value && !HAS_METASPACE_POINTERS_DO(U))>
|
||||
void metaspace_pointers_do_impl(MetaspaceClosure* it) {
|
||||
// No pointers to follow
|
||||
}
|
||||
|
||||
// E.g., Array<Annotation>
|
||||
template <typename U, ENABLE_IF(!std::is_pointer<U>::value && HAS_METASPACE_POINTERS_DO(U))>
|
||||
void metaspace_pointers_do_impl(MetaspaceClosure* it);
|
||||
|
||||
// E.g., Array<Klass*>
|
||||
template <typename U, ENABLE_IF(std::is_pointer<U>::value && HAS_METASPACE_POINTERS_DO(typename std::remove_pointer<U>::type))>
|
||||
void metaspace_pointers_do_impl(MetaspaceClosure* it);
|
||||
|
||||
public:
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print(outputStream* st) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2026, 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
|
||||
@ -29,6 +29,7 @@
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
#include "memory/metaspace.hpp"
|
||||
#include "memory/metaspaceClosure.hpp"
|
||||
|
||||
template <typename T>
|
||||
inline void* Array<T>::operator new(size_t size, ClassLoaderData* loader_data, int length, TRAPS) throw() {
|
||||
@ -52,4 +53,26 @@ inline void* Array<T>::operator new(size_t size, int length, MemTag flags) throw
|
||||
return p;
|
||||
}
|
||||
|
||||
// E.g., Array<Annotation>
|
||||
template <typename T>
|
||||
template <typename U, ENABLE_IF_SDEFN(!std::is_pointer<U>::value && HAS_METASPACE_POINTERS_DO(U))>
|
||||
void Array<T>::metaspace_pointers_do_impl(MetaspaceClosure* it) {
|
||||
log_trace(aot)("Iter(MSOArray): %p [%d]", this, length());
|
||||
for (int i = 0; i < length(); i++) {
|
||||
T* elm = adr_at(i);
|
||||
elm->metaspace_pointers_do(it);
|
||||
}
|
||||
}
|
||||
|
||||
// E.g., Array<Klass*>
|
||||
template <typename T>
|
||||
template <typename U, ENABLE_IF_SDEFN(std::is_pointer<U>::value && HAS_METASPACE_POINTERS_DO(typename std::remove_pointer<U>::type))>
|
||||
void Array<T>::metaspace_pointers_do_impl(MetaspaceClosure* it) {
|
||||
log_trace(aot)("Iter(MSOPtrArray): %p [%d]", this, length());
|
||||
for (int i = 0; i < length(); i++) {
|
||||
T* mpp = adr_at(i);
|
||||
it->push(mpp);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SHARE_OOPS_ARRAY_INLINE_HPP
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
#include "compiler/compilerDefinitions.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "memory/metaspaceClosure.hpp"
|
||||
#include "oops/array.inline.hpp"
|
||||
#include "oops/instanceKlass.hpp"
|
||||
#include "oops/method.hpp"
|
||||
#include "oops/objArrayKlass.hpp"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user