Skip to content

Commit 86ed850

Browse files
committed
[GR-33516] Inline debuginfo generation for CE debuginfo.
PullRequest: graal/9670
2 parents 41863b1 + 65d5466 commit 86ed850

File tree

17 files changed

+1301
-370
lines changed

17 files changed

+1301
-370
lines changed

compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,8 @@ public InvokeNode replaceWithInvoke() {
248248
AbstractBeginNode oldException = this.exceptionEdge;
249249
graph().replaceSplitWithFixed(this, newInvoke, this.next());
250250
GraphUtil.killCFG(oldException);
251+
// copy across any original node source position
252+
newInvoke.setNodeSourcePosition(getNodeSourcePosition());
251253
return newInvoke;
252254
}
253255

substratevm/mx.substratevm/testhello.py

Lines changed: 240 additions & 49 deletions
Large diffs are not rendered by default.

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java

Lines changed: 31 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import java.util.ArrayList;
3131
import java.util.HashMap;
3232
import java.util.List;
33-
import java.util.ListIterator;
3433
import java.util.Map;
3534

3635
import org.graalvm.compiler.debug.DebugContext;
@@ -63,6 +62,10 @@ public class ClassEntry extends StructureTypeEntry {
6362
* Details of methods located in this instance.
6463
*/
6564
protected List<MethodEntry> methods;
65+
/**
66+
* An index of all currently known methods keyed by the unique local symbol name of the method.
67+
*/
68+
private Map<String, MethodEntry> methodsIndex;
6669
/**
6770
* A list recording details of all primary ranges included in this class sorted by ascending
6871
* address range.
@@ -98,6 +101,7 @@ public ClassEntry(String className, FileEntry fileEntry, int size) {
98101
this.interfaces = new ArrayList<>();
99102
this.fileEntry = fileEntry;
100103
this.methods = new ArrayList<>();
104+
this.methodsIndex = new HashMap<>();
101105
this.primaryEntries = new ArrayList<>();
102106
this.primaryIndex = new HashMap<>();
103107
this.localFiles = new ArrayList<>();
@@ -137,9 +141,7 @@ public void addDebugInfo(DebugInfoBase debugInfoBase, DebugTypeInfo debugTypeInf
137141
/* Add details of fields and field types */
138142
debugInstanceTypeInfo.fieldInfoProvider().forEach(debugFieldInfo -> this.processField(debugFieldInfo, debugInfoBase, debugContext));
139143
/* Add details of methods and method types */
140-
debugInstanceTypeInfo.methodInfoProvider().forEach(methodFieldInfo -> this.methods.add(this.processMethod(methodFieldInfo, debugInfoBase, debugContext, false)));
141-
/* Sort methods to improve lookup speed */
142-
this.methods.sort(MethodEntry::compareTo);
144+
debugInstanceTypeInfo.methodInfoProvider().forEach(debugMethodInfo -> this.processMethod(debugMethodInfo, debugInfoBase, debugContext));
143145
}
144146

145147
public void indexPrimary(Range primary, List<DebugFrameSizeChange> frameSizeInfos, int frameSize) {
@@ -168,13 +170,19 @@ public void indexSubRange(Range subrange) {
168170
/* We should already have seen the primary range. */
169171
assert primaryEntry != null;
170172
assert primaryEntry.getClassEntry() == this;
171-
primaryEntry.addSubRange(subrange);
172173
FileEntry subFileEntry = subrange.getFileEntry();
173174
if (subFileEntry != null) {
174175
indexLocalFileEntry(subFileEntry);
175176
}
176177
}
177178

179+
private void indexMethodEntry(MethodEntry methodEntry) {
180+
String methodName = methodEntry.getSymbolName();
181+
assert methodsIndex.get(methodName) == null : methodName;
182+
methods.add(methodEntry);
183+
methodsIndex.put(methodName, methodEntry);
184+
}
185+
178186
private void indexLocalFileEntry(FileEntry localFileEntry) {
179187
if (localFilesIndex.get(localFileEntry) == null) {
180188
localFiles.add(localFileEntry);
@@ -273,8 +281,8 @@ private void processInterface(String interfaceName, DebugInfoBase debugInfoBase,
273281
interfaceClassEntry.addImplementor(this, debugContext);
274282
}
275283

276-
protected MethodEntry processMethod(DebugMethodInfo debugMethodInfo, DebugInfoBase debugInfoBase, DebugContext debugContext, boolean fromRangeInfo) {
277-
String methodName = debugInfoBase.uniqueDebugString(debugMethodInfo.name());
284+
protected MethodEntry processMethod(DebugMethodInfo debugMethodInfo, DebugInfoBase debugInfoBase, DebugContext debugContext) {
285+
String methodName = debugMethodInfo.name();
278286
String resultTypeName = TypeEntry.canonicalize(debugMethodInfo.valueType());
279287
int modifiers = debugMethodInfo.modifiers();
280288
List<String> paramTypes = debugMethodInfo.paramTypes();
@@ -297,8 +305,11 @@ protected MethodEntry processMethod(DebugMethodInfo debugMethodInfo, DebugInfoBa
297305
* substitution
298306
*/
299307
FileEntry methodFileEntry = debugInfoBase.ensureFileEntry(debugMethodInfo);
300-
return new MethodEntry(methodFileEntry, debugMethodInfo.symbolNameForMethod(), methodName, this, resultType,
301-
paramTypeArray, paramNameArray, modifiers, debugMethodInfo.isDeoptTarget(), fromRangeInfo);
308+
MethodEntry methodEntry = new MethodEntry(debugInfoBase, debugMethodInfo, methodFileEntry, methodName,
309+
this, resultType, paramTypeArray, paramNameArray);
310+
indexMethodEntry(methodEntry);
311+
312+
return methodEntry;
302313
}
303314

304315
@Override
@@ -340,35 +351,19 @@ public ClassEntry getSuperClass() {
340351
}
341352

342353
public MethodEntry ensureMethodEntryForDebugRangeInfo(DebugRangeInfo debugRangeInfo, DebugInfoBase debugInfoBase, DebugContext debugContext) {
343-
assert listIsSorted(methods);
344-
ListIterator<MethodEntry> methodIterator = methods.listIterator();
345-
String methodName = debugInfoBase.uniqueDebugString(debugRangeInfo.name());
346-
String paramSignature = debugRangeInfo.paramSignature();
347-
String returnTypeName = debugRangeInfo.valueType();
348-
while (methodIterator.hasNext()) {
349-
MethodEntry methodEntry = methodIterator.next();
350-
int comparisonResult = methodEntry.compareTo(methodName, paramSignature, returnTypeName);
351-
if (comparisonResult == 0) {
352-
methodEntry.setInRangeAndUpdateFileEntry(debugInfoBase, debugRangeInfo);
353-
if (methodEntry.fileEntry != null) {
354-
/* Ensure that the methodEntry's fileEntry is present in the localsFileIndex */
355-
indexLocalFileEntry(methodEntry.fileEntry);
356-
}
357-
return methodEntry;
358-
} else if (comparisonResult > 0) {
359-
methodIterator.previous();
360-
break;
354+
355+
MethodEntry methodEntry = methodsIndex.get(debugRangeInfo.symbolNameForMethod());
356+
if (methodEntry == null) {
357+
methodEntry = processMethod(debugRangeInfo, debugInfoBase, debugContext);
358+
} else {
359+
methodEntry.updateRangeInfo(debugInfoBase, debugRangeInfo);
360+
/* Ensure that the methodEntry's fileEntry is present in the localsFileIndex */
361+
FileEntry methodFileEntry = methodEntry.fileEntry;
362+
if (methodFileEntry != null) {
363+
indexLocalFileEntry(methodFileEntry);
361364
}
362365
}
363-
MethodEntry newMethodEntry = processMethod(debugRangeInfo, debugInfoBase, debugContext, true);
364-
methodIterator.add(newMethodEntry);
365-
return newMethodEntry;
366-
}
367-
368-
private static boolean listIsSorted(List<MethodEntry> list) {
369-
List<MethodEntry> copy = new ArrayList<>(list);
370-
copy.sort(MethodEntry::compareTo);
371-
return list.equals(copy);
366+
return methodEntry;
372367
}
373368

374369
public List<MethodEntry> getMethods() {

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/DebugInfoBase.java

Lines changed: 59 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.util.Map;
3636

3737
import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugFileInfo;
38+
import jdk.vm.ci.meta.ResolvedJavaType;
3839
import org.graalvm.compiler.debug.DebugContext;
3940

4041
import com.oracle.objectfile.debuginfo.DebugInfoProvider;
@@ -103,7 +104,7 @@ public abstract class DebugInfoBase {
103104
/**
104105
* index of already seen classes.
105106
*/
106-
private Map<String, ClassEntry> primaryClassesIndex = new HashMap<>();
107+
private Map<ResolvedJavaType, ClassEntry> primaryClassesIndex = new HashMap<>();
107108
/**
108109
* Index of files which contain primary or secondary ranges.
109110
*/
@@ -238,38 +239,24 @@ public void installDebugInfo(DebugInfoProvider debugInfoProvider) {
238239
*/
239240
String fileName = debugCodeInfo.fileName();
240241
Path filePath = debugCodeInfo.filePath();
241-
String className = TypeEntry.canonicalize(debugCodeInfo.ownerType());
242+
ResolvedJavaType ownerType = debugCodeInfo.ownerType();
242243
String methodName = debugCodeInfo.name();
243244
int lo = debugCodeInfo.addressLo();
244245
int hi = debugCodeInfo.addressHi();
245246
int primaryLine = debugCodeInfo.line();
246247

247248
/* Search for a method defining this primary range. */
248-
ClassEntry classEntry = ensureClassEntry(className);
249+
ClassEntry classEntry = ensureClassEntry(ownerType);
249250
MethodEntry methodEntry = classEntry.ensureMethodEntryForDebugRangeInfo(debugCodeInfo, this, debugContext);
250251
Range primaryRange = new Range(stringTable, methodEntry, lo, hi, primaryLine);
251-
debugContext.log(DebugContext.INFO_LEVEL, "PrimaryRange %s.%s %s %s:%d [0x%x, 0x%x]", className, methodName, filePath, fileName, primaryLine, lo, hi);
252+
debugContext.log(DebugContext.INFO_LEVEL, "PrimaryRange %s.%s %s %s:%d [0x%x, 0x%x]", ownerType.toJavaName(), methodName, filePath, fileName, primaryLine, lo, hi);
252253
classEntry.indexPrimary(primaryRange, debugCodeInfo.getFrameSizeChanges(), debugCodeInfo.getFrameSize());
253-
debugCodeInfo.lineInfoProvider().forEach(debugLineInfo -> {
254-
String fileNameAtLine = debugLineInfo.fileName();
255-
Path filePathAtLine = debugLineInfo.filePath();
256-
String classNameAtLine = TypeEntry.canonicalize(debugLineInfo.ownerType());
257-
String methodNameAtLine = debugLineInfo.name();
258-
int loAtLine = lo + debugLineInfo.addressLo();
259-
int hiAtLine = lo + debugLineInfo.addressHi();
260-
int line = debugLineInfo.line();
261-
/*
262-
* Record all subranges even if they have no line or file so we at least get a
263-
* symbol for them and don't see a break in the address range.
264-
*/
265-
ClassEntry subClassEntry = ensureClassEntry(classNameAtLine);
266-
MethodEntry subMethodEntry = subClassEntry.ensureMethodEntryForDebugRangeInfo(debugLineInfo, this, debugContext);
267-
Range subRange = new Range(stringTable, subMethodEntry, loAtLine, hiAtLine, line, primaryRange);
268-
classEntry.indexSubRange(subRange);
269-
try (DebugContext.Scope s = debugContext.scope("Subranges")) {
270-
debugContext.log(DebugContext.VERBOSE_LEVEL, "SubRange %s.%s %s %s:%d 0x%x, 0x%x]", classNameAtLine, methodNameAtLine, filePathAtLine, fileNameAtLine, line, loAtLine, hiAtLine);
271-
}
272-
});
254+
/*
255+
* Record all subranges even if they have no line or file so we at least get a symbol
256+
* for them and don't see a break in the address range.
257+
*/
258+
debugCodeInfo.lineInfoProvider().forEach(debugLineInfo -> recursivelyAddSubRanges(debugLineInfo, primaryRange, classEntry, debugContext));
259+
primaryRange.mergeSubranges(debugContext);
273260
}));
274261

275262
debugInfoProvider.dataInfoProvider().forEach(debugDataInfo -> debugDataInfo.debugContext((debugContext) -> {
@@ -350,17 +337,60 @@ ClassEntry lookupClassEntry(String typeName) {
350337
return (ClassEntry) typeEntry;
351338
}
352339

353-
private ClassEntry ensureClassEntry(String className) {
340+
/**
341+
* Recursively creates subranges based on DebugLineInfo including, and appropriately linking,
342+
* nested inline subranges.
343+
*
344+
* @param lineInfo
345+
* @param primaryRange
346+
* @param classEntry
347+
* @param debugContext
348+
* @return the subrange for {@code lineInfo} linked with all its caller subranges up to the
349+
* primaryRange
350+
*/
351+
@SuppressWarnings("try")
352+
private Range recursivelyAddSubRanges(DebugInfoProvider.DebugLineInfo lineInfo, Range primaryRange, ClassEntry classEntry, DebugContext debugContext) {
353+
if (lineInfo == null) {
354+
return primaryRange;
355+
}
356+
/*
357+
* We still insert subranges for the primary method but they don't actually count as inline.
358+
* we only need a range so that subranges for inline code can refer to the top level line
359+
* number
360+
*/
361+
boolean isInline = lineInfo.getCaller() != null;
362+
assert (isInline || (lineInfo.name().equals(primaryRange.getMethodName()) && TypeEntry.canonicalize(lineInfo.ownerType().toJavaName()).equals(primaryRange.getClassName())));
363+
364+
Range caller = recursivelyAddSubRanges(lineInfo.getCaller(), primaryRange, classEntry, debugContext);
365+
final String fileName = lineInfo.fileName();
366+
final Path filePath = lineInfo.filePath();
367+
final ResolvedJavaType ownerType = lineInfo.ownerType();
368+
final String methodName = lineInfo.name();
369+
final int lo = primaryRange.getLo() + lineInfo.addressLo();
370+
final int hi = primaryRange.getLo() + lineInfo.addressHi();
371+
final int line = lineInfo.line();
372+
ClassEntry subRangeClassEntry = ensureClassEntry(ownerType);
373+
MethodEntry subRangeMethodEntry = subRangeClassEntry.ensureMethodEntryForDebugRangeInfo(lineInfo, this, debugContext);
374+
Range subRange = new Range(stringTable, subRangeMethodEntry, lo, hi, line, primaryRange, isInline, caller);
375+
classEntry.indexSubRange(subRange);
376+
try (DebugContext.Scope s = debugContext.scope("Subranges")) {
377+
debugContext.log(DebugContext.VERBOSE_LEVEL, "SubRange %s.%s %s %s:%d 0x%x, 0x%x]",
378+
ownerType.toJavaName(), methodName, filePath, fileName, line, lo, hi);
379+
}
380+
return subRange;
381+
}
382+
383+
private ClassEntry ensureClassEntry(ResolvedJavaType type) {
354384
/* See if we already have an entry. */
355-
ClassEntry classEntry = primaryClassesIndex.get(className);
385+
ClassEntry classEntry = primaryClassesIndex.get(type);
356386
if (classEntry == null) {
357-
TypeEntry typeEntry = typesIndex.get(className);
387+
TypeEntry typeEntry = typesIndex.get(TypeEntry.canonicalize(type.toJavaName()));
358388
assert (typeEntry != null && typeEntry.isClass());
359389
classEntry = (ClassEntry) typeEntry;
360390
primaryClasses.add(classEntry);
361-
primaryClassesIndex.put(className, classEntry);
391+
primaryClassesIndex.put(type, classEntry);
362392
}
363-
assert (classEntry.getTypeName().equals(className));
393+
assert (classEntry.getTypeName().equals(TypeEntry.canonicalize(type.toJavaName())));
364394
return classEntry;
365395
}
366396

0 commit comments

Comments
 (0)