From 36240f8c4d08d259b78d85af73278da5d697da5a Mon Sep 17 00:00:00 2001 From: Yudi Zheng Date: Thu, 17 Oct 2024 16:07:55 +0200 Subject: [PATCH] Adapt JDK-8338383: Implementation of Synchronize Virtual Threads without Pinning --- .../hotspot/GraalHotSpotVMConfig.java | 9 +++- .../meta/HotSpotGraphBuilderPlugins.java | 23 ++++++++ .../replacements/HotSpotReplacementsUtil.java | 19 +++++++ .../hotspot/replacements/MonitorSnippets.java | 54 ++++++++++++------- .../methodhandles/MethodHandleFeature.java | 12 +++-- 5 files changed, 94 insertions(+), 23 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java index 49db5ec2be51..37a75490360d 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java @@ -307,6 +307,8 @@ public final int arrayOopDescLengthOffset() { public final int threadCarrierThreadObjectOffset = getFieldOffset("JavaThread::_threadObj", Integer.class, "OopHandle"); public final int threadScopedValueCacheOffset = getFieldOffset("JavaThread::_scopedValueCache", Integer.class, "OopHandle"); + public final int javaThreadLockIDOffset = getFieldOffset("JavaThread::_lock_id", Integer.class, "int64_t", -1, JDK >= 24); + public final int threadIsInVTMSTransitionOffset = getFieldOffset("JavaThread::_is_in_VTMS_transition", Integer.class, "bool"); public final int threadIsInTmpVTMSTransitionOffset = getFieldOffset("JavaThread::_is_in_tmp_VTMS_transition", Integer.class, "bool", -1, JDK == 21); public final int threadIsDisableSuspendOffset = getFieldOffset("JavaThread::_is_disable_suspend", Integer.class, "bool", -1, JDK >= 22); @@ -381,13 +383,16 @@ public int threadLastJavaFpOffset() { public final int lockMaskInPlace = getConstant("markWord::lock_mask_in_place", Integer.class); public final int unlockedValue = getConstant("markWord::unlocked_value", Integer.class); public final int monitorValue = getConstant("markWord::monitor_value", Integer.class); + public final int ageMaskInPlace = getConstant("markWord::age_mask_in_place", Integer.class); + public final int unusedMark = getConstant("markWord::marked_value", Integer.class); // This field has no type in vmStructs.cpp - public final int objectMonitorOwner = getFieldOffset("ObjectMonitor::_owner", Integer.class, null); + public final int objectMonitorOwner = getFieldOffset("ObjectMonitor::_owner", Integer.class, JDK >= 24 ? "int64_t" : null); public final int objectMonitorRecursions = getFieldOffset("ObjectMonitor::_recursions", Integer.class, "intptr_t"); public final int objectMonitorCxq = getFieldOffset("ObjectMonitor::_cxq", Integer.class, "ObjectWaiter*"); public final int objectMonitorEntryList = getFieldOffset("ObjectMonitor::_EntryList", Integer.class, "ObjectWaiter*"); - public final int objectMonitorSucc = getFieldOffset("ObjectMonitor::_succ", Integer.class, "JavaThread*"); + public final int objectMonitorSucc = getFieldOffset("ObjectMonitor::_succ", Integer.class, JDK >= 24 ? "int64_t" : "JavaThread*"); + public final int objectMonitorStackLocker = getFieldOffset("ObjectMonitor::_stack_locker", Integer.class, "BasicLock*"); public final int markWordNoHashInPlace = getConstant("markWord::no_hash_in_place", Integer.class); public final int markWordNoLockInPlace = getConstant("markWord::no_lock_in_place", Integer.class); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index ca510da47e28..51f118a855e7 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -45,6 +45,7 @@ import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HOTSPOT_JAVA_THREAD_CONT_ENTRY; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HOTSPOT_JAVA_THREAD_SCOPED_VALUE_CACHE_HANDLE_LOCATION; +import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_LOCK_ID_LOCATION; import static jdk.graal.compiler.java.BytecodeParserOptions.InlineDuringParsing; import static jdk.graal.compiler.nodes.ConstantNode.forBoolean; import static jdk.graal.compiler.nodes.ProfileData.BranchProbabilityData.injected; @@ -728,6 +729,13 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec b.add(new WriteNode(handleAddress, HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION, thread, barrierSet.writeBarrierType(HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION), MemoryOrderMode.PLAIN)); + if (JavaVersionUtil.JAVA_SPEC >= 24) { + GraalError.guarantee(config.javaThreadLockIDOffset != -1, "JavaThread::_lock_id should have been exported"); + // Change the lock_id of the JavaThread + ValueNode tid = helper.loadField(thread, helper.getField(b.getMetaAccess().lookupJavaType(Thread.class), "tid")); + OffsetAddressNode address = b.add(new OffsetAddressNode(javaThread, helper.asWord(config.javaThreadLockIDOffset))); + b.add(new JavaWriteNode(JavaKind.Long, address, JAVA_THREAD_LOCK_ID_LOCATION, tid, BarrierType.NONE, false)); + } if (HotSpotReplacementsUtil.supportsVirtualThreadUpdateJFR(config)) { b.add(new VirtualThreadUpdateJFRNode(thread)); } @@ -955,6 +963,21 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec } }); } + + if (JavaVersionUtil.JAVA_SPEC >= 24) { + r.registerConditional(config.javaThreadLockIDOffset != -1, new InvocationPlugin("setLockId", Receiver.class, long.class) { + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode tid) { + try (HotSpotInvocationPluginHelper helper = new HotSpotInvocationPluginHelper(b, targetMethod, config)) { + receiver.get(true); + CurrentJavaThreadNode javaThread = b.add(new CurrentJavaThreadNode(helper.getWordKind())); + OffsetAddressNode address = b.add(new OffsetAddressNode(javaThread, helper.asWord(config.javaThreadLockIDOffset))); + b.add(new JavaWriteNode(JavaKind.Long, address, JAVA_THREAD_LOCK_ID_LOCATION, tid, BarrierType.NONE, false)); + } + return true; + } + }); + } } private static ResolvedJavaType resolveTypeAESCrypt(ResolvedJavaType context) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotReplacementsUtil.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotReplacementsUtil.java index a33037501696..a71517b2b78a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotReplacementsUtil.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotReplacementsUtil.java @@ -315,6 +315,8 @@ public static Object getPendingException(Word thread) { public static final LocationIdentity JAVA_THREAD_CARRIER_THREAD_OBJECT_LOCATION = NamedLocationIdentity.mutable("JavaThread::_threadObj"); + public static final LocationIdentity JAVA_THREAD_LOCK_ID_LOCATION = NamedLocationIdentity.mutable("JavaThread::_lock_id"); + public static final LocationIdentity JAVA_THREAD_OSTHREAD_LOCATION = NamedLocationIdentity.mutable("JavaThread::_osthread"); public static final LocationIdentity JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION = NamedLocationIdentity.mutable("JavaThread::_held_monitor_count"); @@ -504,6 +506,11 @@ public static int monitorValue(@InjectedParameter GraalHotSpotVMConfig config) { return config.monitorValue; } + @Fold + public static int unusedMark(@InjectedParameter GraalHotSpotVMConfig config) { + return config.unusedMark; + } + @Fold public static int objectMonitorOwnerOffset(@InjectedParameter GraalHotSpotVMConfig config) { return config.objectMonitorOwner; @@ -529,6 +536,11 @@ public static int objectMonitorSuccOffset(@InjectedParameter GraalHotSpotVMConfi return config.objectMonitorSucc; } + @Fold + public static int objectMonitorStackLockerOffset(@InjectedParameter GraalHotSpotVMConfig config) { + return config.objectMonitorStackLocker; + } + /** * Mask for a biasable, locked or unlocked mark word. It is the least significant 3 bits prior * to Java 18 (1 bit for biased locking and 2 bits for stack locking or heavy locking), and 2 @@ -679,6 +691,8 @@ public static int secondarySupersOffset(@InjectedParameter GraalHotSpotVMConfig public static final LocationIdentity OBJECT_MONITOR_SUCC_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_succ"); + public static final LocationIdentity OBJECT_MONITOR_STACK_LOCKER_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_stack_locker"); + @Fold public static int lockMetadataOffset(@InjectedParameter GraalHotSpotVMConfig config) { return config.basicLockMetadataOffset; @@ -689,6 +703,11 @@ static int heldMonitorCountOffset(@InjectedParameter GraalHotSpotVMConfig config return config.threadHeldMonitorCountOffset; } + @Fold + static int javaThreadLockIDOffset(@InjectedParameter GraalHotSpotVMConfig config) { + return config.javaThreadLockIDOffset; + } + @Fold static int javaThreadLockStackTopOffset(@InjectedParameter GraalHotSpotVMConfig config) { return config.threadLockStackOffset + config.lockStackTopOffset; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/MonitorSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/MonitorSnippets.java index 9bbdbbac6112..fdde3409029c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/MonitorSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/MonitorSnippets.java @@ -34,6 +34,7 @@ import static jdk.graal.compiler.hotspot.nodes.VMErrorNode.vmError; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.BASICLOCK_METADATA_LOCATION; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION; +import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_LOCK_ID_LOCATION; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_LOCK_STACK_LOCATION; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_LOCK_STACK_TOP_LOCATION; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_OM_CACHE_LOCATION; @@ -45,10 +46,12 @@ import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_ENTRY_LIST_LOCATION; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_OWNER_LOCATION; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_RECURSION_LOCATION; +import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_STACK_LOCKER_LOCATION; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_SUCC_LOCATION; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.diagnoseSyncOnValueBasedClasses; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.heldMonitorCountOffset; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.isCAssertEnabled; +import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.javaThreadLockIDOffset; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.javaThreadLockStackEndOffset; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.javaThreadLockStackTopOffset; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.javaThreadOomCacheOffset; @@ -72,6 +75,7 @@ import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.shouldUseKlassMiscFlags; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.unlockedValue; +import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.unusedMark; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.useLightweightLocking; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.useObjectMonitorTable; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.useStackLocking; @@ -90,6 +94,7 @@ import static jdk.graal.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; import static jdk.graal.compiler.replacements.nodes.CStringConstant.cstring; import static org.graalvm.word.LocationIdentity.any; +import static org.graalvm.word.WordFactory.nullPointer; import static org.graalvm.word.WordFactory.unsigned; import static org.graalvm.word.WordFactory.zero; @@ -230,7 +235,9 @@ public static void monitorenter(Object object, KlassPointer hub, @ConstantParame } if (tryFastPathLocking(object, stackPointerRegister, trace, counters, mark, lock, thread)) { - incrementHeldMonitorCount(thread); + if (JavaVersionUtil.JAVA_SPEC == 21 || useStackLocking(INJECTED_VMCONFIG)) { + incrementHeldMonitorCount(thread); + } } else { // slow-path runtime-call monitorenterStubC(MONITORENTER, object, lock); @@ -290,6 +297,10 @@ private static boolean tryEnterInflated(Object object, Word lock, Word mark, Wor cacheIter = cacheIter.add(stepSize); } } + + // Cache the monitor for unlock before trashing box. On failure to acquire + // the lock, the slow path will reset the entry accordingly (see CacheSetter). + writeMonitorCache(lock, monitor); } else { // mark is a pointer to the ObjectMonitor + monitorMask monitor = mark.subtract(monitorValue(INJECTED_VMCONFIG)); @@ -297,15 +308,16 @@ private static boolean tryEnterInflated(Object object, Word lock, Word mark, Wor int ownerOffset = objectMonitorOwnerOffset(INJECTED_VMCONFIG); Word owner = monitor.readWord(ownerOffset, OBJECT_MONITOR_OWNER_LOCATION); + Word newOwner = JavaVersionUtil.JAVA_SPEC == 21 ? thread : thread.readWord(javaThreadLockIDOffset(INJECTED_VMCONFIG), JAVA_THREAD_LOCK_ID_LOCATION); + // The following owner null check is essential. In the case where the null check fails, it // avoids the subsequent bound-to-fail CAS operation, which would have caused the // invalidation of the L1 cache of the core that runs the lock owner thread, and thus causes // the lock to be held slightly longer. - if (probability(FREQUENT_PROBABILITY, owner.equal(0))) { - // it appears unlocked (owner == 0) - if (probability(FREQUENT_PROBABILITY, monitor.logicCompareAndSwapWord(ownerOffset, owner, thread, OBJECT_MONITOR_OWNER_LOCATION))) { + if (probability(FREQUENT_PROBABILITY, owner.equal(nullPointer()))) { + // it appears unlocked (owner == null) + if (probability(FREQUENT_PROBABILITY, monitor.logicCompareAndSwapWord(ownerOffset, owner, newOwner, OBJECT_MONITOR_OWNER_LOCATION))) { // success - writeMonitorCache(lock, monitor); traceObject(trace, "+lock{heavyweight:cas}", object, true); counters.lockHeavyCas.inc(); return true; @@ -313,11 +325,10 @@ private static boolean tryEnterInflated(Object object, Word lock, Word mark, Wor traceObject(trace, "+lock{heavyweight:failed-cas}", object, true); counters.lockHeavyFailedCas.inc(); } - } else if (probability(NOT_LIKELY_PROBABILITY, owner.equal(thread))) { + } else if (probability(NOT_LIKELY_PROBABILITY, owner.equal(newOwner))) { int recursionsOffset = objectMonitorRecursionsOffset(INJECTED_VMCONFIG); Word recursions = monitor.readWord(recursionsOffset, OBJECT_MONITOR_RECURSION_LOCATION); monitor.writeWord(recursionsOffset, recursions.add(1), OBJECT_MONITOR_RECURSION_LOCATION); - writeMonitorCache(lock, monitor); traceObject(trace, "+lock{heavyweight:recursive}", object, true); counters.lockHeavyRecursive.inc(); return true; @@ -332,7 +343,7 @@ private static boolean tryStackLocking(Object object, Word lock, Word mark, Word if (probability(SLOW_PATH_PROBABILITY, mark.and(monitorValue(INJECTED_VMCONFIG)).notEqual(0))) { // Inflated case // Set the lock slot's displaced mark to unused. Any non-0 value suffices. - lock.writeWord(lockMetadataOffset(INJECTED_VMCONFIG), WordFactory.unsigned(3), BASICLOCK_METADATA_LOCATION); + lock.writeWord(lockMetadataOffset(INJECTED_VMCONFIG), WordFactory.unsigned(unusedMark(INJECTED_VMCONFIG)), BASICLOCK_METADATA_LOCATION); return tryEnterInflated(object, lock, mark, thread, trace, counters); } @@ -464,7 +475,9 @@ public static void monitorexit(Object object, @ConstantParameter int lockDepth, trace(trace, " lock: 0x%016lx\n", lock); if (tryFastPathUnlocking(object, trace, counters, thread, lock)) { - decrementHeldMonitorCount(thread); + if (JavaVersionUtil.JAVA_SPEC == 21 || useStackLocking(INJECTED_VMCONFIG)) { + decrementHeldMonitorCount(thread); + } } else { monitorexitStubC(MONITOREXIT, object, lock); } @@ -499,7 +512,7 @@ private static boolean tryStackUnlocking(Object object, Word thread, Word lock, Word mark = loadWordFromObject(object, markOffset(INJECTED_VMCONFIG)); if (probability(SLOW_PATH_PROBABILITY, mark.and(monitorValue(INJECTED_VMCONFIG)).notEqual(0))) { - return tryExitInflated(object, thread, lock, trace, counters); + return tryExitInflated(object, mark, thread, lock, trace, counters); } if (probability(VERY_FAST_PATH_PROBABILITY, Word.objectToTrackedPointer(object).logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), @@ -539,7 +552,7 @@ private static boolean tryLightweightUnlocking(Object object, Word thread, Word AssertionSnippets.vmMessageC(VM_MESSAGE_C, true, cstring("Fast Unlock not monitor"), 0L, 0L, 0L); } } - return tryExitInflated(object, thread, lock, trace, counters); + return tryExitInflated(object, mark, thread, lock, trace, counters); } // Pop lock-stack. @@ -576,10 +589,8 @@ private static boolean tryLightweightUnlocking(Object object, Word thread, Word return false; } - private static boolean tryExitInflated(Object object, Word thread, Word lock, boolean trace, Counters counters) { + private static boolean tryExitInflated(Object object, Word mark, Word thread, Word lock, boolean trace, Counters counters) { // Inflated case - // mark is a pointer to the ObjectMonitor + monitorMask - Word mark = loadWordFromObject(object, markOffset(INJECTED_VMCONFIG)); Word monitor; if (useObjectMonitorTable(INJECTED_VMCONFIG)) { monitor = lock.readWord(lockMetadataOffset(INJECTED_VMCONFIG), BASICLOCK_METADATA_LOCATION); @@ -589,10 +600,12 @@ private static boolean tryExitInflated(Object object, Word thread, Word lock, bo return false; } } else { + // mark is a pointer to the ObjectMonitor + monitorMask monitor = mark.subtract(monitorValue(INJECTED_VMCONFIG)); } int ownerOffset = objectMonitorOwnerOffset(INJECTED_VMCONFIG); + int recursionsOffset = objectMonitorRecursionsOffset(INJECTED_VMCONFIG); Word recursions = monitor.readWord(recursionsOffset, OBJECT_MONITOR_RECURSION_LOCATION); if (probability(FAST_PATH_PROBABILITY, recursions.equal(0))) { @@ -605,7 +618,7 @@ private static boolean tryExitInflated(Object object, Word thread, Word lock, bo // Nobody is waiting, success // release_store memoryBarrier(MembarNode.FenceKind.STORE_RELEASE); - monitor.writeWord(ownerOffset, zero()); + monitor.writeWord(ownerOffset, nullPointer(), OBJECT_MONITOR_OWNER_LOCATION); traceObject(trace, "-lock{heavyweight:simple}", object, false); counters.unlockHeavySimple.inc(); return true; @@ -615,7 +628,7 @@ private static boolean tryExitInflated(Object object, Word thread, Word lock, bo if (probability(FREQUENT_PROBABILITY, succ.isNonNull())) { // There may be a thread spinning on this monitor. Temporarily setting // the monitor owner to null, and hope that the other thread will grab it. - monitor.writeWordVolatile(ownerOffset, zero()); + monitor.writeWordVolatile(ownerOffset, nullPointer()); succ = monitor.readWordVolatile(succOffset, OBJECT_MONITOR_SUCC_LOCATION); if (probability(NOT_FREQUENT_PROBABILITY, succ.isNonNull())) { // We manage to release the monitor before the other running thread even @@ -817,7 +830,8 @@ public Templates(OptionValues options, SnippetCounter.Group.Factory factory, Hot JAVA_THREAD_LOCK_STACK_LOCATION, JAVA_THREAD_LOCK_STACK_TOP_LOCATION, JAVA_THREAD_OM_CACHE_LOCATION, - JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION}; + JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION, + JAVA_THREAD_LOCK_ID_LOCATION}; exitLocations = new LocationIdentity[]{ JAVA_THREAD_LOCK_STACK_LOCATION, JAVA_THREAD_LOCK_STACK_TOP_LOCATION, @@ -827,10 +841,13 @@ public Templates(OptionValues options, SnippetCounter.Group.Factory factory, Hot OBJECT_MONITOR_ENTRY_LIST_LOCATION, OBJECT_MONITOR_RECURSION_LOCATION, OBJECT_MONITOR_SUCC_LOCATION, + OBJECT_MONITOR_STACK_LOCKER_LOCATION, MARK_WORD_LOCATION, JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION}; } else { - enterLocations = new LocationIdentity[]{JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION}; + enterLocations = new LocationIdentity[]{ + JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION, + JAVA_THREAD_LOCK_ID_LOCATION}; exitLocations = new LocationIdentity[]{ BASICLOCK_METADATA_LOCATION, OBJECT_MONITOR_OWNER_LOCATION, @@ -838,6 +855,7 @@ public Templates(OptionValues options, SnippetCounter.Group.Factory factory, Hot OBJECT_MONITOR_ENTRY_LIST_LOCATION, OBJECT_MONITOR_RECURSION_LOCATION, OBJECT_MONITOR_SUCC_LOCATION, + OBJECT_MONITOR_STACK_LOCKER_LOCATION, MARK_WORD_LOCATION, JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION}; } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/methodhandles/MethodHandleFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/methodhandles/MethodHandleFeature.java index 485fc871aeb9..01699fc87374 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/methodhandles/MethodHandleFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/methodhandles/MethodHandleFeature.java @@ -121,10 +121,16 @@ public void duringSetup(DuringSetupAccess access) { if (JavaVersionUtil.JAVA_SPEC >= 22) { try { Class referencedKeySetClass = ReflectionUtil.lookupClass("jdk.internal.util.ReferencedKeySet"); - Method create = ReflectionUtil.lookupMethod(referencedKeySetClass, "create", boolean.class, boolean.class, Supplier.class); // The following call must match the static initializer of MethodType#internTable. - runtimeMethodTypeInternTable = create.invoke(null, - /* isSoft */ false, /* useNativeQueue */ true, (Supplier) () -> new ConcurrentHashMap<>(512)); + if (JavaVersionUtil.JAVA_SPEC >= 24) { + Method create = ReflectionUtil.lookupMethod(referencedKeySetClass, "create", boolean.class, Supplier.class); + runtimeMethodTypeInternTable = create.invoke(null, + /* isSoft */ false, (Supplier) () -> new ConcurrentHashMap<>(512)); + } else { + Method create = ReflectionUtil.lookupMethod(referencedKeySetClass, "create", boolean.class, boolean.class, Supplier.class); + runtimeMethodTypeInternTable = create.invoke(null, + /* isSoft */ false, /* useNativeQueue */ true, (Supplier) () -> new ConcurrentHashMap<>(512)); + } referencedKeySetAdd = ReflectionUtil.lookupMethod(referencedKeySetClass, "add", Object.class); } catch (ReflectiveOperationException e) { throw VMError.shouldNotReachHere(e);