Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • Requires source level >= JDK14 (since LW2, the prototype is based on mainline JDK, whose version string is JDK 14 at the time of writing)
  • A class declaration of inline type is made by using the "inline class" modifier, or (for IDE syntax parsing convenience) with "@__inline__" annotation (since LW2)
    • Interfaces, annotation types, enums can not be inline types
    • Top level, inner, nested, local classes may be inline types. Inline types may declare inner, nested, local types
    • Inline Types are implicitly final, so cannot be abstract
  • Inline Types may not declare an explicit super class (except Object). They implicitly extend java.lang.Object akin to enums, annotation types and interfaces
  • Inline Types may declare explicit interfaces
  • Inline Types constructors may not pass the "this" handle until all instance fields are definitely assigned.
  • All instance fields of a an inline class are implicitly final
  • "Indirect" projections of inline types via the "?" operator (since LW2)
    • E.g. the projection of Point is Point?
    • Point? IS also an inline type which allows null for backward compatibility
    • maintains type of a field,  array element, or generic parametric argument, but they may be null
    • Point is a subtype of Point?
    • cast between inline type and indirect type
    • Is implicitly a "NullableType"
    • enables compatibility with current generics via erasure to null-object object references
    • Arrays subtyping relationships: InlineType[] <: IndirectType[] <: Object[] <: Object
      • Widening conversions may be carried out from in the order above
      • Narrowing from an array of IndirectType to an InlineType is not possible.
      • This array covariance enables compatibility with existing API, especially generic type erasure
  • Inline types may not declare fields of its own type directly.  If A and B are inline classes, A may not contain a field B if B contains a field A.
    • There is a method to do this "indirectly" using the "?" operator, but it's value is still final. (since LW2
  • java.lang.Object methods:
    • javac automatically generates hashCode, equals, longHashCode and toString computed solely from the instance's state and not from its identity
    • javac does not clone(), finalize(), wait*), notify*() on inline type receivers
  • javac allows comparison of inline type using ==, != (since LW2)
    • By default this implies a test in the instance state (i.e. field by field "substitutability" test), as inline types have no identity (i.e. not a reference test).
  • Inline Types can not be assigned null, null can not be cast to or compared with inline types
    • With the exception of an "indirect" reference using the "?" operator. (since LW2)
  • Indirect Types cannot be type arguments in generic type parameterizations, type witnesses in generic method invocations, wildcard bounds
    • With the exception of an "indirect" reference using the "?" operator. (since LW2
  • Type migration, including partial recompilation is not supported.

...

  • Class new /modified API:
    • isInlineClass()
    • asPrimaryType()
    • asIndirectType() / isIndirectType()
    • asNullableType() / isNullableType()
    • getName() reflects the Q or L type signatures for arrays of inline types (since LW2)
      • In the .class file, the null-free inline type today is represented by a Q type signature, and the indirect projection is represented by an L type descriptor
    • newInstance() on an inline type throws NoSuchMethodException
  • setAccessible() on a an inline type throws InaccessibleObjectException
  • Initial core Reflection and VarHandles support in place (since LW2)
  • Attempts to build Reference objects with inline type will result in IllegalArgumentException

...

  • IllegalMonitorException thrown on attempts to synchronize or call wait(*) or notify*() on an inline type
  • ClassCircularityError thrown if loading an instance field of a an inline type which declares its own type either directly
  • Attempts to serialize an inline type will throw NotSerializableException
  • Cast from indirect type to inline type may result in NullPointerException (since LW2)
  • Attempts to store "null" into Inline type array will throw NullPointerException
    • Whereas null into indirect type array works as normal (since LW2)

...

  • platforms: x64 Linux, x64 Mac OS X, and x64 Windows
  • no support for atomic fields containing indirect types
  • no support for @Contended inline type fields
  • no AOT, CDS, ZGC, serviceability agent, JVMTI, limited JNI
  • -Xint and C2 only, no C1, no tiered-compilation, no Graal
  • unsafe field and array accessor APIs are not supported for inline types
    • low-level unsafe APIs are UNSAFE and will not be changed to support inline types
    • risks: If a an inline type has been flattened in a container, unsafe does not know the layout
      • getObject could return the first flattened element rather than the expected reference
  • interpreter is not optimized, focus is on JIT optimization
  • Some major changes to JIT compiler are still a work in progress

...

http://jdk.java.net/valhalla/

Change log:

  • jdk-14-valhalla+2-18 (20190704)
    • Minor bug fixes
  • jdk-14-valhalla+1-8 (20190628)
    • Initial LW2 prototype

...

A note on "?" operator and indirect projectsprojections

This is really only the beginning of a compatibility story, there is more to come (e.g. "null-default inline types"). Today it is a stop gap measure to enable use of current generics, until we get real generic specialization in place. New code should avoid indirect "?" like the plague and only use it for interfacing with code that must deal with "null" (e.g. current generics with type erasure). A good performance story does not exist for indirect, and it is not likely to improve too much in the future.

...