From e99f6a65a8307e6b31a08a677914dfd20d46687f Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Fri, 31 May 2024 17:53:35 +0000 Subject: [PATCH] 8333236: Test java/foreign/TestAccessModes.java is timing out after passing Reviewed-by: jvernee --- .../jdk/internal/foreign/LayoutPath.java | 2 +- .../classes/jdk/internal/foreign/Utils.java | 28 +++++++++++++++++-- 2 files changed, 27 insertions(+), 3 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 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 HANDLE_MAP = new ConcurrentHashMap<>(); + } + return VarHandleCache.HANDLE_MAP + .computeIfAbsent(layout.withoutName(), Utils::makeRawSegmentViewVarHandleInternal); + } + + private static VarHandle makeRawSegmentViewVarHandleInternal(ValueLayout layout) { Class baseCarrier = layout.carrier(); if (layout.carrier() == MemorySegment.class) { baseCarrier = switch ((int) ValueLayout.ADDRESS.byteSize()) { @@ -108,7 +132,7 @@ public final class Utils { handle = MethodHandles.filterValue(handle, MethodHandles.explicitCastArguments(ADDRESS_TO_LONG, MethodType.methodType(baseCarrier, MemorySegment.class)), MethodHandles.explicitCastArguments(MethodHandles.insertArguments(LONG_TO_ADDRESS, 1, - pointeeByteSize(addressLayout), pointeeByteAlign(addressLayout)), + pointeeByteSize(addressLayout), pointeeByteAlign(addressLayout)), MethodType.methodType(MemorySegment.class, baseCarrier))); } return handle;