No segment method for MemoryAddress?
Ty Young
youngty1997 at gmail.com
Sat Aug 22 02:45:10 UTC 2020
On 8/21/20 4:03 AM, Maurizio Cimadamore wrote:
>
> On 21/08/2020 01:40, Ty Young wrote:
>>
>> On 8/20/20 4:43 PM, Maurizio Cimadamore wrote:
>>>
>>> On 20/08/2020 21:32, Ty Young wrote:
>>>> So, apparently the <MemoryAddress>.segment() method was removed and
>>>> now provides a seemingly redundant address() method:
>>>
>>> This was all described here:
>>>
>>> https://mail.openjdk.java.net/pipermail/panama-dev/2020-July/009928.html
>>>
>>>
>>> Basically, a MemoryAddress no longer has a link to a segment. An
>>> address is just a thin wrapper around an Object/long unsafe
>>> addressing pair.
>>>
>>> Addressable is mostly there so that _everything_ that can be
>>> converted to an address can be passed to a function. We use this in
>>> jextract, so that clients can avoid a lot of calls to
>>> ".baseAddress()". If you don't need it, you can ignore it.
>>
>>
>> I read that and came to that very conclusion as you give for the
>> reason. I thought it was a minor, optional API change and not
>> something that breaks the API's flow though which is why I never
>> bothered making a new JDK build.
>>
>>
>> I don't personally understand the logic here - It makes more sense(to
>> me, anyway) to talk in MemoryAddress(s) rather than MemorySegment(s),
>> MemoryAddress takes up heap representing what could be represented
>> using primitive longs(unless I'm missing something?), and you have
>> this address() method on MemoryAddress that presumably just returns
>> itself(?). The way it was before really wasn't bad, it just needed
>> some method name changes(baseAddress() -> address()).
>
> I think we should largely leave the address() method alone in this
> discussion. That is part of the Addressable interface, which is a way
> to abstract over MemorySegment, MemoryAddress, LibraryLookup.Symbol
> and VaList. It's totally orthogonal to the discussion.
>
> While the change might be surprising for people used to the way the
> API was, I think in reality is more natural to people coming to the
> API for the first time. Note that the recent "state" documents already
> explained things in that light. In general, if you want to dereference
> memory, its' way clearer if you do so by having a segment; a segment
> has spatial and temporal boundaries (which can make dereference safe).
> An address doesn't.
>
> Before this change we had a very subtle distinction between *checked*
> and *unchecked* addresses; that is, the segment() returned by an
> address might sometimes be NULL (which means no dereference, sorry).
> This made it extremely difficult to write libraries on top of the FMA,
> because whenever you accepted a MemoryAddress you had to ask: is this
> a MA which is dereference-able, or not? This was very visible as soon
> as we started to add some helper methods in the CSupport class.
>
> The new state is much cleaner: need to dereference? Then you need a
> segment. But sometimes a native library will "just" give you a
> MemoryAddress back; at which point you can either construct a segment
> out of it (using the restricted factory), or dereference it directly,
> by projecting it into a long offset (and using the _everything_
> segment as the base segment).
>
> Why not just using a long? Because we cannot represent heap addresses
> with just a long. An address is both an Object (base) and a long
> (offset); in case of a *native* address, the base is NULL and only the
> offset matters. But for an address into an heap array you need both.
> As for the "heap waste" argument, since now memory address is a dumb
> holder of two final fields (Object, long), making this an inline type
> is a no brainer, when Valhalla will allow us to do so.
Makes sense I guess, but it introduces issues for me. There really isn't
a great alternative to:
public MemoryAddress getAddress();
which my abstraction used extensively. MemorySegment can't be used
because of library symbols(which don't have segments) and doing:
public <E extends Addressable> E getAddressable();
doesn't work since depending purely on the interface will only ever get
me the lower Addressable bounds. Best solution I can come up with is
declaring a generic type at the interface level, using Addressable as
the lower bounds. Doing that increases the amount of generic type
declarations for static methods which are already decently sized:
public static <T, E extends NativeValue<T>> E
ofUnsafeValueLayout(MemoryAddress address, ValueLayout layout)
I guess I'll have to figure something out or bite the bullet and go with
an additional interface generic argument.
>
> Maurizio
>
>
>>
>>
>> I guess I'll be creating yet another abstraction interface
>> "NativeAddress" or something. I hope it doesn't get to the point
>> where I need to abstract everything about FMA.
>>
>>
>>>
>>> Maurizio
>>>
>>>
>>>>
>>>>
>>>> private final MemoryAddress address;
>>>>
>>>>
>>>> ...
>>>>
>>>>
>>>> this.address.address();
>>>>
>>>>
>>>> which has the Javadoc:
>>>>
>>>>
>>>> "Map this object into a MemoryAddress instance."
>>>>
>>>>
>>>> ...but it is already a MemoryAddress? What is going on here? How
>>>> are you supposed to get a segment from an address? Why is there a
>>>> seemingly redundant address() method?
>>>>
>>>>
>>>> Reading the Javadoc of Addressable:
>>>>
>>>>
>>>> "Represents a type which is addressable. An addressable type is one
>>>> which can be projected down to a memory address instance (see
>>>> address()). Examples of addressable types are MemorySegment,
>>>> MemoryAddress, LibraryLookup.Symbol and CSupport.VaList."
>>>>
>>>>
>>>> provides context on why the address() method exists but not why
>>>> segment() has been removed.
>>>>
>>>>
>>>> Personally, I think the address() method should be removed and the
>>>> components that make up a MemoryAddress be exposed instead if
>>>> possible, but that's my 2 cents.
>>>>
>>>>
>>>>
>>>>
>>>>
More information about the panama-dev
mailing list