RFR: 8334220: Optimize Klass layout after JDK-8180450

Xiaolong Peng xpeng at openjdk.org
Sat Jun 29 20:03:26 UTC 2024


Hi all, 
    This PR is created to optimize the layout of Klass in hotspot, after JDK-8180450 the layout of Klsss seems broken, there are 3 holes, they are caused by alignment issue introduced by the 1 byte ```_hash_slot```. 


(gdb) ptype /ox Klass
/* offset      |    size */  type = class Klass : public Metadata {
                             public:
                               static const uint KLASS_KIND_COUNT;
                             protected:
/* 0x000c      |  0x0004 */    jint _layout_helper;
/* 0x0010      |  0x0004 */    const enum Klass::KlassKind _kind;
/* 0x0014      |  0x0004 */    jint _modifier_flags;
/* 0x0018      |  0x0004 */    juint _super_check_offset;
/* XXX  4-byte hole      */
/* 0x0020      |  0x0008 */    class Symbol *_name;
/* 0x0028      |  0x0008 */    class Klass *_secondary_super_cache;
/* 0x0030      |  0x0008 */    class Array<Klass*> *_secondary_supers;
/* 0x0038      |  0x0040 */    class Klass *_primary_supers[8];
/* 0x0078      |  0x0008 */    class OopHandle {
                                 private:
/* 0x0078      |  0x0008 */        class oop *_obj;

                                   /* total size (bytes):    8 */
                               } _java_mirror;
/* 0x0080      |  0x0008 */    class Klass *_super;
/* 0x0088      |  0x0008 */    class Klass * volatile _subklass;
/* 0x0090      |  0x0008 */    class Klass * volatile _next_sibling;
/* 0x0098      |  0x0008 */    class Klass *_next_link;
/* 0x00a0      |  0x0008 */    class ClassLoaderData *_class_loader_data;
/* 0x00a8      |  0x0008 */    uintx _bitmap;
/* 0x00b0      |  0x0001 */    uint8_t _hash_slot;
/* XXX  3-byte hole      */
/* 0x00b4      |  0x0004 */    int _vtable_len;
/* 0x00b8      |  0x0004 */    class AccessFlags {
                                 private:
/* 0x00b8      |  0x0004 */        jint _flags;

                                   /* total size (bytes):    4 */
                               } _access_flags;
/* XXX  4-byte hole      */
/* 0x00c0      |  0x0008 */    traceid _trace_id;
                             private:
/* 0x00c8      |  0x0002 */    s2 _shared_class_path_index;
/* 0x00ca      |  0x0002 */    u2 _shared_class_flags;
/* 0x00cc      |  0x0004 */    int _archived_mirror_index;
                             public:
                               static const int SECONDARY_SUPERS_TABLE_SIZE;
                               static const int SECONDARY_SUPERS_TABLE_MASK;
                               static const uintx SECONDARY_SUPERS_BITMAP_EMPTY;
                               static const uintx SECONDARY_SUPERS_BITMAP_FULL;
                               static const int _lh_neutral_value;
                               static const int _lh_instance_slow_path_bit;
                               static const int _lh_log2_element_size_shift;
                               static const int _lh_log2_element_size_mask;
                               static const int _lh_element_type_shift;
                               static const int _lh_element_type_mask;
                               static const int _lh_header_size_shift;
                               static const int _lh_header_size_mask;
                               static const int _lh_array_tag_bits;
                               static const int _lh_array_tag_shift;
                               static const int _lh_array_tag_obj_value;
                               static const unsigned int _lh_array_tag_type_value;

                               /* total size (bytes):  208 */
                             }


As Aleksey suggested, moving _hash_slot to somewhere later could solve the alignments issue, I have tested it it works well, but causes 2 smaller holes in the private fields which could be solved by padding. 

Layout after moving _hash_slot w/o padding

/* offset      |    size */  type = class Klass : public Metadata {
                             public:
                               static const uint KLASS_KIND_COUNT;
                             protected:
/* 0x0008      |  0x0004 */    jint _layout_helper;
/* 0x000c      |  0x0004 */    const enum Klass::KlassKind _kind;
/* 0x0010      |  0x0004 */    jint _modifier_flags;
/* 0x0014      |  0x0004 */    juint _super_check_offset;
/* 0x0018      |  0x0008 */    class Symbol *_name;
/* 0x0020      |  0x0008 */    class Klass *_secondary_super_cache;
/* 0x0028      |  0x0008 */    class Array<Klass*> *_secondary_supers;
/* 0x0030      |  0x0040 */    class Klass *_primary_supers[8];
/* 0x0070      |  0x0008 */    class OopHandle {
                                 private:
/* 0x0070      |  0x0008 */        oop *_obj;

                                   /* total size (bytes):    8 */
                               } _java_mirror;
/* 0x0078      |  0x0008 */    class Klass *_super;
/* 0x0080      |  0x0008 */    class Klass * volatile _subklass;
/* 0x0088      |  0x0008 */    class Klass * volatile _next_sibling;
/* 0x0090      |  0x0008 */    class Klass *_next_link;
/* 0x0098      |  0x0008 */    class ClassLoaderData *_class_loader_data;
/* 0x00a0      |  0x0008 */    uintx _bitmap;
/* 0x00a8      |  0x0004 */    int _vtable_len;
/* 0x00ac      |  0x0004 */    class AccessFlags {
                                 private:
/* 0x00ac      |  0x0004 */        jint _flags;

                                   /* total size (bytes):    4 */
                               } _access_flags;
/* 0x00b0      |  0x0008 */    traceid _trace_id;
/* 0x00b8      |  0x0001 */    uint8_t _hash_slot;
                             private:
/* XXX  1-byte hole      */
/* 0x00ba      |  0x0002 */    s2 _shared_class_path_index;
/* 0x00bc      |  0x0002 */    u2 _shared_class_flags;
/* XXX  2-byte hole      */
/* 0x00c0      |  0x0004 */    int _archived_mirror_index;
                             public:
                               static const int SECONDARY_SUPERS_TABLE_SIZE;
                               static const int SECONDARY_SUPERS_TABLE_MASK;
                               static const uintx SECONDARY_SUPERS_BITMAP_EMPTY;
                               static const uintx SECONDARY_SUPERS_BITMAP_FULL;
                               static const int _lh_neutral_value;
                               static const int _lh_instance_slow_path_bit;
                               static const int _lh_log2_element_size_shift;
                               static const int _lh_log2_element_size_mask;
                               static const int _lh_element_type_shift;
                               static const int _lh_element_type_mask;
                               static const int _lh_header_size_shift;
                               static const int _lh_header_size_mask;
                               static const int _lh_array_tag_bits;
                               static const int _lh_array_tag_shift;
                               static const int _lh_array_tag_obj_value;
                               static const unsigned int _lh_array_tag_type_value;
/* XXX  4-byte padding   */

                               /* total size (bytes):  200 */
                             }

```  

Layout after moving _hash_slot with padding:

/* offset      |    size */  type = class Klass : public Metadata {
                             public:
                               static const uint KLASS_KIND_COUNT;
                             protected:
/* 0x0008      |  0x0004 */    jint _layout_helper;
/* 0x000c      |  0x0004 */    const enum Klass::KlassKind _kind;
/* 0x0010      |  0x0004 */    jint _modifier_flags;
/* 0x0014      |  0x0004 */    juint _super_check_offset;
/* 0x0018      |  0x0008 */    class Symbol *_name;
/* 0x0020      |  0x0008 */    class Klass *_secondary_super_cache;
/* 0x0028      |  0x0008 */    class Array<Klass*> *_secondary_supers;
/* 0x0030      |  0x0040 */    class Klass *_primary_supers[8];
/* 0x0070      |  0x0008 */    class OopHandle {
                                 private:
/* 0x0070      |  0x0008 */        oop *_obj;

                                   /* total size (bytes):    8 */
                               } _java_mirror;
/* 0x0078      |  0x0008 */    class Klass *_super;
/* 0x0080      |  0x0008 */    class Klass * volatile _subklass;
/* 0x0088      |  0x0008 */    class Klass * volatile _next_sibling;
/* 0x0090      |  0x0008 */    class Klass *_next_link;
/* 0x0098      |  0x0008 */    class ClassLoaderData *_class_loader_data;
/* 0x00a0      |  0x0008 */    uintx _bitmap;
/* 0x00a8      |  0x0004 */    int _vtable_len;
/* 0x00ac      |  0x0004 */    class AccessFlags {
                                 private:
/* 0x00ac      |  0x0004 */        jint _flags;

                                   /* total size (bytes):    4 */
                               } _access_flags;
/* 0x00b0      |  0x0008 */    traceid _trace_id;
/* 0x00b8      |  0x0001 */    uint8_t _hash_slot;
/* 0x00b9      |  0x0003 */    char _pad_buf1[3];
                             private:
/* 0x00bc      |  0x0002 */    s2 _shared_class_path_index;
/* 0x00be      |  0x0002 */    u2 _shared_class_flags;
/* 0x00c0      |  0x0004 */    int _archived_mirror_index;
                             public:
                               static const int SECONDARY_SUPERS_TABLE_SIZE;
                               static const int SECONDARY_SUPERS_TABLE_MASK;
                               static const uintx SECONDARY_SUPERS_BITMAP_EMPTY;
                               static const uintx SECONDARY_SUPERS_BITMAP_FULL;
                               static const int _lh_neutral_value;
                               static const int _lh_instance_slow_path_bit;
                               static const int _lh_log2_element_size_shift;
                               static const int _lh_log2_element_size_mask;
                               static const int _lh_element_type_shift;
                               static const int _lh_element_type_mask;
                               static const int _lh_header_size_shift;
                               static const int _lh_header_size_mask;
                               static const int _lh_array_tag_bits;
                               static const int _lh_array_tag_shift;
                               static const int _lh_array_tag_obj_value;
                               static const unsigned int _lh_array_tag_type_value;
/* XXX  4-byte padding   */

                               /* total size (bytes):  200 */
                             }


Best,
Xiaolong.

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

Commit messages:
 - Merge branch 'openjdk:master' into klass-layout
 - 8334220: Optimize Klass layout after JDK-8180450

Changes: https://git.openjdk.org/jdk/pull/19958/files
  Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=19958&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8334220
  Stats: 4 lines in 1 file changed: 3 ins; 1 del; 0 mod
  Patch: https://git.openjdk.org/jdk/pull/19958.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/19958/head:pull/19958

PR: https://git.openjdk.org/jdk/pull/19958


More information about the hotspot-dev mailing list