RFR: 8329532: Add an internal MemoryLayout transformer
Maurizio Cimadamore
mcimadamore at openjdk.org
Tue Apr 16 10:35:41 UTC 2024
On Tue, 2 Apr 2024 15:04:40 GMT, Per Minborg <pminborg at 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
More information about the core-libs-dev
mailing list