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