From 43b82b1cf3e9a65267f5e3af1183e3d568de3ced Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Wed, 21 Aug 2024 15:17:20 -0400 Subject: [PATCH 1/4] lazy vthread registration --- .../svm/core/jfr/JfrThreadRepository.java | 5 ----- .../com/oracle/svm/core/jfr/SubstrateJVM.java | 22 +++++++++++++++++++ .../jfr/events/JavaMonitorEnterEvent.java | 8 +++---- .../svm/core/jfr/traceid/JfrTraceIdEpoch.java | 7 ++++++ .../oracle/svm/core/monitor/JavaMonitor.java | 9 ++++---- .../monitor/MultiThreadedMonitorSupport.java | 2 +- .../Target_java_lang_VirtualThread.java | 9 ++++---- 7 files changed, 42 insertions(+), 20 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadRepository.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadRepository.java index fa8b9ffc7ff0..a7670399c93e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadRepository.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadRepository.java @@ -92,11 +92,6 @@ public void registerRunningThreads() { Thread thread = PlatformThreads.fromVMThread(isolateThread); if (thread != null) { registerThread(thread); - // Re-register vthreads that are already mounted. - Thread vthread = PlatformThreads.getMountedVirtualThread(thread); - if (vthread != null) { - registerThread(vthread); - } } } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java index eff3527c0480..ddbcbff7c5fd 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java @@ -26,6 +26,7 @@ import java.util.List; +import com.oracle.svm.core.SubstrateUtil; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.IsolateThread; import org.graalvm.nativeimage.Platform; @@ -42,6 +43,7 @@ import com.oracle.svm.core.jfr.oldobject.JfrOldObjectRepository; import com.oracle.svm.core.jfr.sampler.JfrExecutionSampler; import com.oracle.svm.core.jfr.throttling.JfrEventThrottling; +import com.oracle.svm.core.jfr.traceid.JfrTraceIdEpoch; import com.oracle.svm.core.log.Log; import com.oracle.svm.core.sampler.SamplerBufferPool; import com.oracle.svm.core.sampler.SamplerBuffersAccess; @@ -49,6 +51,7 @@ import com.oracle.svm.core.sampler.SubstrateSigprofHandler; import com.oracle.svm.core.thread.JavaThreads; import com.oracle.svm.core.thread.JavaVMOperation; +import com.oracle.svm.core.thread.Target_java_lang_VirtualThread; import com.oracle.svm.core.thread.VMThreads; import com.oracle.svm.core.util.VMError; @@ -303,6 +306,7 @@ public long getStackTraceId(JfrEvent eventType, int skipCount) { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static long getThreadId(Thread thread) { if (HasJfrSupport.get()) { + maybeRegisterVirtualThread(thread); return JavaThreads.getThreadId(thread); } return 0; @@ -311,11 +315,29 @@ public static long getThreadId(Thread thread) { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static long getCurrentThreadId() { if (HasJfrSupport.get()) { + maybeRegisterVirtualThread(Thread.currentThread()); return JavaThreads.getCurrentThreadId(); } return 0; } + /** + * Register virtual threads if they aren't registered already. Platform threads are registered + * eagerly when started and at chunk rotations. + */ + @Uninterruptible(reason = "Epoch should not change while checking generation.") + private static void maybeRegisterVirtualThread(Thread thread) { + // Do quick preliminary checks to avoid global locking unless necessary. + if (JavaThreads.isVirtual(thread)) { + Target_java_lang_VirtualThread tjlv = SubstrateUtil.cast(thread, Target_java_lang_VirtualThread.class); + int currentEpochGen = JfrTraceIdEpoch.getInstance().currentEpochGeneration(); + if (tjlv.jfrGeneration != currentEpochGen) { + getThreadRepo().registerThread(thread); + tjlv.jfrGeneration = currentEpochGen; + } + } + } + /** * See {@link JVM#storeMetadataDescriptor}. */ diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/JavaMonitorEnterEvent.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/JavaMonitorEnterEvent.java index 671924ba1a48..b32c64b056df 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/JavaMonitorEnterEvent.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/JavaMonitorEnterEvent.java @@ -39,14 +39,14 @@ import com.oracle.svm.core.jfr.SubstrateJVM; public class JavaMonitorEnterEvent { - public static void emit(Object obj, long previousOwnerTid, long startTicks) { + public static void emit(Object obj, Thread previousOwner, long startTicks) { if (HasJfrSupport.get()) { - emit0(obj, previousOwnerTid, startTicks); + emit0(obj, previousOwner, startTicks); } } @Uninterruptible(reason = "Accesses a JFR buffer.") - public static void emit0(Object obj, long previousOwnerTid, long startTicks) { + public static void emit0(Object obj, Thread previousOwner, long startTicks) { long duration = JfrTicks.duration(startTicks); if (JfrEvent.JavaMonitorEnter.shouldEmit(duration)) { JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class); @@ -58,7 +58,7 @@ public static void emit0(Object obj, long previousOwnerTid, long startTicks) { JfrNativeEventWriter.putEventThread(data); JfrNativeEventWriter.putLong(data, SubstrateJVM.get().getStackTraceId(JfrEvent.JavaMonitorEnter, 0)); JfrNativeEventWriter.putClass(data, obj.getClass()); - JfrNativeEventWriter.putLong(data, previousOwnerTid); + JfrNativeEventWriter.putThread(data, previousOwner); JfrNativeEventWriter.putLong(data, Word.objectToUntrackedPointer(obj).rawValue()); JfrNativeEventWriter.endSmallEvent(data); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/traceid/JfrTraceIdEpoch.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/traceid/JfrTraceIdEpoch.java index 400d919c4973..c6437f2551aa 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/traceid/JfrTraceIdEpoch.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/traceid/JfrTraceIdEpoch.java @@ -43,6 +43,7 @@ public class JfrTraceIdEpoch { private static final long EPOCH_1_BIT = 0b10; private boolean epoch; + private int epochGeneration; @Fold public static JfrTraceIdEpoch getInstance() { @@ -57,6 +58,7 @@ public JfrTraceIdEpoch() { public void changeEpoch() { assert VMOperation.isInProgressAtSafepoint(); epoch = !epoch; + epochGeneration++; } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) @@ -74,6 +76,11 @@ public boolean currentEpoch() { return epoch; } + @Uninterruptible(reason = "Avoid epoch changing while checking generation.", callerMustBe = true) + public int currentEpochGeneration() { + return epochGeneration; + } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public boolean previousEpoch() { return !epoch; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitor.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitor.java index f0d580123079..26882730c6da 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitor.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitor.java @@ -36,7 +36,6 @@ import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.jfr.JfrTicks; -import com.oracle.svm.core.jfr.SubstrateJVM; import com.oracle.svm.core.jfr.events.JavaMonitorEnterEvent; import com.oracle.svm.core.thread.JavaThreads; import com.oracle.svm.core.util.BasedOnJDKClass; @@ -61,20 +60,20 @@ @BasedOnJDKClass(ReentrantLock.class) @BasedOnJDKClass(value = ReentrantLock.class, innerClass = "Sync") public class JavaMonitor extends JavaMonitorQueuedSynchronizer { - protected long latestJfrTid; + protected Thread latest; public JavaMonitor() { - latestJfrTid = 0; + latest = null; } public void monitorEnter(Object obj) { if (!tryLock()) { long startTicks = JfrTicks.elapsedTicks(); acquire(1); - JavaMonitorEnterEvent.emit(obj, latestJfrTid, startTicks); + JavaMonitorEnterEvent.emit(obj, latest, startTicks); } - latestJfrTid = SubstrateJVM.getCurrentThreadId(); + latest = Thread.currentThread(); } public void monitorExit() { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java index 7a458f0a0c65..c61ba67c87a2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java @@ -260,7 +260,7 @@ public void monitorEnter(Object obj, MonitorInflationCause cause) { monitor = (JavaMonitor) UNSAFE.compareAndExchangeReference(obj, monitorOffset, null, newMonitor); if (monitor == null) { // successful JavaMonitorInflateEvent.emit(obj, startTicks, MonitorInflationCause.MONITOR_ENTER); - newMonitor.latestJfrTid = current; + newMonitor.latest = Thread.currentThread(); return; } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_VirtualThread.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_VirtualThread.java index de0fab47147a..c3f080632602 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_VirtualThread.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_VirtualThread.java @@ -47,8 +47,6 @@ import com.oracle.svm.core.annotate.TargetElement; import com.oracle.svm.core.jdk.JDK21OrEarlier; import com.oracle.svm.core.jdk.JDKLatest; -import com.oracle.svm.core.jfr.HasJfrSupport; -import com.oracle.svm.core.jfr.SubstrateJVM; import com.oracle.svm.core.monitor.MonitorInflationCause; import com.oracle.svm.core.monitor.MonitorSupport; import com.oracle.svm.core.util.VMError; @@ -113,6 +111,10 @@ public final class Target_java_lang_VirtualThread { private Executor nondefaultScheduler; // Checkstyle: resume + @Inject // + @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) // + public volatile int jfrGeneration = -1; + @Alias private static native ForkJoinPool createDefaultScheduler(); @@ -330,9 +332,6 @@ void mount() { } carrier.setCurrentThread(asThread(this)); - if (HasJfrSupport.get()) { - SubstrateJVM.getThreadRepo().registerThread(asThread(this)); - } } @Substitute // not needed on newer JDKs that use safe disableSuspendAndPreempt() From e33f0ac5f6bd58064be2fd19b1f467dd5f98810f Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Wed, 4 Sep 2024 11:07:14 -0400 Subject: [PATCH 2/4] remove epoch boolean --- .../svm/core/jfr/traceid/JfrTraceIdEpoch.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/traceid/JfrTraceIdEpoch.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/traceid/JfrTraceIdEpoch.java index c6437f2551aa..8efcaab0532b 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/traceid/JfrTraceIdEpoch.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/traceid/JfrTraceIdEpoch.java @@ -42,7 +42,6 @@ public class JfrTraceIdEpoch { private static final long EPOCH_0_BIT = 0b01; private static final long EPOCH_1_BIT = 0b10; - private boolean epoch; private int epochGeneration; @Fold @@ -53,27 +52,29 @@ public static JfrTraceIdEpoch getInstance() { @Platforms(Platform.HOSTED_ONLY.class) public JfrTraceIdEpoch() { } - + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + private boolean getEpoch() { + return (epochGeneration & 1) == 0; + } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public void changeEpoch() { assert VMOperation.isInProgressAtSafepoint(); - epoch = !epoch; epochGeneration++; } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) long thisEpochBit() { - return epoch ? EPOCH_1_BIT : EPOCH_0_BIT; + return getEpoch() ? EPOCH_1_BIT : EPOCH_0_BIT; } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) long previousEpochBit() { - return epoch ? EPOCH_0_BIT : EPOCH_1_BIT; + return getEpoch() ? EPOCH_0_BIT : EPOCH_1_BIT; } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public boolean currentEpoch() { - return epoch; + return getEpoch(); } @Uninterruptible(reason = "Avoid epoch changing while checking generation.", callerMustBe = true) @@ -83,6 +84,6 @@ public int currentEpochGeneration() { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public boolean previousEpoch() { - return !epoch; + return !getEpoch(); } } From c1e4ab092f58f328c5a5eb46ad36fcb3ecddf468 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Wed, 4 Sep 2024 11:16:55 -0400 Subject: [PATCH 3/4] style --- .../src/com/oracle/svm/core/jfr/traceid/JfrTraceIdEpoch.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/traceid/JfrTraceIdEpoch.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/traceid/JfrTraceIdEpoch.java index 8efcaab0532b..b45a67e60c2f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/traceid/JfrTraceIdEpoch.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/traceid/JfrTraceIdEpoch.java @@ -52,10 +52,12 @@ public static JfrTraceIdEpoch getInstance() { @Platforms(Platform.HOSTED_ONLY.class) public JfrTraceIdEpoch() { } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) private boolean getEpoch() { return (epochGeneration & 1) == 0; } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public void changeEpoch() { assert VMOperation.isInProgressAtSafepoint(); From 22add5c2f8c815c9109faa6fba8649a847b749a5 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Fri, 13 Sep 2024 12:27:37 -0400 Subject: [PATCH 4/4] Use putThread to avoid races. --- .../svm/core/jfr/JfrNativeEventWriter.java | 2 ++ .../svm/core/jfr/JfrThreadRepository.java | 27 ++++++++++++++++--- .../com/oracle/svm/core/jfr/SubstrateJVM.java | 13 ++++++--- .../core/jfr/events/ExecutionSampleEvent.java | 2 +- .../core/jfr/events/JavaMonitorWaitEvent.java | 6 ++--- .../svm/core/jfr/events/ThreadStartEvent.java | 2 +- .../JavaMonitorQueuedSynchronizer.java | 13 +++++---- 7 files changed, 46 insertions(+), 19 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrNativeEventWriter.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrNativeEventWriter.java index 9c6da80d0ee7..3f12858073b7 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrNativeEventWriter.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrNativeEventWriter.java @@ -250,12 +250,14 @@ public static void putThread(JfrNativeEventWriterData data, Thread thread) { if (thread == null) { putThread(data, 0L); } else { + SubstrateJVM.maybeRegisterVirtualThread(thread); putThread(data, SubstrateJVM.getThreadId(thread)); } } @Uninterruptible(reason = "Accesses a native JFR buffer.", callerMustBe = true) public static void putThread(JfrNativeEventWriterData data, long threadId) { + SubstrateJVM.maybeRegisterVirtualThread(threadId); putLong(data, threadId); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadRepository.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadRepository.java index a7670399c93e..0f0e033e98ab 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadRepository.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadRepository.java @@ -24,6 +24,8 @@ */ package com.oracle.svm.core.jfr; +import static com.oracle.svm.core.Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE; + import org.graalvm.nativeimage.IsolateThread; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -96,6 +98,19 @@ public void registerRunningThreads() { } } + /** + * If this method is called on platform threads, nothing will happen since they are already + * registered eagerly upon starting and at epoch changes. + */ + @Uninterruptible(reason = "Locking without transition requires that the whole critical section is uninterruptible.") + public void registerThread(long threadId) { + if (!SubstrateJVM.get().isRecording()) { + return; + } + + registerThread0(threadId, 0, true, null, null); + } + @Uninterruptible(reason = "Locking without transition requires that the whole critical section is uninterruptible.") public void registerThread(Thread thread) { if (!SubstrateJVM.get().isRecording()) { @@ -103,7 +118,13 @@ public void registerThread(Thread thread) { } long threadId = JavaThreads.getThreadId(thread); + boolean isVirtual = JavaThreads.isVirtual(thread); + long osThreadId = isVirtual ? 0 : threadId; + registerThread0(threadId, osThreadId, isVirtual, thread, thread.getName()); + } + @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true) + private void registerThread0(long threadId, long osThreadId, boolean isVirtual, Thread thread, String name) { JfrVisited visitedThread = StackValue.get(JfrVisited.class); visitedThread.setId(threadId); visitedThread.setHash(UninterruptibleUtils.Long.hashCode(threadId)); @@ -124,14 +145,12 @@ public void registerThread(Thread thread) { JfrNativeEventWriterDataAccess.initialize(data, epochData.threadBuffer); /* Similar to JfrThreadConstant::serialize in HotSpot. */ - boolean isVirtual = JavaThreads.isVirtual(thread); - long osThreadId = isVirtual ? 0 : threadId; long threadGroupId = registerThreadGroup(thread, isVirtual); JfrNativeEventWriter.putLong(data, threadId); - JfrNativeEventWriter.putString(data, thread.getName()); // OS thread name + JfrNativeEventWriter.putString(data, name); // OS thread name JfrNativeEventWriter.putLong(data, osThreadId); // OS thread id - JfrNativeEventWriter.putString(data, thread.getName()); // Java thread name + JfrNativeEventWriter.putString(data, name); // Java thread name JfrNativeEventWriter.putLong(data, threadId); // Java thread id JfrNativeEventWriter.putLong(data, threadGroupId); // Java thread group JfrNativeEventWriter.putBoolean(data, isVirtual); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java index ddbcbff7c5fd..b678420bc817 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java @@ -306,7 +306,6 @@ public long getStackTraceId(JfrEvent eventType, int skipCount) { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static long getThreadId(Thread thread) { if (HasJfrSupport.get()) { - maybeRegisterVirtualThread(thread); return JavaThreads.getThreadId(thread); } return 0; @@ -315,7 +314,6 @@ public static long getThreadId(Thread thread) { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static long getCurrentThreadId() { if (HasJfrSupport.get()) { - maybeRegisterVirtualThread(Thread.currentThread()); return JavaThreads.getCurrentThreadId(); } return 0; @@ -326,7 +324,7 @@ public static long getCurrentThreadId() { * eagerly when started and at chunk rotations. */ @Uninterruptible(reason = "Epoch should not change while checking generation.") - private static void maybeRegisterVirtualThread(Thread thread) { + public static void maybeRegisterVirtualThread(Thread thread) { // Do quick preliminary checks to avoid global locking unless necessary. if (JavaThreads.isVirtual(thread)) { Target_java_lang_VirtualThread tjlv = SubstrateUtil.cast(thread, Target_java_lang_VirtualThread.class); @@ -338,6 +336,15 @@ private static void maybeRegisterVirtualThread(Thread thread) { } } + /** + * {@link SubstrateJVM#maybeRegisterVirtualThread(Thread)} Is preferred over this method since + * it can perform preliminary checks to avoid locking the Thread Repository unnecessarily. + */ + @Uninterruptible(reason = "Epoch should not change while checking generation.") + public static void maybeRegisterVirtualThread(long tid) { + getThreadRepo().registerThread(tid); + } + /** * See {@link JVM#storeMetadataDescriptor}. */ diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ExecutionSampleEvent.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ExecutionSampleEvent.java index 1a6723b9a532..0a14b381b7af 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ExecutionSampleEvent.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ExecutionSampleEvent.java @@ -41,7 +41,7 @@ public static void writeExecutionSample(long elapsedTicks, long threadId, long s JfrNativeEventWriter.beginSmallEvent(data, JfrEvent.ExecutionSample); JfrNativeEventWriter.putLong(data, elapsedTicks); - JfrNativeEventWriter.putLong(data, threadId); + JfrNativeEventWriter.putThread(data, threadId); JfrNativeEventWriter.putLong(data, stackTraceId); JfrNativeEventWriter.putLong(data, threadState); JfrNativeEventWriter.endSmallEvent(data); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/JavaMonitorWaitEvent.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/JavaMonitorWaitEvent.java index 27322780e18a..85ab907e2d30 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/JavaMonitorWaitEvent.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/JavaMonitorWaitEvent.java @@ -40,7 +40,7 @@ import jdk.graal.compiler.word.Word; public class JavaMonitorWaitEvent { - public static void emit(long startTicks, Object obj, long notifier, long timeout, boolean timedOut) { + public static void emit(long startTicks, Object obj, Thread notifier, long timeout, boolean timedOut) { if (HasJfrSupport.get() && obj != null && !Target_jdk_jfr_internal_JVM_ChunkRotationMonitor.class.equals(obj.getClass()) && !Target_jdk_jfr_internal_management_HiddenWait.class.equals(obj.getClass())) { emit0(startTicks, obj, notifier, timeout, timedOut); @@ -48,7 +48,7 @@ public static void emit(long startTicks, Object obj, long notifier, long timeout } @Uninterruptible(reason = "Accesses a JFR buffer.") - private static void emit0(long startTicks, Object obj, long notifier, long timeout, boolean timedOut) { + private static void emit0(long startTicks, Object obj, Thread notifier, long timeout, boolean timedOut) { long duration = JfrTicks.duration(startTicks); if (JfrEvent.JavaMonitorWait.shouldEmit(duration)) { JfrNativeEventWriterData data = org.graalvm.nativeimage.StackValue.get(JfrNativeEventWriterData.class); @@ -60,7 +60,7 @@ private static void emit0(long startTicks, Object obj, long notifier, long timeo JfrNativeEventWriter.putEventThread(data); JfrNativeEventWriter.putLong(data, SubstrateJVM.get().getStackTraceId(JfrEvent.JavaMonitorWait, 0)); JfrNativeEventWriter.putClass(data, obj.getClass()); - JfrNativeEventWriter.putLong(data, notifier); + JfrNativeEventWriter.putThread(data, notifier); JfrNativeEventWriter.putLong(data, timeout); JfrNativeEventWriter.putBoolean(data, timedOut); JfrNativeEventWriter.putLong(data, Word.objectToUntrackedPointer(obj).rawValue()); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ThreadStartEvent.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ThreadStartEvent.java index 1eb36418442e..e6965cba15e1 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ThreadStartEvent.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ThreadStartEvent.java @@ -47,7 +47,7 @@ public static void emit(Thread thread) { JfrNativeEventWriter.putEventThread(data); JfrNativeEventWriter.putLong(data, SubstrateJVM.get().getStackTraceId(JfrEvent.ThreadStart, 0)); JfrNativeEventWriter.putThread(data, thread); - JfrNativeEventWriter.putLong(data, JavaThreads.getParentThreadId(thread)); + JfrNativeEventWriter.putThread(data, JavaThreads.getParentThreadId(thread)); JfrNativeEventWriter.endSmallEvent(data); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitorQueuedSynchronizer.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitorQueuedSynchronizer.java index c20e2fc2b058..9dd7b0a55def 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitorQueuedSynchronizer.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitorQueuedSynchronizer.java @@ -32,7 +32,6 @@ import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.jfr.JfrTicks; -import com.oracle.svm.core.jfr.SubstrateJVM; import com.oracle.svm.core.jfr.events.JavaMonitorWaitEvent; import com.oracle.svm.core.thread.JavaThreads; import com.oracle.svm.core.util.BasedOnJDKClass; @@ -120,7 +119,7 @@ static final class ExclusiveNode extends Node { @BasedOnJDKClass(value = AbstractQueuedLongSynchronizer.class, innerClass = "ConditionNode") static final class ConditionNode extends Node { ConditionNode nextWaiter; - long notifierJfrTid; + Thread notifierJfr; // see AbstractQueuedLongSynchronizer.ConditionNode.isReleasable() public boolean isReleasable() { @@ -457,7 +456,7 @@ private void doSignal(ConditionNode first, boolean all) { first.nextWaiter = null; // GC assistance } if ((first.getAndUnsetStatus(COND) & COND) != 0) { - first.notifierJfrTid = SubstrateJVM.getCurrentThreadId(); + first.notifierJfr = Thread.currentThread(); enqueue(first); if (!all) { break; @@ -564,7 +563,7 @@ private ConditionNode newConditionNode() { public void await(Object obj) throws InterruptedException { long startTicks = JfrTicks.elapsedTicks(); if (Thread.interrupted()) { - JavaMonitorWaitEvent.emit(startTicks, obj, 0, 0L, false); + JavaMonitorWaitEvent.emit(startTicks, obj, null, 0L, false); throw new InterruptedException(); } ConditionNode node = newConditionNode(); @@ -587,7 +586,7 @@ public void await(Object obj) throws InterruptedException { } node.clearStatus(); // waiting is done, emit wait event - JavaMonitorWaitEvent.emit(startTicks, obj, node.notifierJfrTid, 0L, false); + JavaMonitorWaitEvent.emit(startTicks, obj, node.notifierJfr, 0L, false); acquire(node, savedAcquisitions); if (interrupted) { if (cancelled) { @@ -604,7 +603,7 @@ public boolean await(Object obj, long time, TimeUnit unit) throws InterruptedExc long startTicks = JfrTicks.elapsedTicks(); long nanosTimeout = unit.toNanos(time); if (Thread.interrupted()) { - JavaMonitorWaitEvent.emit(startTicks, obj, 0, 0L, false); + JavaMonitorWaitEvent.emit(startTicks, obj, null, 0L, false); throw new InterruptedException(); } ConditionNode node = newConditionNode(); @@ -627,7 +626,7 @@ public boolean await(Object obj, long time, TimeUnit unit) throws InterruptedExc } node.clearStatus(); // waiting is done, emit wait event - JavaMonitorWaitEvent.emit(startTicks, obj, node.notifierJfrTid, time, cancelled); + JavaMonitorWaitEvent.emit(startTicks, obj, node.notifierJfr, time, cancelled); acquire(node, savedAcquisitions); if (cancelled) { unlinkCancelledWaiters(node);