< prev index next > src/hotspot/share/memory/metaspaceClosure.hpp
Print this page
/*
! * Copyright (c) 2017, 2023, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
/*
! * Copyright (c) 2017, 2025, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
#include "logging/log.hpp"
#include "memory/allocation.hpp"
#include "metaprogramming/enableIf.hpp"
#include "oops/array.hpp"
+ #include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
#include "utilities/resizeableResourceHash.hpp"
#include <type_traits>
// MetaspaceObj *_obj;
// Array<int>* foo() { return (Array<int>*)_obj; }
// Symbol* bar() { return (Symbol*) _obj; }
//
// [2] All Array<T> dimensions are statically declared.
+ //
+ // Pointer Tagging
+ //
+ // All metaspace pointers are at least 4 byte aligned. Therefore, it's possible for
+ // certain pointers to contain "tags" in their lowest 2 bits.
+ //
+ // Ref::obj() clears the tag bits in the return values. As a result, most
+ // callers who just want walk a closure of metaspace objects do not need to worry
+ // about the tag bits.
+ //
+ // If you need to use the tags, you can access the tagged pointer with Ref::addr()
+ // and manipulate its parts with strip_tags(), decode_tags() and add_tags()
class Ref : public CHeapObj<mtMetaspace> {
Writability _writability;
address _enclosing_obj;
Ref* _next;
NONCOPYABLE(Ref);
virtual MetaspaceObj::Type msotype() const = 0;
virtual bool is_read_only_by_default() const = 0;
virtual ~Ref() {}
address obj() const {
! return *addr();
}
address* addr() const {
return (address*)mpp();
}
virtual MetaspaceObj::Type msotype() const = 0;
virtual bool is_read_only_by_default() const = 0;
virtual ~Ref() {}
address obj() const {
! return strip_tags(*addr());
}
address* addr() const {
return (address*)mpp();
}
Writability writability() const { return _writability; };
void set_next(Ref* n) { _next = n; }
Ref* next() const { return _next; }
};
private:
// MSORef -- iterate an instance of MetaspaceObj
template <class T> class MSORef : public Ref {
T** _mpp;
T* dereference() const {
! return *_mpp;
}
protected:
virtual void** mpp() const {
return (void**)_mpp;
}
Writability writability() const { return _writability; };
void set_next(Ref* n) { _next = n; }
Ref* next() const { return _next; }
};
+ // Pointer tagging support
+ constexpr static uintx TAG_MASK = 0x03;
+
+ template <typename T>
+ static T strip_tags(T ptr_with_tags) {
+ uintx n = (uintx)ptr_with_tags;
+ return (T)(n & ~TAG_MASK);
+ }
+
+ template <typename T>
+ static uintx decode_tags(T ptr_with_tags) {
+ uintx n = (uintx)ptr_with_tags;
+ return (n & TAG_MASK);
+ }
+
+ template <typename T>
+ static T add_tags(T ptr, uintx tags) {
+ uintx n = (uintx)ptr;
+ assert((n & TAG_MASK) == 0, "sanity");
+ assert(tags <= TAG_MASK, "sanity");
+ return (T)(n | tags);
+ }
+
private:
// MSORef -- iterate an instance of MetaspaceObj
template <class T> class MSORef : public Ref {
T** _mpp;
T* dereference() const {
! return strip_tags(*_mpp);
}
protected:
virtual void** mpp() const {
return (void**)_mpp;
}
// abstract base class for MSOArrayRef, MSOPointerArrayRef and OtherArrayRef
template <class T> class ArrayRef : public Ref {
Array<T>** _mpp;
protected:
Array<T>* dereference() const {
! return *_mpp;
}
virtual void** mpp() const {
return (void**)_mpp;
}
// abstract base class for MSOArrayRef, MSOPointerArrayRef and OtherArrayRef
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;
}
< prev index next >