Indirect specialized calls

Jan Lahoda jan.lahoda at oracle.com
Tue Sep 23 13:09:44 UTC 2014


Hello,

While experimenting with accessors to private specialized fields, I ran 
across a case where javac produces a classfile that crashes at runtime 
(on a custom build from valhalla forest). I apologize if this is a known 
problem, or if I am doing something wrong.

The code is like this:
---
public class SpecializationTest<any T> {

     public T i;

     public static <any TT> TT get(SpecializationTest<TT> t) {
         return t.i;
     }

     public static void main(String[] args) {
         Nested.main(args);
     }

     public static class Nested<any TT> {
         public static void main(String[] args) {
             SpecializationTest<int> v = new SpecializationTest<>();

             new Nested<int>().call(v);
         }
         public TT call(SpecializationTest<TT> v) {
             return get(v);
         }
     }
}
---

The output of javap for the compiled classes is attached.

Running the compiled class leads to:
---
Specializing SpecializationTest${0=I}; searching for 
SpecializationTest.class (not found)
Specializing SpecializationTest${0=I}; searching for 
SpecializationTest.class (found)
Specializing SpecializationTest$Nested${0=I}; searching for 
SpecializationTest$Nested.class (not found)
Specializing SpecializationTest$Nested${0=I}; searching for 
SpecializationTest$Nested.class (found)
Specializing (LSpecializationTest;)Ljava/lang/Object; to 
(LSpecializationTest${0=I};)I
Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
Exception Details:
   Location:
     SpecializationTest$Nested${0=I}.call(LSpecializationTest${0=I};)I 
@1: invokedynamic
   Reason:
     Type 'SpecializationTest${0=I}' (current frame, stack[0]) is not 
assignable to 'SpecializationTest'
   Current Frame:
     bci: @1
     flags: { }
     locals: { 'SpecializationTest$Nested${0=I}', 
'SpecializationTest${0=I}' }
     stack: { 'SpecializationTest${0=I}' }
   Bytecode:
     0000000: 2bba 002e 0000 ac

         at SpecializationTest$Nested.main(SpecializationTest.java:17)
         at SpecializationTest.main(SpecializationTest.java:10)
---

Any idea what is wrong?

Thanks,
     Jan
-------------- next part --------------
Classfile /tmp/specialization-test/src/SpecializationTest.class
  Last modified Sep 23, 2014; size 767 bytes
  MD5 checksum ccfa8a4d719eb35806b3b0d4083430d6
  Compiled from "SpecializationTest.java"
public class SpecializationTest<T extends java.lang.Object> extends java.lang.Object
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #5.#29         // java/lang/Object."<init>":()V
   #2 = Fieldref           #4.#30         // SpecializationTest.i:Ljava/lang/Object;
   #3 = Methodref          #6.#31         // SpecializationTest$Nested.main:([Ljava/lang/String;)V
   #4 = Class              #32            // SpecializationTest
   #5 = Class              #33            // java/lang/Object
   #6 = Class              #34            // SpecializationTest$Nested
   #7 = Utf8               Nested
   #8 = Utf8               InnerClasses
   #9 = Utf8               i
  #10 = Utf8               Ljava/lang/Object;
  #11 = Utf8               Signature
  #12 = Utf8               TT;
  #13 = Utf8               <init>
  #14 = Utf8               ()V
  #15 = Utf8               Code
  #16 = Utf8               LineNumberTable
  #17 = Utf8               get
  #18 = Utf8               (LSpecializationTest;)Ljava/lang/Object;
  #19 = Utf8               BytecodeMapping
  #20 = Utf8               LSpecializationTest<TTT;>;::TTT;
  #21 = Utf8               TTT;
  #22 = Utf8               <TT:Ljava/lang/Object;>(LSpecializationTest<TTT;>;)TTT;
  #23 = Utf8               TypeVariablesMap
  #24 = Utf8               main
  #25 = Utf8               ([Ljava/lang/String;)V
  #26 = Utf8               <T:Ljava/lang/Object;>Ljava/lang/Object;
  #27 = Utf8               SourceFile
  #28 = Utf8               SpecializationTest.java
  #29 = NameAndType        #13:#14        // "<init>":()V
  #30 = NameAndType        #9:#10         // i:Ljava/lang/Object;
  #31 = NameAndType        #24:#25        // main:([Ljava/lang/String;)V
  #32 = Utf8               SpecializationTest
  #33 = Utf8               java/lang/Object
  #34 = Utf8               SpecializationTest$Nested
{
  public T i;
    descriptor: Ljava/lang/Object;
    flags: ACC_PUBLIC
    Signature: #12                          // TT;

  public SpecializationTest();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0
        line 13: 4

  public static <TT extends java.lang.Object> TT get(SpecializationTest<TT>);
    descriptor: (LSpecializationTest;)Ljava/lang/Object;
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #2                  // Field i:Ljava/lang/Object;
         4: areturn
      LineNumberTable:
        line 6: 0
    BytecodeMapping:
      Code_idx  Signature
          1:    LSpecializationTest<TTT;>;::TTT;
          4:    TTT;
    Signature: #22                          // <TT:Ljava/lang/Object;>(LSpecializationTest<TTT;>;)TTT;
    TypeVariablesMap:
      Tvar_idx  Flags
          1     [ANY]     Ljava/lang/Object;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokestatic  #3                  // Method SpecializationTest$Nested.main:([Ljava/lang/String;)V
         4: return
      LineNumberTable:
        line 10: 0
        line 11: 4
}
Signature: #26                          // <T:Ljava/lang/Object;>Ljava/lang/Object;
SourceFile: "SpecializationTest.java"
TypeVariablesMap:
  Tvar_idx  Flags
      1     [ANY]     Ljava/lang/Object;
InnerClasses:
     public static #7= #6 of #4; //Nested=class SpecializationTest$Nested of class SpecializationTest


Classfile /tmp/specialization-test/src/SpecializationTest$Nested.class
  Last modified Sep 23, 2014; size 1248 bytes
  MD5 checksum 02d07c1bb9f3fa4b92d9ca4ba4afbd3f
  Compiled from "SpecializationTest.java"
public class SpecializationTest$Nested<TT extends java.lang.Object> extends java.lang.Object
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #9.#28         // java/lang/Object."<init>":()V
   #2 = Class              #29            // "SpecializationTest${0=I}"
   #3 = Methodref          #2.#28         // "SpecializationTest${0=I}"."<init>":()V
   #4 = Class              #31            // "SpecializationTest$Nested${0=I}"
   #5 = Methodref          #4.#28         // "SpecializationTest$Nested${0=I}"."<init>":()V
   #6 = Methodref          #4.#34         // "SpecializationTest$Nested${0=I}".call:(LSpecializationTest${0=I};)I
   #7 = InvokeDynamic      #0:#39         // #0:get:(LSpecializationTest;)Ljava/lang/Object;
   #8 = Class              #40            // SpecializationTest$Nested
   #9 = Class              #42            // java/lang/Object
  #10 = Utf8               <init>
  #11 = Utf8               ()V
  #12 = Utf8               Code
  #13 = Utf8               LineNumberTable
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Utf8               call
  #17 = Utf8               (LSpecializationTest;)Ljava/lang/Object;
  #18 = Utf8               BytecodeMapping
  #19 = Utf8               LSpecializationTest<TT;>;::(LSpecializationTest<TTT;>;)TTT;
  #20 = Utf8               TTT;
  #21 = Utf8               Signature
  #22 = Utf8               (LSpecializationTest<TTT;>;)TTT;
  #23 = Utf8               <TT:Ljava/lang/Object;>Ljava/lang/Object;
  #24 = Utf8               SourceFile
  #25 = Utf8               SpecializationTest.java
  #26 = Utf8               TypeVariablesMap
  #27 = Utf8               Ljava/lang/Object;
  #28 = NameAndType        #10:#11        // "<init>":()V
  #29 = Utf8               SpecializationTest${0=I}
  #30 = Class              #43            // SpecializationTest
  #31 = Utf8               SpecializationTest$Nested${0=I}
  #32 = Utf8               Nested${0=I}
  #33 = Utf8               InnerClasses
  #34 = NameAndType        #16:#44        // call:(LSpecializationTest${0=I};)I
  #35 = Utf8               BootstrapMethods
  #36 = MethodHandle       #6:#45         // invokestatic java/lang/invoke/GenericMethodSpecializer.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
  #37 = MethodHandle       #6:#46         // invokestatic SpecializationTest.get:(LSpecializationTest;)Ljava/lang/Object;
  #38 = String             #20            // TTT;
  #39 = NameAndType        #47:#17        // get:(LSpecializationTest;)Ljava/lang/Object;
  #40 = Utf8               SpecializationTest$Nested
  #41 = Utf8               Nested
  #42 = Utf8               java/lang/Object
  #43 = Utf8               SpecializationTest
  #44 = Utf8               (LSpecializationTest${0=I};)I
  #45 = Methodref          #48.#49        // java/lang/invoke/GenericMethodSpecializer.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
  #46 = Methodref          #30.#39        // SpecializationTest.get:(LSpecializationTest;)Ljava/lang/Object;
  #47 = Utf8               get
  #48 = Class              #50            // java/lang/invoke/GenericMethodSpecializer
  #49 = NameAndType        #51:#54        // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
  #50 = Utf8               java/lang/invoke/GenericMethodSpecializer
  #51 = Utf8               metafactory
  #52 = Class              #56            // java/lang/invoke/MethodHandles$Lookup
  #53 = Utf8               Lookup
  #54 = Utf8               (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
  #55 = Class              #57            // java/lang/invoke/MethodHandles
  #56 = Utf8               java/lang/invoke/MethodHandles$Lookup
  #57 = Utf8               java/lang/invoke/MethodHandles
{
  public SpecializationTest$Nested();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 13: 0

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #2                  // class "SpecializationTest${0=I}"
         3: dup
         4: invokespecial #3                  // Method "SpecializationTest${0=I}"."<init>":()V
         7: astore_1
         8: new           #4                  // class "SpecializationTest$Nested${0=I}"
        11: dup
        12: invokespecial #5                  // Method "SpecializationTest$Nested${0=I}"."<init>":()V
        15: aload_1
        16: invokevirtual #6                  // Method "SpecializationTest$Nested${0=I}".call:(LSpecializationTest${0=I};)I
        19: pop
        20: return
      LineNumberTable:
        line 15: 0
        line 17: 8
        line 18: 20

  public TT call(SpecializationTest<TT>);
    descriptor: (LSpecializationTest;)Ljava/lang/Object;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=2, args_size=2
         0: aload_1
         1: invokedynamic #7,  0              // InvokeDynamic #0:get:(LSpecializationTest;)Ljava/lang/Object;
         6: areturn
      LineNumberTable:
        line 20: 0
    BytecodeMapping:
      Code_idx  Signature
          1:    LSpecializationTest<TT;>;::(LSpecializationTest<TTT;>;)TTT;
          6:    TTT;
    Signature: #22                          // (LSpecializationTest<TTT;>;)TTT;
}
Signature: #23                          // <TT:Ljava/lang/Object;>Ljava/lang/Object;
SourceFile: "SpecializationTest.java"
TypeVariablesMap:
  Tvar_idx  Flags
      1     [ANY]     Ljava/lang/Object;
InnerClasses:
     public static #32= #4 of #30; //Nested${0=I}=class "SpecializationTest$Nested${0=I}" of class SpecializationTest
     public static #41= #8 of #30; //Nested=class SpecializationTest$Nested of class SpecializationTest
     public static final #53= #52 of #55; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
  0: #36 invokestatic java/lang/invoke/GenericMethodSpecializer.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
    Method arguments:
      #37 invokestatic SpecializationTest.get:(LSpecializationTest;)Ljava/lang/Object;
      #38 TTT;


More information about the valhalla-dev mailing list