|
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