From 9d65db1bc2f576d6d0f0c2453c3bbc83a57669fb Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Tue, 30 May 2023 14:10:10 +0200 Subject: [PATCH] Heap accounting improvements and cleanups. --- .../svm/core/genscavenge/GCAccounting.java | 68 +++++++++--------- .../oracle/svm/core/genscavenge/GCImpl.java | 71 +++++++++++-------- .../svm/core/genscavenge/HeapAccounting.java | 21 ++++-- .../genscavenge/JfrGCHeapSummaryEvent.java | 47 ++++-------- .../svm/core/genscavenge/OldGeneration.java | 8 ++- .../svm/core/jfr/JfrFrameTypeSerializer.java | 8 +-- .../com/oracle/svm/core/jfr/JfrGCWhen.java | 18 +++-- .../svm/core/jfr/JfrGCWhenSerializer.java | 11 ++- .../poolparsers/GCWhenConstantPoolParser.java | 2 +- 9 files changed, 129 insertions(+), 125 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java index c006ab6faa54..223bafeb9660 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java @@ -31,7 +31,6 @@ import com.oracle.svm.core.AlwaysInline; import com.oracle.svm.core.Uninterruptible; -import com.oracle.svm.core.log.Log; /** * This data is only updated during a GC. @@ -45,13 +44,14 @@ public final class GCAccounting { private long incrementalCollectionTotalNanos = 0; private long completeCollectionCount = 0; private long completeCollectionTotalNanos = 0; - private UnsignedWord collectedTotalChunkBytes = WordFactory.zero(); - private UnsignedWord allocatedChunkBytes = WordFactory.zero(); + private UnsignedWord totalCollectedChunkBytes = WordFactory.zero(); + private UnsignedWord totalAllocatedChunkBytes = WordFactory.zero(); private UnsignedWord lastIncrementalCollectionPromotedChunkBytes = WordFactory.zero(); private boolean lastIncrementalCollectionOverflowedSurvivors = false; /* Before and after measures. */ private UnsignedWord edenChunkBytesBefore = WordFactory.zero(); + private UnsignedWord edenChunkBytesAfter = WordFactory.zero(); private UnsignedWord youngChunkBytesBefore = WordFactory.zero(); private UnsignedWord youngChunkBytesAfter = WordFactory.zero(); private UnsignedWord oldChunkBytesBefore = WordFactory.zero(); @@ -61,7 +61,7 @@ public final class GCAccounting { * Bytes allocated in Objects, as opposed to bytes of chunks. These are only maintained if * -R:+PrintGCSummary because they are expensive. */ - private UnsignedWord collectedTotalObjectBytes = WordFactory.zero(); + private UnsignedWord totalCollectedObjectBytes = WordFactory.zero(); private UnsignedWord youngObjectBytesBefore = WordFactory.zero(); private UnsignedWord oldObjectBytesBefore = WordFactory.zero(); private UnsignedWord allocatedObjectBytes = WordFactory.zero(); @@ -78,8 +78,8 @@ public long getIncrementalCollectionTotalNanos() { return incrementalCollectionTotalNanos; } - UnsignedWord getAllocatedChunkBytes() { - return allocatedChunkBytes; + UnsignedWord getTotalAllocatedChunkBytes() { + return totalAllocatedChunkBytes; } public long getCompleteCollectionCount() { @@ -90,12 +90,12 @@ public long getCompleteCollectionTotalNanos() { return completeCollectionTotalNanos; } - UnsignedWord getCollectedTotalChunkBytes() { - return collectedTotalChunkBytes; + UnsignedWord getTotalCollectedChunkBytes() { + return totalCollectedChunkBytes; } - UnsignedWord getCollectedTotalObjectBytes() { - return collectedTotalObjectBytes; + UnsignedWord getTotalCollectedObjectBytes() { + return totalCollectedObjectBytes; } UnsignedWord getAllocatedObjectBytes() { @@ -110,6 +110,10 @@ UnsignedWord getEdenChunkBytesBefore() { return edenChunkBytesBefore; } + UnsignedWord getEdenChunkBytesAfter() { + return edenChunkBytesAfter; + } + UnsignedWord getYoungChunkBytesBefore() { return youngChunkBytesBefore; } @@ -127,30 +131,27 @@ public boolean hasLastIncrementalCollectionOverflowedSurvivors() { } void beforeCollection(boolean completeCollection) { - Log trace = Log.noopLog().string("[GCImpl.Accounting.beforeCollection:").newline(); /* Gather some space statistics. */ HeapImpl heap = HeapImpl.getHeapImpl(); YoungGeneration youngGen = heap.getYoungGeneration(); + OldGeneration oldGen = heap.getOldGeneration(); + edenChunkBytesBefore = youngGen.getEden().getChunkBytes(); youngChunkBytesBefore = youngGen.getChunkBytes(); - /* This is called before the collection, so OldSpace is FromSpace. */ - Space oldSpace = heap.getOldGeneration().getFromSpace(); - oldChunkBytesBefore = oldSpace.getChunkBytes(); + oldChunkBytesBefore = oldGen.getChunkBytes(); + /* Objects are allocated in the young generation. */ - allocatedChunkBytes = allocatedChunkBytes.add(youngGen.getEden().getChunkBytes()); + totalAllocatedChunkBytes = totalAllocatedChunkBytes.add(youngGen.getEden().getChunkBytes()); + if (SerialGCOptions.PrintGCSummary.getValue()) { UnsignedWord edenObjectBytesBefore = youngGen.getEden().computeObjectBytes(); youngObjectBytesBefore = edenObjectBytesBefore.add(youngGen.computeSurvivorObjectBytes()); - oldObjectBytesBefore = oldSpace.computeObjectBytes(); + oldObjectBytesBefore = oldGen.computeObjectBytes(); allocatedObjectBytes = allocatedObjectBytes.add(edenObjectBytesBefore); } if (!completeCollection) { lastIncrementalCollectionOverflowedSurvivors = false; } - trace.string(" edenChunkBytesBefore: ").unsigned(edenChunkBytesBefore) - .string(" youngChunkBytesBefore: ").unsigned(youngChunkBytesBefore) - .string(" oldChunkBytesBefore: ").unsigned(oldChunkBytesBefore); - trace.string("]").newline(); } /** Called after an object has been promoted from the young generation to the old generation. */ @@ -169,7 +170,6 @@ void afterCollection(boolean completeCollection, Timer collectionTimer) { } private void afterIncrementalCollection(Timer collectionTimer) { - Log trace = Log.noopLog().string("[GCImpl.Accounting.afterIncrementalCollection:"); /* * Aggregating collection information is needed because any given collection policy may not * be called for all collections, but may want to make decisions based on the aggregate @@ -179,39 +179,35 @@ private void afterIncrementalCollection(Timer collectionTimer) { afterCollectionCommon(); lastIncrementalCollectionPromotedChunkBytes = oldChunkBytesAfter.subtract(oldChunkBytesBefore); incrementalCollectionTotalNanos += collectionTimer.getMeasuredNanos(); - trace.string(" incrementalCollectionCount: ").signed(incrementalCollectionCount) - .string(" oldChunkBytesAfter: ").unsigned(oldChunkBytesAfter) - .string(" oldChunkBytesBefore: ").unsigned(oldChunkBytesBefore); - trace.string("]").newline(); } private void afterCompleteCollection(Timer collectionTimer) { - Log trace = Log.noopLog().string("[GCImpl.Accounting.afterCompleteCollection:"); completeCollectionCount += 1; afterCollectionCommon(); completeCollectionTotalNanos += collectionTimer.getMeasuredNanos(); - trace.string(" completeCollectionCount: ").signed(completeCollectionCount) - .string(" oldChunkBytesAfter: ").unsigned(oldChunkBytesAfter); - trace.string("]").newline(); } private void afterCollectionCommon() { HeapImpl heap = HeapImpl.getHeapImpl(); - // This is called after the collection, after the space flip, so OldSpace is FromSpace. YoungGeneration youngGen = heap.getYoungGeneration(); + OldGeneration oldGen = heap.getOldGeneration(); + + edenChunkBytesAfter = youngGen.getEden().getChunkBytes(); youngChunkBytesAfter = youngGen.getChunkBytes(); - Space oldSpace = heap.getOldGeneration().getFromSpace(); - oldChunkBytesAfter = oldSpace.getChunkBytes(); + oldChunkBytesAfter = oldGen.getChunkBytes(); + UnsignedWord beforeChunkBytes = youngChunkBytesBefore.add(oldChunkBytesBefore); - UnsignedWord afterChunkBytes = oldChunkBytesAfter.add(youngChunkBytesAfter); + UnsignedWord afterChunkBytes = youngChunkBytesAfter.add(oldChunkBytesAfter); + assert beforeChunkBytes.aboveOrEqual(afterChunkBytes); UnsignedWord collectedChunkBytes = beforeChunkBytes.subtract(afterChunkBytes); - collectedTotalChunkBytes = collectedTotalChunkBytes.add(collectedChunkBytes); + totalCollectedChunkBytes = totalCollectedChunkBytes.add(collectedChunkBytes); + if (SerialGCOptions.PrintGCSummary.getValue()) { UnsignedWord youngObjectBytesAfter = youngGen.computeObjectBytes(); - UnsignedWord oldObjectBytesAfter = oldSpace.computeObjectBytes(); + UnsignedWord oldObjectBytesAfter = oldGen.computeObjectBytes(); UnsignedWord beforeObjectBytes = youngObjectBytesBefore.add(oldObjectBytesBefore); UnsignedWord collectedObjectBytes = beforeObjectBytes.subtract(oldObjectBytesAfter).subtract(youngObjectBytesAfter); - collectedTotalObjectBytes = collectedTotalObjectBytes.add(collectedObjectBytes); + totalCollectedObjectBytes = totalCollectedObjectBytes.add(collectedObjectBytes); } } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java index 0be24f3c2964..b85f49c85c45 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java @@ -107,7 +107,6 @@ public final class GCImpl implements GC { private final Timers timers = new Timers(); private final CollectionVMOperation collectOperation = new CollectionVMOperation(); - private final NoAllocationVerifier noAllocationVerifier = NoAllocationVerifier.factory("GCImpl.GCImpl()", false); private final ChunkReleaser chunkReleaser = new ChunkReleaser(); private final CollectionPolicy policy; @@ -207,9 +206,11 @@ private void collectOperation(CollectionVMOperationData data) { GCCause cause = GCCause.fromId(data.getCauseId()); printGCBefore(cause.getName()); - JfrGCHeapSummaryEvent.emit(getCollectionEpoch(), JfrTicks.elapsedTicks(), getPolicy().getCurrentHeapCapacity().rawValue(), getChunkBytes().rawValue(), JfrGCWhen.BEFORE_GC); + + JfrGCHeapSummaryEvent.emit(JfrGCWhen.BEFORE_GC); boolean outOfMemory = collectImpl(cause, data.getRequestingNanoTime(), data.getForceFullGC()); - JfrGCHeapSummaryEvent.emit(getCollectionEpoch(), JfrTicks.elapsedTicks(), getPolicy().getCurrentHeapCapacity().rawValue(), getChunkBytes().rawValue(), JfrGCWhen.AFTER_GC); + JfrGCHeapSummaryEvent.emit(JfrGCWhen.AFTER_GC); + printGCAfter(cause.getName()); finishCollection(); @@ -219,36 +220,34 @@ private void collectOperation(CollectionVMOperationData data) { } private boolean collectImpl(GCCause cause, long requestingNanoTime, boolean forceFullGC) { - boolean outOfMemory; - precondition(); + HeapImpl.getHeapImpl().getAccounting().notifyBeforeCollection(); - NoAllocationVerifier nav = noAllocationVerifier.open(); + boolean outOfMemory; + long startTicks = JfrTicks.elapsedTicks(); try { - long startTicks = JfrTicks.elapsedTicks(); - try { - outOfMemory = doCollectImpl(cause, requestingNanoTime, forceFullGC, false); - if (outOfMemory) { - // Avoid running out of memory with a full GC that reclaims softly reachable - // objects - ReferenceObjectProcessing.setSoftReferencesAreWeak(true); - try { - outOfMemory = doCollectImpl(cause, requestingNanoTime, true, true); - } finally { - ReferenceObjectProcessing.setSoftReferencesAreWeak(false); - } + outOfMemory = doCollectImpl(cause, requestingNanoTime, forceFullGC, false); + if (outOfMemory) { + // Avoid running out of memory with a full GC that reclaims softly reachable + // objects + ReferenceObjectProcessing.setSoftReferencesAreWeak(true); + try { + outOfMemory = doCollectImpl(cause, requestingNanoTime, true, true); + } finally { + ReferenceObjectProcessing.setSoftReferencesAreWeak(false); } - } finally { - JfrGCEvents.emitGarbageCollectionEvent(getCollectionEpoch(), cause, startTicks); } } finally { - nav.close(); + JfrGCEvents.emitGarbageCollectionEvent(getCollectionEpoch(), cause, startTicks); } - postcondition(); + HeapImpl.getHeapImpl().getAccounting().notifyAfterCollection(this.accounting); + GenScavengeMemoryPoolMXBeans.notifyAfterCollection(this.accounting); return outOfMemory; } private boolean doCollectImpl(GCCause cause, long requestingNanoTime, boolean forceFullGC, boolean forceNoIncremental) { + precondition(); + CommittedMemoryProvider.get().beforeGarbageCollection(); boolean incremental = !forceNoIncremental && !policy.shouldCollectCompletely(false); @@ -276,6 +275,8 @@ private boolean doCollectImpl(GCCause cause, long requestingNanoTime, boolean fo HeapImpl.getChunkProvider().freeExcessAlignedChunks(); CommittedMemoryProvider.get().afterGarbageCollection(); + + postcondition(); return outOfMemory; } @@ -300,12 +301,9 @@ private boolean doCollectOnce(GCCause cause, long requestingNanoTime, boolean co collectionTimer.close(); } - HeapImpl.getHeapImpl().getAccounting().setEdenAndYoungGenBytes(WordFactory.zero(), accounting.getYoungChunkBytesAfter()); accounting.afterCollection(completeCollection, collectionTimer); policy.onCollectionEnd(completeCollection, cause); - GenScavengeMemoryPoolMXBeans.notifyAfterCollection(accounting); - UnsignedWord usedBytes = getChunkBytes(); UnsignedWord freeBytes = policy.getCurrentHeapCapacity().subtract(usedBytes); ReferenceObjectProcessing.afterCollection(freeBytes); @@ -1269,6 +1267,8 @@ private CollectionInProgressError() { } private static class CollectionVMOperation extends NativeVMOperation { + private final NoAllocationVerifier noAllocationVerifier = NoAllocationVerifier.factory("CollectionVMOperation", false); + CollectionVMOperation() { super(VMOperationInfos.get(CollectionVMOperation.class, "Garbage collection", SystemEffect.SAFEPOINT)); } @@ -1282,6 +1282,17 @@ public boolean isGC() { @Override @RestrictHeapAccess(access = RestrictHeapAccess.Access.NO_ALLOCATION, reason = "Must not allocate while collecting") protected void operate(NativeVMOperationData data) { + NoAllocationVerifier nav = noAllocationVerifier.open(); + try { + collect((CollectionVMOperationData) data); + } catch (Throwable t) { + throw VMError.shouldNotReachHere(t); + } finally { + nav.close(); + } + } + + private static void collect(CollectionVMOperationData data) { /* * Exceptions during collections are fatal. The heap is likely in an inconsistent state. * The GC must also be allocation free, i.e., we cannot allocate exception stack traces @@ -1292,9 +1303,7 @@ protected void operate(NativeVMOperationData data) { */ ImplicitExceptions.activateImplicitExceptionsAreFatal(); try { - HeapImpl.getGCImpl().collectOperation((CollectionVMOperationData) data); - } catch (Throwable t) { - throw VMError.shouldNotReachHere(t); + HeapImpl.getGCImpl().collectOperation(data); } finally { ImplicitExceptions.deactivateImplicitExceptionsAreFatal(); } @@ -1422,11 +1431,11 @@ private void printGCSummary() { UnsignedWord youngChunkBytes = edenSpace.getChunkBytes(); UnsignedWord youngObjectBytes = edenSpace.computeObjectBytes(); - UnsignedWord allocatedChunkBytes = accounting.getAllocatedChunkBytes().add(youngChunkBytes); + UnsignedWord allocatedChunkBytes = accounting.getTotalAllocatedChunkBytes().add(youngChunkBytes); UnsignedWord allocatedObjectBytes = accounting.getAllocatedObjectBytes().add(youngObjectBytes); - log.string(prefix).string("CollectedTotalChunkBytes: ").signed(accounting.getCollectedTotalChunkBytes()).newline(); - log.string(prefix).string("CollectedTotalObjectBytes: ").signed(accounting.getCollectedTotalObjectBytes()).newline(); + log.string(prefix).string("CollectedTotalChunkBytes: ").signed(accounting.getTotalCollectedChunkBytes()).newline(); + log.string(prefix).string("CollectedTotalObjectBytes: ").signed(accounting.getTotalCollectedObjectBytes()).newline(); log.string(prefix).string("AllocatedNormalChunkBytes: ").signed(allocatedChunkBytes).newline(); log.string(prefix).string("AllocatedNormalObjectBytes: ").signed(allocatedObjectBytes).newline(); diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapAccounting.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapAccounting.java index 599adb600cf0..0b38c250835d 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapAccounting.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapAccounting.java @@ -40,14 +40,25 @@ public final class HeapAccounting { private final UninterruptibleUtils.AtomicUnsigned edenUsedBytes = new UninterruptibleUtils.AtomicUnsigned(); private final UninterruptibleUtils.AtomicUnsigned youngUsedBytes = new UninterruptibleUtils.AtomicUnsigned(); + /* During a GC, the values are invalid. They are updated once the GC ends. */ + private boolean invalidData; + @Platforms(Platform.HOSTED_ONLY.class) HeapAccounting() { } - public void setEdenAndYoungGenBytes(UnsignedWord edenBytes, UnsignedWord youngBytes) { + public void notifyBeforeCollection() { + assert VMOperation.isGCInProgress(); + invalidData = true; + } + + public void notifyAfterCollection(GCAccounting accounting) { assert VMOperation.isGCInProgress() : "would cause races otherwise"; - youngUsedBytes.set(youngBytes); - edenUsedBytes.set(edenBytes); + assert invalidData; + + youngUsedBytes.set(accounting.getYoungChunkBytesAfter()); + edenUsedBytes.set(accounting.getEdenChunkBytesAfter()); + invalidData = false; } @Uninterruptible(reason = "Must be done during TLAB registration to not race with a potential collection.", callerMustBe = true) @@ -58,13 +69,13 @@ public void increaseEdenUsedBytes(UnsignedWord value) { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public UnsignedWord getYoungUsedBytes() { - assert !VMOperation.isGCInProgress() : "value is incorrect during a GC"; + assert !invalidData : "value is incorrect during a GC"; return youngUsedBytes.get(); } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public UnsignedWord getEdenUsedBytes() { - assert !VMOperation.isGCInProgress() : "value is incorrect during a GC"; + assert !invalidData : "value is incorrect during a GC"; return edenUsedBytes.get(); } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/JfrGCHeapSummaryEvent.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/JfrGCHeapSummaryEvent.java index 4993ce18922e..48d2880f332f 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/JfrGCHeapSummaryEvent.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/JfrGCHeapSummaryEvent.java @@ -24,66 +24,45 @@ */ package com.oracle.svm.core.genscavenge; -import org.graalvm.compiler.api.replacements.Fold; - import org.graalvm.nativeimage.StackValue; import org.graalvm.word.UnsignedWord; -import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.Uninterruptible; - import com.oracle.svm.core.jfr.HasJfrSupport; import com.oracle.svm.core.jfr.JfrEvent; import com.oracle.svm.core.jfr.JfrGCWhen; 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; class JfrGCHeapSummaryEvent { - - public static void emit(UnsignedWord gcEpoch, long start, long committedSize, long heapUsed, JfrGCWhen gcWhen) { - if (HasJfrSupport.get() && isEnabled()) { - emit0(gcEpoch, start, committedSize, heapUsed, gcWhen); + public static void emit(JfrGCWhen gcWhen) { + if (HasJfrSupport.get()) { + emit0(GCImpl.getGCImpl().getCollectionEpoch(), JfrTicks.elapsedTicks(), HeapImpl.getHeapImpl().getCommittedBytes(), HeapImpl.getHeapImpl().getUsedBytes(), gcWhen); } } @Uninterruptible(reason = "Accesses a JFR buffer.") - private static void emit0(UnsignedWord gcEpoch, long start, long committedSize, long heapUsed, JfrGCWhen gcWhen) { - + private static void emit0(UnsignedWord gcEpoch, long start, UnsignedWord committedSize, UnsignedWord heapUsed, JfrGCWhen gcWhen) { if (JfrEvent.GCHeapSummary.shouldEmit()) { - JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class); JfrNativeEventWriterDataAccess.initializeThreadLocalNativeBuffer(data); JfrNativeEventWriter.beginSmallEvent(data, JfrEvent.GCHeapSummary); - - JfrNativeEventWriter.putLong(data, start); // @Label("Start Time") @Timestamp("TICKS") - // long startTime; - - JfrNativeEventWriter.putLong(data, gcEpoch.rawValue()); // @Label("GC Identifier") int - // gcId; - JfrNativeEventWriter.putLong(data, gcWhen.ordinal()); // @Label("When") String when; + JfrNativeEventWriter.putLong(data, start); + JfrNativeEventWriter.putLong(data, gcEpoch.rawValue()); + JfrNativeEventWriter.putLong(data, gcWhen.getId()); // VirtualSpace JfrNativeEventWriter.putLong(data, 0L); // start - JfrNativeEventWriter.putLong(data, 0L); // committedEnd : ulong - JfrNativeEventWriter.putLong(data, committedSize); // committedSize : ulong - JfrNativeEventWriter.putLong(data, 0L); // reservedEnd : ulong - JfrNativeEventWriter.putLong(data, 0L); // reservedSize : ulong - - JfrNativeEventWriter.putLong(data, heapUsed); // @Unsigned @DataAmount("BYTES") - // @Label("Heap Used") @Description("Bytes - // allocated by objects in the heap") long - // heapUsed; + JfrNativeEventWriter.putLong(data, 0L); // committedEnd + JfrNativeEventWriter.putLong(data, committedSize.rawValue()); + JfrNativeEventWriter.putLong(data, 0L); // reservedEnd + JfrNativeEventWriter.putLong(data, 0L); // reservedSize + JfrNativeEventWriter.putLong(data, heapUsed.rawValue()); JfrNativeEventWriter.endSmallEvent(data); } - } - - @Fold - static boolean isEnabled() { - return SubstrateOptions.UseSerialGC.getValue(); - } - } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGeneration.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGeneration.java index 8c77d261b9b5..6ecf2f04d3fa 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGeneration.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGeneration.java @@ -159,9 +159,11 @@ boolean walkHeapChunks(MemoryWalker.Visitor visitor) { */ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) UnsignedWord getChunkBytes() { - UnsignedWord fromBytes = getFromSpace().getChunkBytes(); - UnsignedWord toBytes = getToSpace().getChunkBytes(); - return fromBytes.add(toBytes); + return fromSpace.getChunkBytes().add(toSpace.getChunkBytes()); + } + + UnsignedWord computeObjectBytes() { + return fromSpace.computeObjectBytes().add(toSpace.computeObjectBytes()); } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrFrameTypeSerializer.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrFrameTypeSerializer.java index 9bb9d56a516c..6689e2a58be1 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrFrameTypeSerializer.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrFrameTypeSerializer.java @@ -37,12 +37,12 @@ public JfrFrameTypeSerializer() { @Override public void write(JfrChunkWriter writer) { - writer.writeCompressedLong(JfrType.FrameType.getId()); JfrFrameType[] values = JfrFrameType.values(); + writer.writeCompressedLong(JfrType.FrameType.getId()); writer.writeCompressedLong(values.length); - for (int i = 0; i < values.length; i++) { - writer.writeCompressedInt(i); - writer.writeString(values[i].getText()); + for (JfrFrameType value : values) { + writer.writeCompressedLong(value.getId()); + writer.writeString(value.getText()); } } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrGCWhen.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrGCWhen.java index 9cdb4326148a..8ecb804e8e7f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrGCWhen.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrGCWhen.java @@ -24,17 +24,25 @@ */ package com.oracle.svm.core.jfr; +import com.oracle.svm.core.Uninterruptible; + public enum JfrGCWhen { BEFORE_GC("Before GC"), AFTER_GC("After GC"); - private final String gcWhen; + private final String text; + + JfrGCWhen(String text) { + this.text = text; + } - JfrGCWhen(String gcWhen) { - this.gcWhen = gcWhen; + public String getText() { + return this.text; } - public String getGcWhen() { - return this.gcWhen; + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public long getId() { + // First entry needs to have id 0. + return ordinal(); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrGCWhenSerializer.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrGCWhenSerializer.java index 34b62dc44d4a..6570c116edaa 100755 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrGCWhenSerializer.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrGCWhenSerializer.java @@ -34,13 +34,12 @@ public JfrGCWhenSerializer() { @Override public void write(JfrChunkWriter writer) { - JfrGCWhen[] gcWhens = JfrGCWhen.values(); - + JfrGCWhen[] values = JfrGCWhen.values(); writer.writeCompressedLong(JfrType.GCWhen.getId()); - writer.writeCompressedLong(gcWhens.length); - for (JfrGCWhen when : gcWhens) { - writer.writeCompressedLong(when.ordinal()); - writer.writeString(when.getGcWhen()); + writer.writeCompressedLong(values.length); + for (JfrGCWhen value : values) { + writer.writeCompressedLong(value.getId()); + writer.writeString(value.getText()); } } } diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/poolparsers/GCWhenConstantPoolParser.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/poolparsers/GCWhenConstantPoolParser.java index b1be4fd4444e..17040b7363ba 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/poolparsers/GCWhenConstantPoolParser.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/poolparsers/GCWhenConstantPoolParser.java @@ -43,7 +43,7 @@ public void parse(RecordingInput input) throws IOException { Assert.assertTrue(count > 0); for (int i = 0; i < count; i++) { addFoundId(input.readInt()); // Id. - Assert.assertFalse("GC when is empty!", input.readUTF().isEmpty()); + Assert.assertFalse("GCWhen text is empty!", input.readUTF().isEmpty()); } } }