[lworld] RFR: javac support for Parametric VM, first stab

Maurizio Cimadamore mcimadamore at openjdk.java.net
Tue Mar 9 12:06:25 UTC 2021


On Tue, 9 Mar 2021 11:51:15 GMT, Maurizio Cimadamore <mcimadamore at openjdk.org> wrote:

>> This patch is the initial support for Parametric VM in javac. This is the first iteration of the prototype, so still a work in progress. In order to test the new code users need to pass the hidden option: `-XDsupportParametricVM` to javac. See the examples below for an illustration of the bytecode the compiler can generate now. Lets assume we have the following class annotated with the `@Parametric` annotation:
>> 
>> import java.lang.annotation.*;
>> 
>> @Parametric(id="PAIR")
>> class Pair<X, Y> {
>>     @Parametric(id="PAIR")
>>     X fst;
>>     @Parametric(id="PAIR")
>>     Y snd;
>> 
>>     Pair(X fst, Y snd) {
>>         this.fst = fst;
>>         this.snd = snd;
>>     }
>> 
>>     Pair<Y, X> swap() {
>>         return new Pair<>(snd, fst);
>>     }
>> 
>>     @Parametric(id="make", kind=ParamKind.METHOD_ONLY)
>>     static <U, W> Pair<U, W> make(U fst, W snd) {
>>         return new Pair<>(fst, snd);
>>     }
>> 
>>     @Parametric(id="setFst", kind=ParamKind.METHOD_AND_CLASS)
>>     <Z> Pair<Z, Y> setFst(Z newFst) {
>>         return null;
>>     }
>> }
>> 
>> After compilation this class will contain the following new entries in the constant pool:
>> 
>> #22 = Parameter          CLASS:0        // CLASS:0
>> #37 = Parameter          METHOD_ONLY:0  // METHOD_ONLY:0
>> #44 = Parameter          METHOD_AND_CLASS:0 // METHOD_AND_CLASS:0
>> also there will be several elements with the new attribute `Parametric` which will appear in both fields, the `Pair` class per-se and methods: `make` and `setFst`.
>> 
>> Let's now assume we define a Client willing to use class `Pair`, it will need to define values to bound to the "holes" defined in class `Pair` using the `Parametric` annotation. For this class Client should use annotations `@LinkageClass` and or `@LinkageMethod` depending on the kind of hole in class `Pair` it is intending to bound to. Let's define class `Client` as:
>> 
>> import java.lang.annotation.*;
>> 
>> class Client {
>>     @LinkageClass("linkageClass")
>>     void linkClassParams() {
>>         Pair<String, Integer> psi = new Pair<>("first", 2);
>>     }
>> 
>>     @LinkageClass("linkageClass")
>>     void linkClassParamsFieldAccess(Pair<String, Integer> psi) {
>>         psi.fst = "field";
>>     }
>> 
>> 
>>     @LinkageMethod("linkageMethod1")
>>     void linkMethodParams(Pair<String, Integer> psi) {
>>         Pair<String, Integer> pair = Pair.make("hello", 1);
>>     }
>> 
>>     @LinkageClass("linkageClass")
>>     @LinkageMethod("linkageMethod2")
>>     void linkClassAndMethodParams(Pair<String, Integer> psi) {
>>         Pair<String, Integer> pss = psi.setFst("b");
>>     }
>> }
>> 
>> again compiling this class with the hidden option `-XDsupportParametricVM` we can find these new entries in the CP:
>> 
>>    #7 = Linkage            #8:#9          // linkageClass:Pair
>>    #8 = String             #10            // linkageClass
>>    #9 = Class              #11            // Pair
>> 
>> this Linkage CP entry is referred from method: `linkClassParams` as:
>> 
>>   void linkClassParams();
>>     descriptor: ()V
>>     flags: (0x0000)
>>     Code:
>>       stack=4, locals=2, args_size=1
>>          0: new           #7                  // Linkage linkageClass:Pair
>> 
>> also:
>> 
>>   #25 = Linkage            #8:#26         // linkageClass:Pair.fst:Ljava/lang/Object;
>>   #26 = Fieldref           #7.#27         // Pair.fst:Ljava/lang/Object;
>>   #27 = NameAndType        #28:#29        // fst:Ljava/lang/Object;
>> 
>> referred from method: `linkClassParamsFieldAccess` the bytecode looks like:
>> 
>>   void linkClassParamsFieldAccess(Pair<java.lang.String, java.lang.Integer>);
>>     descriptor: (LPair;)V
>>     flags: (0x0000)
>>     Code:
>>       stack=2, locals=2, args_size=2
>>          0: aload_1
>>          1: ldc           #23                 // String field
>>          3: putfield      #25                 // Linkage linkageClass:Pair.fst:Ljava/lang/Object;
>>          6: return
>> 
>> also:
>> 
>>   #32 = Linkage            #33:#34        // linkageMethod1:Pair.make:(Ljava/lang/Object;Ljava/lang/Object;)LPair;
>>   #33 = String             #35            // linkageMethod1
>>   #34 = Methodref          #9.#36         // Pair.make:(Ljava/lang/Object;Ljava/lang/Object;)LPair;
>> 
>> this time referred by method: `linkMethodParams` with bytecode:
>> 
>>   void linkMethodParams(Pair<java.lang.String, java.lang.Integer>);
>>     descriptor: (LPair;)V
>>     flags: (0x0000)
>>     Code:
>>       stack=2, locals=3, args_size=2
>>          0: ldc           #30                 // String hello
>>          2: iconst_1
>>          3: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
>>          6: invokestatic  #32                 // Linkage linkageMethod1:Pair.make:(Ljava/lang/Object;Ljava/lang/Object;)LPair;
>>          9: astore_2
>>         10: return
>> 
>> and finally:
>> 
>>   #41 = Linkage            #42:#43        // linkageMethod2:Pair.setFst:(Ljava/lang/Object;)LPair;
>>   #42 = String             #44            // linkageMethod2
>>   #43 = Methodref          #7.#45         // Pair.setFst:(Ljava/lang/Object;)LPair;
>> 
>> in this last example it can be seen that Methodref at #43 is also pointing to #7 which, as commented above, is another Linkage_info entry in the CP.
>> 
>> TIA, for the feedback and comments,
>> Vicente
>
> Overall looks solid - I see that that there's no ClassReader support, which is probably ok given that we rely on (declaration) annotations to do the job.

Tried out on few examples, and it seems to work as expected - javap support working too. Well done!

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

PR: https://git.openjdk.java.net/valhalla/pull/364



More information about the valhalla-dev mailing list