abstract layouts
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Fri Aug 13 00:59:08 UTC 2021
I will not reply to this thread any further. Not only the discussion is
not productive, but I find some of the claims offensive, not to me (I
can take it :-) ), but to everyone else who has contributed in this
mailing list thus far. If this is your idea of "contributing", I think
we must live on different planets.
Maurizio
On 13/08/2021 01:28, Ty Young wrote:
>
> On 8/12/21 4:32 PM, Maurizio Cimadamore wrote:
>>
>> On 12/08/2021 19:49, Ty Young wrote:
>>> My understanding is that if:
>>>
>>>
>>> -XX:+UnlockExperimentalVMOptions
>>> -XX:+TrustFinalNonStaticFields
>>>
>>>
>>> are set then non-static final fields are optimized. Is that not true?
>> Well, that's not my idea of "supported" - but ok.
>>>
>>>
>>> Anyway, I don't want to hear anything about what I'm doing being
>>> "problematic" when the whole reason I'm doing what I'm doing is
>>> because of issues with FMA/FFI API. If you don't like it then open
>>> up layouts, otherwise I really don't want to hear it. It was well
>>> known that attributes were going to be used(and was even encouraged)
>>> for this purpose so I have no clue why all of a sudden it's a bad
>>> idea in your mind. I knew it was less optimal idea well over a year
>>> ago, but it's not like I have the power to change it.
>>
>> There are many things that are wrong with this statement. But let me
>> back off.
>>
>>
>> In general, when the design of an API evolves, one learn more things.
>> The main reason why layout attributes were added in the first place
>> was (solely) to support metadata which would help the linker going
>> about its business. Then, since we were there, we decided to open up
>> the machinery.
>>
>> I think it is legitimate, after some time, to ask the question of
>> who's using layout attributes (apart from the linker itself) and why.
>> If it turns out that there's little uses for the attribute API, and
>> that the few uses there are can be done in other ways, then I think
>> it is a legitimate question to ask whether we want to expose layouts
>> attributes in the final API.
>>
>> As for "why not just use inheritance" which has been brought up other
>> times too, I gave an explanation earlier today; having immutable
>> classes with withers, and have them also extensible via subclassing
>> is not something that is very common. It's either one or the other,
>> typically. So, it's not like there's an obvious solution to this
>> problem which we are failing for some reason to see - it's either:
>>
>> 1. keep attributes as they are
>> 2. drop attributes and allow inheritance (but with the 99% chance of
>> having broken subclasses)
>> 3. drop attributes period
>>
>> I don't think (2) is such a great place to be. So it's either (1) or
>> (3). Your use case doesn't shift the balance one way or another, as
>> you can do same things even w/o layout attributes, sorry. But maybe
>> somebody else has a different use case, in which case I'd be
>> interested to hear.
>
>
> The gaslighting is strong in this statement. You have never up to this
> point even indicated that attributes may be removed. In fact, up to
> this point, you have at the very least implied that attributes were
> going to be a thing for higher-level APIs that need decorating layouts
> in order to work, never that it was solely for linker that I can
> remember. You yourself claimed that higher level APIs would be
> supported, knowing that layouts and their attributes were used in this
> exact same way as it is here because the source code was public at the
> time.
>
>
> And to add insult to injury you're suggesting that there is some
> magical way in which I can support all use cases by... doing what?
> Creating explicit dereference types for every standard type? How deep
> should I go with that? 1 explicit dereference class for each type? 2?
> 3? 4? 10? For someone who refuses to add 3 tiny and simple methods and
> a small API change and doesn't seem to want to breakout GroupLayout
> into StructLayout and UnionLayout, that suggestion is a bit ironic.
>
>
> I've probably used Panama since the beginning, have promoted it, have
> one of the few real-world actual applications that use it, and have
> reported bugs that somehow people working on Panama full time weren't
> able to find *because* I have an actual application that uses Panama
> and not just a few classes that are modified from using
> Unsafe/ByteBuffers, which seems to be what everyone else is doing and
> **cannot** be compared to my projects. To claim that my use case is
> somehow not valid and gaslight out of such a small sample side(1/1,
> AFAIK) sure is a slap in the face. Seems to be a trend with the death
> of the system wide JRE(not really, there are JREs and programs that
> need them but we'll pretend otherwise) and the deprecation of
> SecurityManager, so I guess at least you're being consistent.
>
>
> Is there even anyone else using Project Panama in a real-world GUI
> application or something? Even internally at Oracle? If not, FFI
> support should be removed too. Since so few people are using it, It's
> too much API baggage for too little return! If a sample size of 1
> outside of Oracle isn't enough to keep attributes then surely it's not
> enough to keep FFI support, right? I mean, JNI/JNA/GraalVM/other
> projects exist already, why complicate things further? It's such a
> corner-case and not worth supporting.
>
>
>>
>> (For the records, when thinking about (3) I also did an exercise and
>> I went back and reimplemented jextract - which uses 4-5 different
>> layout attributes. Turns out none of them was _really_ needed and in
>> fact the code ended up cleaner w/o them).
>
>
> Great! Don't remember it ever being said it was explicitly for
> jextract until... now? Over a year(2? So long ago!) later?
>
>
>>
>> Maurizio
>>
>>
>>>
>>>
>>>
>>> On 8/12/21 1:27 PM, Maurizio Cimadamore wrote:
>>>> I think what you are trying to do is problematic.
>>>>
>>>> You have NativeInteger, and NativeInteger has a static layout. You
>>>> want to attach other static information (method handles). The
>>>> information has to be _static_ if you want to have any chance of
>>>> the JVM to optimize all that.
>>>>
>>>> But, with attributes, you are storing the MHs in a map - so, not
>>>> static. Even if you could declare your own layout class, storing
>>>> the method handles in final fields of the custom layout won't help
>>>> (if the final fields aren't trusted by the JVM, which they are not,
>>>> except for special provisions for some JDK packages).
>>>>
>>>> In other words, I don't see a path (besides spinning a new
>>>> NativePointer64 instance which is exclusively dedicated to
>>>> NativeInteger) by which you can get performance when accessing the
>>>> NativeInteger from the NativePointer64.
>>>>
>>>> But, if you don't care much about inlining/performance, then maybe
>>>> you can just use a ClassValue and store all the MethodHandles
>>>> related to NativeInteger in there? That is going to provide similar
>>>> (if not better) performance than those with layout attributes.
>>>>
>>>> I guess what I'm trying to say is that, unless I misunderstood your
>>>> example, it seems another case of "layout attributes are attractive
>>>> nuisance" - e.g. once they are there, one is tempted to just inject
>>>> stuff into layouts, but you already have custom classes wrapping
>>>> layouts, so why don't you associate the (static) metadata with the
>>>> classes, rather than the layouts?
>>>>
>>>> Maurizio
>>>>
>>>> On 12/08/2021 19:00, Ty Young wrote:
>>>>> Because it's needed for a NativePointer64 type:
>>>>>
>>>>>
>>>>> NativePointer64<NativeInteger> intPointer = new
>>>>> NativePointer64<>(NativeInteger.LAYOUT);
>>>>>
>>>>>
>>>>> NativeInteger has 3 MethodHandles embedded into it, one which
>>>>> accepts nothing(safe), one which accepts a MemorySegment(unsafe),
>>>>> and one which accepts a MemoryAddress(unsafe, what is used by
>>>>> NativePointer64). NativePointer then takes the given layout,
>>>>> embeds it inside of itself, then reads it later when getting the
>>>>> dereferenced value. Doing this generates garbage because of
>>>>> Optional since the NativePointer64.LAYOUT needs to have
>>>>> NativeInteger embedded inside of it, which then needs to be
>>>>> resolved according to a type attribute, e.g. enum, pointer,
>>>>> number. It's wasteful(in terms of memory) and slow(have to go
>>>>> through a tree of static methods to resolve). Layouts being opened
>>>>> up would help.
>>>>>
>>>>>
>>>>>
>>>>> On 8/12/21 8:39 AM, Maurizio Cimadamore wrote:
>>>>>> May I suggest, for the benefit of the conversation, that instead
>>>>>> of focusing on the _hows_ we focus instead on the _whys_ ?
>>>>>>
>>>>>> E.g. "I'd like to decorate a layout with information X and Y,
>>>>>> because I use these information in order to do Z"
>>>>>>
>>>>>> In other words, by having a full picture of what you are trying
>>>>>> to do we might understand better what the requirements really are.
>>>>>>
>>>>>> Thanks
>>>>>> Maurizio
>>>>>>
>>>>>> On 12/08/2021 14:12, Maurizio Cimadamore wrote:
>>>>>>>
>>>>>>> On 12/08/2021 12:24, Ty Young wrote:
>>>>>>>> I'd very much like it if layouts were opened up and non-sealed.
>>>>>>>> It would allow for less wasteful(no Optional) and faster
>>>>>>>> code(no HashMap, things can be final).
>>>>>>> I agree that would work better.
>>>>>>>
>>>>>>>> It also would be nice if GroupLayout was removed and replaced
>>>>>>>> with StructLayout and UnionLayout, or used as a shared/common
>>>>>>>> interface/class for them.
>>>>>>> That is largely orthogonal and irrelevant in the discussion
>>>>>>> we're having here.
>>>>>>>>
>>>>>>>>
>>>>>>>> I feel like the with* issues could be fixed with generics, e.g.:
>>>>>>>>
>>>>>>>>
>>>>>>>> public interface MemoryLayout<L extends MemoryLayout<?>> {
>>>>>>>>
>>>>>>>> public L withName(String name);
>>>>>>>>
>>>>>>>> }
>>>>>>>
>>>>>>> I don't think this solves much - as you will have, likely:
>>>>>>>
>>>>>>> ValueLayout extends MemoryLayout<ValueLayout>
>>>>>>>
>>>>>>> At which point you're back to square one - if you define
>>>>>>> `TyLayout extends ValueLayout`, there's nothing forcing you to
>>>>>>> override withName.
>>>>>>>
>>>>>>> I did experiments adding generic types to all layouts two years
>>>>>>> ago and honestly, it doesn't work very well. About 99% of the
>>>>>>> times, the most helpful thing the client has to say about a
>>>>>>> layout is MemoryLayout<?>, which seems like forcing 99% of the
>>>>>>> users to use generics because 1% of use cases might need them.
>>>>>>> But that's beside the point - generics do not solve the problem
>>>>>>> I was talking about. Also, in my experience, having f-bounded
>>>>>>> type variables in hierarchies works very well when you have one
>>>>>>> top class and a single level of leaves (which are all peers). It
>>>>>>> works much less when you have to start defining sub-hierarchies
>>>>>>> in the leaves - because either the intermediate nodes are
>>>>>>> conscious about the type variables and leave them open (leading
>>>>>>> to very verbose and borderline uncomprehensible generic
>>>>>>> declarations), or they fix the type variables, in which case the
>>>>>>> leaves will not take advantage of the f-bound, and you'll be
>>>>>>> back in no-generic-land.
>>>>>>>
>>>>>>>
>>>>>>>>
>>>>>>>> All of the basic layout types should be interfaces, not classes
>>>>>>>> IMO. Basic implementations could be put in a non-exported
>>>>>>>> package. Users can get a basic implementation from MemoryLayout
>>>>>>>> static methods, as they do now.
>>>>>>> Again, this seems a bit of a shallow comment. We can turn
>>>>>>> layouts from interface to classes in 2 minutes, by doing a
>>>>>>> targeted refactoring. But again, whether classes or interfaces,
>>>>>>> the problem I pointed out is still there and is the one we'd
>>>>>>> need to solve to be able to let clients to subclass layouts freely.
>>>>>>>>
>>>>>>>>
>>>>>>>> I don't think what I'm proposing could be done with static
>>>>>>>> decorator methods. The information being added as attributes
>>>>>>>> include MethodHandles for the class's constructor, e.g. a
>>>>>>>> constructor MethodHandle for a NativeInteger class, something
>>>>>>>> that specific can only be done at the class level I think.
>>>>>>>
>>>>>>> Well, the original proposal was to add a bunch of methods:
>>>>>>>
>>>>>>> * MemoryLayout::isAbstract
>>>>>>> * MemroyLayout::asAbstract
>>>>>>> * MemoryLayout::unfilledAttributes
>>>>>>>
>>>>>>> If we have layout attributes (like we do in today's API), there
>>>>>>> is no need for these methods to _be_ in MemoryLayout. They can
>>>>>>> be static methods taking a layout, defined wherever you want.
>>>>>>> Just use a special name to encode the attribute names - e.g.
>>>>>>> "abstract/foo" - then:
>>>>>>>
>>>>>>> * isAbstract --> does the layout have any attribute whose name
>>>>>>> starts with "abstract/" which are set to null?
>>>>>>> * asAbstract --> encode the attribute names to use the
>>>>>>> "abstract/" prefix
>>>>>>> * unfilledAttributes -> get all the attributes whose name start
>>>>>>> with "abstract/" and return those that have no value set
>>>>>>>
>>>>>>> Maurizio
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
More information about the panama-dev
mailing list