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 @@ -209,7 +209,7 @@ private boolean collectImpl(GCCause cause, long requestingNanoTime, boolean forc

NoAllocationVerifier nav = noAllocationVerifier.open();
try {
long startTicks = JfrGCEventSupport.startGCPhasePause();
long startTicks = JfrGCEventSupport.getTicks();
try {
outOfMemory = doCollectImpl(cause, requestingNanoTime, forceFullGC, false);
if (outOfMemory) {
Expand All @@ -223,7 +223,7 @@ private boolean collectImpl(GCCause cause, long requestingNanoTime, boolean forc
}
}
} finally {
JfrGCEventSupport.emitGCPhasePauseEvent(getCollectionEpoch(), cause.getName(), startTicks);
JfrGCEventSupport.emitGarbageCollectionEvent(getCollectionEpoch(), cause, startTicks);
}
} finally {
nav.close();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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.genscavenge;

import com.oracle.svm.core.heap.GCName;
import com.oracle.svm.core.SubstrateOptions;

final class GenScavengeGCName extends GCName {
public static final GCName GenScavenge;

static {
if (SubstrateOptions.UseEpsilonGC.getValue()) {
GenScavenge = new GenScavengeGCName("epsilon");
} else {
assert SubstrateOptions.UseSerialGC.getValue();
GenScavenge = new GenScavengeGCName("serial");
}
}

private GenScavengeGCName(String name) {
super(name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,11 @@
import org.graalvm.word.UnsignedWord;

import com.oracle.svm.core.annotate.Uninterruptible;
import com.oracle.svm.core.jfr.JfrBuffer;
import com.oracle.svm.core.heap.GCCause;
import com.oracle.svm.core.jfr.JfrEvent;
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.JfrThreadLocal;
import com.oracle.svm.core.jfr.JfrTicks;
import com.oracle.svm.core.jfr.SubstrateJVM;
import com.oracle.svm.core.util.VMError;
Expand All @@ -44,6 +43,13 @@ class JfrGCEventSupport {
private static final int MAX_PHASE_LEVEL = 4;
private static int currentPhase;

public static long getTicks() {
if (!HasJfrSupport.get()) {
return 0;
}
return JfrTicks.elapsedTicks();
}

public static long startGCPhasePause() {
if (!HasJfrSupport.get()) {
return 0;
Expand All @@ -52,6 +58,31 @@ public static long startGCPhasePause() {
return JfrTicks.elapsedTicks();
}

@Uninterruptible(reason = "Accesses a JFR buffer.")
public static void emitGarbageCollectionEvent(UnsignedWord gcEpoch, GCCause cause, long start) {
if (!HasJfrSupport.get()) {
return;
}

long end = JfrTicks.elapsedTicks();
long pauseTime = end - start;
if (SubstrateJVM.isRecording() && SubstrateJVM.get().isEnabled(JfrEvent.GarbageCollection)) {
JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class);
JfrNativeEventWriterDataAccess.initializeThreadLocalNativeBuffer(data);

JfrNativeEventWriter.beginEventWrite(data, false);
JfrNativeEventWriter.putLong(data, JfrEvent.GarbageCollection.getId());
JfrNativeEventWriter.putLong(data, start);
JfrNativeEventWriter.putLong(data, pauseTime);
JfrNativeEventWriter.putLong(data, gcEpoch.rawValue());
JfrNativeEventWriter.putLong(data, GenScavengeGCName.GenScavenge.getId());
JfrNativeEventWriter.putLong(data, cause.getId());
JfrNativeEventWriter.putLong(data, pauseTime); // sum of pause
JfrNativeEventWriter.putLong(data, pauseTime); // longest pause
JfrNativeEventWriter.endEventWrite(data, false);
}
}

@Uninterruptible(reason = "Accesses a JFR buffer.")
public static void emitGCPhasePauseEvent(UnsignedWord gcEpoch, String name, long startTicks) {
if (!HasJfrSupport.get()) {
Expand All @@ -62,9 +93,8 @@ public static void emitGCPhasePauseEvent(UnsignedWord gcEpoch, String name, long
JfrEvent event = getGCPhasePauseEvent(level);
if (SubstrateJVM.isRecording() && SubstrateJVM.get().isEnabled(event)) {
long end = JfrTicks.elapsedTicks();
JfrBuffer buffer = ((JfrThreadLocal) SubstrateJVM.getThreadLocal()).getNativeBuffer();
JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class);
JfrNativeEventWriterDataAccess.initialize(data, buffer);
JfrNativeEventWriterDataAccess.initializeThreadLocalNativeBuffer(data);

JfrNativeEventWriter.beginEventWrite(data, false);
JfrNativeEventWriter.putLong(data, event.getId());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. 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
Expand Down Expand Up @@ -82,6 +82,10 @@ public static GCCause fromId(int causeId) {
return GCCauses[causeId];
}

public static GCCause[] getGCCauses() {
return GCCauses;
}

@Platforms(Platform.HOSTED_ONLY.class)
public static void cacheReverseMapping() {
GCCauses = HostedGCCauseList.toArray(new GCCause[HostedGCCauseList.size()]);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* 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.heap;

import java.util.ArrayList;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.hosted.Feature;

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

/**
* This class holds supported garbage collector names.
*/
public class GCName {
@Platforms(Platform.HOSTED_ONLY.class) private static final ArrayList<GCName> HostedGCNameList = new ArrayList<>();

@UnknownObjectField(types = {GCName[].class}) protected static GCName[] GCNames;

private final int id;
private final String name;

@Platforms(Platform.HOSTED_ONLY.class)
protected GCName(String name) {
this.name = name;
this.id = addGCNameMapping();
}

@Platforms(Platform.HOSTED_ONLY.class)
private int addGCNameMapping() {
synchronized (HostedGCNameList) {
int newId = HostedGCNameList.size();
HostedGCNameList.add(newId, this);
return newId;
}
}

public String getName() {
return name;
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public int getId() {
return id;
}

public static GCName[] getGCNames() {
return GCNames;
}

@Platforms(Platform.HOSTED_ONLY.class)
public static void cacheReverseMapping() {
GCNames = HostedGCNameList.toArray(new GCName[HostedGCNameList.size()]);
}
}

@AutomaticFeature
class GCNameFeature implements Feature {
@Override
public void beforeCompilation(BeforeCompilationAccess access) {
GCName.cacheReverseMapping();
access.registerAsImmutable(GCName.GCNames);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public enum JfrEvent {
PhysicalMemory("jdk.PhysicalMemory"),
ExecutionSample("jdk.ExecutionSample"),
NativeMethodSample("jdk.NativeMethodSample"),
GarbageCollection("jdk.GarbageCollection"),
GCPhasePauseEvent("jdk.GCPhasePause"),
GCPhasePauseLevel1Event("jdk.GCPhasePauseLevel1"),
GCPhasePauseLevel2Event("jdk.GCPhasePauseLevel2"),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. 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
Expand Down Expand Up @@ -39,7 +39,9 @@ public enum JfrType {
Symbol("jdk.types.Symbol"),
Module("jdk.types.Module"),
Package("jdk.types.Package"),
FrameType("jdk.types.FrameType");
FrameType("jdk.types.FrameType"),
GCCause("jdk.types.GCCause"),
GCName("jdk.types.GCName");

private final long id;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. 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
Expand Down Expand Up @@ -35,6 +35,8 @@

import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.annotate.Uninterruptible;
import com.oracle.svm.core.heap.GCCause;
import com.oracle.svm.core.heap.GCName;
import com.oracle.svm.core.heap.Heap;
import com.oracle.svm.core.jfr.traceid.JfrTraceId;

Expand Down Expand Up @@ -62,6 +64,8 @@ public int write(JfrChunkWriter writer) {
count += writePackages(writer, typeInfo);
count += writeModules(writer, typeInfo);
count += writeClassLoaders(writer, typeInfo);
count += writeGCCauses(writer);
count += writeGCNames(writer);
return count;
}

Expand Down Expand Up @@ -186,6 +190,42 @@ private static int writeClassLoaders(JfrChunkWriter writer, TypeInfo typeInfo) {
return NON_EMPTY;
}

private static int writeGCCauses(JfrChunkWriter writer) {
// GCCauses has null entries
GCCause[] causes = GCCause.getGCCauses();
int nonNullItems = 0;
for (int index = 0; index < causes.length; index++) {
if (causes[index] != null) {
nonNullItems++;
}
}

assert nonNullItems > 0;

writer.writeCompressedLong(JfrType.GCCause.getId());
writer.writeCompressedLong(nonNullItems);
for (GCCause cause : causes) {
if (cause != null) {
writer.writeCompressedLong(cause.getId());
writer.writeString(cause.getName());
}
}
return NON_EMPTY;
}

private static int writeGCNames(JfrChunkWriter writer) {
GCName[] gcNames = GCName.getGCNames();
assert gcNames != null && gcNames.length > 0;

writer.writeCompressedLong(JfrType.GCName.getId());
writer.writeCompressedLong(gcNames.length);
for (GCName name : gcNames) {
writer.writeCompressedLong(name.getId());
writer.writeString(name.getName());
}
return NON_EMPTY;
}

private static void writeClassLoader(JfrChunkWriter writer, ClassLoader cl, long id) {
JfrSymbolRepository symbolRepo = SubstrateJVM.getSymbolRepository();
writer.writeCompressedLong(id);
Expand Down
Loading