I think we need to separate goals (optimization) from mechanism (syntax).

The optimizations you want to support seem to be exposing more flattening possibilities when an interface is sealed to a union of values, and especially one such class.  Which is a fine goal.

But if an interface is sealed to a union of values, the compiler already knows that, and can issue a preload request anyway.

If it turns out that later a `value` modifier has benefit _to the user_, we can consider adding it later.  But right now, this seems like extrapolating syntax from no implementation examples.



On 1/22/2024 1:34 PM, fo...@univ-mlv.fr wrote:


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

    *From: *"Dan Heidinga" <dan.heidi...@oracle.com>
    *To: *"Remi Forax" <fo...@univ-mlv.fr>, "daniel smith"
    <daniel.sm...@oracle.com>
    *Cc: *"valhalla-spec-experts" <valhalla-spec-expe...@openjdk.java.net>
    *Sent: *Monday, January 22, 2024 4:48:56 PM
    *Subject: *Re: Simplifying 'value' and 'identity'


Hello,


    Snip


    >
    > Interfaces: all interfaces can be implemented by value classes
    and identity
    > classes. Full stop. If you have a particular need to limit the
    kinds of
    > implementing classes, you can use a sealed interface and provide the
    > implementation yourself, or you can make it an informal part of
    the contract.
    > But, like access control, synchronization, and other fine-grained,
    > implementation-oriented features, identity is not something
    interfaces can
    > explicitly control.
    >
    > This approach has a two-state categorization scheme for classes
    expressed with
    > one keyword ('value' and identity). This corresponds to one JVM flag
    > (ACC_IDENTITY, for {reasons}). Interfaces have only one state.
    >
    > What do we lose?
    > - You can't force an abstract class/interface to be implemented
    by *only* value
    > classes
    > - You can't force an interface to be implemented by *only*
    identity classes
    > - You can't declare an abstract class or interface whose type
    will refuse to
    > support the 'synchronized' keyword
    >
    > I don't think any of these are enough to justify the extra costs
    of 3 states or
    > an 'identity' keyword. (For awhile, I was considering keeping
    around the
    > 'identity' keyword, just for the purpose of interfaces. But, eh,
    nobody is
    > going to use it.)

    Removing the 'identity' keyword is a good things, but i'm not so
    sure about not allowing users to declare a value interface,
    because i think that sealing the interface does not convey the
    right semantics.

    The problem is that in the future, a VM may want to flatten a
    sealed interface (with all its subtypes being value type),
    currently this is possible on stack but not on heap because '!'
    can not be used on anything but a value class.

    I’m not clear on how this would work at the VM level.  To flatten
    on heap we need a single known layout that we can embed in the
    containing object / array.  If we added value interfaces back into
    the language, we’d still be unable to know the field layout to
    embed in the containing object.


If the interface is preloaded, the VM has enough information to compute the tagged union. But storing on heap is IMO harder than reserving registers on stack + discriminator (the real class | null).

    An interface that is sealed to a single value class may be a good
    candidate for layout heroics (and in some distance future, maybe
    an interface that is sealed to a small set of layouts could be
    flattened), but in both cases, the key determinate is that the
    interface is sealed to a set of value classes.  Whether the
    interface is marked as value or not is irrelevant.


Currently, the VM will no try to flatten something which is not explicitly marked by a user as 'value'. I think it should be the same for sealed interfaces, the user should ask by tagging it as 'value' for the VM to consider it as a value interface.
It will make the performance more predictable from the user POV.



    I think we should allow an interface to be prefixed by "value" so
    - the compiler adds the interface in the Preload attribute
    - '!' is allowed on that interface (in that case all subtypes must
    be either a value interface or a value class with an implicit
    constructor)

    Guidance on when to add a class to the preload attribute is
    something that still needs to be worked out. A good first
    approximation is anywhere we had put a “Q” descriptor is a good
    candidate but there may be others (like the sealed interface case)
    that are interesting.


Being in the Preload attribute or not is something a user should be able to predict IMO and not something magic that the compiler may or may not do.

    --Dan


regards,
Rémi



    regards,
    Rémi


Reply via email to