MemoryAddress object changes once put into memory
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Tue Jan 14 17:12:48 UTC 2020
On 14/01/2020 16:58, Ty Young wrote:
>
> On 1/14/20 10:46 AM, Maurizio Cimadamore wrote:
>>
>> 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))
>
>
> IIRC no decision has been made regarding the mechanism of making
> ForeignUnsafe available and Netbeans isn't suggesting a class import.
> Which module do I need to add for that?
No decision has been made yet.
For now you will need something like
--add-exports=jdk.incubator.foreign/jdk.incubator.foreign.unsafe=<your
module>
>
>
> Or is there any other "safe" way of implementing multi-dimensional
> arrays that I'm not aware of?
It largely depends on how your implementation works - but if your
mutidimensional array is just a sparse collection of pointers to other
arrays with given size, which can live anywhere in memory, I don't think
there's much you can do safely (at least not on top of my head).
If you implement a more dense representation (e.g. like a tensor - where
elements are stored in a N1 * N2 * ... NM matrix) then you know by
construction that rows, columns, elements will always be bound by the
toplevel segment which contains the entire tensor. But a dense
representation doesn't need pointers, so the code would be very
different from the one you have.
Maurizio
>
>
>>
>> Maurizio
More information about the panama-dev
mailing list