< prev index next >

src/hotspot/share/memory/metaspaceClosure.hpp

Print this page
*** 1,7 ***
  /*
!  * 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.
--- 1,7 ---
  /*
!  * 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.

*** 27,10 ***
--- 27,11 ---
  
  #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>

*** 102,10 ***
--- 103,22 ---
    //         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);

*** 121,11 ***
      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();
      }
--- 134,11 ---
      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();
      }

*** 141,16 ***
      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;
      }
--- 154,39 ---
      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;
      }

*** 174,11 ***
    // 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;
      }
  
--- 210,11 ---
    // 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 >