On Sun, 9 Feb 2025 19:43:29 GMT, Vladimir Kozlov <k...@openjdk.org> wrote:

>> Remove virtual methods from CodeBlob and nmethod to simplify 
>> saving/restoring in Leyden AOT cache. It avoids the need to patch hidden 
>> VPTR pointer to class's virtual table.
>> 
>> Added C++ static asserts to make sure no virtual methods are added in a 
>> future.
>> 
>> Fixed/cleaned SA code which process CodeBlob and its subclasses. Use 
>> `CodeBlob::_kind` field value to determine the type of blob.
>> 
>> Tested tier1-5, hs-tier6-rt (for JFR testing), stress, xcomp
>
> Vladimir Kozlov has updated the pull request incrementally with one 
> additional commit since the last revision:
> 
>   Fix Zero and Minimal VM builds

src/hotspot/share/code/codeBlob.cpp line 58:

> 56: #include <type_traits>
> 57: 
> 58: // Virtual methods are not allowed in code blobs to simplify caching 
> compiled code.

Is it worth considering generating this code plus also some of the existing 
code in the header using an iterator template macro? e.g.

    #define CODEBLOBS_DO(do_codeblob_abstract, do_codeblob_nonleaf, \
                         do_codeblob_leaf)                          \
      do_codeblob_abstract(CodeBlob)                                \
      do_codeblob_leaf(nmethod, Nmethod, nmethod)                   \
      do_codeblob_abstract(RuntimeBlob)                             \
      do_codeblob_nonleaf(BufferBlob, Buffer, buffer)               \
      do_codeblob_leaf(AdapterBlob, Adapter, adapter)               \
      . . .                                                         \
      do_codeblob_leaf(RuntimeStub, Runtime_Stub, runtime_stub)     \
      . . .

The macro arguments to the templates would themselves be macros:

    do_codeblob_abstract(classname) // abstract, non-instantiable class
    do_codeblob_nonleaf(classname, kindname, accessorname) // instantiable, 
subclassable
    do_codeblob_leaf(classname, kindname, accessorname) // instantiable, 
non-subclassable

Using a template macro like this to generate the code below -- *plus also* some 
of the code currently declared piecemeal in the header -- would guarantee all 
cases are covered now and will remain so later so when the macro is updated. I 
think it would probably also allow case handling code in AOT cache code to be 
generated.

So, we would generate the code here as follows

    #define EMPTY1(classname) 
    #define EMPTY3(classname, kindname, accessorname)

    #define assert_nonvirtual_leaf(classname, kindname, accessorname) \
      static_assert(!std::is_polymorphic<classname>::value,            \
                    "no virtual methods are allowed in " # classname );

    CODEBLOBS_DO(empty1, empty3, assert_nonvirtual_leaf)

    #undef assert_nonvirtual_leaf

Likewise in codeBlob.hpp we could generate `enum CodeBlobKind` to cover all the 
non-abstract classes and likewise generate the accessor methods `is_nmethod()`, 
`is_buffer_blob()` in class `CodeBlob` which allow the kind to be tested.

    #define codekind_enum_tag(classname, kindname, accessorname) \
      kindname,

    enum CodeBlobKind : u1 {
      None,
      CODEBLOBS_DO(empty1, codekind_enum_tag, codekind_enum_tag)
      Number_Of_Kinds
    };

    #define is_codeblob_define(classname, kindname, accessorname) \
        void is_ # accessor_name () { return _kind == kindname; }

    class CodeBlob {
      . . .
      CODEBLOBS_DO(empty1, is_codeblob_define, is_codeblob_define);
      . . .
There may be other opportunities to use the iterator (e.g. in vmStructs.cpp?) 
but this looks like a good start.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/23533#discussion_r1948849392

Reply via email to