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 92b94fe612e..ebd83d1c5da 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 class LayoutPath { 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 f05666b88b6..2ed65e3dd04 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 @@ package jdk.internal.foreign; 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; @@ -37,6 +38,8 @@ import java.lang.invoke.MethodType; import java.lang.invoke.VarHandle; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; import jdk.internal.access.SharedSecrets; @@ -87,7 +90,28 @@ public final class Utils { 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
+ * with 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