From b70c6402d6b37e74e4f5c9df4f83ecfafc84c82f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Wed, 26 Apr 2023 16:48:08 +0200 Subject: [PATCH] Only build full FrameTree when OmitInlinedMethodDebugLineInfo is false --- .../com/oracle/svm/core/SubstrateOptions.java | 6 + .../core/code/CompilationResultFrameTree.java | 106 +++++++++++------- .../image/NativeImageDebugInfoProvider.java | 16 ++- 3 files changed, 86 insertions(+), 42 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java index a5a048fe2f0b..569190e9536f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java @@ -686,6 +686,12 @@ private static void validateStripDebugInfo(HostedOptionKey optionKey) { @Option(help = "Omit generation of DebugLineInfo originating from inlined methods") // public static final HostedOptionKey OmitInlinedMethodDebugLineInfo = new HostedOptionKey<>(true); + @Option(help = "Specify maximum inlining depth to consider when building DebugCodeInfo") // + public static final HostedOptionKey DebugCodeInfoMaxDepth = new HostedOptionKey<>(Integer.MAX_VALUE); + + @Option(help = "Do not use SourceMappings for generating DebugCodeInfo (i.e. only use Infopoints)") // + public static final HostedOptionKey DebugCodeInfoUseSourceMappings = new HostedOptionKey<>(true); + @Option(help = "Emit debuginfo debug.svm.imagebuild.* sections with detailed image-build options.")// public static final HostedOptionKey UseImagebuildDebugSections = new HostedOptionKey<>(true); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CompilationResultFrameTree.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CompilationResultFrameTree.java index deab01bcdeed..4692a58d23fe 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CompilationResultFrameTree.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CompilationResultFrameTree.java @@ -31,26 +31,35 @@ import java.util.List; import java.util.function.Consumer; -import jdk.vm.ci.code.BytecodeFrame; -import jdk.vm.ci.meta.JavaValue; -import jdk.vm.ci.meta.Local; -import jdk.vm.ci.meta.LocalVariableTable; -import jdk.vm.ci.meta.ResolvedJavaMethod; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.code.SourceMapping; import org.graalvm.compiler.debug.DebugContext; import com.oracle.svm.core.util.VMError; +import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.BytecodePosition; import jdk.vm.ci.code.site.Call; import jdk.vm.ci.code.site.Infopoint; import jdk.vm.ci.code.site.InfopointReason; import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.JavaValue; +import jdk.vm.ci.meta.Local; +import jdk.vm.ci.meta.LocalVariableTable; +import jdk.vm.ci.meta.ResolvedJavaMethod; public final class CompilationResultFrameTree { public abstract static class SourcePositionSupplier implements Comparable { + + private final BytecodePosition bytecodePosition; + private final int callDepth; + + protected SourcePositionSupplier(BytecodePosition bytecodePosition, int callDepth) { + this.bytecodePosition = bytecodePosition; + this.callDepth = callDepth; + } + public abstract int getStartOffset(); public abstract int getSize(); @@ -59,7 +68,9 @@ public int getEndOffset() { return getStartOffset() + getSize() - 1; } - public abstract BytecodePosition getBytecodePosition(); + public BytecodePosition getBytecodePosition() { + return bytecodePosition; + } public static StackTraceElement getStackTraceElement(BytecodePosition pos) { return pos.getMethod().asStackTraceElement(pos.getBCI()); @@ -82,9 +93,13 @@ public final String getStackFrameStr() { } } - public final int getCallDepth() { + public int getCallDepth() { + return callDepth; + } + + protected static int getCallDepth(BytecodePosition startPos) { int depth = 0; - BytecodePosition pos = getBytecodePosition(); + BytecodePosition pos = startPos; while (pos != null) { depth += 1; pos = pos.getCaller(); @@ -119,14 +134,20 @@ public int compareTo(SourcePositionSupplier o) { public static final class InfopointSourceWrapper extends SourcePositionSupplier { public final Infopoint infopoint; - public static InfopointSourceWrapper create(Infopoint infopoint) { + public static InfopointSourceWrapper create(Infopoint infopoint, int maxDepth) { if (infopoint.debugInfo == null || infopoint.debugInfo.getBytecodePosition() == null) { return null; } - return new InfopointSourceWrapper(infopoint); + BytecodePosition pos = infopoint.debugInfo.getBytecodePosition(); + int depth = getCallDepth(pos); + if (depth > maxDepth) { + return null; + } + return new InfopointSourceWrapper(pos, depth, infopoint); } - private InfopointSourceWrapper(Infopoint infopoint) { + private InfopointSourceWrapper(BytecodePosition bytecodePosition, int callDepth, Infopoint infopoint) { + super(bytecodePosition, callDepth); this.infopoint = infopoint; } @@ -143,11 +164,6 @@ public int getSize() { return 1; } - @Override - public BytecodePosition getBytecodePosition() { - return infopoint.debugInfo.getBytecodePosition(); - } - @Override public int compareTo(SourcePositionSupplier o) { int res = super.compareTo(o); @@ -166,22 +182,29 @@ public int compareTo(SourcePositionSupplier o) { public static final class SourceMappingWrapper extends SourcePositionSupplier { public final SourceMapping sourceMapping; - public static SourceMappingWrapper create(SourceMapping sourceMapping) { + public static SourceMappingWrapper create(SourceMapping sourceMapping, int maxDepth) { if (sourceMapping.getSourcePosition() == null) { return null; } + BytecodePosition pos = sourceMapping.getSourcePosition(); + int depth = getCallDepth(pos); + if (depth > maxDepth) { + return null; + } if (sourceMapping.getStartOffset() > sourceMapping.getEndOffset()) { JVMCIError.shouldNotReachHere("Invalid SourceMapping " + getSourceMappingString(sourceMapping)); } - return new SourceMappingWrapper(sourceMapping); + return new SourceMappingWrapper(pos, depth, sourceMapping); } static String getSourceMappingString(SourceMapping sourceMapping) { - SourceMappingWrapper tmp = new SourceMappingWrapper(sourceMapping); + BytecodePosition pos = sourceMapping.getSourcePosition(); + SourceMappingWrapper tmp = new SourceMappingWrapper(pos, getCallDepth(pos), sourceMapping); return tmp.getPosStr() + " with " + tmp.getStackFrameStr(); } - private SourceMappingWrapper(SourceMapping sourceMapping) { + private SourceMappingWrapper(BytecodePosition bytecodePosition, int callDepth, SourceMapping sourceMapping) { + super(bytecodePosition, callDepth); this.sourceMapping = sourceMapping; } @@ -208,11 +231,6 @@ public int getSize() { return sourceMapping.getEndOffset() - sourceMapping.getStartOffset(); } - @Override - public BytecodePosition getBytecodePosition() { - return sourceMapping.getSourcePosition(); - } - @Override public int compareTo(SourcePositionSupplier o) { int res = super.compareTo(o); @@ -417,7 +435,9 @@ public String toString() { public static final class Builder { private Builder.RootNode root = null; private final int targetCodeSize; + private final int maxDepth; private final DebugContext debug; + private final boolean useSourceMappings; private final boolean verify; int indexLeft; @@ -446,8 +466,10 @@ public String toString() { } } - public Builder(DebugContext debug, int targetCodeSize, boolean verify) { + public Builder(DebugContext debug, int targetCodeSize, int maxDepth, boolean useSourceMappings, boolean verify) { this.targetCodeSize = targetCodeSize; + this.maxDepth = maxDepth; + this.useSourceMappings = useSourceMappings; this.verify = verify; this.debug = debug; } @@ -462,34 +484,38 @@ public CallNode build(CompilationResult compilationResult) { List sourcePosData = new ArrayList<>(infopoints.size() + sourceMappings.size()); InfopointSourceWrapper infopointForRoot = null; for (Infopoint infopoint : infopoints) { - InfopointSourceWrapper wrapper = InfopointSourceWrapper.create(infopoint); + InfopointSourceWrapper wrapper = InfopointSourceWrapper.create(infopoint, maxDepth); if (wrapper != null) { sourcePosData.add(wrapper); infopointForRoot = wrapper; } else { - debug.log(DebugContext.DETAILED_LEVEL, " Discard Infopoint without BytecodePosition %s", infopoint); + debug.log(DebugContext.DETAILED_LEVEL, " Discard Infopoint %s", infopoint); } } - for (SourceMapping sourceMapping : sourceMappings) { - SourceMappingWrapper wrapper = SourceMappingWrapper.create(sourceMapping); - if (wrapper != null) { - if (wrapper.getStartOffset() > targetCodeSize - 1) { + if (useSourceMappings) { + for (SourceMapping sourceMapping : sourceMappings) { + SourceMappingWrapper wrapper = SourceMappingWrapper.create(sourceMapping, maxDepth); + if (wrapper != null) { + if (wrapper.getStartOffset() > targetCodeSize - 1) { + if (debug.isLogEnabled(DebugContext.DETAILED_LEVEL)) { + debug.log(" Discard SourceMapping outside code-range %s", SourceMappingWrapper.getSourceMappingString(sourceMapping)); + } + continue; + } + sourcePosData.add(wrapper); + } else { if (debug.isLogEnabled(DebugContext.DETAILED_LEVEL)) { - debug.log(" Discard SourceMapping outside code-range %s", SourceMappingWrapper.getSourceMappingString(sourceMapping)); + debug.log(" Discard SourceMapping %s", SourceMappingWrapper.getSourceMappingString(sourceMapping)); } - continue; - } - sourcePosData.add(wrapper); - } else { - if (debug.isLogEnabled(DebugContext.DETAILED_LEVEL)) { - debug.log(" Discard SourceMapping without NodeSourcePosition %s", SourceMappingWrapper.getSourceMappingString(sourceMapping)); } } } sourcePosData.sort(Comparator.naturalOrder()); - nullifyOverlappingSourcePositions(sourcePosData); + if (useSourceMappings) { + nullifyOverlappingSourcePositions(sourcePosData); + } if (debug.isLogEnabled(DebugContext.DETAILED_LEVEL)) { debug.log("Sorted input data:"); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageDebugInfoProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageDebugInfoProvider.java index a69da19bd4d0..f26d86b0b724 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageDebugInfoProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageDebugInfoProvider.java @@ -1246,12 +1246,24 @@ public Stream locationInfoProvider() { if (fileName().length() == 0) { return Stream.empty(); } - final CallNode root = new Builder(debugContext, compilation.getTargetCodeSize(), true).build(compilation); + boolean omitInline = SubstrateOptions.OmitInlinedMethodDebugLineInfo.getValue(); + int maxDepth = SubstrateOptions.DebugCodeInfoMaxDepth.getValue(); + boolean useSourceMappings = SubstrateOptions.DebugCodeInfoUseSourceMappings.getValue(); + if (omitInline) { + if (!SubstrateOptions.DebugCodeInfoMaxDepth.hasBeenSet()) { + /* TopLevelVisitor will not go deeper than level 2 */ + maxDepth = 2; + } + if (!SubstrateOptions.DebugCodeInfoUseSourceMappings.hasBeenSet()) { + /* Skip expensive CompilationResultFrameTree building with SourceMappings */ + useSourceMappings = false; + } + } + final CallNode root = new Builder(debugContext, compilation.getTargetCodeSize(), maxDepth, useSourceMappings, true).build(compilation); if (root == null) { return Stream.empty(); } final List locationInfos = new ArrayList<>(); - final boolean omitInline = SubstrateOptions.OmitInlinedMethodDebugLineInfo.getValue(); int frameSize = getFrameSize(); final Visitor visitor = (omitInline ? new TopLevelVisitor(locationInfos, frameSize) : new MultiLevelVisitor(locationInfos, frameSize)); // arguments passed by visitor to apply are