Proposal: java.lang.runtime.Carrier
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Thu Mar 3 18:49:43 UTC 2022
Seems sensible.
As a possible "test", we could perhaps use this mechanism in the JDK
implementation of LambdaForms? We do have places where we spin "species"
classes:
https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java
(that said, maybe species classes contain a bit more than just data, so
perhaps that's a wrong fit - but anyway, worth talking a look for
possible code duplication).
Maurizio
On 03/03/2022 13:57, Jim Laskey wrote:
>
> We propose to provide a runtime /anonymous carrier class object
> generator/; *java.lang.runtime.Carrier*. This generator class is
> designed to share /anonymous classes/ when shapes are similar. For
> example, if several clients require objects containing two integer
> fields, then *Carrier* will ensure that each client generates carrier
> objects using the same underlying anonymous class.
>
> Providing this mechanism decouples the strategy for carrier class
> generation from the client facility. One could implement one class per
> shape; one class for all shapes (with an Object[]), or something in
> the middle; having this decision behind a bootstrap means that it can
> be evolved at runtime, and optimized differently for different situations.
>
>
> Motivation
>
> The String Templates JEP draft
> <https://bugs.openjdk.java.net/browse/JDK-8273943> proposes the
> introduction of a /TemplatedString/ object for the primary purpose of
> /carrying/ the /template/ and associated /values/ derived from a
> /template literal/. To avoid value boxing, early prototypes described
> these /carrier/objects using /per-callsite/ anonymous classes shaped
> by value types, The use of distinct anonymous classes here is
> overkill, especially considering that many of these classes are
> similar; containing one or two object fields and/or one or two
> integral fields. /Pattern matching/ has a similar issue when carrying
> the values for the /holes/ of a pattern. With potentially hundreds
> (thousands?) of template literals or patterns per application, we need
> to find an alternate approach for these /value carriers/.
>
>
> Description
>
> In general terms, the *Carrier* class simply caches anonymous classes
> keyed on shape. To further increase similarity in shape, the ordering
> of value types is handled by the API and not in the underlying
> anonymous class. If one client requires an object with one object
> value and one integer value and a second client requires an object
> with one integer value and one object value, then both clients will
> use the same underlying anonymous class. Further, types are folded as
> either integer (byte, short, int, boolean, char, float), long (long,
> double) or object. [We've seen that performance hit by folding the
> long group into the integer group is significant, hence the separate
> group.]
>
> The *Carrier* API uses MethodType parameter types to describe the
> shape of a carrier. This incorporates with the primary use case where
> bootstrap methods need to capture indy non-static arguments. The API
> has three static methods;
>
> |// Return a constructor MethodHandle for a carrier with components //
> aligning with the parameter types of the supplied methodType. static
> MethodHandle constructor(MethodType methodType) // Return a component
> getter MethodHandle for component i. static MethodHandle
> component(MethodType methodType, int i) // Return component getter
> MethodHandles for all the carrier's components. static MethodHandle[]
> components(MethodType methodType)|
>
>
> Examples
>
> |import java.lang.runtime.Carrier; ... // Define the carrier
> description. MethodType methodType =
> MethodType.methodType(Object.class, byte.class, short.class,
> char.class, int.class, long.class, float.class, double.class,
> boolean.class, String.class); // Fetch the carrier constructor.
> MethodHandle constructor = Carrier.constructor(methodType); // Create
> a carrier object. Object object =
> (Object)constructor.invokeExact((byte)0xFF, (short)0xFFFF, 'C',
> 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFFL, 1.0f / 3.0f, 1.0 / 3.0, true,
> "abcde"); // Get an array of accessors for the carrier object.
> MethodHandle[] components = Carrier.components(methodType); // Access
> fields. byte b = (byte)components[0].invokeExact(object); short s =
> (short)components[1].invokeExact(object); char c
> =(char)components[2].invokeExact(object); int i =
> (int)components[3].invokeExact(object); long l =
> (long)components[4].invokeExact(object); float f
> =(float)components[5].invokeExact(object); double d =
> (double)components[6].invokeExact(object); boolean tf
> (boolean)components[7].invokeExact(object); String s =
> (String)components[8].invokeExact(object)); // Access a specific
> field. MethodHandle component = Carrier.component(methodType, 3); int
> ii = (int)component.invokeExact(object);|
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20220303/fdb4ce40/attachment-0001.htm>
More information about the amber-spec-experts
mailing list