From 45fd729794140fd4fa24878d710bfa378d83029d Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Mon, 19 Dec 2022 15:29:10 -0500 Subject: [PATCH 1/5] event reports correct class values --- .../genscavenge/ThreadLocalAllocation.java | 7 ++ .../src/com/oracle/svm/core/jfr/JfrEvent.java | 1 + .../oracle/svm/core/jfr/JfrThreadLocal.java | 5 +- .../ObjectAllocationInNewTLABEvent.java | 67 +++++++++++++++++++ 4 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ObjectAllocationInNewTLABEvent.java diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java index 3bfd58aa59e9..561a1a847a7a 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java @@ -226,6 +226,7 @@ private static Object slowPathNewInstance(Word objectHeader) { @RestrictHeapAccess(access = RestrictHeapAccess.Access.NO_ALLOCATION, reason = "Must not allocate in the implementation of allocation.") private static Object slowPathNewInstanceWithoutAllocating(DynamicHub hub) { DeoptTester.disableDeoptTesting(); + long startTicks = com.oracle.svm.core.jfr.JfrTicks.elapsedTicks(); try { HeapImpl.exitIfAllocationDisallowed("ThreadLocalAllocation.slowPathNewInstanceWithoutAllocating", DynamicHub.toClass(hub).getName()); GCImpl.getGCImpl().maybeCollectOnAllocation(); @@ -233,6 +234,10 @@ private static Object slowPathNewInstanceWithoutAllocating(DynamicHub hub) { AlignedHeader newTlab = HeapImpl.getChunkProvider().produceAlignedChunk(); return allocateInstanceInNewTlab(hub, newTlab); } finally { + com.oracle.svm.core.jfr.events.ObjectAllocationInNewTLABEvent.emit(startTicks, + DynamicHub.toClass(hub), + LayoutEncoding.getPureInstanceSize(hub.getLayoutEncoding()).rawValue(), + HeapParameters.getAlignedHeapChunkSize().rawValue()); DeoptTester.enableDeoptTesting(); } } @@ -287,6 +292,7 @@ private static Object slowPathNewArrayLikeObject(Word objectHeader, int length, @RestrictHeapAccess(access = RestrictHeapAccess.Access.NO_ALLOCATION, reason = "Must not allocate in the implementation of allocation.") private static Object slowPathNewArrayLikeObject0(DynamicHub hub, int length, UnsignedWord size, byte[] podReferenceMap) { DeoptTester.disableDeoptTesting(); + long startTicks = com.oracle.svm.core.jfr.JfrTicks.elapsedTicks(); try { HeapImpl.exitIfAllocationDisallowed("ThreadLocalAllocation.slowPathNewArrayOrPodWithoutAllocating", DynamicHub.toClass(hub).getName()); GCImpl.getGCImpl().maybeCollectOnAllocation(); @@ -308,6 +314,7 @@ private static Object slowPathNewArrayLikeObject0(DynamicHub hub, int length, Un } return array; } finally { + com.oracle.svm.core.jfr.events.ObjectAllocationInNewTLABEvent.emit(startTicks, DynamicHub.toClass(hub),size.rawValue(), UnalignedHeapChunk.getChunkSizeForObject(size).rawValue()); DeoptTester.enableDeoptTesting(); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrEvent.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrEvent.java index 3635233cfd5c..85f9450bf6eb 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrEvent.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrEvent.java @@ -63,6 +63,7 @@ public final class JfrEvent { public static final JfrEvent ThreadSleep = create("jdk.ThreadSleep", JDK17OrEarlier.class); public static final JfrEvent ThreadPark = create("jdk.ThreadPark"); public static final JfrEvent JavaMonitorWait = create("jdk.JavaMonitorWait"); + public static final JfrEvent ObjectAllocationInNewTLAB = create("jdk.ObjectAllocationInNewTLAB"); private final long id; private final String name; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java index 5dbcb2c2f8c8..3793922ed979 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java @@ -203,7 +203,10 @@ public JfrBuffer getNativeBuffer() { } return result; } - + @Uninterruptible(reason = "Accesses a JFR buffer.", callerMustBe = true) + public boolean JfrThreadLocalInitialized() { + return threadId.get() > 0; + } @Uninterruptible(reason = "Accesses a JFR buffer.", callerMustBe = true) public static JfrBuffer getJavaBuffer(IsolateThread thread) { assert (VMOperation.isInProgressAtSafepoint()); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ObjectAllocationInNewTLABEvent.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ObjectAllocationInNewTLABEvent.java new file mode 100644 index 000000000000..4ffe1aa5c9c1 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ObjectAllocationInNewTLABEvent.java @@ -0,0 +1,67 @@ +/* + * 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.Uninterruptible; +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.JfrTicks; +import com.oracle.svm.core.jfr.SubstrateJVM; +import com.oracle.svm.core.jfr.HasJfrSupport; +import com.oracle.svm.core.jfr.JfrThreadLocal; +import org.graalvm.nativeimage.StackValue; + +public class ObjectAllocationInNewTLABEvent { + public static void emit(long startTicks, Class clazz, long allocationSize, long tlabSize) { + if (HasJfrSupport.get()) { + emit0(startTicks, clazz, allocationSize, tlabSize); + } + } + + @Uninterruptible(reason = "Accesses a JFR buffer.") + private static void emit0(long startTicks, Class clazz, long allocationSize, long tlabSize) { + + if (SubstrateJVM.isRecording() && SubstrateJVM.get().isEnabled(JfrEvent.ObjectAllocationInNewTLAB)) { + JfrThreadLocal jfrThreadLocal = (JfrThreadLocal) SubstrateJVM.getThreadLocal(); + if (!jfrThreadLocal.JfrThreadLocalInitialized()){ + return; + } + JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class); + JfrNativeEventWriterDataAccess.initializeThreadLocalNativeBuffer(data); + JfrNativeEventWriter.beginSmallEvent(data, JfrEvent.ObjectAllocationInNewTLAB); + JfrNativeEventWriter.putLong(data, startTicks); + JfrNativeEventWriter.putEventThread(data); + JfrNativeEventWriter.putLong(data, SubstrateJVM.get().getStackTraceId(JfrEvent.ObjectAllocationInNewTLAB, 0)); + JfrNativeEventWriter.putClass(data, clazz); + JfrNativeEventWriter.putLong(data, allocationSize); + JfrNativeEventWriter.putLong(data, tlabSize); + JfrNativeEventWriter.endSmallEvent(data); + } + } +} From 0502869a6bc3abd9bc55e8a0ac8773e3af51e509 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Mon, 19 Dec 2022 16:21:32 -0500 Subject: [PATCH 2/5] comment for clarity. Checkstyle --- .../core/genscavenge/ThreadLocalAllocation.java | 16 +++++++++------- .../com/oracle/svm/core/jfr/JfrThreadLocal.java | 4 +++- .../events/ObjectAllocationInNewTLABEvent.java | 8 +++++--- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java index 561a1a847a7a..9956e0f09e18 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java @@ -73,6 +73,8 @@ import com.oracle.svm.core.threadlocal.FastThreadLocalFactory; import com.oracle.svm.core.threadlocal.FastThreadLocalWord; import com.oracle.svm.core.util.VMError; +import com.oracle.svm.core.jfr.events.ObjectAllocationInNewTLABEvent; +import com.oracle.svm.core.jfr.JfrTicks; /** * Bump-pointer allocation from thread-local top and end Pointers. Many of these methods are called @@ -226,7 +228,7 @@ private static Object slowPathNewInstance(Word objectHeader) { @RestrictHeapAccess(access = RestrictHeapAccess.Access.NO_ALLOCATION, reason = "Must not allocate in the implementation of allocation.") private static Object slowPathNewInstanceWithoutAllocating(DynamicHub hub) { DeoptTester.disableDeoptTesting(); - long startTicks = com.oracle.svm.core.jfr.JfrTicks.elapsedTicks(); + long startTicks = JfrTicks.elapsedTicks(); try { HeapImpl.exitIfAllocationDisallowed("ThreadLocalAllocation.slowPathNewInstanceWithoutAllocating", DynamicHub.toClass(hub).getName()); GCImpl.getGCImpl().maybeCollectOnAllocation(); @@ -234,10 +236,10 @@ private static Object slowPathNewInstanceWithoutAllocating(DynamicHub hub) { AlignedHeader newTlab = HeapImpl.getChunkProvider().produceAlignedChunk(); return allocateInstanceInNewTlab(hub, newTlab); } finally { - com.oracle.svm.core.jfr.events.ObjectAllocationInNewTLABEvent.emit(startTicks, - DynamicHub.toClass(hub), - LayoutEncoding.getPureInstanceSize(hub.getLayoutEncoding()).rawValue(), - HeapParameters.getAlignedHeapChunkSize().rawValue()); + ObjectAllocationInNewTLABEvent.emit(startTicks, + DynamicHub.toClass(hub), + LayoutEncoding.getPureInstanceSize(hub.getLayoutEncoding()).rawValue(), + HeapParameters.getAlignedHeapChunkSize().rawValue()); DeoptTester.enableDeoptTesting(); } } @@ -292,7 +294,7 @@ private static Object slowPathNewArrayLikeObject(Word objectHeader, int length, @RestrictHeapAccess(access = RestrictHeapAccess.Access.NO_ALLOCATION, reason = "Must not allocate in the implementation of allocation.") private static Object slowPathNewArrayLikeObject0(DynamicHub hub, int length, UnsignedWord size, byte[] podReferenceMap) { DeoptTester.disableDeoptTesting(); - long startTicks = com.oracle.svm.core.jfr.JfrTicks.elapsedTicks(); + long startTicks = JfrTicks.elapsedTicks(); try { HeapImpl.exitIfAllocationDisallowed("ThreadLocalAllocation.slowPathNewArrayOrPodWithoutAllocating", DynamicHub.toClass(hub).getName()); GCImpl.getGCImpl().maybeCollectOnAllocation(); @@ -314,7 +316,7 @@ private static Object slowPathNewArrayLikeObject0(DynamicHub hub, int length, Un } return array; } finally { - com.oracle.svm.core.jfr.events.ObjectAllocationInNewTLABEvent.emit(startTicks, DynamicHub.toClass(hub),size.rawValue(), UnalignedHeapChunk.getChunkSizeForObject(size).rawValue()); + ObjectAllocationInNewTLABEvent.emit(startTicks, DynamicHub.toClass(hub), size.rawValue(), UnalignedHeapChunk.getChunkSizeForObject(size).rawValue()); DeoptTester.enableDeoptTesting(); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java index 3793922ed979..7daa524ac580 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java @@ -203,10 +203,12 @@ public JfrBuffer getNativeBuffer() { } return result; } + @Uninterruptible(reason = "Accesses a JFR buffer.", callerMustBe = true) - public boolean JfrThreadLocalInitialized() { + public boolean initialized() { return threadId.get() > 0; } + @Uninterruptible(reason = "Accesses a JFR buffer.", callerMustBe = true) public static JfrBuffer getJavaBuffer(IsolateThread thread) { assert (VMOperation.isInProgressAtSafepoint()); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ObjectAllocationInNewTLABEvent.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ObjectAllocationInNewTLABEvent.java index 4ffe1aa5c9c1..9f89a529a2b9 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ObjectAllocationInNewTLABEvent.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ObjectAllocationInNewTLABEvent.java @@ -31,14 +31,13 @@ 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.SubstrateJVM; import com.oracle.svm.core.jfr.HasJfrSupport; import com.oracle.svm.core.jfr.JfrThreadLocal; import org.graalvm.nativeimage.StackValue; public class ObjectAllocationInNewTLABEvent { - public static void emit(long startTicks, Class clazz, long allocationSize, long tlabSize) { + public static void emit(long startTicks, Class clazz, long allocationSize, long tlabSize) { if (HasJfrSupport.get()) { emit0(startTicks, clazz, allocationSize, tlabSize); } @@ -49,7 +48,10 @@ private static void emit0(long startTicks, Class clazz, long allocationSize, if (SubstrateJVM.isRecording() && SubstrateJVM.get().isEnabled(JfrEvent.ObjectAllocationInNewTLAB)) { JfrThreadLocal jfrThreadLocal = (JfrThreadLocal) SubstrateJVM.getThreadLocal(); - if (!jfrThreadLocal.JfrThreadLocalInitialized()){ + + // This check is needed to avoid issues upon allocation from the thread that invokes the + // Java main method and shutdown. + if (!jfrThreadLocal.initialized()) { return; } JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class); From b9ccd398e2b0d65f17659e9dcaae4eb64b7659b1 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Mon, 19 Dec 2022 16:33:17 -0500 Subject: [PATCH 3/5] fix call to emit event --- .../oracle/svm/core/genscavenge/ThreadLocalAllocation.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java index 9956e0f09e18..e60101e3eb80 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java @@ -295,6 +295,7 @@ private static Object slowPathNewArrayLikeObject(Word objectHeader, int length, private static Object slowPathNewArrayLikeObject0(DynamicHub hub, int length, UnsignedWord size, byte[] podReferenceMap) { DeoptTester.disableDeoptTesting(); long startTicks = JfrTicks.elapsedTicks(); + long tlabSize = HeapParameters.getAlignedHeapChunkSize().rawValue(); try { HeapImpl.exitIfAllocationDisallowed("ThreadLocalAllocation.slowPathNewArrayOrPodWithoutAllocating", DynamicHub.toClass(hub).getName()); GCImpl.getGCImpl().maybeCollectOnAllocation(); @@ -303,6 +304,7 @@ private static Object slowPathNewArrayLikeObject0(DynamicHub hub, int length, Un /* Large arrays go into their own unaligned chunk. */ boolean needsZeroing = !HeapChunkProvider.areUnalignedChunksZeroed(); UnalignedHeapChunk.UnalignedHeader newTlabChunk = HeapImpl.getChunkProvider().produceUnalignedChunk(size); + tlabSize = UnalignedHeapChunk.getChunkSizeForObject(size).rawValue(); return allocateLargeArrayLikeObjectInNewTlab(hub, length, size, newTlabChunk, needsZeroing, podReferenceMap); } /* Small arrays go into the regular aligned chunk. */ @@ -316,7 +318,7 @@ private static Object slowPathNewArrayLikeObject0(DynamicHub hub, int length, Un } return array; } finally { - ObjectAllocationInNewTLABEvent.emit(startTicks, DynamicHub.toClass(hub), size.rawValue(), UnalignedHeapChunk.getChunkSizeForObject(size).rawValue()); + ObjectAllocationInNewTLABEvent.emit(startTicks, DynamicHub.toClass(hub), size.rawValue(), tlabSize); DeoptTester.enableDeoptTesting(); } } From 03bf2c65063e08b3b94cb97c1942a88a104ab57a Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Thu, 2 Feb 2023 16:57:12 -0500 Subject: [PATCH 4/5] updates based on PR 5807 --- .../oracle/svm/core/jfr/JfrThreadLocal.java | 5 - .../ObjectAllocationInNewTLABEvent.java | 11 +- .../TestObjectAllocationInNewTLABEvent.java | 117 ++++++++++++++++++ 3 files changed, 118 insertions(+), 15 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestObjectAllocationInNewTLABEvent.java diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java index a4f6bf94ae3b..7146086e6032 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java @@ -206,11 +206,6 @@ public JfrBuffer getNativeBuffer() { return result; } - @Uninterruptible(reason = "Accesses a JFR buffer.", callerMustBe = true) - public boolean initialized() { - return threadId.get() > 0; - } - @Uninterruptible(reason = "Accesses a JFR buffer.", callerMustBe = true) public static JfrBuffer getJavaBuffer(IsolateThread thread) { assert VMOperation.isInProgressAtSafepoint(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ObjectAllocationInNewTLABEvent.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ObjectAllocationInNewTLABEvent.java index 9f89a529a2b9..317bbf4d4819 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ObjectAllocationInNewTLABEvent.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/ObjectAllocationInNewTLABEvent.java @@ -33,7 +33,6 @@ import com.oracle.svm.core.jfr.JfrNativeEventWriterDataAccess; import com.oracle.svm.core.jfr.SubstrateJVM; import com.oracle.svm.core.jfr.HasJfrSupport; -import com.oracle.svm.core.jfr.JfrThreadLocal; import org.graalvm.nativeimage.StackValue; public class ObjectAllocationInNewTLABEvent { @@ -45,15 +44,7 @@ public static void emit(long startTicks, Class clazz, long allocationSize, lo @Uninterruptible(reason = "Accesses a JFR buffer.") private static void emit0(long startTicks, Class clazz, long allocationSize, long tlabSize) { - - if (SubstrateJVM.isRecording() && SubstrateJVM.get().isEnabled(JfrEvent.ObjectAllocationInNewTLAB)) { - JfrThreadLocal jfrThreadLocal = (JfrThreadLocal) SubstrateJVM.getThreadLocal(); - - // This check is needed to avoid issues upon allocation from the thread that invokes the - // Java main method and shutdown. - if (!jfrThreadLocal.initialized()) { - return; - } + if (JfrEvent.ObjectAllocationInNewTLAB.shouldEmit()) { JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class); JfrNativeEventWriterDataAccess.initializeThreadLocalNativeBuffer(data); JfrNativeEventWriter.beginSmallEvent(data, JfrEvent.ObjectAllocationInNewTLAB); diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestObjectAllocationInNewTLABEvent.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestObjectAllocationInNewTLABEvent.java new file mode 100644 index 000000000000..14446a871ab0 --- /dev/null +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestObjectAllocationInNewTLABEvent.java @@ -0,0 +1,117 @@ +/* + * 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; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.oracle.svm.core.jfr.JfrEvent; + +import jdk.jfr.consumer.RecordedClass; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordedThread; + +import java.util.Arrays; + +public class TestObjectAllocationInNewTLABEvent extends JfrTest { + static final int KILO = 1024; + // the default size for serial and epsilon GC in SVM. + static final int DEFAULT_ALIGNED_HEAP_CHUNK_SIZE = KILO * KILO; + + public static Helper helper = null; + public static byte[] byteArray = null; + + @Override + public String[] getTestedEvents() { + return new String[]{JfrEvent.ObjectAllocationInNewTLAB.getName()}; + } + + @Override + public void validateEvents() throws Throwable { + boolean foundBigByte = false; + boolean foundSmallByte = false; + boolean foundBigChar = false; + boolean foundInstance = false; + for (RecordedEvent event : getEvents()) { + String eventThread = event. getValue("eventThread").getJavaName(); + if (!eventThread.equals("main")) { + continue; + } + // >= To account for size of reference + if (event. getValue("allocationSize").longValue() >= (2 * DEFAULT_ALIGNED_HEAP_CHUNK_SIZE) && + event. getValue("tlabSize").longValue() >= (2 * DEFAULT_ALIGNED_HEAP_CHUNK_SIZE)) { + // verify previous owner + if (event. getValue("objectClass").getName().equals(char[].class.getName())) { + foundBigChar = true; + } else if (event. getValue("objectClass").getName().equals(byte[].class.getName())) { + foundBigByte = true; + } + } else if (event. getValue("allocationSize").longValue() >= KILO && event. getValue("tlabSize").longValue() == (DEFAULT_ALIGNED_HEAP_CHUNK_SIZE) && + event. getValue("objectClass").getName().equals(byte[].class.getName())) { + foundSmallByte = true; + } else if (event. getValue("tlabSize").longValue() == (DEFAULT_ALIGNED_HEAP_CHUNK_SIZE) && event. getValue("objectClass").getName().equals(Helper.class.getName())) { + foundInstance = true; + } + } + if (!foundBigChar || !foundBigByte || !foundSmallByte || !foundInstance) { + assertTrue("Expected events not found. foundBigChar: " + foundBigChar + " foundBigByte:" + foundBigByte + " foundSmallByte:" + foundSmallByte + " foundInstance:" + foundInstance, + foundBigChar && foundBigByte && foundSmallByte && foundInstance); + } + } + + @Test + public void test() throws Exception { + + // These arrays must result in exceeding the large array threshold, resulting in new TLABs. + byte[] bigByte = new byte[2 * DEFAULT_ALIGNED_HEAP_CHUNK_SIZE]; + Arrays.fill(bigByte, (byte) 0); + + // Using char, so it's the same size as bigByte. + char[] bigChar = new char[DEFAULT_ALIGNED_HEAP_CHUNK_SIZE]; + Arrays.fill(bigChar, 'm'); + + // Try to exhaust TLAB with arrays + for (int i = 0; i < DEFAULT_ALIGNED_HEAP_CHUNK_SIZE / KILO; i++) { + byteArray = new byte[KILO]; + Arrays.fill(byteArray, (byte) 0); + } + + // Try to exhaust TLAB with instances + for (int i = 0; i < DEFAULT_ALIGNED_HEAP_CHUNK_SIZE; i++) { + helper = new Helper(); + } + } + + /** + * This class is only needed to provide a unique name in the event's "objectClass" field that we + * check. + */ + static class Helper { + int testField; + } +} From 63461585a0fe2a68f3140f2b3bab19d97c7d16e9 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Fri, 3 Feb 2023 09:14:54 -0500 Subject: [PATCH 5/5] comments --- .../svm/test/jfr/TestObjectAllocationInNewTLABEvent.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestObjectAllocationInNewTLABEvent.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestObjectAllocationInNewTLABEvent.java index 14446a871ab0..d9209ed767c6 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestObjectAllocationInNewTLABEvent.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestObjectAllocationInNewTLABEvent.java @@ -87,21 +87,21 @@ event. getValue("objectClass").getName().equals(byte[].class.getN @Test public void test() throws Exception { - // These arrays must result in exceeding the large array threshold, resulting in new TLABs. + // These arrays must result in exceeding the large array threshold, resulting in new TLABs. Big Byte. byte[] bigByte = new byte[2 * DEFAULT_ALIGNED_HEAP_CHUNK_SIZE]; Arrays.fill(bigByte, (byte) 0); - // Using char, so it's the same size as bigByte. + // Using char, so it's the same size as bigByte. Big Char. char[] bigChar = new char[DEFAULT_ALIGNED_HEAP_CHUNK_SIZE]; Arrays.fill(bigChar, 'm'); - // Try to exhaust TLAB with arrays + // Try to exhaust TLAB with small arrays. Small byte. for (int i = 0; i < DEFAULT_ALIGNED_HEAP_CHUNK_SIZE / KILO; i++) { byteArray = new byte[KILO]; Arrays.fill(byteArray, (byte) 0); } - // Try to exhaust TLAB with instances + // Try to exhaust TLAB with instances. Instance. for (int i = 0; i < DEFAULT_ALIGNED_HEAP_CHUNK_SIZE; i++) { helper = new Helper(); }