From 3b2a33806e86660ba9b675cc9a098195541326be Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Fri, 31 May 2024 17:14:12 +0100 Subject: [PATCH] Address review comments --- .../jdk/internal/foreign/LayoutPath.java | 2 +- .../classes/jdk/internal/foreign/Utils.java | 20 ++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java b/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java index 92b94fe612e24..ebd83d1c5da5f 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java +++ b/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java @@ -205,7 +205,7 @@ public VarHandle dereferenceHandle(boolean adapt) { String.format("Path does not select a value layout: %s", breadcrumbs())); } - VarHandle handle = Utils.makeSegmentViewVarHandle(valueLayout); + VarHandle handle = Utils.makeRawSegmentViewVarHandle(valueLayout); handle = MethodHandles.collectCoordinates(handle, 1, offsetHandle()); // we only have to check the alignment of the root layout for the first dereference we do, diff --git a/src/java.base/share/classes/jdk/internal/foreign/Utils.java b/src/java.base/share/classes/jdk/internal/foreign/Utils.java index 4e4f77ef0906b..8c339a8ce6215 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/Utils.java +++ b/src/java.base/share/classes/jdk/internal/foreign/Utils.java @@ -28,6 +28,7 @@ import java.lang.foreign.AddressLayout; import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemoryLayout.PathElement; import java.lang.foreign.MemorySegment; import java.lang.foreign.StructLayout; import java.lang.foreign.ValueLayout; @@ -89,15 +90,28 @@ public static MemorySegment alignUp(MemorySegment ms, long alignment) { return ms.asSlice(alignUp(offset, alignment) - offset); } - public static VarHandle makeSegmentViewVarHandle(ValueLayout layout) { + /** + * This method returns a raw var handle, that is, a var handle that does not perform any size + * or alignment checks. Such checks are added (using adaptation) by {@link LayoutPath#dereferenceHandle()}. + *

+ * We provide two level of caching of the generated var handles. First, the var handle associated + * to a {@link ValueLayout#varHandle()} call is cached inside a stable field of the value layout implementation. + * This optimizes common code idioms like {@code JAVA_INT.varHandle().getInt(...)}. A second layer of caching + * is then provided by this method: after all, var handles constructed by {@link MemoryLayout#varHandle(PathElement...)} + * will be obtained by adapting some raw var handle generated by this method. + * + * @param layout the value layout for which a raw memory segment var handle is to be created. + * @return a raw memory segment var handle. + */ + public static VarHandle makeRawSegmentViewVarHandle(ValueLayout layout) { final class VarHandleCache { private static final Map HANDLE_MAP = new ConcurrentHashMap<>(); } return VarHandleCache.HANDLE_MAP - .computeIfAbsent(layout.withoutName(), Utils::makeSegmentViewVarHandleInternal); + .computeIfAbsent(layout.withoutName(), Utils::makeRawSegmentViewVarHandleInternal); } - private static VarHandle makeSegmentViewVarHandleInternal(ValueLayout layout) { + private static VarHandle makeRawSegmentViewVarHandleInternal(ValueLayout layout) { Class baseCarrier = layout.carrier(); if (layout.carrier() == MemorySegment.class) { baseCarrier = switch ((int) ValueLayout.ADDRESS.byteSize()) {