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