On Tue, 2 Apr 2024 15:04:40 GMT, Per Minborg <[email protected]> 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