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