Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8244964

[LW3] javac should use Q-envelopes in CONSTANT_Class_info entries referencing inline types

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Withdrawn
    • Icon: P3 P3
    • repo-valhalla
    • repo-valhalla
    • tools

      In LW1, it was possible for a given value type Foo to be referenced in two different ways: LFoo; and QFoo;.
      In LW3, LFoo; and QFoo; now denote two different types.

      It is critical that symbolic references in the constant pool denote unambiguously the correct type. Type descriptors, used for fields and method signatures, already always use an envelope around the class name to specify which type is expected. However, CONSTANT_Class_info entries still use simple binary names in many places.

      The Expert Group has defined a new semantic for CONSTANT_Class_info entries:
        - a symbolic reference to an inline type must always put a Q-envelope around the class name
        - a symbolic reference to a non inline type can either use a L-envelope or a simple binary name (for backward compatibility)

      Example:

      The following source code:

      public inline class CCIEntry {
          int i = 0;

          int getI() {
              return i;
          }
          
          public static void main(String[] args) {
              CCIEntry c = new CCIEntry();
              int i = c.i;
              i = c.getI();
          }

          static boolean isCCIEntry(Object o) {
              return o instanceof CCIEntry;
          }

          static CCIEntry getCCIEntryOrThrow(Object o) {
              return (CCIEntry)o;
          }
      }

      is currently compiled into this class file:

      Classfile CCIEntry.class
        Last modified May 13, 2020; size 1270 bytes
        SHA-256 checksum 0c6fec11effe415da2294aeadf0021c3a3aea3af07599d483eba8dd0bd1cc020
        Compiled from "CCIEntry.java"
      public final value class CCIEntry extends CCIEntry$ref implements java.lang.InlineObject
        minor version: 0
        major version: 59
        flags: (0x0131) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_VALUE
        this_class: #1 // CCIEntry
        super_class: #29 // CCIEntry$ref
        interfaces: 1, fields: 1, methods: 8, attributes: 3
      Constant pool:
         #1 = Class #2 // CCIEntry
         #2 = Utf8 CCIEntry
         #3 = Fieldref #1.#4 // CCIEntry.i:I
         #4 = NameAndType #5:#6 // i:I
         #5 = Utf8 i
         #6 = Utf8 I
         #7 = Methodref #1.#8 // CCIEntry."<init>":()QCCIEntry;
         #8 = NameAndType #9:#10 // "<init>":()QCCIEntry;
         #9 = Utf8 <init>
        #10 = Utf8 ()QCCIEntry;
        #11 = Methodref #1.#12 // CCIEntry.getI:()I
        #12 = NameAndType #13:#14 // getI:()I
        #13 = Utf8 getI
        #14 = Utf8 ()I
        #15 = Class #16 // "QCCIEntry;"
        #16 = Utf8 QCCIEntry;
        #17 = InvokeDynamic #0:#18 // #0:hashCode:(QCCIEntry;)I
        #18 = NameAndType #19:#20 // hashCode:(QCCIEntry;)I
        #19 = Utf8 hashCode
        #20 = Utf8 (QCCIEntry;)I
        #21 = InvokeDynamic #0:#22 // #0:equals:(QCCIEntry;Ljava/lang/Object;)Z
        #22 = NameAndType #23:#24 // equals:(QCCIEntry;Ljava/lang/Object;)Z
        #23 = Utf8 equals
        #24 = Utf8 (QCCIEntry;Ljava/lang/Object;)Z
        #25 = InvokeDynamic #0:#26 // #0:toString:(QCCIEntry;)Ljava/lang/String;
        #26 = NameAndType #27:#28 // toString:(QCCIEntry;)Ljava/lang/String;
        #27 = Utf8 toString
        #28 = Utf8 (QCCIEntry;)Ljava/lang/String;
        #29 = Class #30 // CCIEntry$ref
        #30 = Utf8 CCIEntry$ref
        #31 = Class #32 // java/lang/InlineObject
        #32 = Utf8 java/lang/InlineObject
        #33 = Utf8 Code
        #34 = Utf8 LineNumberTable
        #35 = Utf8 main
        #36 = Utf8 ([Ljava/lang/String;)V
        #37 = Utf8 isCCIEntry
        #38 = Utf8 (Ljava/lang/Object;)Z
        #39 = Utf8 getCCIEntryOrThrow
        #40 = Utf8 (Ljava/lang/Object;)QCCIEntry;
        #41 = Utf8 ()Ljava/lang/String;
        #42 = Utf8 SourceFile
        #43 = Utf8 CCIEntry.java
        #44 = Utf8 BootstrapMethods
        #45 = MethodHandle 6:#46 // REF_invokeStatic java/lang/invoke/ValueBootstrapMethods.makeBootstrapMethod:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
        #46 = Methodref #47.#48 // java/lang/invoke/ValueBootstrapMethods.makeBootstrapMethod:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
        #47 = Class #49 // java/lang/invoke/ValueBootstrapMethods
        #48 = NameAndType #50:#51 // makeBootstrapMethod:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
        #49 = Utf8 java/lang/invoke/ValueBootstrapMethods
        #50 = Utf8 makeBootstrapMethod
        #51 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
        #52 = Utf8 InnerClasses
        #53 = Class #54 // java/lang/invoke/MethodHandles$Lookup
        #54 = Utf8 java/lang/invoke/MethodHandles$Lookup
        #55 = Class #56 // java/lang/invoke/MethodHandles
        #56 = Utf8 java/lang/invoke/MethodHandles
        #57 = Utf8 Lookup
      {
        final int i;
          descriptor: I
          flags: (0x0010) ACC_FINAL

        int getI();
          descriptor: ()I
          flags: (0x0000)
          Code:
            stack=1, locals=1, args_size=1
               0: aload_0
               1: getfield #3 // Field i:I
               4: ireturn
            LineNumberTable:
              line 5: 0

        public static void main(java.lang.String[]);
          descriptor: ([Ljava/lang/String;)V
          flags: (0x0009) ACC_PUBLIC, ACC_STATIC
          Code:
            stack=1, locals=3, args_size=1
               0: invokestatic #7 // Method "<init>":()QCCIEntry;
               3: astore_1
               4: aload_1
               5: getfield #3 // Field i:I
               8: istore_2
               9: aload_1
              10: invokevirtual #11 // Method getI:()I
              13: istore_2
              14: return
            LineNumberTable:
              line 9: 0
              line 10: 4
              line 11: 9
              line 12: 14

        static boolean isCCIEntry(java.lang.Object);
          descriptor: (Ljava/lang/Object;)Z
          flags: (0x0008) ACC_STATIC
          Code:
            stack=1, locals=1, args_size=1
               0: aload_0
               1: instanceof #1 // class CCIEntry
               4: ireturn
            LineNumberTable:
              line 15: 0

        static CCIEntry getCCIEntryOrThrow(java.lang.Object);
          descriptor: (Ljava/lang/Object;)QCCIEntry;
          flags: (0x0008) ACC_STATIC
          Code:
            stack=1, locals=1, args_size=1
               0: aload_0
               1: checkcast #15 // class "QCCIEntry;"
               4: areturn
            LineNumberTable:
              line 19: 0

        public final int hashCode();
          descriptor: ()I
          flags: (0x0011) ACC_PUBLIC, ACC_FINAL
          Code:
            stack=1, locals=1, args_size=1
               0: aload_0
               1: invokedynamic #17, 0 // InvokeDynamic #0:hashCode:(QCCIEntry;)I
               6: ireturn
            LineNumberTable:
              line 1: 0

        public final boolean equals(java.lang.Object);
          descriptor: (Ljava/lang/Object;)Z
          flags: (0x0011) ACC_PUBLIC, ACC_FINAL
          Code:
            stack=2, locals=2, args_size=2
               0: aload_0
               1: aload_1
               2: invokedynamic #21, 0 // InvokeDynamic #0:equals:(QCCIEntry;Ljava/lang/Object;)Z
               7: ireturn
            LineNumberTable:
              line 1: 0

        public final java.lang.String toString();
          descriptor: ()Ljava/lang/String;
          flags: (0x0011) ACC_PUBLIC, ACC_FINAL
          Code:
            stack=1, locals=1, args_size=1
               0: aload_0
               1: invokedynamic #25, 0 // InvokeDynamic #0:toString:(QCCIEntry;)Ljava/lang/String;
               6: areturn
            LineNumberTable:
              line 1: 0

        public static CCIEntry CCIEntry();
          descriptor: ()QCCIEntry;
          flags: (0x0009) ACC_PUBLIC, ACC_STATIC
          Code:
            stack=2, locals=1, args_size=0
               0: defaultvalue #1 // class CCIEntry
               3: astore_0
               4: iconst_0
               5: aload_0
               6: swap
               7: withfield #3 // Field i:I
              10: astore_0
              11: aload_0
              12: areturn
            LineNumberTable:
              line 1: 0
              line 2: 4
      }
      SourceFile: "CCIEntry.java"
      BootstrapMethods:
        0: #45 REF_invokeStatic java/lang/invoke/ValueBootstrapMethods.makeBootstrapMethod:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
          Method arguments:
      InnerClasses:
        public static final #57= #53 of #55; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles


      The entries that need to be fixed are:

      The class name itself, CCIEntry is an inline type, so the CONSTANT_Class_info entry at index 1 should use a Q-envelope, which means the Utf8 at index 2 should be "QCCIEntry;".

      The field reference at index 3 points to a field of an inline type, so its symbolic reference to a class should use a Q-envelope too. Same fix as above.

      The method references at index 7 and 11 points to methods of an inline type, so their symbolic reference to a class should use a Q-envelope too. Same fix as above.

      In method isCCIEntry(java.lang.Object), the instanceof bytecode should point to a CONSTANT_Class_info entry referencing type "QCCIEntry;" (Fixing entry 1 would also fix this one).

      In method getCCIEntryOrThrow(java.lang.Object), the bytecode checkcast already correctly points to a CONSTANT_Class_info entry referencing type ""QCCIEntry;" (but the entry can now be shared will all the other above).





            vromero Vicente Arturo Romero Zaldivar
            fparain Frederic Parain
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: