From 441cef4fa41044ce20f4171bcb4131362c74699f Mon Sep 17 00:00:00 2001 From: jovanstevanovic Date: Tue, 18 Apr 2023 18:01:41 +0200 Subject: [PATCH] Add support for profiling of topmost frame. --- .../oracle/svm/core/SubstrateDiagnostics.java | 2 +- .../oracle/svm/core/code/CodeInfoDecoder.java | 75 +++++++++++++++++-- .../oracle/svm/core/code/CodeInfoEncoder.java | 12 ++- .../svm/core/code/FrameInfoDecoder.java | 6 +- .../svm/core/code/FrameInfoEncoder.java | 44 ++++++++--- .../svm/core/heap/dump/HeapDumpWriter.java | 2 +- .../oracle/svm/core/jdk/BacktraceDecoder.java | 2 +- .../core/sampler/SamplerBuffersAccess.java | 2 +- .../svm/core/stack/ThreadStackPrinter.java | 2 +- 9 files changed, 117 insertions(+), 30 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java index ddf5ca33a06f..0634c5e9e4e3 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java @@ -1035,7 +1035,7 @@ public boolean printLocationInfo(Log log, UnsignedWord value) { private FrameInfoQueryResult getCompilationRoot(CodeInfo imageCodeInfo, CodePointer ip) { FrameInfoQueryResult rootInfo = null; - frameInfoCursor.initialize(imageCodeInfo, ip); + frameInfoCursor.initialize(imageCodeInfo, ip, false); while (frameInfoCursor.advance()) { rootInfo = frameInfoCursor.get(); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoDecoder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoDecoder.java index 656d41658bdc..c48bf9f445ba 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoDecoder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoDecoder.java @@ -38,6 +38,7 @@ import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.c.NonmovableObjectArray; import com.oracle.svm.core.heap.ReferenceMapIndex; +import com.oracle.svm.core.jdk.UninterruptibleUtils; import com.oracle.svm.core.option.HostedOptionKey; import com.oracle.svm.core.util.Counter; import com.oracle.svm.core.util.NonmovableByteArrayReader; @@ -90,7 +91,45 @@ private static long lookupCodeInfoEntryOffset(CodeInfo info, long ip) { entryOffset = advanceOffset(entryOffset, entryFlags); } while (entryIP <= ip); - return -1; + return INVALID_FRAME_INFO_ENTRY_OFFSET; + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + private static long lookupCodeInfoEntryOffsetOrDefault(CodeInfo info, long ip) { + int chunksToSearch = 0; + while (true) { + long defaultFIEntryOffset = INVALID_FRAME_INFO_ENTRY_OFFSET; + long entryIP = UninterruptibleUtils.Math.max(lookupEntryIP(ip) - chunksToSearch * CodeInfoDecoder.indexGranularity(), 0); + long entryOffset = loadEntryOffset(info, entryIP); + do { + int entryFlags = loadEntryFlags(info, entryOffset); + int frameInfoFlag = extractFI(entryFlags); + defaultFIEntryOffset = frameInfoFlag == FI_DEFAULT_INFO_INDEX_S4 ? entryOffset : defaultFIEntryOffset; + if (entryIP == ip) { + if (frameInfoFlag == FI_NO_DEOPT) { + /* There is no frame info. Try to find a default one. */ + break; + } else { + return entryOffset; + } + } + + entryIP = advanceIP(info, entryOffset, entryIP); + entryOffset = advanceOffset(entryOffset, entryFlags); + } while (entryIP <= ip); + + if (defaultFIEntryOffset != INVALID_FRAME_INFO_ENTRY_OFFSET) { + return defaultFIEntryOffset; + } else { + /* + * We should re-try lookup only in case when nearest chunk to a given IP is a call + * instruction i.e. chunk beginning and call have the same IP value. Continue + * searching until you find a chunk that is not a call or method start. + */ + chunksToSearch++; + assert entryIP != 0; + } + } } static void lookupCodeInfo(CodeInfo info, long ip, CodeInfoQueryResult codeInfoQueryResult) { @@ -231,6 +270,7 @@ static int loadEntryFlags(CodeInfo info, long curOffset) { } private static final int INVALID_SIZE_ENCODING = 0; + private static final int INVALID_FRAME_INFO_ENTRY_OFFSET = -1; @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) private static int initialSizeEncoding() { @@ -338,6 +378,11 @@ private static boolean isDeoptEntryPoint(CodeInfo info, long entryOffset, int en * We have frame information, but only for debugging purposes. This is not a * deoptimization entry point. */ + case FI_DEFAULT_INFO_INDEX_S4: + /* + * We have frame information, but without bci and line number. This is not a + * deoptimization entry point. + */ return false; default: throw shouldNotReachHereUnexpectedInput(entryFlags); // ExcludeFromJacocoGeneratedReport @@ -353,6 +398,7 @@ private static FrameInfoQueryResult loadFrameInfo(CodeInfo info, long entryOffse isDeoptEntry = true; break; case FI_INFO_ONLY_INDEX_S4: + case FI_DEFAULT_INFO_INDEX_S4: isDeoptEntry = false; break; default: @@ -414,10 +460,21 @@ private static boolean endOfTable(long entryIP) { static final int FI_BITS = 2; static final int FI_SHIFT = RM_SHIFT + RM_BITS; static final int FI_MASK_IN_PLACE = ((1 << FI_BITS) - 1) << FI_SHIFT; + /* + * Filler frame value. It is needed since we store the nextIP offset in a one-byte field, + * regardless of the CodeInfo index granularity. See CodeInfoEncoder#encodeIPData for more + * information. + */ static final int FI_NO_DEOPT = 0; static final int FI_DEOPT_ENTRY_INDEX_S4 = 1; static final int FI_INFO_ONLY_INDEX_S4 = 2; - static final int[] FI_MEM_SIZE = {0, Integer.BYTES, Integer.BYTES, /* unused */ 0}; + /* + * Frame value for default frame info. A default frame info contains a method name and a class + * but without BCI and line number. It is present on each chunk beginning and method starts. See + * FrameInfoEncoder#addDefaultDebugInfo for more information. + */ + static final int FI_DEFAULT_INFO_INDEX_S4 = 3; + static final int[] FI_MEM_SIZE = {0, Integer.BYTES, Integer.BYTES, Integer.BYTES}; private static final int TOTAL_BITS = FI_SHIFT + FI_BITS; @@ -532,12 +589,12 @@ public FrameInfoCursor() { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) @SuppressWarnings("hiding") - public void initialize(CodeInfo info, CodePointer ip) { + public void initialize(CodeInfo info, CodePointer ip, boolean exactIPMatch) { this.info = info; result = null; frameInfoReader.reset(); state.reset(); - canDecode = initFrameInfoReader(ip); + canDecode = initFrameInfoReader(ip, exactIPMatch); } /** @@ -591,12 +648,13 @@ private void decodeNextEntry() { } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - private boolean initFrameInfoReader(CodePointer ip) { - long entryOffset = lookupCodeInfoEntryOffset(info, CodeInfoAccess.relativeIP(info, ip)); + private boolean initFrameInfoReader(CodePointer ip, boolean exactIPMatch) { + long relativeIP = CodeInfoAccess.relativeIP(info, ip); + long entryOffset = exactIPMatch ? lookupCodeInfoEntryOffset(info, relativeIP) : lookupCodeInfoEntryOffsetOrDefault(info, relativeIP); if (entryOffset >= 0) { int entryFlags = loadEntryFlags(info, entryOffset); if (extractFI(entryFlags) == FI_NO_DEOPT) { - entryOffset = -1; + entryOffset = INVALID_FRAME_INFO_ENTRY_OFFSET; } else { int frameInfoIndex = NonmovableByteArrayReader.getS4(CodeInfoAccess.getCodeInfoEncodings(info), offsetFI(entryOffset, entryFlags)); frameInfoReader.setByteIndex(frameInfoIndex); @@ -604,6 +662,7 @@ private boolean initFrameInfoReader(CodePointer ip) { } } state.entryOffset = entryOffset; + assert exactIPMatch || entryOffset >= 0; return entryOffset >= 0; } } @@ -624,7 +683,7 @@ public FrameInfoState() { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public FrameInfoState reset() { - entryOffset = -1; + entryOffset = INVALID_FRAME_INFO_ENTRY_OFFSET; isFirstFrame = true; isDone = false; firstValue = -1; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoEncoder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoEncoder.java index b34d79e38efa..a936f9039dd3 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoEncoder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoEncoder.java @@ -186,12 +186,15 @@ public void addMethod(SharedMethod method, CompilationResult compilation, int co /* Mark the method start and register the frame size. */ IPData startEntry = makeEntry(compilationOffset); + FrameInfoEncoder.FrameData defaultFrameData = frameInfoEncoder.addDefaultDebugInfo(method, totalFrameSize); + startEntry.frameData = defaultFrameData; startEntry.frameSizeEncoding = encodeFrameSize(totalFrameSize, true, isEntryPoint, hasCalleeSavedRegisters); /* Register the frame size for all entries that are starting points for the index. */ long entryIP = CodeInfoDecoder.lookupEntryIP(CodeInfoDecoder.indexGranularity() + compilationOffset); while (entryIP <= CodeInfoDecoder.lookupEntryIP(compilationSize + compilationOffset - 1)) { IPData entry = makeEntry(entryIP); + entry.frameData = defaultFrameData; entry.frameSizeEncoding = encodeFrameSize(totalFrameSize, false, isEntryPoint, hasCalleeSavedRegisters); entryIP += CodeInfoDecoder.indexGranularity(); } @@ -209,7 +212,7 @@ public void addMethod(SharedMethod method, CompilationResult compilation, int co throw VMError.shouldNotReachHere("Encoding two infopoints at same offset. Conflicting infopoint: " + infopoint); } IPData entry = makeEntry(offset + compilationOffset); - assert entry.referenceMap == null && entry.frameData == null; + assert entry.referenceMap == null && (entry.frameData == null || entry.frameData.isDefaultFrameData); entry.referenceMap = (ReferenceMapEncoder.Input) debugInfo.getReferenceMap(); entry.frameData = frameInfoEncoder.addDebugInfo(method, compilation, infopoint, totalFrameSize); if (entry.frameData != null && entry.frameData.frame.isDeoptEntry) { @@ -433,7 +436,11 @@ private static int flagsForDeoptFrameInfo(IPData data) { if (data.frameData.frame.isDeoptEntry) { return CodeInfoDecoder.FI_DEOPT_ENTRY_INDEX_S4; } else { - return CodeInfoDecoder.FI_INFO_ONLY_INDEX_S4; + if (data.frameData.isDefaultFrameData) { + return CodeInfoDecoder.FI_DEFAULT_INFO_INDEX_S4; + } else { + return CodeInfoDecoder.FI_INFO_ONLY_INDEX_S4; + } } } else { throw new IllegalArgumentException(); @@ -442,6 +449,7 @@ private static int flagsForDeoptFrameInfo(IPData data) { private static void writeEncodedFrameInfo(UnsafeArrayTypeWriter writeBuffer, IPData data, int entryFlags) { switch (CodeInfoDecoder.extractFI(entryFlags)) { + case CodeInfoDecoder.FI_DEFAULT_INFO_INDEX_S4: case CodeInfoDecoder.FI_DEOPT_ENTRY_INDEX_S4: case CodeInfoDecoder.FI_INFO_ONLY_INDEX_S4: writeBuffer.putS4(data.frameData.encodedFrameInfoIndex); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoDecoder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoDecoder.java index 6feb471581b2..561c98387057 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoDecoder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoDecoder.java @@ -530,19 +530,19 @@ private static ValueInfo newValueInfo(ValueInfoAllocator valueInfoAllocator) { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) protected static int decodeBci(long encodedBci) { - assert encodedBci > 0 && encodedBci != FrameInfoDecoder.ENCODED_BCI_NO_CALLER; + assert encodedBci >= 0 && encodedBci != FrameInfoDecoder.ENCODED_BCI_NO_CALLER; long result = (encodedBci >> ENCODED_BCI_SHIFT) - ENCODED_BCI_ADDEND; assert result >= Integer.MIN_VALUE && result <= Integer.MAX_VALUE; return (int) result; } protected static boolean decodeDuringCall(long encodedBci) { - assert encodedBci > 0 && encodedBci != FrameInfoDecoder.ENCODED_BCI_NO_CALLER; + assert encodedBci >= 0 && encodedBci != FrameInfoDecoder.ENCODED_BCI_NO_CALLER; return (encodedBci & ENCODED_BCI_DURING_CALL_MASK) != 0; } protected static boolean decodeRethrowException(long encodedBci) { - assert encodedBci > 0 && encodedBci != FrameInfoDecoder.ENCODED_BCI_NO_CALLER; + assert encodedBci >= 0 && encodedBci != FrameInfoDecoder.ENCODED_BCI_NO_CALLER; return (encodedBci & ENCODED_BCI_RETHROW_EXCEPTION_MASK) != 0; } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoEncoder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoEncoder.java index 342cf591292b..bdae0b7be6e7 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoEncoder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoEncoder.java @@ -123,17 +123,15 @@ protected void recordFrame(ResolvedJavaMethod method, Infopoint infopoint, boole /** * Fills the FrameInfoQueryResult.source* fields. */ - protected abstract void fillSourceFields(BytecodeFrame bytecodeFrame, FrameInfoQueryResult resultFrameInfo); + protected abstract void fillSourceFields(ResolvedJavaMethod method, FrameInfoQueryResult resultFrameInfo); } public abstract static class SourceFieldsFromMethod extends Customization { private final HostedStringDeduplication stringTable = HostedStringDeduplication.singleton(); @Override - protected void fillSourceFields(BytecodeFrame bytecodeFrame, FrameInfoQueryResult resultFrameInfo) { - final ResolvedJavaMethod method = bytecodeFrame.getMethod(); - - final StackTraceElement source = method.asStackTraceElement(bytecodeFrame.getBCI()); + protected void fillSourceFields(ResolvedJavaMethod method, FrameInfoQueryResult resultFrameInfo) { + final StackTraceElement source = method.asStackTraceElement(resultFrameInfo.getBci()); resultFrameInfo.sourceClass = getDeclaringJavaClass(method); /* * There is no need to have method names as interned strings. But at least sometimes the @@ -150,8 +148,8 @@ protected void fillSourceFields(BytecodeFrame bytecodeFrame, FrameInfoQueryResul public abstract static class SourceFieldsFromImage extends Customization { @Override - protected void fillSourceFields(BytecodeFrame bytecodeFrame, FrameInfoQueryResult resultFrameInfo) { - final int deoptOffsetInImage = ((SharedMethod) bytecodeFrame.getMethod()).getDeoptOffsetInImage(); + protected void fillSourceFields(ResolvedJavaMethod method, FrameInfoQueryResult resultFrameInfo) { + final int deoptOffsetInImage = ((SharedMethod) method).getDeoptOffsetInImage(); if (deoptOffsetInImage != 0) { CodeInfoQueryResult targetCodeInfo = CodeInfoTable.lookupDeoptimizationEntrypoint(deoptOffsetInImage, resultFrameInfo.encodedBci); if (targetCodeInfo != null) { @@ -180,14 +178,16 @@ static class FrameData { protected final ValueInfo[][] virtualObjects; protected final FrameInfoQueryResult frame; protected long encodedFrameInfoIndex; + protected boolean isDefaultFrameData; protected int frameSliceIndex = UNCOMPRESSED_FRAME_SLICE_INDEX; - FrameData(DebugInfo debugInfo, int totalFrameSize, ValueInfo[][] virtualObjects, FrameInfoQueryResult frame) { - assert debugInfo != null; + FrameData(DebugInfo debugInfo, int totalFrameSize, ValueInfo[][] virtualObjects, boolean isDefaultFrameData) { + assert (virtualObjects != null && debugInfo != null) || (virtualObjects == null && debugInfo == null); this.debugInfo = debugInfo; this.totalFrameSize = totalFrameSize; this.virtualObjects = virtualObjects; - this.frame = frame; + this.isDefaultFrameData = isDefaultFrameData; + this.frame = new FrameInfoQueryResult(); } } @@ -465,14 +465,14 @@ protected FrameData addDebugInfo(ResolvedJavaMethod method, CompilationResult co boolean includeLocalValues = customization.includeLocalValues(method, infopoint, isDeoptEntry); DebugInfo debugInfo = infopoint.debugInfo; - FrameData data = new FrameData(debugInfo, totalFrameSize, new ValueInfo[countVirtualObjects(debugInfo)][], new FrameInfoQueryResult()); + FrameData data = new FrameData(debugInfo, totalFrameSize, new ValueInfo[countVirtualObjects(debugInfo)][], false); initializeFrameInfo(data.frame, data, debugInfo.frame(), isDeoptEntry, includeLocalValues); List frameSlice = includeLocalValues ? null : new ArrayList<>(); BytecodeFrame bytecodeFrame = data.debugInfo.frame(); for (FrameInfoQueryResult resultFrame = data.frame; resultFrame != null; resultFrame = resultFrame.caller) { assert bytecodeFrame != null; - customization.fillSourceFields(bytecodeFrame, resultFrame); + customization.fillSourceFields(bytecodeFrame.getMethod(), resultFrame); // save source class and method name final Class sourceClass = resultFrame.sourceClass; @@ -498,6 +498,26 @@ protected FrameData addDebugInfo(ResolvedJavaMethod method, CompilationResult co return data; } + protected FrameData addDefaultDebugInfo(ResolvedJavaMethod method, int totalFrameSize) { + FrameData data = new FrameData(null, totalFrameSize, null, true); + data.frame.encodedBci = FrameInfoEncoder.encodeBci(0, false, false); + customization.fillSourceFields(method, data.frame); + // invalidate source line number + data.frame.sourceLineNumber = -1; + // save source class and method name + Class sourceClass = data.frame.sourceClass; + String sourceMethodName = data.frame.sourceMethodName; + encoders.sourceClasses.addObject(sourceClass); + encoders.sourceMethodNames.addObject(sourceMethodName); + + // save encoding metadata + CompressedFrameData frame = new CompressedFrameData(sourceClass, sourceMethodName, data.frame.sourceLineNumber, data.frame.encodedBci, data.frame.methodId, true); + frameMetadata.addFrameSlice(data, List.of(frame)); + + allDebugInfos.add(data); + return data; + } + private static int countVirtualObjects(DebugInfo debugInfo) { /* * We want to know the highest virtual object id in use in this DebugInfo. For that, we have diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/dump/HeapDumpWriter.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/dump/HeapDumpWriter.java index 0827b05eee7b..ba8a14803bf7 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/dump/HeapDumpWriter.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/dump/HeapDumpWriter.java @@ -1212,7 +1212,7 @@ protected boolean visitFrame(Pointer sp, CodePointer ip, CodeInfo codeInfo, Deop */ markStackValuesAsGCRoots(sp, ip, codeInfo); - frameInfoCursor.initialize(codeInfo, ip); + frameInfoCursor.initialize(codeInfo, ip, true); while (frameInfoCursor.advance()) { FrameInfoQueryResult frame = frameInfoCursor.get(); visitFrame(frame); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/BacktraceDecoder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/BacktraceDecoder.java index ba2e2f4849f0..8663bfc0f9f0 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/BacktraceDecoder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/BacktraceDecoder.java @@ -116,7 +116,7 @@ private int visitCodePointer(CodePointer ip, int oldFramesDecoded, int maxFrames @Uninterruptible(reason = "Wraps the now safe call to the possibly interruptible visitor.", callerMustBe = true, calleeMustBe = false) private int visitFrame(CodePointer ip, CodeInfo tetheredCodeInfo, int oldFramesDecoded, int maxFramesProcessed, int maxFramesDecode) { int framesDecoded = oldFramesDecoded; - frameInfoCursor.initialize(tetheredCodeInfo, ip); + frameInfoCursor.initialize(tetheredCodeInfo, ip, true); while (frameInfoCursor.advance()) { FrameInfoQueryResult frameInfo = frameInfoCursor.get(); if (!StackTraceUtils.shouldShowFrame(frameInfo, false, true, false)) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/sampler/SamplerBuffersAccess.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/sampler/SamplerBuffersAccess.java index 422108a169d4..d84377c8a9f9 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/sampler/SamplerBuffersAccess.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/sampler/SamplerBuffersAccess.java @@ -257,7 +257,7 @@ private static int visitFrame(JfrNativeEventWriterData data, long address) { @Uninterruptible(reason = "Prevent JFR recording and epoch change.") private static int visitFrame(JfrNativeEventWriterData data, CodeInfo codeInfo, CodePointer ip) { int numStackTraceElements = 0; - FRAME_INFO_CURSOR.initialize(codeInfo, ip); + FRAME_INFO_CURSOR.initialize(codeInfo, ip, false); while (FRAME_INFO_CURSOR.advance()) { if (data.isNonNull()) { FrameInfoQueryResult frame = FRAME_INFO_CURSOR.get(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/stack/ThreadStackPrinter.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/stack/ThreadStackPrinter.java index 447da531ab1b..c9bd0714ad11 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/stack/ThreadStackPrinter.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/stack/ThreadStackPrinter.java @@ -59,7 +59,7 @@ protected void logFrame(Log log, Pointer sp, CodePointer ip, CodeInfo codeInfo, } boolean isFirst = true; - frameInfoCursor.initialize(codeInfo, ip); + frameInfoCursor.initialize(codeInfo, ip, false); while (frameInfoCursor.advance()) { if (printedFrames >= MAX_STACK_FRAMES_PER_THREAD_TO_PRINT) { log.string("... (truncated)").newline();