From 7495eb331b688262234fb36e0c51ad3c6fdd2933 Mon Sep 17 00:00:00 2001 From: Andrew Dinn Date: Mon, 30 May 2022 16:51:25 +0100 Subject: [PATCH 1/3] Ensure classes are identified using their originating ResolvedJavaClass rather than via class names. --- .../objectfile/debugentry/ArrayTypeEntry.java | 7 +- .../objectfile/debugentry/ClassEntry.java | 30 ++-- .../objectfile/debugentry/DebugInfoBase.java | 39 +++-- .../objectfile/debugentry/EnumClassEntry.java | 4 +- .../objectfile/debugentry/MethodEntry.java | 6 + .../debugentry/StructureTypeEntry.java | 8 +- .../debuginfo/DebugInfoProvider.java | 48 +++--- .../elf/dwarf/DwarfInfoSectionImpl.java | 5 +- .../elf/dwarf/DwarfSectionImpl.java | 9 +- .../image/NativeImageDebugInfoProvider.java | 149 +++++++++++++----- 10 files changed, 209 insertions(+), 96 deletions(-) diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ArrayTypeEntry.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ArrayTypeEntry.java index 3b2d3b75128e..10f4bdfa7b3a 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ArrayTypeEntry.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ArrayTypeEntry.java @@ -29,6 +29,7 @@ import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugArrayTypeInfo; import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugTypeInfo; import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugTypeInfo.DebugTypeKind; +import jdk.vm.ci.meta.ResolvedJavaType; import org.graalvm.compiler.debug.DebugContext; public class ArrayTypeEntry extends StructureTypeEntry { @@ -48,13 +49,13 @@ public DebugTypeKind typeKind() { @Override public void addDebugInfo(DebugInfoBase debugInfoBase, DebugTypeInfo debugTypeInfo, DebugContext debugContext) { DebugArrayTypeInfo debugArrayTypeInfo = (DebugArrayTypeInfo) debugTypeInfo; - String elementTypeName = TypeEntry.canonicalize(debugArrayTypeInfo.elementType()); - this.elementType = debugInfoBase.lookupTypeEntry(elementTypeName); + ResolvedJavaType eltType = debugArrayTypeInfo.elementType(); + this.elementType = debugInfoBase.lookupTypeEntry(eltType); this.baseSize = debugArrayTypeInfo.baseSize(); this.lengthOffset = debugArrayTypeInfo.lengthOffset(); /* Add details of fields and field types */ debugArrayTypeInfo.fieldInfoProvider().forEach(debugFieldInfo -> this.processField(debugFieldInfo, debugInfoBase, debugContext)); - debugContext.log("typename %s element type %s base size %d length offset %d\n", typeName, elementTypeName, baseSize, lengthOffset); + debugContext.log("typename %s element type %s base size %d length offset %d\n", typeName, this.elementType.getTypeName(), baseSize, lengthOffset); } public TypeEntry getElementType() { diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java index 5a2af5ebfbbf..c10295abb5de 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.Map; +import jdk.vm.ci.meta.ResolvedJavaType; import org.graalvm.compiler.debug.DebugContext; import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugFieldInfo; @@ -130,15 +131,18 @@ public void addDebugInfo(DebugInfoBase debugInfoBase, DebugTypeInfo debugTypeInf assert TypeEntry.canonicalize(debugTypeInfo.typeName()).equals(typeName); DebugInstanceTypeInfo debugInstanceTypeInfo = (DebugInstanceTypeInfo) debugTypeInfo; /* Add details of super and interface classes */ - String superName = debugInstanceTypeInfo.superName(); - if (superName != null) { - superName = TypeEntry.canonicalize(superName); + ResolvedJavaType superClass = debugInstanceTypeInfo.superClass(); + String superName; + if (superClass != null) { + superName = TypeEntry.canonicalize(superClass.toJavaName()); + } else { + superName = ""; } debugContext.log("typename %s adding super %s\n", typeName, superName); - if (superName != null) { - this.superClass = debugInfoBase.lookupClassEntry(superName); + if (superClass != null) { + this.superClass = debugInfoBase.lookupClassEntry(superClass); } - debugInstanceTypeInfo.interfaces().forEach(interfaceName -> processInterface(interfaceName, debugInfoBase, debugContext)); + debugInstanceTypeInfo.interfaces().forEach(interfaceType -> processInterface(interfaceType, debugInfoBase, debugContext)); /* Add details of fields and field types */ debugInstanceTypeInfo.fieldInfoProvider().forEach(debugFieldInfo -> this.processField(debugFieldInfo, debugInfoBase, debugContext)); /* Add details of methods and method types */ @@ -273,9 +277,10 @@ public String getCachePath() { return ""; } - private void processInterface(String interfaceName, DebugInfoBase debugInfoBase, DebugContext debugContext) { + private void processInterface(ResolvedJavaType interfaceType, DebugInfoBase debugInfoBase, DebugContext debugContext) { + String interfaceName = interfaceType.toJavaName(); debugContext.log("typename %s adding interface %s\n", typeName, interfaceName); - ClassEntry entry = debugInfoBase.lookupClassEntry(TypeEntry.canonicalize(interfaceName)); + ClassEntry entry = debugInfoBase.lookupClassEntry(interfaceType); assert entry instanceof InterfaceClassEntry; InterfaceClassEntry interfaceClassEntry = (InterfaceClassEntry) entry; interfaces.add(interfaceClassEntry); @@ -284,17 +289,18 @@ private void processInterface(String interfaceName, DebugInfoBase debugInfoBase, protected MethodEntry processMethod(DebugMethodInfo debugMethodInfo, DebugInfoBase debugInfoBase, DebugContext debugContext) { String methodName = debugMethodInfo.name(); - String resultTypeName = TypeEntry.canonicalize(debugMethodInfo.valueType()); + ResolvedJavaType resultType = debugMethodInfo.valueType(); + String resultTypeName = TypeEntry.canonicalize(resultType.toJavaName()); int modifiers = debugMethodInfo.modifiers(); DebugLocalInfo[] paramInfos = debugMethodInfo.getParamInfo(); DebugLocalInfo thisParam = debugMethodInfo.getThisParamInfo(); int paramCount = paramInfos.length; debugContext.log("typename %s adding %s method %s %s(%s)\n", typeName, memberModifiers(modifiers), resultTypeName, methodName, formatParams(paramInfos)); - TypeEntry resultType = debugInfoBase.lookupTypeEntry(resultTypeName); + TypeEntry resultTypeEntry = debugInfoBase.lookupTypeEntry(resultType); TypeEntry[] typeEntries = new TypeEntry[paramCount]; for (int i = 0; i < paramCount; i++) { - typeEntries[i] = debugInfoBase.lookupTypeEntry(TypeEntry.canonicalize(paramInfos[i].typeName())); + typeEntries[i] = debugInfoBase.lookupTypeEntry(paramInfos[i].valueType()); } /* * n.b. the method file may differ from the owning class file when the method is a @@ -302,7 +308,7 @@ protected MethodEntry processMethod(DebugMethodInfo debugMethodInfo, DebugInfoBa */ FileEntry methodFileEntry = debugInfoBase.ensureFileEntry(debugMethodInfo); MethodEntry methodEntry = new MethodEntry(debugInfoBase, debugMethodInfo, methodFileEntry, methodName, - this, resultType, typeEntries, paramInfos, thisParam); + this, resultTypeEntry, typeEntries, paramInfos, thisParam); indexMethodEntry(methodEntry); return methodEntry; diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/DebugInfoBase.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/DebugInfoBase.java index 39f12125b386..1d5b8e43e769 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/DebugInfoBase.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/DebugInfoBase.java @@ -98,7 +98,7 @@ public abstract class DebugInfoBase { /** * index of already seen classes. */ - private Map typesIndex = new HashMap<>(); + private Map typesIndex = new HashMap<>(); /** * List of class entries detailing class info for primary ranges. */ @@ -107,6 +107,10 @@ public abstract class DebugInfoBase { * index of already seen classes. */ private Map primaryClassesIndex = new HashMap<>(); + /** + * Handle on class entry for java.lang.Object. + */ + private ClassEntry objectClass; /** * Index of files which contain primary or secondary ranges. */ @@ -213,6 +217,7 @@ public void installDebugInfo(DebugInfoProvider debugInfoProvider) { /* Create all the types. */ debugInfoProvider.typeInfoProvider().forEach(debugTypeInfo -> debugTypeInfo.debugContext((debugContext) -> { + ResolvedJavaType idType = debugTypeInfo.idType(); String typeName = TypeEntry.canonicalize(debugTypeInfo.typeName()); typeName = stringTable.uniqueDebugString(typeName); DebugTypeKind typeKind = debugTypeInfo.typeKind(); @@ -222,16 +227,17 @@ public void installDebugInfo(DebugInfoProvider debugInfoProvider) { String fileName = debugTypeInfo.fileName(); Path filePath = debugTypeInfo.filePath(); Path cachePath = debugTypeInfo.cachePath(); - addTypeEntry(typeName, fileName, filePath, cachePath, byteSize, typeKind); + addTypeEntry(idType, typeName, fileName, filePath, cachePath, byteSize, typeKind); })); /* Now we can cross reference static and instance field details. */ debugInfoProvider.typeInfoProvider().forEach(debugTypeInfo -> debugTypeInfo.debugContext((debugContext) -> { + ResolvedJavaType idType = debugTypeInfo.idType(); String typeName = TypeEntry.canonicalize(debugTypeInfo.typeName()); DebugTypeKind typeKind = debugTypeInfo.typeKind(); debugContext.log(DebugContext.INFO_LEVEL, "Process %s type %s ", typeKind.toString(), typeName); - TypeEntry typeEntry = lookupTypeEntry(typeName); + TypeEntry typeEntry = lookupTypeEntry(idType); typeEntry.addDebugInfo(this, debugTypeInfo, debugContext); })); @@ -309,12 +315,15 @@ private TypeEntry createTypeEntry(String typeName, String fileName, Path filePat return typeEntry; } - private TypeEntry addTypeEntry(String typeName, String fileName, Path filePath, Path cachePath, int size, DebugTypeKind typeKind) { - TypeEntry typeEntry = typesIndex.get(typeName); + private TypeEntry addTypeEntry(ResolvedJavaType idType, String typeName, String fileName, Path filePath, Path cachePath, int size, DebugTypeKind typeKind) { + TypeEntry typeEntry = typesIndex.get(idType); if (typeEntry == null) { typeEntry = createTypeEntry(typeName, fileName, filePath, cachePath, size, typeKind); types.add(typeEntry); - typesIndex.put(typeName, typeEntry); + typesIndex.put(idType, typeEntry); + if (typeName.equals("java.lang.Object")) { + objectClass = (ClassEntry) typeEntry; + } } else { if (!(typeEntry.isClass())) { assert ((ClassEntry) typeEntry).getFileName().equals(fileName); @@ -323,22 +332,26 @@ private TypeEntry addTypeEntry(String typeName, String fileName, Path filePath, return typeEntry; } - public TypeEntry lookupTypeEntry(String typeName) { - TypeEntry typeEntry = typesIndex.get(typeName); + public TypeEntry lookupTypeEntry(ResolvedJavaType type) { + TypeEntry typeEntry = typesIndex.get(type); if (typeEntry == null) { - throw new RuntimeException("type entry not found " + typeName); + throw new RuntimeException("type entry not found " + TypeEntry.canonicalize(type.getName())); } return typeEntry; } - ClassEntry lookupClassEntry(String typeName) { - TypeEntry typeEntry = typesIndex.get(typeName); + ClassEntry lookupClassEntry(ResolvedJavaType type) { + TypeEntry typeEntry = typesIndex.get(type); if (typeEntry == null || !(typeEntry.isClass())) { - throw new RuntimeException("class entry not found " + typeName); + throw new RuntimeException("class entry not found " + TypeEntry.canonicalize(type.getName())); } return (ClassEntry) typeEntry; } + public ClassEntry lookupObjectClass() { + return objectClass; + } + /** * Recursively creates subranges based on DebugLocationInfo including, and appropriately * linking, nested inline subranges. @@ -396,7 +409,7 @@ private ClassEntry ensureClassEntry(ResolvedJavaType type) { /* See if we already have an entry. */ ClassEntry classEntry = primaryClassesIndex.get(type); if (classEntry == null) { - TypeEntry typeEntry = typesIndex.get(TypeEntry.canonicalize(type.toJavaName())); + TypeEntry typeEntry = typesIndex.get(type); assert (typeEntry != null && typeEntry.isClass()); classEntry = (ClassEntry) typeEntry; primaryClasses.add(classEntry); diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/EnumClassEntry.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/EnumClassEntry.java index cfe8272e0b6a..a6cbaf1bb2ff 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/EnumClassEntry.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/EnumClassEntry.java @@ -26,7 +26,7 @@ package com.oracle.objectfile.debugentry; -import com.oracle.objectfile.debuginfo.DebugInfoProvider; +import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugTypeInfo; import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugEnumTypeInfo; import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugTypeInfo.DebugTypeKind; import org.graalvm.compiler.debug.DebugContext; @@ -42,7 +42,7 @@ public DebugTypeKind typeKind() { } @Override - public void addDebugInfo(DebugInfoBase debugInfoBase, DebugInfoProvider.DebugTypeInfo debugTypeInfo, DebugContext debugContext) { + public void addDebugInfo(DebugInfoBase debugInfoBase, DebugTypeInfo debugTypeInfo, DebugContext debugContext) { assert debugTypeInfo instanceof DebugEnumTypeInfo; super.addDebugInfo(debugInfoBase, debugTypeInfo, debugContext); } diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/MethodEntry.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/MethodEntry.java index dc134445792a..ef21e4f2fc4e 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/MethodEntry.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/MethodEntry.java @@ -36,6 +36,7 @@ import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugMethodInfo; import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaType; public class MethodEntry extends MemberEntry { private final TypeEntry[] paramTypes; @@ -285,6 +286,11 @@ private static class DebugLocalInfoWrapper implements DebugLocalInfo { this.line = value.line(); } + @Override + public ResolvedJavaType valueType() { + return value.valueType(); + } + @Override public String name() { return value.name(); diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/StructureTypeEntry.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/StructureTypeEntry.java index 45eaa5436c1d..d32a3a0a46f1 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/StructureTypeEntry.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/StructureTypeEntry.java @@ -27,6 +27,7 @@ package com.oracle.objectfile.debugentry; import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugFieldInfo; +import jdk.vm.ci.meta.ResolvedJavaType; import org.graalvm.compiler.debug.DebugContext; import java.lang.reflect.Modifier; @@ -60,19 +61,20 @@ protected void processField(DebugFieldInfo debugFieldInfo, DebugInfoBase debugIn protected FieldEntry addField(DebugFieldInfo debugFieldInfo, DebugInfoBase debugInfoBase, DebugContext debugContext) { String fieldName = debugInfoBase.uniqueDebugString(debugFieldInfo.name()); - String valueTypeName = TypeEntry.canonicalize(debugFieldInfo.valueType()); + ResolvedJavaType valueType = debugFieldInfo.valueType(); + String valueTypeName = TypeEntry.canonicalize(valueType.toJavaName()); int fieldSize = debugFieldInfo.size(); int fieldoffset = debugFieldInfo.offset(); int fieldModifiers = debugFieldInfo.modifiers(); debugContext.log("typename %s adding %s field %s type %s size %s at offset 0x%x\n", typeName, memberModifiers(fieldModifiers), fieldName, valueTypeName, fieldSize, fieldoffset); - TypeEntry valueType = debugInfoBase.lookupTypeEntry(valueTypeName); + TypeEntry valueTypeEntry = debugInfoBase.lookupTypeEntry(valueType); /* * n.b. the field file may differ from the owning class file when the field is a * substitution */ FileEntry fileEntry = debugInfoBase.ensureFileEntry(debugFieldInfo); - FieldEntry fieldEntry = new FieldEntry(fileEntry, fieldName, this, valueType, fieldSize, fieldoffset, fieldModifiers); + FieldEntry fieldEntry = new FieldEntry(fileEntry, fieldName, this, valueTypeEntry, fieldSize, fieldoffset, fieldModifiers); fields.add(fieldEntry); return fieldEntry; } diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debuginfo/DebugInfoProvider.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debuginfo/DebugInfoProvider.java index 7619c6140560..4228c03e4b31 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debuginfo/DebugInfoProvider.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debuginfo/DebugInfoProvider.java @@ -71,7 +71,7 @@ public interface DebugInfoProvider { /** * An interface implemented by items that can be located in a file. */ - interface DebugFileInfo { + public interface DebugFileInfo { /** * @return the name of the file containing a file element excluding any path. */ @@ -90,7 +90,9 @@ interface DebugFileInfo { Path cachePath(); } - interface DebugTypeInfo extends DebugFileInfo { + public interface DebugTypeInfo extends DebugFileInfo { + ResolvedJavaType idType(); + enum DebugTypeKind { PRIMITIVE, ENUM, @@ -132,35 +134,35 @@ public String toString() { int size(); } - interface DebugInstanceTypeInfo extends DebugTypeInfo { + public interface DebugInstanceTypeInfo extends DebugTypeInfo { int headerSize(); Stream fieldInfoProvider(); Stream methodInfoProvider(); - String superName(); + ResolvedJavaType superClass(); - Stream interfaces(); + Stream interfaces(); } - interface DebugEnumTypeInfo extends DebugInstanceTypeInfo { + public interface DebugEnumTypeInfo extends DebugInstanceTypeInfo { } - interface DebugInterfaceTypeInfo extends DebugInstanceTypeInfo { + public interface DebugInterfaceTypeInfo extends DebugInstanceTypeInfo { } - interface DebugArrayTypeInfo extends DebugTypeInfo { + public interface DebugArrayTypeInfo extends DebugTypeInfo { int baseSize(); int lengthOffset(); - String elementType(); + ResolvedJavaType elementType(); Stream fieldInfoProvider(); } - interface DebugPrimitiveTypeInfo extends DebugTypeInfo { + public interface DebugPrimitiveTypeInfo extends DebugTypeInfo { /* * NUMERIC excludes LOGICAL types boolean and void */ @@ -181,27 +183,27 @@ interface DebugPrimitiveTypeInfo extends DebugTypeInfo { int flags(); } - interface DebugHeaderTypeInfo extends DebugTypeInfo { + public interface DebugHeaderTypeInfo extends DebugTypeInfo { Stream fieldInfoProvider(); } - interface DebugMemberInfo extends DebugFileInfo { + public interface DebugMemberInfo extends DebugFileInfo { String name(); - String valueType(); + ResolvedJavaType valueType(); int modifiers(); } - interface DebugFieldInfo extends DebugMemberInfo { + public interface DebugFieldInfo extends DebugMemberInfo { int offset(); int size(); } - interface DebugMethodInfo extends DebugMemberInfo { + public interface DebugMethodInfo extends DebugMemberInfo { /** * @return an array of DebugLocalInfo objects holding details of this method's parameters */ @@ -256,7 +258,7 @@ interface DebugMethodInfo extends DebugMemberInfo { * Access details of a compiled top level or inline method producing the code in a specific * {@link com.oracle.objectfile.debugentry.Range}. */ - interface DebugRangeInfo extends DebugMethodInfo { + public interface DebugRangeInfo extends DebugMethodInfo { /** * @return the lowest address containing code generated for an outer or inlined code segment @@ -280,7 +282,7 @@ interface DebugRangeInfo extends DebugMethodInfo { /** * Access details of a specific compiled method. */ - interface DebugCodeInfo extends DebugRangeInfo { + public interface DebugCodeInfo extends DebugRangeInfo { void debugContext(Consumer action); /** @@ -304,7 +306,7 @@ interface DebugCodeInfo extends DebugRangeInfo { /** * Access details of a specific heap object. */ - interface DebugDataInfo { + public interface DebugDataInfo { void debugContext(Consumer action); String getProvenance(); @@ -324,7 +326,7 @@ interface DebugDataInfo { * Access details of code generated for a specific outer or inlined method at a given line * number. */ - interface DebugLocationInfo extends DebugRangeInfo { + public interface DebugLocationInfo extends DebugRangeInfo { /** * @return the {@link DebugLocationInfo} of the nested inline caller-line */ @@ -341,7 +343,9 @@ interface DebugLocationInfo extends DebugRangeInfo { * A DebugLocalInfo details a local or parameter variable recording its name and type, the * (abstract machine) local slot index it resides in and the number of slots it occupies. */ - interface DebugLocalInfo { + public interface DebugLocalInfo { + ResolvedJavaType valueType(); + String name(); String typeName(); @@ -360,7 +364,7 @@ interface DebugLocalInfo { * frame. The value may be undefined. If not then the instance records its type and either its * (constant) value or the register or stack location in which the value resides. */ - interface DebugLocalValueInfo extends DebugLocalInfo { + public interface DebugLocalValueInfo extends DebugLocalInfo { enum LocalKind { UNDEFINED, REGISTER, @@ -379,7 +383,7 @@ enum LocalKind { JavaConstant constantValue(); } - interface DebugFrameSizeChange { + public interface DebugFrameSizeChange { enum Type { EXTEND, CONTRACT diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java index 281ef3a4b4f3..88307d0a957b 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java @@ -1214,8 +1214,9 @@ private int writeArrayElementField(DebugContext context, int offset, int arrayDa private int writeArraySuperReference(DebugContext context, byte[] buffer, int p) { int pos = p; /* Arrays all inherit from java.lang.Object */ - String superName = "java.lang.Object"; - TypeEntry objectType = lookupType(superName); + TypeEntry objectType = lookupObjectClass(); + String superName = objectType.getTypeName(); + assert objectType != null; assert objectType instanceof ClassEntry; int superOffset = getLayoutIndex((ClassEntry) objectType); return writeSuperReference(context, superOffset, superName, buffer, pos); diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfSectionImpl.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfSectionImpl.java index b16facf67b83..921583ac6618 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfSectionImpl.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfSectionImpl.java @@ -40,6 +40,7 @@ import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugLocalValueInfo; import com.oracle.objectfile.elf.ELFMachine; import com.oracle.objectfile.elf.ELFObjectFile; +import jdk.vm.ci.meta.ResolvedJavaType; import org.graalvm.compiler.debug.DebugContext; import java.nio.ByteOrder; @@ -607,8 +608,12 @@ protected String uniqueDebugString(String str) { return dwarfSections.uniqueDebugString(str); } - protected TypeEntry lookupType(String typeName) { - return dwarfSections.lookupTypeEntry(typeName); + protected TypeEntry lookupType(ResolvedJavaType type) { + return dwarfSections.lookupTypeEntry(type); + } + + protected TypeEntry lookupObjectClass() { + return dwarfSections.lookupObjectClass(); } protected int getTypeIndex(String typeName) { 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 0121fb28006e..1f6eac3905ac 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 @@ -54,6 +54,22 @@ import com.oracle.graal.pointsto.infrastructure.WrappedJavaType; import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.objectfile.debuginfo.DebugInfoProvider; +import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugArrayTypeInfo; +import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugCodeInfo; +import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugDataInfo; +import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugEnumTypeInfo; +import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugFieldInfo; +import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugFileInfo; +import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugFrameSizeChange; +import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugHeaderTypeInfo; +import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugInstanceTypeInfo; +import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugInterfaceTypeInfo; +import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugLocalInfo; +import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugLocalValueInfo; +import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugLocationInfo; +import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugMethodInfo; +import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugPrimitiveTypeInfo; +import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugTypeInfo; import com.oracle.svm.core.OS; import com.oracle.svm.core.StaticFieldsSupport; import com.oracle.svm.core.SubstrateOptions; @@ -108,6 +124,7 @@ import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.Signature; import jdk.vm.ci.meta.Value; +import java.util.HashMap; /** * Implementation of the DebugInfoProvider API interface that allows type, code and heap data info @@ -127,6 +144,8 @@ class NativeImageDebugInfoProvider implements DebugInfoProvider { int referenceStartOffset; private final Set allOverrides; HostedType wordBaseType; + HostedType hubType; + HashMap javaKindToHostedType; NativeImageDebugInfoProvider(DebugContext debugContext, NativeImageCodeCache codeCache, NativeImageHeap heap, HostedMetaAccess metaAccess) { super(); @@ -158,6 +177,27 @@ class NativeImageDebugInfoProvider implements DebugInfoProvider { .filter(Predicate.not(m::equals))) .collect(Collectors.toSet()); wordBaseType = metaAccess.lookupJavaType(WordBase.class); + hubType = metaAccess.lookupJavaType(Class.class); + javaKindToHostedType = initJavaKindToHostedTypes(metaAccess); + } + + private HashMap initJavaKindToHostedTypes(HostedMetaAccess metaAccess) { + HashMap map = new HashMap<>(); + for (JavaKind kind : JavaKind.values()) { + Class clazz = kind.toJavaClass(); + assert clazz != null || kind == JavaKind.Illegal || kind == JavaKind.Object; + HostedType javaType; + if (kind == JavaKind.Object) { + clazz = java.lang.Object.class; + } + if (clazz == null) { + javaType = null; + } else { + javaType = metaAccess.lookupJavaType(clazz); + } + map.put(kind, javaType); + } + return map; } @Override @@ -308,6 +348,9 @@ private static String toJavaName(JavaType javaType) { private final Path cachePath = SubstrateOptions.getDebugInfoSourceCacheRoot(); + private HostedType hostedTypeForKind(JavaKind kind) { + return javaKindToHostedType.get(kind); + } private abstract class NativeImageDebugFileInfo implements DebugFileInfo { private final Path fullFilePath; @@ -410,6 +453,12 @@ public String toJavaName(@SuppressWarnings("hiding") HostedType hostedType) { return getDeclaringClass(hostedType, true).toJavaName(); } + @Override + public ResolvedJavaType idType() { + // always use the original type for establishing identity + return getOriginal(hostedType); + } + @Override public String typeName() { return toJavaName(hostedType); @@ -446,11 +495,17 @@ private class NativeImageHeaderTypeInfo implements DebugHeaderTypeInfo { this.fieldInfos = new LinkedList<>(); } - void addField(String name, String valueType, int offset, @SuppressWarnings("hiding") int size) { + void addField(String name, ResolvedJavaType valueType, int offset, @SuppressWarnings("hiding") int size) { NativeImageDebugHeaderFieldInfo fieldinfo = new NativeImageDebugHeaderFieldInfo(name, valueType, offset, size); fieldInfos.add(fieldinfo); } + @Override + public ResolvedJavaType idType() { + // The header type is unique in that it does not have an associated ResolvedJavaType + return null; + } + @SuppressWarnings("try") @Override public void debugContext(Consumer action) { @@ -499,12 +554,12 @@ public Stream fieldInfoProvider() { private class NativeImageDebugHeaderFieldInfo implements DebugFieldInfo { private final String name; - private final String valueType; + private final ResolvedJavaType valueType; private final int offset; private final int size; private final int modifiers; - NativeImageDebugHeaderFieldInfo(String name, String valueType, int offset, int size) { + NativeImageDebugHeaderFieldInfo(String name, ResolvedJavaType valueType, int offset, int size) { this.name = name; this.valueType = valueType; this.offset = offset; @@ -518,7 +573,10 @@ public String name() { } @Override - public String valueType() { + public ResolvedJavaType valueType() { + if (valueType instanceof HostedType) { + return getOriginal((HostedType) valueType); + } return valueType; } @@ -557,7 +615,6 @@ private Stream computeHeaderTypeInfo() { List infos = new LinkedList<>(); int hubOffset = getObjectLayout().getHubOffset(); int hubFieldSize = referenceSize; - String hubTypeName = "java.lang.Class"; int idHashOffset = getObjectLayout().getIdentityHashCodeOffset(); int idHashSize = getObjectLayout().sizeInBytes(JavaKind.Int); int objHeaderSize = getObjectLayout().getMinimumInstanceObjectSize(); @@ -565,9 +622,9 @@ private Stream computeHeaderTypeInfo() { /* We need array headers for all Java kinds */ NativeImageHeaderTypeInfo objHeader = new NativeImageHeaderTypeInfo("_objhdr", objHeaderSize); - objHeader.addField("hub", hubTypeName, hubOffset, hubFieldSize); + objHeader.addField("hub", hubType, hubOffset, hubFieldSize); if (idHashOffset > 0) { - objHeader.addField("idHash", "int", idHashOffset, idHashSize); + objHeader.addField("idHash", javaKindToHostedType.get(JavaKind.Int), idHashOffset, idHashSize); } infos.add(objHeader); @@ -618,7 +675,7 @@ public Stream methodInfoProvider() { } @Override - public String superName() { + public ResolvedJavaType superClass() { HostedClass superClass = hostedType.getSuperclass(); /* * HostedType wraps an AnalysisType and both HostedType and AnalysisType punt calls to @@ -626,14 +683,15 @@ public String superName() { * lookup relative to the doubly unwrapped HostedType. */ if (superClass != null) { - return getDeclaringClass(superClass, true).toJavaName(); + return getDeclaringClass(superClass, true); } return null; } @Override - public Stream interfaces() { - return Arrays.stream(hostedType.getInterfaces()).map(this::toJavaName); + public Stream interfaces() { + // map through getOriginal so we can use the result as an id type + return Arrays.stream(hostedType.getInterfaces()).map(interfaceType -> getOriginal(interfaceType)); } private NativeImageDebugFieldInfo createDebugFieldInfo(HostedField field) { @@ -662,9 +720,8 @@ public String name() { } @Override - public String valueType() { - HostedType valueType = field.getType(); - return toJavaName(valueType); + public ResolvedJavaType valueType() { + return getOriginal(field.getType()); } @Override @@ -740,10 +797,10 @@ private class NativeImageDebugArrayTypeInfo extends NativeImageDebugTypeInfo imp int arrayLengthSize = getObjectLayout().sizeInBytes(JavaKind.Int); assert arrayLengthOffset + arrayLengthSize <= headerSize; - addField("len", "int", arrayLengthOffset, arrayLengthSize); + addField("len", javaKindToHostedType.get(JavaKind.Int), arrayLengthOffset, arrayLengthSize); } - void addField(String name, String valueType, int offset, @SuppressWarnings("hiding") int size) { + void addField(String name, ResolvedJavaType valueType, int offset, @SuppressWarnings("hiding") int size) { NativeImageDebugHeaderFieldInfo fieldinfo = new NativeImageDebugHeaderFieldInfo(name, valueType, offset, size); fieldInfos.add(fieldinfo); } @@ -764,9 +821,9 @@ public int lengthOffset() { } @Override - public String elementType() { + public ResolvedJavaType elementType() { HostedType elementType = arrayClass.getComponentType(); - return toJavaName(elementType); + return getOriginal(elementType); } @Override @@ -881,6 +938,22 @@ private ResolvedJavaMethod promoteAnalysisToHosted(ResolvedJavaMethod m) { return m; } + private ResolvedJavaMethod originalMethod() { + // unwrap to an original method as far as we can + ResolvedJavaMethod targetMethod = method; + while (targetMethod instanceof WrappedJavaMethod) { + targetMethod = ((WrappedJavaMethod) targetMethod).getWrapped(); + } + // if we hit these two substitutions then we can translate to the original + // for identity otherwise we use whatever we unwrapped to. + if (targetMethod instanceof SubstitutionMethod) { + targetMethod = ((SubstitutionMethod) targetMethod).getOriginal(); + } else if (targetMethod instanceof CustomSubstitutionMethod) { + targetMethod = ((CustomSubstitutionMethod) targetMethod).getOriginal(); + } + return targetMethod; + } + /** * Return the unique type that owns this method. *

@@ -933,15 +1006,7 @@ public ResolvedJavaType ownerType() { @Override public String name() { - ResolvedJavaMethod targetMethod = method; - while (targetMethod instanceof WrappedJavaMethod) { - targetMethod = ((WrappedJavaMethod) targetMethod).getWrapped(); - } - if (targetMethod instanceof SubstitutionMethod) { - targetMethod = ((SubstitutionMethod) targetMethod).getOriginal(); - } else if (targetMethod instanceof CustomSubstitutionMethod) { - targetMethod = ((CustomSubstitutionMethod) targetMethod).getOriginal(); - } + ResolvedJavaMethod targetMethod = originalMethod(); String name = targetMethod.getName(); if (name.equals("")) { if (method instanceof HostedMethod) { @@ -963,8 +1028,12 @@ public String name() { } @Override - public String valueType() { - return toJavaName(method.getSignature().getReturnType(null)); + public ResolvedJavaType valueType() { + ResolvedJavaType resultType = (ResolvedJavaType) method.getSignature().getReturnType(null); + if (resultType instanceof HostedType) { + return getOriginal((HostedType) resultType); + } + return resultType; } @Override @@ -2080,6 +2149,11 @@ public class NativeImageDebugLocalValueInfo implements DebugLocalValueInfo { this.type = type; this.slot = slot; this.line = line; + // if we don't have a type default it for the JavaKind + // it may still end up null when kind is Undefined. + if (type == null) { + type = hostedTypeForKind(kind); + } if (value instanceof RegisterValue) { this.localKind = LocalKind.REGISTER; this.value = new NativeImageDebugRegisterValue((RegisterValue) value); @@ -2125,6 +2199,14 @@ public class NativeImageDebugLocalValueInfo implements DebugLocalValueInfo { this.value = value; } + @Override + public ResolvedJavaType valueType() { + if (type != null && type instanceof HostedType) { + return getOriginal((HostedType) type); + } + return type; + } + @Override public boolean equals(Object o) { if (!(o instanceof NativeImageDebugLocalValueInfo)) { @@ -2166,14 +2248,7 @@ public String name() { @Override public String typeName() { - if (type != null) { - return toJavaName(type); - } - if (kind == JavaKind.Object) { - return "java.lang.Object"; - } else { - return kind.getJavaName(); - } + return valueType().toJavaName(); } @Override From 70de7ff42085a6d33362ae4c92d1a1efded58522 Mon Sep 17 00:00:00 2001 From: Andrew Dinn Date: Mon, 6 Jun 2022 14:46:19 +0100 Subject: [PATCH 2/3] Ensure methods are identified using their originating ResolvedJavaMethod rather than their symbol name. style fixes --- .../objectfile/debugentry/ClassEntry.java | 27 +-- .../objectfile/debugentry/DebugInfoBase.java | 19 +- .../debuginfo/DebugInfoProvider.java | 13 +- .../objectfile/elf/dwarf/DwarfDebugInfo.java | 181 +++++++++--------- .../elf/dwarf/DwarfInfoSectionImpl.java | 47 ++--- .../elf/dwarf/DwarfSectionImpl.java | 24 +-- .../image/NativeImageDebugInfoProvider.java | 52 ++--- 7 files changed, 191 insertions(+), 172 deletions(-) diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java index c10295abb5de..222eaad55413 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.Map; +import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; import org.graalvm.compiler.debug.DebugContext; @@ -65,9 +66,10 @@ public class ClassEntry extends StructureTypeEntry { */ protected List methods; /** - * An index of all currently known methods keyed by the unique local symbol name of the method. + * An index of all currently known methods keyed by the unique, associated, identifying + * ResolvedJavaMethod. */ - private Map methodsIndex; + private Map methodsIndex; /** * A list recording details of all primary ranges included in this class sorted by ascending * address range. @@ -131,16 +133,16 @@ public void addDebugInfo(DebugInfoBase debugInfoBase, DebugTypeInfo debugTypeInf assert TypeEntry.canonicalize(debugTypeInfo.typeName()).equals(typeName); DebugInstanceTypeInfo debugInstanceTypeInfo = (DebugInstanceTypeInfo) debugTypeInfo; /* Add details of super and interface classes */ - ResolvedJavaType superClass = debugInstanceTypeInfo.superClass(); + ResolvedJavaType superType = debugInstanceTypeInfo.superClass(); String superName; - if (superClass != null) { - superName = TypeEntry.canonicalize(superClass.toJavaName()); + if (superType != null) { + superName = TypeEntry.canonicalize(superType.toJavaName()); } else { superName = ""; } debugContext.log("typename %s adding super %s\n", typeName, superName); - if (superClass != null) { - this.superClass = debugInfoBase.lookupClassEntry(superClass); + if (superType != null) { + this.superClass = debugInfoBase.lookupClassEntry(superType); } debugInstanceTypeInfo.interfaces().forEach(interfaceType -> processInterface(interfaceType, debugInfoBase, debugContext)); /* Add details of fields and field types */ @@ -181,11 +183,10 @@ public void indexSubRange(Range subrange) { } } - private void indexMethodEntry(MethodEntry methodEntry) { - String methodName = methodEntry.getSymbolName(); - assert methodsIndex.get(methodName) == null : methodName; + private void indexMethodEntry(MethodEntry methodEntry, ResolvedJavaMethod idMethod) { + assert methodsIndex.get(idMethod) == null : methodEntry.getSymbolName(); methods.add(methodEntry); - methodsIndex.put(methodName, methodEntry); + methodsIndex.put(idMethod, methodEntry); } private void indexLocalFileEntry(FileEntry localFileEntry) { @@ -309,7 +310,7 @@ protected MethodEntry processMethod(DebugMethodInfo debugMethodInfo, DebugInfoBa FileEntry methodFileEntry = debugInfoBase.ensureFileEntry(debugMethodInfo); MethodEntry methodEntry = new MethodEntry(debugInfoBase, debugMethodInfo, methodFileEntry, methodName, this, resultTypeEntry, typeEntries, paramInfos, thisParam); - indexMethodEntry(methodEntry); + indexMethodEntry(methodEntry, debugMethodInfo.idMethod()); return methodEntry; } @@ -351,7 +352,7 @@ public ClassEntry getSuperClass() { public MethodEntry ensureMethodEntryForDebugRangeInfo(DebugRangeInfo debugRangeInfo, DebugInfoBase debugInfoBase, DebugContext debugContext) { - MethodEntry methodEntry = methodsIndex.get(debugRangeInfo.symbolNameForMethod()); + MethodEntry methodEntry = methodsIndex.get(debugRangeInfo.idMethod()); if (methodEntry == null) { methodEntry = processMethod(debugRangeInfo, debugInfoBase, debugContext); } else { diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/DebugInfoBase.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/DebugInfoBase.java index 1d5b8e43e769..987667958526 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/DebugInfoBase.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/DebugInfoBase.java @@ -72,7 +72,7 @@ public abstract class DebugInfoBase { * * An alternative traversal option is * - * 1) by top level class (String id) + * 1) by top level class (unique ResolvedJavaType id) * * 2) by top level compiled method (primary Range) within a class ordered by ascending address * @@ -83,6 +83,18 @@ public abstract class DebugInfoBase { * means we can treat each class as a compilation unit, allowing data common to all methods of * the class to be shared. * + * Just as an aside, for full disclosure, this is not strictly the full story. Sometimes a class + * can include speculatively optimized, compiled methods plus deopt fallback compiled variants + * of those same methods. In such cases the normal and/or speculatively compiled methods occupy + * one contiguous range and deopt methods occupy a separate higher range. The current + * compilation strategy ensures that the union across all classes of the normal/speculative + * ranges and the union across all classes of the deopt ranges lie in two distinct intervals + * where the highest address in the first union is strictly less than the lowest address in the + * second union. The implication is twofold. An address order traversal requires generating + * details for classes, methods and non-deopt primary ranges before generating details for the + * deopt primary ranges. The former details need to be generated in a distinct CU from deopt + * method details. + * * A third option appears to be to traverse via files, then top level class within file etc. * Unfortunately, files cannot be treated as the compilation unit. A file F may contain multiple * classes, say C1 and C2. There is no guarantee that methods for some other class C' in file F' @@ -96,7 +108,8 @@ public abstract class DebugInfoBase { */ private List types = new ArrayList<>(); /** - * index of already seen classes. + * Index of already seen classes keyed by the unique, associated, identifying ResolvedJavaType + * or, in the single special case of the TypeEntry for the Java header structure, by key null. */ private Map typesIndex = new HashMap<>(); /** @@ -104,7 +117,7 @@ public abstract class DebugInfoBase { */ private List primaryClasses = new ArrayList<>(); /** - * index of already seen classes. + * Index of already seen classes. */ private Map primaryClassesIndex = new HashMap<>(); /** diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debuginfo/DebugInfoProvider.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debuginfo/DebugInfoProvider.java index 4228c03e4b31..db10586430a0 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debuginfo/DebugInfoProvider.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debuginfo/DebugInfoProvider.java @@ -33,6 +33,7 @@ import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; import org.graalvm.compiler.debug.DebugContext; @@ -248,10 +249,20 @@ public interface DebugMethodInfo extends DebugMemberInfo { /* * Return the unique type that owns this method.

- * + * * @return the unique type that owns this method */ ResolvedJavaType ownerType(); + + /* + * Return the unique identifier for this method. The result can be used to unify details of + * methods presented via interface DebugTypeInfo with related details of compiled methods + * presented via interface DebugRangeInfo and of call frame methods presented via interface + * DebugLocationInfo.

+ * + * @return the unique identifier for this method + */ + ResolvedJavaMethod idMethod(); } /** diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfDebugInfo.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfDebugInfo.java index 500e1c4172ab..03d3b482f5ea 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfDebugInfo.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfDebugInfo.java @@ -327,7 +327,25 @@ public class DwarfDebugInfo extends DebugInfoBase { * n.b. this collection includes entries for the structure types used to define the object and * array headers which do not have an associated TypeEntry. */ - private HashMap propertiesIndex; + private HashMap typePropertiesIndex; + + /** + * A collection of method properties associated with each generated method record. + */ + private HashMap methodPropertiesIndex; + + /** + * A collection of local variable properties associated with a generated method record, + * potentially including a method which is abstract (hence why it is not indexed off the primary + * range). + */ + + private HashMap methodLocalPropertiesIndex; + + /** + * A collection of local variable properties associated with an inlined subrange. + */ + private HashMap rangeLocalPropertiesIndex; public DwarfDebugInfo(ELFMachine elfMachine, ByteOrder byteOrder) { super(byteOrder); @@ -348,7 +366,8 @@ public DwarfDebugInfo(ELFMachine elfMachine, ByteOrder byteOrder) { this.heapbaseRegister = rheapbase_x86; this.threadRegister = rthread_x86; } - propertiesIndex = new HashMap<>(); + typePropertiesIndex = new HashMap<>(); + methodPropertiesIndex = new HashMap<>(); methodLocalPropertiesIndex = new HashMap<>(); rangeLocalPropertiesIndex = new HashMap<>(); } @@ -480,14 +499,6 @@ static class DwarfClassProperties extends DwarfTypeProperties { * Map from field names to info section index for the field declaration. */ private HashMap fieldDeclarationIndex; - /** - * Map from method names to info section index for the field declaration. - */ - private HashMap methodDeclarationIndex; - /** - * Map from method names to info section index for the field declaration. - */ - private HashMap abstractInlineMethodIndex; DwarfClassProperties(StructureTypeEntry entry) { super(entry); @@ -499,35 +510,76 @@ static class DwarfClassProperties extends DwarfTypeProperties { this.linePrologueSize = -1; this.lineSectionSize = -1; fieldDeclarationIndex = null; - methodDeclarationIndex = null; - abstractInlineMethodIndex = null; + } + } + + /** + * A class used to associate properties with a specific method. + */ + static class DwarfMethodProperties { + /** + * The index in the info section at which the method's declaration resides. + */ + private int methodDeclarationIndex; + /** + * The index in the info section at which the method's abstract inline declaration resides. + */ + private int abstractInlineMethodIndex; + + DwarfMethodProperties() { + methodDeclarationIndex = -1; + abstractInlineMethodIndex = -1; + } + + public int getMethodDeclarationIndex() { + assert methodDeclarationIndex >= 0 : "unset declaration index"; + return methodDeclarationIndex; + } + + public int getAbstractInlineMethodIndex() { + assert abstractInlineMethodIndex >= 0 : "unset inline index"; + return abstractInlineMethodIndex; + } + + public void setMethodDeclarationIndex(int pos) { + assert methodDeclarationIndex == -1 || methodDeclarationIndex == pos : "bad declaration index"; + methodDeclarationIndex = pos; + } + + public void setAbstractInlineMethodIndex(int pos) { + assert abstractInlineMethodIndex == -1 || abstractInlineMethodIndex == pos : "bad inline index"; + abstractInlineMethodIndex = pos; } } private DwarfTypeProperties addTypeProperties(TypeEntry typeEntry) { assert typeEntry != null; assert !typeEntry.isClass(); - String typeName = typeEntry.getTypeName(); - assert propertiesIndex.get(typeName) == null; + assert typePropertiesIndex.get(typeEntry) == null; DwarfTypeProperties typeProperties = new DwarfTypeProperties(typeEntry); - this.propertiesIndex.put(typeName, typeProperties); + this.typePropertiesIndex.put(typeEntry, typeProperties); return typeProperties; } private DwarfClassProperties addClassProperties(StructureTypeEntry entry) { - String typeName = entry.getTypeName(); - assert propertiesIndex.get(typeName) == null; + assert typePropertiesIndex.get(entry) == null; DwarfClassProperties classProperties = new DwarfClassProperties(entry); - this.propertiesIndex.put(typeName, classProperties); + this.typePropertiesIndex.put(entry, classProperties); return classProperties; } + private DwarfMethodProperties addMethodProperties(MethodEntry methodEntry) { + assert methodPropertiesIndex.get(methodEntry) == null; + DwarfMethodProperties methodProperties = new DwarfMethodProperties(); + this.methodPropertiesIndex.put(methodEntry, methodProperties); + return methodProperties; + } + private DwarfTypeProperties lookupTypeProperties(TypeEntry typeEntry) { if (typeEntry instanceof ClassEntry) { return lookupClassProperties((ClassEntry) typeEntry); } else { - String typeName = typeEntry.getTypeName(); - DwarfTypeProperties typeProperties = propertiesIndex.get(typeName); + DwarfTypeProperties typeProperties = typePropertiesIndex.get(typeEntry); if (typeProperties == null) { typeProperties = addTypeProperties(typeEntry); } @@ -536,8 +588,7 @@ private DwarfTypeProperties lookupTypeProperties(TypeEntry typeEntry) { } private DwarfClassProperties lookupClassProperties(StructureTypeEntry entry) { - String typeName = entry.getTypeName(); - DwarfTypeProperties typeProperties = propertiesIndex.get(typeName); + DwarfTypeProperties typeProperties = typePropertiesIndex.get(entry); assert typeProperties == null || typeProperties instanceof DwarfClassProperties; DwarfClassProperties classProperties = (DwarfClassProperties) typeProperties; if (classProperties == null) { @@ -546,20 +597,12 @@ private DwarfClassProperties lookupClassProperties(StructureTypeEntry entry) { return classProperties; } - private DwarfTypeProperties lookupTypeProperties(String typeName) { - DwarfTypeProperties typeProperties = propertiesIndex.get(typeName); - assert typeProperties != null; - assert typeProperties.getTypeEntry().getTypeName().equals(typeName); - return typeProperties; - } - - @SuppressWarnings("unused") - private DwarfClassProperties lookupClassProperties(String typeName) { - DwarfTypeProperties classProperties = propertiesIndex.get(typeName); - assert classProperties != null; - assert classProperties.getClass() == DwarfClassProperties.class; - assert classProperties.getTypeEntry().getTypeName().equals(typeName); - return (DwarfClassProperties) classProperties; + private DwarfMethodProperties lookupMethodProperties(MethodEntry methodEntry) { + DwarfMethodProperties methodProperties = methodPropertiesIndex.get(methodEntry); + if (methodProperties == null) { + methodProperties = addMethodProperties(methodEntry); + } + return methodProperties; } void setTypeIndex(TypeEntry typeEntry, int idx) { @@ -568,8 +611,8 @@ void setTypeIndex(TypeEntry typeEntry, int idx) { typeProperties.setTypeInfoIndex(idx); } - int getTypeIndex(String typeName) { - DwarfTypeProperties typeProperties = lookupTypeProperties(typeName); + int getTypeIndex(TypeEntry typeEntry) { + DwarfTypeProperties typeProperties = lookupTypeProperties(typeEntry); return getTypeIndex(typeProperties); } @@ -584,8 +627,8 @@ void setIndirectTypeIndex(TypeEntry typeEntry, int idx) { typeProperties.setIndirectTypeInfoIndex(idx); } - int getIndirectTypeIndex(String typeName) { - DwarfTypeProperties typeProperties = lookupTypeProperties(typeName); + int getIndirectTypeIndex(TypeEntry typeEntry) { + DwarfTypeProperties typeProperties = lookupTypeProperties(typeEntry); return getIndirectTypeIndex(typeProperties); } @@ -729,54 +772,24 @@ public int getFieldDeclarationIndex(StructureTypeEntry entry, String fieldName) return fieldDeclarationIndex.get(fieldName); } - public void setMethodDeclarationIndex(ClassEntry classEntry, String methodName, int pos) { - DwarfClassProperties classProperties; - classProperties = lookupClassProperties(classEntry); - assert classProperties.getTypeEntry() == classEntry; - HashMap methodDeclarationIndex = classProperties.methodDeclarationIndex; - if (methodDeclarationIndex == null) { - classProperties.methodDeclarationIndex = methodDeclarationIndex = new HashMap<>(); - } - if (methodDeclarationIndex.get(methodName) != null) { - assert methodDeclarationIndex.get(methodName) == pos : classEntry.getTypeName() + methodName; - } else { - methodDeclarationIndex.put(methodName, pos); - } + public void setMethodDeclarationIndex(MethodEntry methodEntry, int pos) { + DwarfMethodProperties methodProperties = lookupMethodProperties(methodEntry); + methodProperties.setMethodDeclarationIndex(pos); } - public int getMethodDeclarationIndex(ClassEntry classEntry, String methodName) { - DwarfClassProperties classProperties; - classProperties = lookupClassProperties(classEntry); - assert classProperties.getTypeEntry() == classEntry; - HashMap methodDeclarationIndex = classProperties.methodDeclarationIndex; - assert methodDeclarationIndex != null : classEntry.getTypeName() + methodName; - assert methodDeclarationIndex.get(methodName) != null : classEntry.getTypeName() + methodName; - return methodDeclarationIndex.get(methodName); + public int getMethodDeclarationIndex(MethodEntry methodEntry) { + DwarfMethodProperties methodProperties = lookupMethodProperties(methodEntry); + return methodProperties.getMethodDeclarationIndex(); } - public void setAbstractInlineMethodIndex(ClassEntry classEntry, String methodName, int pos) { - DwarfClassProperties classProperties; - classProperties = lookupClassProperties(classEntry); - assert classProperties.getTypeEntry() == classEntry; - HashMap abstractInlineMethodIndex = classProperties.abstractInlineMethodIndex; - if (abstractInlineMethodIndex == null) { - classProperties.abstractInlineMethodIndex = abstractInlineMethodIndex = new HashMap<>(); - } - if (abstractInlineMethodIndex.get(methodName) != null) { - assert abstractInlineMethodIndex.get(methodName) == pos : classEntry.getTypeName() + methodName; - } else { - abstractInlineMethodIndex.put(methodName, pos); - } + public void setAbstractInlineMethodIndex(MethodEntry methodEntry, int pos) { + DwarfMethodProperties methodProperties = lookupMethodProperties(methodEntry); + methodProperties.setAbstractInlineMethodIndex(pos); } - public int getAbstractInlineMethodIndex(ClassEntry classEntry, String methodName) { - DwarfClassProperties classProperties; - classProperties = lookupClassProperties(classEntry); - assert classProperties.getTypeEntry() == classEntry; - HashMap abstractInlineMethodIndex = classProperties.abstractInlineMethodIndex; - assert abstractInlineMethodIndex != null : classEntry.getTypeName() + methodName; - assert abstractInlineMethodIndex.get(methodName) != null : classEntry.getTypeName() + methodName; - return abstractInlineMethodIndex.get(methodName); + public int getAbstractInlineMethodIndex(MethodEntry methodEntry) { + DwarfMethodProperties methodProperties = lookupMethodProperties(methodEntry); + return methodProperties.getAbstractInlineMethodIndex(); } /** @@ -804,10 +817,6 @@ void setIndex(DebugLocalInfo localInfo, int index) { } } - private HashMap methodLocalPropertiesIndex; - - private HashMap rangeLocalPropertiesIndex; - private DwarfLocalProperties addMethodLocalProperties(MethodEntry methodEntry) { DwarfLocalProperties localProperties = new DwarfLocalProperties(); methodLocalPropertiesIndex.put(methodEntry, localProperties); diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java index 88307d0a957b..41ebf203dfac 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java @@ -311,7 +311,7 @@ private int writeHeaderField(DebugContext context, FieldEntry fieldEntry, byte[] TypeEntry valueType = fieldEntry.getValueType(); String valueTypeName = valueType.getTypeName(); /* use the indirect type for the field so pointers get translated */ - int valueTypeIdx = getIndirectTypeIndex(valueTypeName); + int valueTypeIdx = getIndirectTypeIndex(valueType); log(context, " [0x%08x] header field", pos); int abbrevCode = DwarfDebugInfo.DW_ABBREV_CODE_header_field; log(context, " [0x%08x] <2> Abbrev Number %d", pos, abbrevCode); @@ -520,7 +520,8 @@ private int writeClassLayout(DebugContext context, ClassEntry classEntry, byte[] } else { /* Inherit layout from object header. */ superName = OBJECT_HEADER_STRUCT_NAME; - superTypeOffset = getTypeIndex(superName); + TypeEntry headerType = lookupType(null); + superTypeOffset = getTypeIndex(headerType); } /* Now write the child fields. */ pos = writeSuperReference(context, superTypeOffset, superName, buffer, pos); @@ -625,9 +626,10 @@ private int writeField(DebugContext context, StructureTypeEntry entry, FieldEntr pos = writeAttrData2((short) fileIdx, buffer, pos); /* At present we definitely don't have line numbers. */ } - String valueTypeName = fieldEntry.getValueType().getTypeName(); + TypeEntry valueType = fieldEntry.getValueType(); + String valueTypeName = valueType.getTypeName(); /* use the indirect type for the field so pointers get translated if needed */ - int typeIdx = getIndirectTypeIndex(valueTypeName); + int typeIdx = getIndirectTypeIndex(valueType); log(context, " [0x%08x] type 0x%x (%s)", pos, typeIdx, valueTypeName); pos = writeAttrRefAddr(typeIdx, buffer, pos); if (!isStatic) { @@ -665,7 +667,7 @@ private int writeMethodDeclarations(DebugContext context, ClassEntry classEntry, private int writeMethodDeclaration(DebugContext context, ClassEntry classEntry, MethodEntry method, byte[] buffer, int p) { int pos = p; String methodKey = method.getSymbolName(); - setMethodDeclarationIndex(classEntry, methodKey, pos); + setMethodDeclarationIndex(method, pos); int modifiers = method.getModifiers(); boolean isStatic = Modifier.isStatic(modifiers); log(context, " [0x%08x] method declaration %s", pos, methodKey); @@ -685,8 +687,9 @@ private int writeMethodDeclaration(DebugContext context, ClassEntry classEntry, int fileIdx = classEntry.localFilesIdx(fileEntry); log(context, " [0x%08x] file 0x%x (%s)", pos, fileIdx, fileEntry.getFullName()); pos = writeAttrData2((short) fileIdx, buffer, pos); - String returnTypeName = method.getValueType().getTypeName(); - int retTypeIdx = getTypeIndex(returnTypeName); + TypeEntry returnType = method.getValueType(); + String returnTypeName = returnType.getTypeName(); + int retTypeIdx = getTypeIndex(returnType); log(context, " [0x%08x] type 0x%x (%s)", pos, retTypeIdx, returnTypeName); pos = writeAttrRefAddr(retTypeIdx, buffer, pos); log(context, " [0x%08x] artificial %s", pos, method.isDeopt() ? "true" : "false"); @@ -745,7 +748,8 @@ private int writeMethodParameterDeclaration(DebugContext context, DebugLocalInfo log(context, " [0x%08x] method parameter declaration", pos); int abbrevCode; String paramName = paramInfo.name(); - String paramTypeName = paramInfo.typeName(); + TypeEntry paramType = lookupType(paramInfo.valueType()); + String paramTypeName = paramType.getTypeName(); int line = paramInfo.line(); if (artificial) { abbrevCode = DwarfDebugInfo.DW_ABBREV_CODE_method_parameter_declaration1; @@ -764,7 +768,7 @@ private int writeMethodParameterDeclaration(DebugContext context, DebugLocalInfo log(context, " [0x%08x] line 0x%x", pos, line); pos = writeAttrData2((short) line, buffer, pos); } - int typeIdx = getTypeIndex(paramTypeName); + int typeIdx = getTypeIndex(paramType); log(context, " [0x%08x] type 0x%x (%s)", pos, typeIdx, paramTypeName); pos = writeAttrRefAddr(typeIdx, buffer, pos); if (abbrevCode == DwarfDebugInfo.DW_ABBREV_CODE_method_parameter_declaration1) { @@ -794,7 +798,8 @@ private int writeMethodLocalDeclaration(DebugContext context, DebugLocalInfo par log(context, " [0x%08x] method local declaration", pos); int abbrevCode; String paramName = paramInfo.name(); - String paramTypeName = paramInfo.typeName(); + TypeEntry paramType = lookupType(paramInfo.valueType()); + String paramTypeName = paramType.getTypeName(); int line = paramInfo.line(); if (line >= 0) { abbrevCode = DwarfDebugInfo.DW_ABBREV_CODE_method_local_declaration1; @@ -811,7 +816,7 @@ private int writeMethodLocalDeclaration(DebugContext context, DebugLocalInfo par log(context, " [0x%08x] line 0x%x", pos, line); pos = writeAttrData2((short) line, buffer, pos); } - int typeIdx = getTypeIndex(paramTypeName); + int typeIdx = getTypeIndex(paramType); log(context, " [0x%08x] type 0x%x (%s)", pos, typeIdx, paramTypeName); pos = writeAttrRefAddr(typeIdx, buffer, pos); log(context, " [0x%08x] declaration true", pos); @@ -981,7 +986,7 @@ private int writeMethodLocations(DebugContext context, ClassEntry classEntry, bo if (primary.isDeoptTarget() != deoptTargets) { continue; } - pos = writeMethodLocation(context, classEntry, primaryEntry, buffer, pos); + pos = writeMethodLocation(context, primaryEntry, buffer, pos); } return pos; } @@ -990,9 +995,8 @@ private int writeAbstractInlineMethods(DebugContext context, ClassEntry classEnt int pos = p; for (MethodEntry method : classEntry.getMethods()) { if (method.isInlined()) { - String methodKey = method.getSymbolName(); - setAbstractInlineMethodIndex(classEntry, methodKey, pos); - pos = writeAbstractInlineMethod(context, classEntry, method, buffer, pos); + setAbstractInlineMethodIndex(method, pos); + pos = writeAbstractInlineMethod(context, method, buffer, pos); } } return pos; @@ -1185,7 +1189,7 @@ private int writeArrayDataType(DebugContext context, TypeEntry elementType, byte pos = writeAttrData1((byte) size, buffer, pos); String elementTypeName = elementType.getTypeName(); /* use the indirect type for the element type so pointers get translated */ - int elementTypeIdx = getIndirectTypeIndex(elementTypeName); + int elementTypeIdx = getIndirectTypeIndex(elementType); log(context, " [0x%08x] type idx 0x%x (%s)", pos, elementTypeIdx, elementTypeName); pos = writeAttrRefAddr(elementTypeIdx, buffer, pos); return pos; @@ -1297,7 +1301,7 @@ private int writeDeoptMethodsCU(DebugContext context, ClassEntry classEntry, byt return writeAttrNull(buffer, pos); } - private int writeMethodLocation(DebugContext context, ClassEntry classEntry, PrimaryEntry primaryEntry, byte[] buffer, int p) { + private int writeMethodLocation(DebugContext context, PrimaryEntry primaryEntry, byte[] buffer, int p) { int pos = p; Range primary = primaryEntry.getPrimary(); log(context, " [0x%08x] method location", pos); @@ -1314,7 +1318,7 @@ private int writeMethodLocation(DebugContext context, ClassEntry classEntry, Pri log(context, " [0x%08x] external true", pos); pos = writeFlag(DwarfDebugInfo.DW_FLAG_true, buffer, pos); String methodKey = primary.getSymbolName(); - int methodSpecOffset = getMethodDeclarationIndex(classEntry, methodKey); + int methodSpecOffset = getMethodDeclarationIndex(primary.getMethodEntry()); log(context, " [0x%08x] specification 0x%x (%s)", pos, methodSpecOffset, methodKey); pos = writeAttrRefAddr(methodSpecOffset, buffer, pos); HashMap> varRangeMap = primary.getVarRangeMap(); @@ -1421,7 +1425,7 @@ private int writeMethodLocalLocation(DebugContext context, Range range, DebugLoc return pos; } - private int writeAbstractInlineMethod(DebugContext context, ClassEntry classEntry, MethodEntry method, byte[] buffer, int p) { + private int writeAbstractInlineMethod(DebugContext context, MethodEntry method, byte[] buffer, int p) { int pos = p; String methodKey = method.getSymbolName(); log(context, " [0x%08x] abstract inline method %s", pos, method.getSymbolName()); @@ -1435,7 +1439,7 @@ private int writeAbstractInlineMethod(DebugContext context, ClassEntry classEntr */ log(context, " [0x%08x] external true", pos); pos = writeFlag(DwarfDebugInfo.DW_FLAG_true, buffer, pos); - int methodSpecOffset = getMethodDeclarationIndex(classEntry, methodKey); + int methodSpecOffset = getMethodDeclarationIndex(method); log(context, " [0x%08x] specification 0x%x (%s)", pos, methodSpecOffset, methodKey); pos = writeAttrRefAddr(methodSpecOffset, buffer, pos); /* @@ -1452,10 +1456,9 @@ private int writeInlineSubroutine(DebugContext context, Range caller, int depth, // identify the inlined method by looking at the first callee Range callee = caller.getFirstCallee(); MethodEntry methodEntry = callee.getMethodEntry(); - ClassEntry methodClassEntry = methodEntry.ownerType(); String methodKey = methodEntry.getSymbolName(); /* the abstract index was written in the method's class entry */ - int specificationIndex = getAbstractInlineMethodIndex(methodClassEntry, methodKey); + int specificationIndex = getAbstractInlineMethodIndex(methodEntry); int pos = p; log(context, " [0x%08x] concrete inline subroutine [0x%x, 0x%x] %s", pos, caller.getLo(), caller.getHi(), methodKey); diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfSectionImpl.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfSectionImpl.java index 921583ac6618..4ce7aeaf6c20 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfSectionImpl.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfSectionImpl.java @@ -616,22 +616,22 @@ protected TypeEntry lookupObjectClass() { return dwarfSections.lookupObjectClass(); } - protected int getTypeIndex(String typeName) { + protected int getTypeIndex(TypeEntry typeEntry) { if (!contentByteArrayCreated()) { return 0; } - return dwarfSections.getTypeIndex(typeName); + return dwarfSections.getTypeIndex(typeEntry); } protected void setTypeIndex(TypeEntry typeEntry, int pos) { dwarfSections.setTypeIndex(typeEntry, pos); } - protected int getIndirectTypeIndex(String typeName) { + protected int getIndirectTypeIndex(TypeEntry typeEntry) { if (!contentByteArrayCreated()) { return 0; } - return dwarfSections.getIndirectTypeIndex(typeName); + return dwarfSections.getIndirectTypeIndex(typeEntry); } protected void setIndirectTypeIndex(TypeEntry typeEntry, int pos) { @@ -726,26 +726,26 @@ protected int getFieldDeclarationIndex(StructureTypeEntry entry, String fieldNam return dwarfSections.getFieldDeclarationIndex(entry, fieldName); } - protected void setMethodDeclarationIndex(ClassEntry classEntry, String methodName, int pos) { - dwarfSections.setMethodDeclarationIndex(classEntry, methodName, pos); + protected void setMethodDeclarationIndex(MethodEntry methodEntry, int pos) { + dwarfSections.setMethodDeclarationIndex(methodEntry, pos); } - protected int getMethodDeclarationIndex(ClassEntry classEntry, String methodName) { + protected int getMethodDeclarationIndex(MethodEntry methodEntry) { if (!contentByteArrayCreated()) { return 0; } - return dwarfSections.getMethodDeclarationIndex(classEntry, methodName); + return dwarfSections.getMethodDeclarationIndex(methodEntry); } - protected void setAbstractInlineMethodIndex(ClassEntry classEntry, String methodName, int pos) { - dwarfSections.setAbstractInlineMethodIndex(classEntry, methodName, pos); + protected void setAbstractInlineMethodIndex(MethodEntry methodEntry, int pos) { + dwarfSections.setAbstractInlineMethodIndex(methodEntry, pos); } - protected int getAbstractInlineMethodIndex(ClassEntry classEntry, String methodName) { + protected int getAbstractInlineMethodIndex(MethodEntry methodEntry) { if (!contentByteArrayCreated()) { return 0; } - return dwarfSections.getAbstractInlineMethodIndex(classEntry, methodName); + return dwarfSections.getAbstractInlineMethodIndex(methodEntry); } protected void setMethodLocalIndex(MethodEntry methodEntry, DebugLocalInfo localInfo, int index) { 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 1f6eac3905ac..289ad9fab999 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 @@ -54,22 +54,6 @@ import com.oracle.graal.pointsto.infrastructure.WrappedJavaType; import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.objectfile.debuginfo.DebugInfoProvider; -import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugArrayTypeInfo; -import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugCodeInfo; -import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugDataInfo; -import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugEnumTypeInfo; -import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugFieldInfo; -import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugFileInfo; -import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugFrameSizeChange; -import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugHeaderTypeInfo; -import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugInstanceTypeInfo; -import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugInterfaceTypeInfo; -import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugLocalInfo; -import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugLocalValueInfo; -import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugLocationInfo; -import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugMethodInfo; -import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugPrimitiveTypeInfo; -import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugTypeInfo; import com.oracle.svm.core.OS; import com.oracle.svm.core.StaticFieldsSupport; import com.oracle.svm.core.SubstrateOptions; @@ -84,7 +68,7 @@ import com.oracle.svm.core.heap.ObjectHeader; import com.oracle.svm.core.image.ImageHeapPartition; import com.oracle.svm.core.meta.SubstrateObjectConstant; -import com.oracle.svm.hosted.annotation.CustomSubstitutionMethod; +// import com.oracle.svm.hosted.annotation.CustomSubstitutionMethod; import com.oracle.svm.hosted.annotation.CustomSubstitutionType; import com.oracle.svm.hosted.image.NativeImageHeap.ObjectInfo; import com.oracle.svm.hosted.image.sources.SourceManager; @@ -181,10 +165,10 @@ class NativeImageDebugInfoProvider implements DebugInfoProvider { javaKindToHostedType = initJavaKindToHostedTypes(metaAccess); } - private HashMap initJavaKindToHostedTypes(HostedMetaAccess metaAccess) { + private static HashMap initJavaKindToHostedTypes(HostedMetaAccess metaAccess) { HashMap map = new HashMap<>(); for (JavaKind kind : JavaKind.values()) { - Class clazz = kind.toJavaClass(); + Class clazz = kind.toJavaClass(); assert clazz != null || kind == JavaKind.Illegal || kind == JavaKind.Object; HostedType javaType; if (kind == JavaKind.Object) { @@ -329,8 +313,8 @@ private static ResolvedJavaMethod getOriginal(HostedMethod hostedMethod) { if (javaMethod instanceof SubstitutionMethod) { SubstitutionMethod substitutionMethod = (SubstitutionMethod) javaMethod; javaMethod = substitutionMethod.getAnnotated(); - } else if (javaMethod instanceof CustomSubstitutionMethod) { - javaMethod = ((CustomSubstitutionMethod) javaMethod).getOriginal(); + // } else if (javaMethod instanceof CustomSubstitutionMethod) { + // javaMethod = ((CustomSubstitutionMethod) javaMethod).getOriginal(); } return javaMethod; } @@ -339,18 +323,12 @@ private static int getOriginalModifiers(HostedMethod hostedMethod) { return getOriginal(hostedMethod).getModifiers(); } - private static String toJavaName(JavaType javaType) { - if (javaType instanceof HostedType) { - return getDeclaringClass((HostedType) javaType, true).toJavaName(); - } - return javaType.toJavaName(); - } - private final Path cachePath = SubstrateOptions.getDebugInfoSourceCacheRoot(); private HostedType hostedTypeForKind(JavaKind kind) { return javaKindToHostedType.get(kind); } + private abstract class NativeImageDebugFileInfo implements DebugFileInfo { private final Path fullFilePath; @@ -948,8 +926,8 @@ private ResolvedJavaMethod originalMethod() { // for identity otherwise we use whatever we unwrapped to. if (targetMethod instanceof SubstitutionMethod) { targetMethod = ((SubstitutionMethod) targetMethod).getOriginal(); - } else if (targetMethod instanceof CustomSubstitutionMethod) { - targetMethod = ((CustomSubstitutionMethod) targetMethod).getOriginal(); + // } else if (targetMethod instanceof CustomSubstitutionMethod) { + // targetMethod = ((CustomSubstitutionMethod) targetMethod).getOriginal(); } return targetMethod; } @@ -1004,6 +982,13 @@ public ResolvedJavaType ownerType() { return result; } + @Override + public ResolvedJavaMethod idMethod() { + // translating to the original ensures we equate a + // substituted method with the original in case we ever see both + return originalMethod(); + } + @Override public String name() { ResolvedJavaMethod targetMethod = originalMethod(); @@ -2143,17 +2128,14 @@ public class NativeImageDebugLocalValueInfo implements DebugLocalValueInfo { this(name, Value.ILLEGAL, 0, kind, type, slot, line); } - NativeImageDebugLocalValueInfo(String name, JavaValue value, int framesize, JavaKind kind, ResolvedJavaType type, int slot, int line) { + NativeImageDebugLocalValueInfo(String name, JavaValue value, int framesize, JavaKind kind, ResolvedJavaType t, int slot, int line) { this.name = name; this.kind = kind; - this.type = type; this.slot = slot; this.line = line; // if we don't have a type default it for the JavaKind // it may still end up null when kind is Undefined. - if (type == null) { - type = hostedTypeForKind(kind); - } + this.type = (t != null ? t : hostedTypeForKind(kind)); if (value instanceof RegisterValue) { this.localKind = LocalKind.REGISTER; this.value = new NativeImageDebugRegisterValue((RegisterValue) value); From f1b32e71e84a789ff3207ae8cd290e1f64b300f5 Mon Sep 17 00:00:00 2001 From: Andrew Dinn Date: Wed, 8 Jun 2022 13:20:27 +0100 Subject: [PATCH 3/3] review rework --- .../objectfile/debugentry/ClassEntry.java | 6 +- .../objectfile/debugentry/DebugInfoBase.java | 12 ++-- .../debugentry/HeaderTypeEntry.java | 2 +- .../debugentry/StructureTypeEntry.java | 2 +- .../objectfile/debugentry/TypeEntry.java | 4 -- .../elf/dwarf/DwarfInfoSectionImpl.java | 15 ++--- .../image/NativeImageDebugInfoProvider.java | 63 +++++++++++-------- 7 files changed, 53 insertions(+), 51 deletions(-) diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java index 222eaad55413..58344ce941f4 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java @@ -130,13 +130,13 @@ public DebugTypeKind typeKind() { @Override public void addDebugInfo(DebugInfoBase debugInfoBase, DebugTypeInfo debugTypeInfo, DebugContext debugContext) { - assert TypeEntry.canonicalize(debugTypeInfo.typeName()).equals(typeName); + assert debugTypeInfo.typeName().equals(typeName); DebugInstanceTypeInfo debugInstanceTypeInfo = (DebugInstanceTypeInfo) debugTypeInfo; /* Add details of super and interface classes */ ResolvedJavaType superType = debugInstanceTypeInfo.superClass(); String superName; if (superType != null) { - superName = TypeEntry.canonicalize(superType.toJavaName()); + superName = superType.toJavaName(); } else { superName = ""; } @@ -291,7 +291,7 @@ private void processInterface(ResolvedJavaType interfaceType, DebugInfoBase debu protected MethodEntry processMethod(DebugMethodInfo debugMethodInfo, DebugInfoBase debugInfoBase, DebugContext debugContext) { String methodName = debugMethodInfo.name(); ResolvedJavaType resultType = debugMethodInfo.valueType(); - String resultTypeName = TypeEntry.canonicalize(resultType.toJavaName()); + String resultTypeName = resultType.toJavaName(); int modifiers = debugMethodInfo.modifiers(); DebugLocalInfo[] paramInfos = debugMethodInfo.getParamInfo(); DebugLocalInfo thisParam = debugMethodInfo.getThisParamInfo(); diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/DebugInfoBase.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/DebugInfoBase.java index 987667958526..cae5c20fb575 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/DebugInfoBase.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/DebugInfoBase.java @@ -231,7 +231,7 @@ public void installDebugInfo(DebugInfoProvider debugInfoProvider) { /* Create all the types. */ debugInfoProvider.typeInfoProvider().forEach(debugTypeInfo -> debugTypeInfo.debugContext((debugContext) -> { ResolvedJavaType idType = debugTypeInfo.idType(); - String typeName = TypeEntry.canonicalize(debugTypeInfo.typeName()); + String typeName = debugTypeInfo.typeName(); typeName = stringTable.uniqueDebugString(typeName); DebugTypeKind typeKind = debugTypeInfo.typeKind(); int byteSize = debugTypeInfo.size(); @@ -246,7 +246,7 @@ public void installDebugInfo(DebugInfoProvider debugInfoProvider) { /* Now we can cross reference static and instance field details. */ debugInfoProvider.typeInfoProvider().forEach(debugTypeInfo -> debugTypeInfo.debugContext((debugContext) -> { ResolvedJavaType idType = debugTypeInfo.idType(); - String typeName = TypeEntry.canonicalize(debugTypeInfo.typeName()); + String typeName = debugTypeInfo.typeName(); DebugTypeKind typeKind = debugTypeInfo.typeKind(); debugContext.log(DebugContext.INFO_LEVEL, "Process %s type %s ", typeKind.toString(), typeName); @@ -348,7 +348,7 @@ private TypeEntry addTypeEntry(ResolvedJavaType idType, String typeName, String public TypeEntry lookupTypeEntry(ResolvedJavaType type) { TypeEntry typeEntry = typesIndex.get(type); if (typeEntry == null) { - throw new RuntimeException("type entry not found " + TypeEntry.canonicalize(type.getName())); + throw new RuntimeException("type entry not found " + type.getName()); } return typeEntry; } @@ -356,7 +356,7 @@ public TypeEntry lookupTypeEntry(ResolvedJavaType type) { ClassEntry lookupClassEntry(ResolvedJavaType type) { TypeEntry typeEntry = typesIndex.get(type); if (typeEntry == null || !(typeEntry.isClass())) { - throw new RuntimeException("class entry not found " + TypeEntry.canonicalize(type.getName())); + throw new RuntimeException("class entry not found " + type.getName()); } return (ClassEntry) typeEntry; } @@ -386,7 +386,7 @@ private Range addSubrange(DebugLocationInfo locationInfo, Range primaryRange, Cl DebugLocationInfo callerLocationInfo = locationInfo.getCaller(); boolean isTopLevel = callerLocationInfo == null; assert (!isTopLevel || (locationInfo.name().equals(primaryRange.getMethodName()) && - TypeEntry.canonicalize(locationInfo.ownerType().toJavaName()).equals(primaryRange.getClassName()))); + locationInfo.ownerType().toJavaName().equals(primaryRange.getClassName()))); Range caller = (isTopLevel ? primaryRange : subRangeIndex.get(callerLocationInfo)); // the frame tree is walked topdown so inline ranges should always have a caller range assert caller != null; @@ -428,7 +428,7 @@ private ClassEntry ensureClassEntry(ResolvedJavaType type) { primaryClasses.add(classEntry); primaryClassesIndex.put(type, classEntry); } - assert (classEntry.getTypeName().equals(TypeEntry.canonicalize(type.toJavaName()))); + assert (classEntry.getTypeName().equals(type.toJavaName())); return classEntry; } diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/HeaderTypeEntry.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/HeaderTypeEntry.java index 6d3ff469f802..2dc9da5af94f 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/HeaderTypeEntry.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/HeaderTypeEntry.java @@ -45,7 +45,7 @@ public DebugTypeKind typeKind() { @Override public void addDebugInfo(DebugInfoBase debugInfoBase, DebugTypeInfo debugTypeInfo, DebugContext debugContext) { - assert TypeEntry.canonicalize(debugTypeInfo.typeName()).equals(typeName); + assert debugTypeInfo.typeName().equals(typeName); DebugHeaderTypeInfo debugHeaderTypeInfo = (DebugHeaderTypeInfo) debugTypeInfo; debugHeaderTypeInfo.fieldInfoProvider().forEach(debugFieldInfo -> this.processField(debugFieldInfo, debugInfoBase, debugContext)); } diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/StructureTypeEntry.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/StructureTypeEntry.java index d32a3a0a46f1..b95d55f270ea 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/StructureTypeEntry.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/StructureTypeEntry.java @@ -62,7 +62,7 @@ protected void processField(DebugFieldInfo debugFieldInfo, DebugInfoBase debugIn protected FieldEntry addField(DebugFieldInfo debugFieldInfo, DebugInfoBase debugInfoBase, DebugContext debugContext) { String fieldName = debugInfoBase.uniqueDebugString(debugFieldInfo.name()); ResolvedJavaType valueType = debugFieldInfo.valueType(); - String valueTypeName = TypeEntry.canonicalize(valueType.toJavaName()); + String valueTypeName = valueType.toJavaName(); int fieldSize = debugFieldInfo.size(); int fieldoffset = debugFieldInfo.offset(); int fieldModifiers = debugFieldInfo.modifiers(); diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/TypeEntry.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/TypeEntry.java index afbbf01e117d..16190562185b 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/TypeEntry.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/TypeEntry.java @@ -96,8 +96,4 @@ public boolean isStructure() { } public abstract void addDebugInfo(DebugInfoBase debugInfoBase, DebugTypeInfo debugTypeInfo, DebugContext debugContext); - - public static String canonicalize(String typeName) { - return typeName.replace(" ", "__"); - } } diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java index 41ebf203dfac..134a127f6e8f 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java @@ -309,7 +309,6 @@ private int writeHeaderField(DebugContext context, FieldEntry fieldEntry, byte[] int pos = p; String fieldName = fieldEntry.fieldName(); TypeEntry valueType = fieldEntry.getValueType(); - String valueTypeName = valueType.getTypeName(); /* use the indirect type for the field so pointers get translated */ int valueTypeIdx = getIndirectTypeIndex(valueType); log(context, " [0x%08x] header field", pos); @@ -318,7 +317,7 @@ private int writeHeaderField(DebugContext context, FieldEntry fieldEntry, byte[] pos = writeAbbrevCode(abbrevCode, buffer, pos); log(context, " [0x%08x] name 0x%x (%s)", pos, debugStringIndex(fieldName), fieldName); pos = writeAttrStrp(fieldName, buffer, pos); - log(context, " [0x%08x] type 0x%x (%s)", pos, valueTypeIdx, valueTypeName); + log(context, " [0x%08x] type 0x%x (%s)", pos, valueTypeIdx, valueType.getTypeName()); pos = writeAttrRefAddr(valueTypeIdx, buffer, pos); byte offset = (byte) fieldEntry.getOffset(); int size = fieldEntry.getSize(); @@ -627,10 +626,9 @@ private int writeField(DebugContext context, StructureTypeEntry entry, FieldEntr /* At present we definitely don't have line numbers. */ } TypeEntry valueType = fieldEntry.getValueType(); - String valueTypeName = valueType.getTypeName(); /* use the indirect type for the field so pointers get translated if needed */ int typeIdx = getIndirectTypeIndex(valueType); - log(context, " [0x%08x] type 0x%x (%s)", pos, typeIdx, valueTypeName); + log(context, " [0x%08x] type 0x%x (%s)", pos, typeIdx, valueType.getTypeName()); pos = writeAttrRefAddr(typeIdx, buffer, pos); if (!isStatic) { int memberOffset = fieldEntry.getOffset(); @@ -688,9 +686,8 @@ private int writeMethodDeclaration(DebugContext context, ClassEntry classEntry, log(context, " [0x%08x] file 0x%x (%s)", pos, fileIdx, fileEntry.getFullName()); pos = writeAttrData2((short) fileIdx, buffer, pos); TypeEntry returnType = method.getValueType(); - String returnTypeName = returnType.getTypeName(); int retTypeIdx = getTypeIndex(returnType); - log(context, " [0x%08x] type 0x%x (%s)", pos, retTypeIdx, returnTypeName); + log(context, " [0x%08x] type 0x%x (%s)", pos, retTypeIdx, returnType.getTypeName()); pos = writeAttrRefAddr(retTypeIdx, buffer, pos); log(context, " [0x%08x] artificial %s", pos, method.isDeopt() ? "true" : "false"); pos = writeFlag((method.isDeopt() ? (byte) 1 : (byte) 0), buffer, pos); @@ -749,7 +746,6 @@ private int writeMethodParameterDeclaration(DebugContext context, DebugLocalInfo int abbrevCode; String paramName = paramInfo.name(); TypeEntry paramType = lookupType(paramInfo.valueType()); - String paramTypeName = paramType.getTypeName(); int line = paramInfo.line(); if (artificial) { abbrevCode = DwarfDebugInfo.DW_ABBREV_CODE_method_parameter_declaration1; @@ -769,7 +765,7 @@ private int writeMethodParameterDeclaration(DebugContext context, DebugLocalInfo pos = writeAttrData2((short) line, buffer, pos); } int typeIdx = getTypeIndex(paramType); - log(context, " [0x%08x] type 0x%x (%s)", pos, typeIdx, paramTypeName); + log(context, " [0x%08x] type 0x%x (%s)", pos, typeIdx, paramType.getTypeName()); pos = writeAttrRefAddr(typeIdx, buffer, pos); if (abbrevCode == DwarfDebugInfo.DW_ABBREV_CODE_method_parameter_declaration1) { log(context, " [0x%08x] artificial true", pos); @@ -799,7 +795,6 @@ private int writeMethodLocalDeclaration(DebugContext context, DebugLocalInfo par int abbrevCode; String paramName = paramInfo.name(); TypeEntry paramType = lookupType(paramInfo.valueType()); - String paramTypeName = paramType.getTypeName(); int line = paramInfo.line(); if (line >= 0) { abbrevCode = DwarfDebugInfo.DW_ABBREV_CODE_method_local_declaration1; @@ -817,7 +812,7 @@ private int writeMethodLocalDeclaration(DebugContext context, DebugLocalInfo par pos = writeAttrData2((short) line, buffer, pos); } int typeIdx = getTypeIndex(paramType); - log(context, " [0x%08x] type 0x%x (%s)", pos, typeIdx, paramTypeName); + log(context, " [0x%08x] type 0x%x (%s)", pos, typeIdx, paramType.getTypeName()); pos = writeAttrRefAddr(typeIdx, buffer, pos); log(context, " [0x%08x] declaration true", pos); pos = writeFlag((byte) 1, buffer, pos); 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 289ad9fab999..f0ea9563e5b0 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 @@ -68,7 +68,6 @@ import com.oracle.svm.core.heap.ObjectHeader; import com.oracle.svm.core.image.ImageHeapPartition; import com.oracle.svm.core.meta.SubstrateObjectConstant; -// import com.oracle.svm.hosted.annotation.CustomSubstitutionMethod; import com.oracle.svm.hosted.annotation.CustomSubstitutionType; import com.oracle.svm.hosted.image.NativeImageHeap.ObjectInfo; import com.oracle.svm.hosted.image.sources.SourceManager; @@ -168,17 +167,18 @@ class NativeImageDebugInfoProvider implements DebugInfoProvider { private static HashMap initJavaKindToHostedTypes(HostedMetaAccess metaAccess) { HashMap map = new HashMap<>(); for (JavaKind kind : JavaKind.values()) { - Class clazz = kind.toJavaClass(); - assert clazz != null || kind == JavaKind.Illegal || kind == JavaKind.Object; - HostedType javaType; - if (kind == JavaKind.Object) { - clazz = java.lang.Object.class; - } - if (clazz == null) { - javaType = null; - } else { - javaType = metaAccess.lookupJavaType(clazz); + Class clazz; + switch (kind) { + case Illegal: + clazz = null; + break; + case Object: + clazz = java.lang.Object.class; + break; + default: + clazz = kind.toJavaClass(); } + HostedType javaType = clazz != null ? metaAccess.lookupJavaType(clazz) : null; map.put(kind, javaType); } return map; @@ -283,7 +283,7 @@ protected static ResolvedJavaType getDeclaringClass(HostedMethod hostedMethod, b } // we want a substituted target if there is one. if there is a substitution at the end of // the method chain fetch the annotated target class - ResolvedJavaMethod javaMethod = getOriginal(hostedMethod); + ResolvedJavaMethod javaMethod = getAnnotatedOrOriginal(hostedMethod); return javaMethod.getDeclaringClass(); } @@ -308,19 +308,32 @@ private static ResolvedJavaType getOriginal(HostedType hostedType) { return javaType; } - private static ResolvedJavaMethod getOriginal(HostedMethod hostedMethod) { + private static ResolvedJavaMethod getAnnotatedOrOriginal(HostedMethod hostedMethod) { ResolvedJavaMethod javaMethod = hostedMethod.getWrapped().getWrapped(); + // This method is only used when identifying the modifiers or the declaring class + // of a HostedMethod. Normally the method unwraps to the underlying JVMCI method + // which is the one that provides bytecode to the compiler as well as, line numbers + // and local info. If we unwrap to a SubstitutionMethod then we use the annotated + // method, not the JVMCI method that the annotation refers to since that will be the + // one providing the bytecode etc used by the compiler. If we unwrap to any other, + // custom substitution method we simply use it rather than dereferencing to the + // original. The difference is that the annotated method's bytecode will be used to + // replace the original and the debugger needs to use it to identify the file and access + // permissions. A custom substitution may exist alongside the original, as is the case + // with some uses for reflection. So, we don't want to conflate the custom substituted + // method and the original. In this latter case the method code will be synthesized without + // reference to the bytecode of the original. Hence there is no associated file and the + // permissions need to be determined from the custom substitution method itself. + if (javaMethod instanceof SubstitutionMethod) { SubstitutionMethod substitutionMethod = (SubstitutionMethod) javaMethod; javaMethod = substitutionMethod.getAnnotated(); - // } else if (javaMethod instanceof CustomSubstitutionMethod) { - // javaMethod = ((CustomSubstitutionMethod) javaMethod).getOriginal(); } return javaMethod; } private static int getOriginalModifiers(HostedMethod hostedMethod) { - return getOriginal(hostedMethod).getModifiers(); + return getAnnotatedOrOriginal(hostedMethod).getModifiers(); } private final Path cachePath = SubstrateOptions.getDebugInfoSourceCacheRoot(); @@ -656,12 +669,11 @@ public Stream methodInfoProvider() { public ResolvedJavaType superClass() { HostedClass superClass = hostedType.getSuperclass(); /* - * HostedType wraps an AnalysisType and both HostedType and AnalysisType punt calls to - * getSourceFilename to the wrapped class so for consistency we need to do the path - * lookup relative to the doubly unwrapped HostedType. + * Unwrap the hosted type's super class to the original to provide the correct identity + * type. */ if (superClass != null) { - return getDeclaringClass(superClass, true); + return getOriginal(superClass); } return null; } @@ -922,12 +934,10 @@ private ResolvedJavaMethod originalMethod() { while (targetMethod instanceof WrappedJavaMethod) { targetMethod = ((WrappedJavaMethod) targetMethod).getWrapped(); } - // if we hit these two substitutions then we can translate to the original + // if we hit a substitution then we can translate to the original // for identity otherwise we use whatever we unwrapped to. if (targetMethod instanceof SubstitutionMethod) { targetMethod = ((SubstitutionMethod) targetMethod).getOriginal(); - // } else if (targetMethod instanceof CustomSubstitutionMethod) { - // targetMethod = ((CustomSubstitutionMethod) targetMethod).getOriginal(); } return targetMethod; } @@ -2128,14 +2138,14 @@ public class NativeImageDebugLocalValueInfo implements DebugLocalValueInfo { this(name, Value.ILLEGAL, 0, kind, type, slot, line); } - NativeImageDebugLocalValueInfo(String name, JavaValue value, int framesize, JavaKind kind, ResolvedJavaType t, int slot, int line) { + NativeImageDebugLocalValueInfo(String name, JavaValue value, int framesize, JavaKind kind, ResolvedJavaType resolvedType, int slot, int line) { this.name = name; this.kind = kind; this.slot = slot; this.line = line; // if we don't have a type default it for the JavaKind // it may still end up null when kind is Undefined. - this.type = (t != null ? t : hostedTypeForKind(kind)); + this.type = (resolvedType != null ? resolvedType : hostedTypeForKind(kind)); if (value instanceof RegisterValue) { this.localKind = LocalKind.REGISTER; this.value = new NativeImageDebugRegisterValue((RegisterValue) value); @@ -2230,7 +2240,8 @@ public String name() { @Override public String typeName() { - return valueType().toJavaName(); + ResolvedJavaType valueType = valueType(); + return (valueType == null ? "" : valueType().toJavaName()); } @Override