[lworld] RFR: 8237072: [lworld] Add support for denoting and deriving the reference projection

Srikanth Adayapalam sadayapalam at openjdk.java.net
Thu Apr 30 04:45:23 UTC 2020

Hello Maurizio & Jim,

    May I request you to please review this patch for valhalla inline types support
under the new scheme ? TIA.

I.   What does this patch do?
II.  What can be skipped in the review?
III. Recommended order for review.
IV.  Known problems, limitations and deferred tasks.
V.   Report to language designers on open problems.

I. What does this patch do:

    - From every inline class declaration V, derive two classes V and V.ref
    - These two are subtypes at the VM level, but are related (only) by inline
      widening conversion and narrowing conversion at the language level.
    - The two types have the same fields and methods with the same shape and
      accessibility rules.
    - Add source level support for V.ref and V.val notation.
    - Get rid of the experimental support for generics over values. Until we
      figure out the full story with generics and inlines, carrying along this
      experimental support is becoming untenable/unsustainable.
    - Get rid of the experimental support added for noncovariant value arrays
    - Get rid of LW2's "Nullable Projections" including the V? syntax

II. These files can be skipped as they simply revert change and align
    with origin/master: (roll back V and V? nullable projections of LW2)


III. Recommended order for review:

    - Type.java, Symbol.java

            Look at the new internal APIs to query/compute various projections.
            Every class type, class symbol, method and field support an API
            to return the "other" projection i.e its doppleganger in the alternate

            Most crucially ClassSymbol.referenceProjection()

    - Attr.java:

            Source support for .ref/.val

    - MemberEnter.java:
    - TypeEnter.java:
    - TransTypes.java:

            Co-evolve V.val and V.ref in lock step (also TransValues.java)

    - TransValues.java:

            Fold all V.ref.member accesses to ((V) V.ref).member access.

    - Resolve.java:

            Changes to make sure method look up works OK in a world where values are islands.

    - Types.java:
            Implement inline widening/narrowing relationship.

    - ProjectionRelationsTest.java:

            Verify all relationships between V and V.ref and V[] and V.ref[]

    - ClassWriter.java:
            Dual class generation scheme with subtyping relationship at the binary/VM level.

    - ClassReader.java:

            Merge the dual classes back, sever the subtyping relationship and make
            them operate as a pair of classes that can convert to each other.

    - New tests:
            Most importantly ProjectionRelationsTest.java

    - Other files.

IV. There are many known issues that have been deliberately deferred to a later iteration:

    - With Brian's consent I am using a simpler translation strategy than what is
      outlined in the SoV documents. These are good enough for now, but when
      VBC migration is undertaken, will have to enhanced.
    - No support for ref-default and val-default classes yet.
    - No support for class hierarchy sealing.
    - You can't do new V.ref() (V.ref is abstract) although SoV calls for it.
    - Handling of .ref and .val is quick and dirty; Need revisit.
    - The nest mate related attributes are not fully properly emitted as of now
    - Need to verify that attributes from V are not carried over inadvertantly to
    - Class hierarchy walking in a world where inline types are islands calls for
      a type switch. I have done this only in places uncovered by existing tests.
      We need to go through various utility methods (similar to what is done in
      Symbol.java and Resolve.java) to make sure these changes are consistently
    - Diamond inference with value classes crashes now (implementation creates factory
      methods, projections are missing and need to be created)

V. Problems in the interplay of inlines types with generics and inference:

    Removing the experimental support for generics over values results in several
constructs that used to compile earlier (albeit only with -XDallowGenericsOverValues)
not compiling anymore.

    These expose some issues that feed into the language design. We need to evolve
a short term answer (so that the JDK components tests that are impacted don't get
blocked) and a long term one (the real solution)

Here is a snippet that captures these problems:

import java.util.Arrays;

interface I {}

public inline class X implements I {

    int x = 10;

    void problem_01() {
        X [] a1 = new X[0];
        X [] a2 = Arrays.copyOf(a1, a2.length, X[].class);
error: incompatible types: inference variable T has incompatible bounds
        X [] a2 = Arrays.copyOf(a1, a2.length, X[].class);
    lower bounds: X,Object
    lower bounds: X$ref
  where T,U are type-variables:
    T extends Object declared in method <T,U>copyOf(U[],int,Class<? extends T[]>)
    U extends Object declared in method <T,U>copyOf(U[],int,Class<? extends T[]>)
1 error

    void foo(Class<? extends I> p) {}

    void problem_02() {
error: incompatible types: Class<X> cannot be converted to Class<? extends I>

    String data() {
        return null;

    // Problem: 3, we infer a stream of X.ref's causing
    // the method reference to not type check.
    void unbound_lookup_with_projected_receiver() {
        X [] a = new X[0];
        Arrays.stream(a).map(X::data).filter(p -> p != null).forEach(System.out::println);
error: incompatible types: invalid method reference
        Arrays.stream(a).map(X::data).filter(p -> p != null).forEach(System.out::println);
    method data in class X cannot be applied to given types
      required: no arguments
      found:    X$ref
      reason: actual and formal argument lists differ in length

    void problem_04() {
    test/hotspot/jtreg/runtime/valhalla/valuetypes/UnsafeTest.java:125: warning: [removal] putObject(Object,long,Object) in
    Unsafe has been deprecated and marked for removal
            U.putObject(v, off_o, List.of("Value1", "Value2", "Value3"));
/home/srikanth/valhalla/test/valhalla/test/hotspot/jtreg/runtime/valhalla/valuetypes/UnsafeTest.java:127: error: method
valueHeaderSize in class Unsafe cannot be applied to given types;
            U.putInt(v, off_v + off_i - U.valueHeaderSize(Value2.class), 999);
  required: Class<V>
  found:    Class<Value2>
  reason: inference variable V has incompatible bounds
    equality constraints: Value2
    lower bounds: Object
  where V is a type-variable:
    V extends Object declared in method <V>valueHeaderSize(Class<V>)

    void problem_05() {
test/hotspot/jtreg/compiler/valhalla/valuetypes/TestIntrinsics.java:119: error: incomparable types: Class<CAP#1> and
        boolean check2 = MyValue1.class.asIndirectType().getSuperclass() == MyValue1.ref.class;
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Object super: MyValue1 from capture of ? super MyValue1

    public static void main(String [] args) {


Commit messages:
 - Fix trailing white spaces
 - 8237072: [lworld] Add support for denoting and deriving the reference projection
 - 8237072: [lworld] Add support for denoting and deriving the reference projection

Changes: https://git.openjdk.java.net/valhalla/pull/32/files
 Webrev: https://webrevs.openjdk.java.net/valhalla/32/webrev.00
  Issue: https://bugs.openjdk.java.net/browse/JDK-8237072
  Stats: 1405 lines in 53 files changed: 1003 ins; 253 del; 149 mod
  Patch: https://git.openjdk.java.net/valhalla/pull/32.diff
  Fetch: git fetch https://git.openjdk.java.net/valhalla pull/32/head:pull/32

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

More information about the valhalla-dev mailing list