Skip to content

Commit c8fd386

Browse files
[GR-44087] Support JFR event JavaMonitorInflate.
PullRequest: graal/13745
2 parents 6243be6 + 4dd8a9d commit c8fd386

17 files changed

+405
-45
lines changed

substratevm/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ This changelog summarizes major changes to GraalVM Native Image.
1717
* (GR-42964) Deprecate `--enable-monitoring` without an argument. The option will no longer default to `all` in a future release. Instead, please always explicitly specify the list of monitoring features to be enabled (for example, `--enable-monitoring=heapdump,jfr,jvmstat`").
1818
* (GR-19890) Native Image now sets up build environments for Windows users automatically. Running in an x64 Native Tools Command Prompt is no longer a requirement.
1919
* (GR-43410) Added support for the JFR event `ExecutionSample`.
20-
* (GR-44058) Red Hat added support for the JFR event `ObjectAllocationInNewTLAB`.
20+
* (GR-44058) (GR-44087) Red Hat added support for the JFR events `ObjectAllocationInNewTLAB` and `JavaMonitorInflate`.
2121
* (GR-42467) The search path for `System.loadLibrary()` by default includes the directory containing the native image.
2222

2323
## Version 22.3.0

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrEvent.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public final class JfrEvent {
5858
public static final JfrEvent JavaMonitorEnter = create("jdk.JavaMonitorEnter");
5959
public static final JfrEvent ThreadPark = create("jdk.ThreadPark");
6060
public static final JfrEvent JavaMonitorWait = create("jdk.JavaMonitorWait");
61+
public static final JfrEvent JavaMonitorInflate = create("jdk.JavaMonitorInflate");
6162
public static final JfrEvent ObjectAllocationInNewTLAB = create("jdk.ObjectAllocationInNewTLAB");
6263

6364
private final long id;

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrFeature.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ public void afterRegistration(AfterRegistrationAccess access) {
169169

170170
JfrSerializerSupport.get().register(new JfrFrameTypeSerializer());
171171
JfrSerializerSupport.get().register(new JfrThreadStateSerializer());
172+
JfrSerializerSupport.get().register(new JfrMonitorInflationCauseSerializer());
172173
JfrSerializerSupport.get().register(new JfrGCCauseSerializer());
173174
JfrSerializerSupport.get().register(new JfrGCNameSerializer());
174175
JfrSerializerSupport.get().register(new JfrVMOperationNameSerializer());
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2023, 2023, Red Hat Inc. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
27+
package com.oracle.svm.core.jfr;
28+
29+
import org.graalvm.nativeimage.Platform;
30+
import org.graalvm.nativeimage.Platforms;
31+
32+
import com.oracle.svm.core.monitor.MonitorInflationCause;
33+
34+
public class JfrMonitorInflationCauseSerializer implements JfrConstantPool {
35+
@Platforms(Platform.HOSTED_ONLY.class)
36+
public JfrMonitorInflationCauseSerializer() {
37+
}
38+
39+
@Override
40+
public int write(JfrChunkWriter writer) {
41+
writer.writeCompressedLong(JfrType.MonitorInflationCause.getId());
42+
43+
MonitorInflationCause[] inflationCauses = MonitorInflationCause.values();
44+
writer.writeCompressedLong(inflationCauses.length);
45+
for (int i = 0; i < inflationCauses.length; i++) {
46+
writer.writeCompressedInt(i);
47+
writer.writeString(inflationCauses[i].getText());
48+
}
49+
50+
return NON_EMPTY;
51+
}
52+
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrType.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ public enum JfrType {
4242
FrameType("jdk.types.FrameType"),
4343
GCCause("jdk.types.GCCause"),
4444
GCName("jdk.types.GCName"),
45-
VMOperation("jdk.types.VMOperationType");
45+
VMOperation("jdk.types.VMOperationType"),
46+
MonitorInflationCause("jdk.types.InflateCause");
4647

4748
private final long id;
4849

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2023, 2023, Red Hat Inc. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
27+
package com.oracle.svm.core.jfr.events;
28+
29+
import org.graalvm.compiler.word.Word;
30+
import org.graalvm.nativeimage.StackValue;
31+
32+
import com.oracle.svm.core.Uninterruptible;
33+
import com.oracle.svm.core.jfr.HasJfrSupport;
34+
import com.oracle.svm.core.jfr.JfrEvent;
35+
import com.oracle.svm.core.jfr.JfrNativeEventWriter;
36+
import com.oracle.svm.core.jfr.JfrNativeEventWriterData;
37+
import com.oracle.svm.core.jfr.JfrNativeEventWriterDataAccess;
38+
import com.oracle.svm.core.jfr.JfrTicks;
39+
import com.oracle.svm.core.jfr.SubstrateJVM;
40+
import com.oracle.svm.core.monitor.MonitorInflationCause;
41+
42+
public class JavaMonitorInflateEvent {
43+
public static void emit(Object obj, long startTicks, MonitorInflationCause cause) {
44+
if (HasJfrSupport.get()) {
45+
emit0(obj, startTicks, cause);
46+
}
47+
}
48+
49+
@Uninterruptible(reason = "Accesses a JFR buffer.")
50+
public static void emit0(Object obj, long startTicks, MonitorInflationCause cause) {
51+
if (JfrEvent.JavaMonitorInflate.shouldEmit()) {
52+
JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class);
53+
JfrNativeEventWriterDataAccess.initializeThreadLocalNativeBuffer(data);
54+
55+
JfrNativeEventWriter.beginSmallEvent(data, JfrEvent.JavaMonitorInflate);
56+
JfrNativeEventWriter.putLong(data, startTicks);
57+
JfrNativeEventWriter.putLong(data, JfrTicks.elapsedTicks() - startTicks);
58+
JfrNativeEventWriter.putEventThread(data);
59+
JfrNativeEventWriter.putLong(data, SubstrateJVM.get().getStackTraceId(JfrEvent.JavaMonitorInflate, 0));
60+
JfrNativeEventWriter.putClass(data, obj.getClass());
61+
JfrNativeEventWriter.putLong(data, Word.objectToUntrackedPointer(obj).rawValue());
62+
JfrNativeEventWriter.putLong(data, getId(cause));
63+
JfrNativeEventWriter.endSmallEvent(data);
64+
}
65+
}
66+
67+
@Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true)
68+
private static long getId(MonitorInflationCause cause) {
69+
/* First entry needs to have id 0. */
70+
return cause.ordinal();
71+
}
72+
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/functions/JNIFunctions.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
import com.oracle.svm.core.jni.headers.JNIVersion;
106106
import com.oracle.svm.core.jni.headers.JNIVersionJDK19OrLater;
107107
import com.oracle.svm.core.log.Log;
108+
import com.oracle.svm.core.monitor.MonitorInflationCause;
108109
import com.oracle.svm.core.monitor.MonitorSupport;
109110
import com.oracle.svm.core.snippets.KnownIntrinsics;
110111
import com.oracle.svm.core.stack.StackOverflowCheck;
@@ -1015,7 +1016,7 @@ static int MonitorEnter(JNIEnvironment env, JNIObjectHandle handle) {
10151016
}
10161017
boolean acquired = false;
10171018
try {
1018-
MonitorSupport.singleton().monitorEnter(obj);
1019+
MonitorSupport.singleton().monitorEnter(obj, MonitorInflationCause.JNI_ENTER);
10191020
assert Thread.holdsLock(obj);
10201021
acquired = true;
10211022

@@ -1024,7 +1025,8 @@ static int MonitorEnter(JNIEnvironment env, JNIObjectHandle handle) {
10241025
} catch (Throwable t) {
10251026
try {
10261027
if (acquired) {
1027-
MonitorSupport.singleton().monitorExit(obj);
1028+
/* The thread acquired the monitor, so monitor inflation can't happen here. */
1029+
MonitorSupport.singleton().monitorExit(obj, MonitorInflationCause.VM_INTERNAL);
10281030
}
10291031
if (pinned) {
10301032
VirtualThreads.singleton().unpinCurrent();
@@ -1049,7 +1051,7 @@ static int MonitorExit(JNIEnvironment env, JNIObjectHandle handle) {
10491051
if (!Thread.holdsLock(obj)) {
10501052
throw new IllegalMonitorStateException();
10511053
}
1052-
MonitorSupport.singleton().monitorExit(obj);
1054+
MonitorSupport.singleton().monitorExit(obj, MonitorInflationCause.JNI_EXIT);
10531055
JNIThreadOwnedMonitors.exited(obj);
10541056
if (VirtualThreads.isSupported() && JavaThreads.isCurrentThreadVirtual()) {
10551057
try {

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/functions/JNIInvocationInterface.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
import org.graalvm.word.WordFactory;
4343

4444
import com.oracle.svm.core.SubstrateOptions;
45-
import com.oracle.svm.core.UnmanagedMemoryUtil;
4645
import com.oracle.svm.core.Uninterruptible;
46+
import com.oracle.svm.core.UnmanagedMemoryUtil;
4747
import com.oracle.svm.core.c.CGlobalData;
4848
import com.oracle.svm.core.c.CGlobalDataFactory;
4949
import com.oracle.svm.core.c.function.CEntryPointActions;
@@ -73,6 +73,7 @@
7373
import com.oracle.svm.core.jni.headers.JNIJavaVMPointer;
7474
import com.oracle.svm.core.jni.headers.JNIVersion;
7575
import com.oracle.svm.core.log.FunctionPointerLogHandler;
76+
import com.oracle.svm.core.monitor.MonitorInflationCause;
7677
import com.oracle.svm.core.monitor.MonitorSupport;
7778
import com.oracle.svm.core.snippets.ImplicitExceptions;
7879
import com.oracle.svm.core.thread.PlatformThreads;
@@ -265,11 +266,8 @@ static int AttachCurrentThreadAsDaemon(JNIJavaVM vm, JNIEnvironmentPointer penv,
265266
*/
266267
@CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class, publishAs = Publish.NotPublished)
267268
@CEntryPointOptions(prologue = JNIJavaVMEnterAttachThreadEnsureJavaThreadPrologue.class, epilogue = LeaveDetachThreadEpilogue.class)
268-
static int DetachCurrentThread(JNIJavaVM vm) {
269+
static int DetachCurrentThread(@SuppressWarnings("unused") JNIJavaVM vm) {
269270
int result = JNIErrors.JNI_OK();
270-
if (!vm.equal(JNIFunctionTables.singleton().getGlobalJavaVM())) {
271-
result = JNIErrors.JNI_ERR();
272-
}
273271
// JNI specification requires releasing all owned monitors
274272
Support.releaseCurrentThreadOwnedMonitors();
275273
return result;
@@ -353,7 +351,7 @@ static void attachCurrentThread(JNIJavaVM vm, JNIEnvironmentPointer penv, JNIJav
353351
static void releaseCurrentThreadOwnedMonitors() {
354352
JNIThreadOwnedMonitors.forEach((obj, depth) -> {
355353
for (int i = 0; i < depth; i++) {
356-
MonitorSupport.singleton().monitorExit(obj);
354+
MonitorSupport.singleton().monitorExit(obj, MonitorInflationCause.VM_INTERNAL);
357355
}
358356
assert !Thread.holdsLock(obj);
359357
});
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2023, 2023, Red Hat Inc. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
27+
package com.oracle.svm.core.monitor;
28+
29+
import org.graalvm.nativeimage.Platform;
30+
import org.graalvm.nativeimage.Platforms;
31+
32+
public enum MonitorInflationCause {
33+
VM_INTERNAL("VM Internal"),
34+
MONITOR_ENTER("Monitor Enter"),
35+
WAIT("Monitor Wait"),
36+
NOTIFY("Monitor Notify"),
37+
JNI_ENTER("JNI Monitor Enter"),
38+
JNI_EXIT("JNI Monitor Exit");
39+
40+
private final String text;
41+
42+
@Platforms(Platform.HOSTED_ONLY.class)
43+
MonitorInflationCause(String text) {
44+
this.text = text;
45+
}
46+
47+
public String getText() {
48+
return text;
49+
}
50+
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MonitorSupport.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ public static MonitorSupport singleton() {
4444
/**
4545
* Implements the semantics of the monitorenter bytecode.
4646
*/
47-
public abstract void monitorEnter(Object obj);
47+
public abstract void monitorEnter(Object obj, MonitorInflationCause cause);
4848

4949
/**
5050
* Implements the semantics of the monitorexit bytecode.
5151
*/
52-
public abstract void monitorExit(Object obj);
52+
public abstract void monitorExit(Object obj, MonitorInflationCause cause);
5353

5454
/*
5555
* Support for objects that are re-locked during deoptimization. This method is called when

0 commit comments

Comments
 (0)