[foreign-memaccess+abi] RFR: 8301360: Add dereference layout paths to memory layout API

Maurizio Cimadamore mcimadamore at openjdk.org
Mon Jan 30 21:43:21 UTC 2023


On Mon, 30 Jan 2023 18:43:12 GMT, Jorn Vernee <jvernee at openjdk.org> wrote:

>> Now that we have a more general way to attach target layouts to address layouts (see https://git.openjdk.org/panama-foreign/pull/775), it might be useful to add support for layout paths which perform dereference of a given address value. Consider this case:
>> 
>> 
>> struct b {
>>    int x;
>> };
>> 
>> struct a {
>>     struct b *b;
>> };
>> 
>> 
>> Here, our goal is to construct a layout path for "a->b.x".
>> 
>> To do this, we use a *dereference path element* (see `PathElement#dereferenceElement`). These comes in two flavors:
>> 
>> * no argument factory - this assumes that the address layout being dereferenced has some target layout set;
>> * layout argument factory - this assumes that the address layout being dereferenced does *not* have a target layout set (e.g. it is not always possible to associate a target layout, especially in cyclic cases like a -> b -> a).
>> 
>> When a dereference element is applied to an existing path, a var handle that fetches the address pointed to by the current path is pushed on the stack, and a new layout path is started. This way, dereference path can be used to "chain" together multiple layout paths. All the intermediate memory read operations occur using a *plain* get. For more complex access operation (e.g. if atomic access is required for the whole dereference chain), multiple var handles have to be obtained.
>> 
>> It is an error to pass a dereference path to other layout operations such as `select`, `byte/bitOffset[Handle]`.
>
> src/java.base/share/classes/java/lang/foreign/MemoryLayout.java line 658:
> 
>> 656:          * @return a path element which dereferences an address layout.
>> 657:          */
>> 658:         static PathElement dereferenceElement(MemoryLayout layout) {
> 
> This method needs to be restricted, I believe. Since it allows resizing a MemorySegment. The other overload of `dereferenceElement` is already covered because attaching a pointee layout to an address layout is restricted already.
> 
> Consider the following:
> 
> 
> StructLayout hasAddr = MemoryLayout.structLayout(ADDRESS.withName("addr"));
> 
> MemorySegment rawSeg = MemorySegment.allocateNative(0, SegmentScope.auto()); // inaccessible segment
> // rawSeg.get(JAVA_INT, 0); // not allowed
> MemorySegment addrHolder = MemorySegment.allocateNative(hasAddr, SegmentScope.auto());
> addrHolder.set(ADDRESS, 0, rawSeg); // fine
> VarHandle derefHandle = hasAddr.varHandle(groupElement("addr"), dereferenceElement(JAVA_INT));
> int x = derefHandle.get(addrHolder); // oops!
> 
> 
> Assuming I eye-balled this code correctly, I think this is problematic?

Sure - the layout accepting one needs to be restricted - I started off with only the other one (which doesn't need to be restricted), then added the layout accepting one, and forgot to add the restricted check. Any way - as a validation, do we agree that it is handy to have both forms? If you have a layout like A -> B -> A, there is no way to attach target layouts statically - which is the main reason why I added that variant.

-------------

PR: https://git.openjdk.org/panama-foreign/pull/776


More information about the panama-dev mailing list