|
35 | 35 | import java.util.Map;
|
36 | 36 |
|
37 | 37 | import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugFileInfo;
|
| 38 | +import jdk.vm.ci.meta.ResolvedJavaType; |
38 | 39 | import org.graalvm.compiler.debug.DebugContext;
|
39 | 40 |
|
40 | 41 | import com.oracle.objectfile.debuginfo.DebugInfoProvider;
|
@@ -103,7 +104,7 @@ public abstract class DebugInfoBase {
|
103 | 104 | /**
|
104 | 105 | * index of already seen classes.
|
105 | 106 | */
|
106 |
| - private Map<String, ClassEntry> primaryClassesIndex = new HashMap<>(); |
| 107 | + private Map<ResolvedJavaType, ClassEntry> primaryClassesIndex = new HashMap<>(); |
107 | 108 | /**
|
108 | 109 | * Index of files which contain primary or secondary ranges.
|
109 | 110 | */
|
@@ -238,38 +239,24 @@ public void installDebugInfo(DebugInfoProvider debugInfoProvider) {
|
238 | 239 | */
|
239 | 240 | String fileName = debugCodeInfo.fileName();
|
240 | 241 | Path filePath = debugCodeInfo.filePath();
|
241 |
| - String className = TypeEntry.canonicalize(debugCodeInfo.ownerType()); |
| 242 | + ResolvedJavaType ownerType = debugCodeInfo.ownerType(); |
242 | 243 | String methodName = debugCodeInfo.name();
|
243 | 244 | int lo = debugCodeInfo.addressLo();
|
244 | 245 | int hi = debugCodeInfo.addressHi();
|
245 | 246 | int primaryLine = debugCodeInfo.line();
|
246 | 247 |
|
247 | 248 | /* Search for a method defining this primary range. */
|
248 |
| - ClassEntry classEntry = ensureClassEntry(className); |
| 249 | + ClassEntry classEntry = ensureClassEntry(ownerType); |
249 | 250 | MethodEntry methodEntry = classEntry.ensureMethodEntryForDebugRangeInfo(debugCodeInfo, this, debugContext);
|
250 | 251 | 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); |
252 | 253 | 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); |
273 | 260 | }));
|
274 | 261 |
|
275 | 262 | debugInfoProvider.dataInfoProvider().forEach(debugDataInfo -> debugDataInfo.debugContext((debugContext) -> {
|
@@ -350,17 +337,60 @@ ClassEntry lookupClassEntry(String typeName) {
|
350 | 337 | return (ClassEntry) typeEntry;
|
351 | 338 | }
|
352 | 339 |
|
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) { |
354 | 384 | /* See if we already have an entry. */
|
355 |
| - ClassEntry classEntry = primaryClassesIndex.get(className); |
| 385 | + ClassEntry classEntry = primaryClassesIndex.get(type); |
356 | 386 | if (classEntry == null) {
|
357 |
| - TypeEntry typeEntry = typesIndex.get(className); |
| 387 | + TypeEntry typeEntry = typesIndex.get(TypeEntry.canonicalize(type.toJavaName())); |
358 | 388 | assert (typeEntry != null && typeEntry.isClass());
|
359 | 389 | classEntry = (ClassEntry) typeEntry;
|
360 | 390 | primaryClasses.add(classEntry);
|
361 |
| - primaryClassesIndex.put(className, classEntry); |
| 391 | + primaryClassesIndex.put(type, classEntry); |
362 | 392 | }
|
363 |
| - assert (classEntry.getTypeName().equals(className)); |
| 393 | + assert (classEntry.getTypeName().equals(TypeEntry.canonicalize(type.toJavaName()))); |
364 | 394 | return classEntry;
|
365 | 395 | }
|
366 | 396 |
|
|
0 commit comments