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