On Tue, 2 Apr 2024 15:04:40 GMT, Per Minborg <pminb...@openjdk.org> wrote:

> This PR proposes to add an internal layout transformer that could be used to 
> transform MemoryLayout entities. For example, it would be possible to convert 
> a struct layout to use network order ((big-endian) instead of native byte 
> order (often little-endian). Another application is to remove naming 
> recursively for composite layouts when caching shapes etc.

src/java.base/share/classes/jdk/internal/foreign/layout/LayoutTransformers.java 
line 46:

> 44:  * A JDK-internal utility class that provides useful layout 
> transformations.
> 45:  */
> 46: public final class LayoutTransformers {

In my experience when thinking about this problem, I always found that writing 
a layout transformer as a method implemented by pattern matching is almost 
always a better choice. The problem with going down that path is that it's a 
little verbose in cases where no transform needs to occur. Let's consider the 
endianness case:


MemoryLayout setEndianness(MemoryLayout layout, ByteOrder order) {
     return switch (layout) {
           case ValueLayout vl -> yield vl.order(order);
           case SequenceLayout sl -> yield 
MemoryLayout.sequenceLayout(sl.elementCount(), 
setEndianness(sl.elementLayout(), order);
           case StructLayout stl -> yield 
MemoryLayout.structLayout(stl.memberLayouts().stream().map(e -> 
setEndianness(e, order));
           ...
}


The problem with this is that the arms where "nothing" happens need to draw a 
lot of attention, as they need to contain the code which recursively propagates 
the transform.

But what if we had a single utility like this:


MemoryLayout adaptContents(MemoryLayout, UnaryOperator<MemoryLayout>)


Which takes care of applying a transform recursively on the _contents_ of a 
nested layout (e.g. sequence layout element, or the members of a group layout). 
Then the above becomes:


MemoryLayout setEndianness(MemoryLayout layout, ByteOrder order) {
     return switch (layout) {
           case ValueLayout vl -> yield vl.order(order);
           default -> yield layout.adaptContents(e -> setEndianness(e, order));
     }
}


Which is quite simple.

And, the remove names transform can be even simpler:


MemoryLayout removeNames(MemoryLayout layout) {
     return layout.adaptContents(this::removeNames).withoutName();
}

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

PR Review Comment: https://git.openjdk.org/jdk/pull/18582#discussion_r1567127736

Reply via email to