MemoryAddress object changes once put into memory

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Tue Jan 14 16:46:33 UTC 2020


On 14/01/2020 16:38, Ty Young wrote:
>
> On 1/14/20 10:34 AM, Maurizio Cimadamore wrote:
>> If I understand correctly your question, this is to be expected. What 
>> is really happening is that you are serializing a MemoryAddress into 
>> a 'long' (its address) and save it into native memory. Since we're 
>> really only storing a 64-bit number, all the characteristics of a 
>> MemoryAddress are lost after a store - such as the spatial and 
>> temporal bounds.
>>
>> When you read that, later on, you just read a long, and the runtime 
>> will construct a MemoryAddress instance on top of that. Since no 
>> bound information is available, the runtime will resurrect that 
>> MemoryAddress as a Nothing-backed MemoryAddress. Which means the 
>> address will be unusable.
>>
>> But if you are serializing and deserializing segments you know, you 
>> can do a rebase after the deserialization (the get() operation), so 
>> that your address will become functionally equivalent to the one you 
>> started with.
>
>
> Ah, OK. Thanks for the clarification.
>
>
> What would you use to rebase the segment with? Obviously when I go to 
> reconstruct the array in Java all I have is what's stored at that same 
> point in the larger segment:
>
>
>     @Override
>     public Array<E> getValue(int index)
>     {
>         MemorySegment elementSegment = this.segment.asSlice(index*192, 
> 192);
>
>         MemorySegment addressSegment = elementSegment.asSlice(0, 64);
>         MemorySegment layoutSegment = elementSegment.asSlice(64, 64);
>         MemorySegment lengthSegment = elementSegment.asSlice(128, 64);
>
>         VarHandle addressHandle = 
> MemoryHandles.varHandle(MemoryAddress.class, ByteOrder.nativeOrder());
>         VarHandle layoutHandle = MemoryHandles.varHandle(long.class, 
> ByteOrder.nativeOrder());
>         VarHandle lengthHandle = MemoryHandles.varHandle(long.class, 
> ByteOrder.nativeOrder());
>
>         MemoryAddress address = 
> (MemoryAddress)addressHandle.get(addressSegment.baseAddress());
>         long layout = 
> (long)layoutHandle.get(layoutSegment.baseAddress());
>         long length = 
> (long)lengthHandle.get(lengthSegment.baseAddress());
>
>         return new MemoryArray(address, layout, length);
>     }
>
>
> So how do you go about rebasing something like this?

In your case there's not much you can do, other than to rebase to an 
unchecked segment - after all you know the length of the saved array 
(because you are storing and recovering it), so you could do:

MemoryAddress newAddress = 
address.rebase(ForeignUnsafe.ofNativeUnchecked(address, length))

Maurizio

>
>
>>
>> Maurizio
>>
>>
>> On 14/01/2020 16:18, Ty Young wrote:
>>> Hi,
>>>
>>>
>>> As mentioned in a different thread, a MemoryAccess instance changes 
>>> once put into memory. Here are all the relevant bits from the class:
>>>
>>>
>>>     private final MemorySegment segment;
>>>     private final SequenceLayout sequenceLayout;
>>>
>>>     public ArrayArray(long length)
>>>     {
>>>         this.sequenceLayout = MemoryLayout.ofSequence(length*24, 
>>> MemoryLayouts.JAVA_LONG);
>>>
>>>         this.segment = 
>>> MemorySegment.allocateNative(this.sequenceLayout);
>>>     }
>>>
>>>
>>>     @Override
>>>     public void setValue(int index, Array<E> value)
>>>     {
>>>         MemorySegment elementSegment = 
>>> this.segment.asSlice(index*192, 192);
>>>
>>>         MemorySegment addressSegment = elementSegment.asSlice(0, 64);
>>>         MemorySegment layoutSegment = elementSegment.asSlice(64, 64);
>>>         MemorySegment lengthSegment = elementSegment.asSlice(128, 64);
>>>
>>>         VarHandle addressHandle = 
>>> MemoryHandles.varHandle(MemoryAddress.class, ByteOrder.nativeOrder());
>>>         VarHandle layoutHandle = MemoryHandles.varHandle(long.class, 
>>> ByteOrder.nativeOrder());
>>>         VarHandle lengthHandle = MemoryHandles.varHandle(long.class, 
>>> ByteOrder.nativeOrder());
>>>
>>>         addressHandle.set(addressSegment.baseAddress(), 
>>> value.getAddress());
>>>         layoutHandle.set(layoutSegment.baseAddress(), 
>>> value.getElementSequenceLayout().elementLayout().bitSize());
>>>         lengthHandle.set(lengthSegment.baseAddress(), 
>>> value.getLength().getAsLong());
>>>     }
>>>
>>>
>>>     ...
>>>
>>>
>>> As shown here, the address of the array being set is being stored in 
>>> the addressSegment. However, once read back into Java it changes so 
>>> that both it's ID changes, has an offset, and its limit is zero when 
>>> it should be 64 even when read back in using the same VarHandle in 
>>> setValue method. Am I doing something wrong(like no rebasing?) or is 
>>> there something else going on?
>>>


More information about the panama-dev mailing list