[lworld] RFR: Javac support for Parametric VM

Vicente Romero vromero at openjdk.java.net
Sun Mar 7 00:35:31 UTC 2021


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

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

Commit messages:
 - javac support for Experimental Parametric VM, first stab
 - Merge lworld

Changes: https://git.openjdk.java.net/valhalla/pull/364/files
 Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=364&range=00
  Stats: 778 lines in 24 files changed: 772 ins; 2 del; 4 mod
  Patch: https://git.openjdk.java.net/valhalla/pull/364.diff
  Fetch: git fetch https://git.openjdk.java.net/valhalla pull/364/head:pull/364

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


More information about the valhalla-dev mailing list