Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ public enum JfrEvent {
GCPhasePauseLevel3Event("jdk.GCPhasePauseLevel3"),
GCPhasePauseLevel4Event("jdk.GCPhasePauseLevel4"),
SafepointBegin("jdk.SafepointBegin"),
SafepointEnd("jdk.SafepointEnd");
SafepointEnd("jdk.SafepointEnd"),
ExecuteVMOperation("jdk.ExecuteVMOperation");

private final long id;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public enum JfrType {
Package("jdk.types.Package"),
FrameType("jdk.types.FrameType"),
GCCause("jdk.types.GCCause"),
GCName("jdk.types.GCName");
GCName("jdk.types.GCName"),
VMOperation("jdk.types.VMOperationType");

private final long id;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public int write(JfrChunkWriter writer) {
count += writeClassLoaders(writer, typeInfo);
count += writeGCCauses(writer);
count += writeGCNames(writer);
count += writeVMOperations(writer);
return count;
}

Expand Down Expand Up @@ -225,6 +226,20 @@ private static int writeGCNames(JfrChunkWriter writer) {
return NON_EMPTY;
}

private static int writeVMOperations(JfrChunkWriter writer) {
Class<?>[] vmOperations = JfrVMOperations.singleton().getVMOperations();

assert vmOperations.length > 0;
writer.writeCompressedLong(JfrType.VMOperation.getId());
writer.writeCompressedLong(vmOperations.length);
for (int id = 0; id < vmOperations.length; id++) {
writer.writeCompressedLong(id + 1); // id starts with 1
writer.writeString(vmOperations[id].getCanonicalName());
}

return NON_EMPTY;
}

private static void writeClassLoader(JfrChunkWriter writer, ClassLoader cl, long id) {
JfrSymbolRepository symbolRepo = SubstrateJVM.getSymbolRepository();
writer.writeCompressedLong(id);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core.jfr;

import org.graalvm.compiler.api.replacements.Fold;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;

import com.oracle.svm.core.annotate.Uninterruptible;

import java.util.Collection;

public class JfrVMOperations {
private Class<?>[] vmOperations;

@Platforms(Platform.HOSTED_ONLY.class)
public JfrVMOperations() {
vmOperations = new Class<?>[0];
}

@Fold
public static JfrVMOperations singleton() {
return ImageSingletons.lookup(JfrVMOperations.class);
}

@Platforms(Platform.HOSTED_ONLY.class)
public void addVMOperations(Collection<Class<?>> vmOps) {
vmOperations = vmOps.toArray(new Class<?>[vmOps.size()]);
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public int getVMOperationId(Class<?> clazz) {
for (int id = 0; id < vmOperations.length; id++) {
if (vmOperations[id] == clazz) {
return id + 1; // id starts with 1
}
}
return 0;
}

public Class<?>[] getVMOperations() {
return vmOperations;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package com.oracle.svm.core.jfr.events;

import com.oracle.svm.core.annotate.Uninterruptible;
import com.oracle.svm.core.jfr.JfrEvent;
import com.oracle.svm.core.jfr.HasJfrSupport;
import com.oracle.svm.core.jfr.JfrNativeEventWriter;
import com.oracle.svm.core.jfr.JfrNativeEventWriterData;
import com.oracle.svm.core.jfr.JfrNativeEventWriterDataAccess;
import com.oracle.svm.core.jfr.JfrTicks;
import com.oracle.svm.core.jfr.JfrVMOperations;
import com.oracle.svm.core.jfr.SubstrateJVM;
import com.oracle.svm.core.thread.Safepoint;
import com.oracle.svm.core.thread.VMOperation;

import org.graalvm.nativeimage.IsolateThread;
import org.graalvm.nativeimage.StackValue;

public class ExecuteVMOperationEvent {
@Uninterruptible(reason = "Accesses a JFR buffer.")
public static void emit(VMOperation vmOperation, IsolateThread requestingThread, long startTicks) {
if (!HasJfrSupport.get()) {
return;
}

if (SubstrateJVM.isRecording() && SubstrateJVM.get().isEnabled(JfrEvent.ExecuteVMOperation)) {
int id = JfrVMOperations.singleton().getVMOperationId(vmOperation.getClass());
assert id != 0;
JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class);
JfrNativeEventWriterDataAccess.initializeThreadLocalNativeBuffer(data);
JfrNativeEventWriter.beginEventWrite(data, false);
JfrNativeEventWriter.putLong(data, JfrEvent.ExecuteVMOperation.getId());
JfrNativeEventWriter.putLong(data, startTicks);
JfrNativeEventWriter.putLong(data, JfrTicks.elapsedTicks() - startTicks);
JfrNativeEventWriter.putEventThread(data);
JfrNativeEventWriter.putLong(data, JfrVMOperations.singleton().getVMOperationId(vmOperation.getClass()));
JfrNativeEventWriter.putBoolean(data, vmOperation.getCausesSafepoint());
JfrNativeEventWriter.putBoolean(data, true); // Blocking
JfrNativeEventWriter.putThread(data, requestingThread);
JfrNativeEventWriter.putLong(data, vmOperation.getCausesSafepoint() ? Safepoint.Master.singleton().getSafepointId().rawValue() : 0);
JfrNativeEventWriter.endEventWrite(data, false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.annotate.RestrictHeapAccess;
import com.oracle.svm.core.annotate.Uninterruptible;
import com.oracle.svm.core.jfr.JfrTicks;
import com.oracle.svm.core.jfr.events.ExecuteVMOperationEvent;
import com.oracle.svm.core.log.Log;
import com.oracle.svm.core.thread.VMOperationControl.OpInProgress;
import com.oracle.svm.core.util.VMError;
Expand Down Expand Up @@ -83,8 +85,10 @@ protected final void execute(NativeVMOperationData data) {
VMOperation prevOperation = control.getInProgress().getOperation();
IsolateThread prevQueuingThread = control.getInProgress().getQueuingThread();
IsolateThread prevExecutingThread = control.getInProgress().getExecutingThread();
IsolateThread requestingThread = getQueuingThread(data);

control.setInProgress(this, getQueuingThread(data), CurrentIsolate.getCurrentThread(), true);
control.setInProgress(this, requestingThread, CurrentIsolate.getCurrentThread(), true);
long startTicks = JfrTicks.elapsedTicks();
try {
trace.string("[Executing operation ").string(name);
operate(data);
Expand All @@ -93,6 +97,7 @@ protected final void execute(NativeVMOperationData data) {
trace.string("[VMOperation.execute caught: ").string(t.getClass().getName()).string("]").newline();
throw VMError.shouldNotReachHere(t);
} finally {
ExecuteVMOperationEvent.emit(this, requestingThread, startTicks);
control.setInProgress(prevOperation, prevQueuingThread, prevExecutingThread, false);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@
package com.oracle.svm.hosted.jfr;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import com.oracle.svm.core.jfr.JfrGCNames;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.hosted.Feature;
Expand All @@ -47,23 +48,27 @@
import com.oracle.svm.core.jfr.JfrFrameTypeSerializer;
import com.oracle.svm.core.jfr.JfrGlobalMemory;
import com.oracle.svm.core.jfr.JfrManager;
import com.oracle.svm.core.jfr.JfrGCNames;
import com.oracle.svm.core.jfr.JfrNativeEventWriter;
import com.oracle.svm.core.jfr.JfrNativeEventWriterData;
import com.oracle.svm.core.jfr.JfrRecorderThread;
import com.oracle.svm.core.jfr.JfrSerializerSupport;
import com.oracle.svm.core.jfr.JfrThreadLocal;
import com.oracle.svm.core.jfr.JfrThreadStateSerializer;
import com.oracle.svm.core.jfr.JfrVMOperations;
import com.oracle.svm.core.jfr.SubstrateJVM;
import com.oracle.svm.core.jfr.traceid.JfrTraceId;
import com.oracle.svm.core.jfr.traceid.JfrTraceIdEpoch;
import com.oracle.svm.core.jfr.traceid.JfrTraceIdMap;
import com.oracle.svm.core.meta.SharedType;
import com.oracle.svm.core.thread.ThreadListenerFeature;
import com.oracle.svm.core.thread.ThreadListenerSupport;
import com.oracle.svm.core.thread.VMOperation;
import com.oracle.svm.core.util.UserError;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.hosted.FeatureImpl;
import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl;
import com.oracle.svm.hosted.meta.HostedType;
import com.oracle.svm.util.ModuleSupport;
import com.oracle.svm.util.ReflectionUtil;
import com.sun.management.HotSpotDiagnosticMXBean;
Expand Down Expand Up @@ -179,6 +184,7 @@ public void afterRegistration(AfterRegistrationAccess access) {
ImageSingletons.add(JfrTraceIdMap.class, new JfrTraceIdMap());
ImageSingletons.add(JfrTraceIdEpoch.class, new JfrTraceIdEpoch());
ImageSingletons.add(JfrGCNames.class, new JfrGCNames());
ImageSingletons.add(JfrVMOperations.class, new JfrVMOperations());

JfrSerializerSupport.get().register(new JfrFrameTypeSerializer());
JfrSerializerSupport.get().register(new JfrThreadStateSerializer());
Expand Down Expand Up @@ -228,12 +234,23 @@ public void beforeCompilation(BeforeCompilationAccess a) {

// Scan all classes and build sets of packages, modules and class-loaders. Count all items.
Collection<? extends SharedType> types = ((FeatureImpl.CompilationAccessImpl) a).getTypes();
Collection<Class<?>> vmOperations = new ArrayList<>();
for (SharedType type : types) {
DynamicHub hub = type.getHub();
Class<?> clazz = hub.getHostedJavaClass();
// Off-set by one for error-catcher
JfrTraceId.assign(clazz, hub.getTypeID() + 1);

// Capture concrete VMOperation types for ExecuteVMOperationEvent
HostedType ht = (HostedType) type;
if (VMOperation.class.isAssignableFrom(clazz) &&
!clazz.isInterface() &&
!Modifier.isAbstract(clazz.getModifiers()) &&
ht.getWrapped().isReachable()) {
vmOperations.add(clazz);
}
}
ImageSingletons.lookup(JfrVMOperations.class).addVMOperations(vmOperations);
}

private static void eventSubtypeReachable(DuringAnalysisAccess a, Class<?> c) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ public String[] getTestedEvents() {
"jdk.GarbageCollection",
"jdk.GCPhasePause",
"jdk.GCPhasePauseLevel1",
"jdk.GCPhasePauseLevel2"
"jdk.GCPhasePauseLevel2",
"jdk.ExecuteVMOperation"
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import com.oracle.svm.test.jfr.utils.poolparsers.ThreadConstantPoolParser;
import com.oracle.svm.test.jfr.utils.poolparsers.ThreadGroupConstantPoolParser;
import com.oracle.svm.test.jfr.utils.poolparsers.ThreadStateConstantPoolParser;
import com.oracle.svm.test.jfr.utils.poolparsers.VMOperationConstantPoolParser;
import jdk.jfr.Recording;
import org.junit.Assert;

Expand All @@ -76,6 +77,7 @@ public class JfrFileParser {

supportedConstantPools.put(JfrType.GCName.getId(), new GCNameConstantPoolParser());
supportedConstantPools.put(JfrType.GCCause.getId(), new GCCauseConstantPoolParser());
supportedConstantPools.put(JfrType.VMOperation.getId(), new VMOperationConstantPoolParser());
}

public static HashMap<Long, ConstantPoolParser> getSupportedConstantPools() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package com.oracle.svm.test.jfr.utils.poolparsers;

import com.oracle.svm.test.jfr.utils.RecordingInput;
import org.junit.Assert;

import java.io.IOException;

public class VMOperationConstantPoolParser extends ConstantPoolParser {

@Override
public void parse(RecordingInput input) throws IOException {
int numberOfVMOperationTypes = input.readInt();
for (int i = 0; i < numberOfVMOperationTypes; i++) {
addFoundId(input.readInt()); // Id.
Assert.assertFalse("VMOperation type is empty!", input.readUTF().isEmpty());
}
}
}