Skip to content

Commit

Permalink
Use a more storage-efficient map implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
adinn committed Nov 15, 2022
1 parent 30b341a commit 5160df9
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,12 @@

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.debug.DebugContext;

import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugFieldInfo;
Expand Down Expand Up @@ -74,7 +73,7 @@ public class ClassEntry extends StructureTypeEntry {
* An index of all currently known methods keyed by the unique, associated, identifying
* ResolvedJavaMethod.
*/
private Map<ResolvedJavaMethod, MethodEntry> methodsIndex;
private EconomicMap<ResolvedJavaMethod, MethodEntry> methodsIndex;
/**
* A list recording details of all normal compiled methods included in this class sorted by
* ascending address range. Note that the associated address ranges are disjoint and contiguous.
Expand All @@ -90,19 +89,19 @@ public class ClassEntry extends StructureTypeEntry {
* An index identifying ranges for compiled method which have already been encountered, whether
* normal or deopt fallback methods.
*/
private Map<Range, CompiledMethodEntry> compiledMethodIndex;
private EconomicMap<Range, CompiledMethodEntry> compiledMethodIndex;
/**
* An index of all primary and secondary files referenced from this class's compilation unit.
*/
private Map<FileEntry, Integer> localFilesIndex;
private EconomicMap<FileEntry, Integer> localFilesIndex;
/**
* A list of the same files.
*/
private List<FileEntry> localFiles;
/**
* An index of all primary and secondary dirs referenced from this class's compilation unit.
*/
private HashMap<DirEntry, Integer> localDirsIndex;
private EconomicMap<DirEntry, Integer> localDirsIndex;
/**
* A list of the same dirs.
*/
Expand All @@ -114,15 +113,15 @@ public ClassEntry(String className, FileEntry fileEntry, int size) {
this.fileEntry = fileEntry;
this.loader = null;
this.methods = new ArrayList<>();
this.methodsIndex = new HashMap<>();
this.methodsIndex = EconomicMap.create();
this.normalCompiledEntries = new ArrayList<>();
// deopt methods list is created on demand
this.deoptCompiledEntries = null;
this.compiledMethodIndex = new HashMap<>();
this.compiledMethodIndex = EconomicMap.create();
this.localFiles = new ArrayList<>();
this.localFilesIndex = new HashMap<>();
this.localFilesIndex = EconomicMap.create();
this.localDirs = new ArrayList<>();
this.localDirsIndex = new HashMap<>();
this.localDirsIndex = EconomicMap.create();
if (fileEntry != null) {
localFiles.add(fileEntry);
localFilesIndex.put(fileEntry, localFiles.size());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugFileInfo;
import jdk.vm.ci.meta.ResolvedJavaType;
import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.debug.DebugContext;

import com.oracle.objectfile.debuginfo.DebugInfoProvider;
Expand Down Expand Up @@ -108,7 +109,7 @@ public abstract class DebugInfoBase {
* Index of all dirs in which files are found to reside either as part of substrate/compiler or
* user code.
*/
private Map<Path, DirEntry> dirsIndex = new HashMap<>();
private EconomicMap<Path, DirEntry> dirsIndex = EconomicMap.create();

/**
* List of all types present in the native image including instance classes, array classes,
Expand All @@ -128,7 +129,11 @@ public abstract class DebugInfoBase {
/**
* Index of already seen classes.
*/
private Map<ResolvedJavaType, ClassEntry> instanceClassesIndex = new HashMap<>();
private EconomicMap<ResolvedJavaType, ClassEntry> instanceClassesIndex = EconomicMap.create();
/**
* Handle on type entry for header structure.
*/
private HeaderTypeEntry headerType;
/**
* Handle on class entry for java.lang.Object.
*/
Expand All @@ -140,7 +145,7 @@ public abstract class DebugInfoBase {
/**
* Index of files which contain primary or secondary ranges keyed by path.
*/
private Map<Path, FileEntry> filesIndex = new HashMap<>();
private EconomicMap<Path, FileEntry> filesIndex = EconomicMap.create();

/**
* List of all loaders associated with classes included in the image.
Expand All @@ -150,7 +155,7 @@ public abstract class DebugInfoBase {
/**
* Index of all loaders associated with classes included in the image.
*/
private Map<String, LoaderEntry> loaderIndex = new HashMap<>();
private EconomicMap<String, LoaderEntry> loaderIndex = EconomicMap.create();

/**
* Flag set to true if heap references are stored as addresses relative to a heap base register
Expand Down Expand Up @@ -270,7 +275,7 @@ public void installDebugInfo(DebugInfoProvider debugInfoProvider) {
DebugTypeKind typeKind = debugTypeInfo.typeKind();

debugContext.log(DebugContext.INFO_LEVEL, "Process %s type %s ", typeKind.toString(), typeName);
TypeEntry typeEntry = lookupTypeEntry(idType);
TypeEntry typeEntry = (idType != null ? lookupTypeEntry(idType) : lookupHeaderType());
typeEntry.addDebugInfo(this, debugTypeInfo, debugContext);
}));

Expand All @@ -296,7 +301,7 @@ public void installDebugInfo(DebugInfoProvider debugInfoProvider) {
* Record all subranges even if they have no line or file so we at least get a symbol
* for them and don't see a break in the address range.
*/
HashMap<DebugLocationInfo, Range> subRangeIndex = new HashMap<>();
EconomicMap<DebugLocationInfo, Range> subRangeIndex = EconomicMap.create();
debugCodeInfo.locationInfoProvider().forEach(debugLocationInfo -> addSubrange(debugLocationInfo, primaryRange, classEntry, subRangeIndex, debugContext));
}));

Expand Down Expand Up @@ -349,11 +354,17 @@ private TypeEntry createTypeEntry(String typeName, String fileName, Path filePat
}

private TypeEntry addTypeEntry(ResolvedJavaType idType, String typeName, String fileName, Path filePath, Path cachePath, int size, DebugTypeKind typeKind) {
TypeEntry typeEntry = typesIndex.get(idType);
TypeEntry typeEntry = (idType != null ? typesIndex.get(idType) : null);
if (typeEntry == null) {
typeEntry = createTypeEntry(typeName, fileName, filePath, cachePath, size, typeKind);
types.add(typeEntry);
typesIndex.put(idType, typeEntry);
if (idType != null) {
typesIndex.put(idType, typeEntry);
}
// track object type and header struct
if (idType == null) {
headerType = (HeaderTypeEntry) typeEntry;
}
if (typeName.equals("java.lang.Object")) {
objectClass = (ClassEntry) typeEntry;
}
Expand Down Expand Up @@ -389,6 +400,12 @@ ClassEntry lookupClassEntry(ResolvedJavaType type) {
return classEntry;
}

public HeaderTypeEntry lookupHeaderType() {
// this should only be looked up after all types have been notified
assert headerType != null;
return headerType;
}

public ClassEntry lookupObjectClass() {
// this should only be looked up after all types have been notified
assert objectClass != null;
Expand All @@ -407,7 +424,7 @@ public ClassEntry lookupObjectClass() {
* primaryRange
*/
@SuppressWarnings("try")
private Range addSubrange(DebugLocationInfo locationInfo, Range primaryRange, ClassEntry classEntry, HashMap<DebugLocationInfo, Range> subRangeIndex, DebugContext debugContext) {
private Range addSubrange(DebugLocationInfo locationInfo, Range primaryRange, ClassEntry classEntry, EconomicMap<DebugLocationInfo, Range> subRangeIndex, DebugContext debugContext) {
/*
* We still insert subranges for the primary method but they don't actually count as inline.
* we only need a range so that subranges for inline code can refer to the top level line
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
package com.oracle.objectfile.elf.dwarf;

import java.nio.ByteOrder;
import java.util.HashMap;

import com.oracle.objectfile.debugentry.ClassEntry;
import com.oracle.objectfile.debugentry.DebugInfoBase;
Expand All @@ -38,6 +37,7 @@
import com.oracle.objectfile.debugentry.TypeEntry;
import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugLocalInfo;
import com.oracle.objectfile.elf.ELFMachine;
import org.graalvm.collections.EconomicMap;

/**
* A class that models the debug info in an organization that facilitates generation of the required
Expand Down Expand Up @@ -334,25 +334,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<TypeEntry, DwarfTypeProperties> typePropertiesIndex;
private EconomicMap<TypeEntry, DwarfTypeProperties> typePropertiesIndex;

/**
* A collection of method properties associated with each generated method record.
*/
private HashMap<MethodEntry, DwarfMethodProperties> methodPropertiesIndex;
private EconomicMap<MethodEntry, DwarfMethodProperties> 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<MethodEntry, DwarfLocalProperties> methodLocalPropertiesIndex;
private EconomicMap<MethodEntry, DwarfLocalProperties> methodLocalPropertiesIndex;

/**
* A collection of local variable properties associated with an inlined subrange.
*/
private HashMap<Range, DwarfLocalProperties> rangeLocalPropertiesIndex;
private EconomicMap<Range, DwarfLocalProperties> rangeLocalPropertiesIndex;

public DwarfDebugInfo(ELFMachine elfMachine, ByteOrder byteOrder) {
super(byteOrder);
Expand All @@ -373,10 +373,10 @@ public DwarfDebugInfo(ELFMachine elfMachine, ByteOrder byteOrder) {
this.heapbaseRegister = rheapbase_x86;
this.threadRegister = rthread_x86;
}
typePropertiesIndex = new HashMap<>();
methodPropertiesIndex = new HashMap<>();
methodLocalPropertiesIndex = new HashMap<>();
rangeLocalPropertiesIndex = new HashMap<>();
typePropertiesIndex = EconomicMap.create();
methodPropertiesIndex = EconomicMap.create();
methodLocalPropertiesIndex = EconomicMap.create();
rangeLocalPropertiesIndex = EconomicMap.create();
}

public DwarfStrSectionImpl getStrSectionImpl() {
Expand Down Expand Up @@ -505,16 +505,16 @@ static class DwarfClassProperties extends DwarfTypeProperties {
/**
* Map from field names to info section index for the field declaration.
*/
private HashMap<String, Integer> fieldDeclarationIndex;
private EconomicMap<String, Integer> fieldDeclarationIndex;
/**
* Map from method entries to associated abstract inline method index.
*/
private HashMap<MethodEntry, Integer> abstractInlineMethodIndex;
private EconomicMap<MethodEntry, Integer> abstractInlineMethodIndex;

/**
* Map from method entries to associated method local properties index.
*/
private HashMap<MethodEntry, DwarfLocalProperties> methodLocalPropertiesIndex;
private EconomicMap<MethodEntry, DwarfLocalProperties> methodLocalPropertiesIndex;

DwarfClassProperties(StructureTypeEntry entry) {
super(entry);
Expand Down Expand Up @@ -769,9 +769,9 @@ public void setFieldDeclarationIndex(StructureTypeEntry entry, String fieldName,
DwarfClassProperties classProperties;
classProperties = lookupClassProperties(entry);
assert classProperties.getTypeEntry() == entry;
HashMap<String, Integer> fieldDeclarationIndex = classProperties.fieldDeclarationIndex;
EconomicMap<String, Integer> fieldDeclarationIndex = classProperties.fieldDeclarationIndex;
if (fieldDeclarationIndex == null) {
classProperties.fieldDeclarationIndex = fieldDeclarationIndex = new HashMap<>();
classProperties.fieldDeclarationIndex = fieldDeclarationIndex = EconomicMap.create();
}
if (fieldDeclarationIndex.get(fieldName) != null) {
assert fieldDeclarationIndex.get(fieldName) == pos : entry.getTypeName() + fieldName;
Expand All @@ -784,7 +784,7 @@ public int getFieldDeclarationIndex(StructureTypeEntry entry, String fieldName)
DwarfClassProperties classProperties;
classProperties = lookupClassProperties(entry);
assert classProperties.getTypeEntry() == entry;
HashMap<String, Integer> fieldDeclarationIndex = classProperties.fieldDeclarationIndex;
EconomicMap<String, Integer> fieldDeclarationIndex = classProperties.fieldDeclarationIndex;
assert fieldDeclarationIndex != null : fieldName;
assert fieldDeclarationIndex.get(fieldName) != null : entry.getTypeName() + fieldName;
return fieldDeclarationIndex.get(fieldName);
Expand All @@ -803,9 +803,9 @@ public int getMethodDeclarationIndex(MethodEntry methodEntry) {
public void setAbstractInlineMethodIndex(ClassEntry classEntry, MethodEntry methodEntry, int pos) {
DwarfClassProperties classProperties = lookupClassProperties(classEntry);
assert classProperties.getTypeEntry() == classEntry;
HashMap<MethodEntry, Integer> abstractInlineMethodIndex = classProperties.abstractInlineMethodIndex;
EconomicMap<MethodEntry, Integer> abstractInlineMethodIndex = classProperties.abstractInlineMethodIndex;
if (abstractInlineMethodIndex == null) {
classProperties.abstractInlineMethodIndex = abstractInlineMethodIndex = new HashMap<>();
classProperties.abstractInlineMethodIndex = abstractInlineMethodIndex = EconomicMap.create();
}
if (abstractInlineMethodIndex.get(methodEntry) != null) {
assert abstractInlineMethodIndex.get(methodEntry) == pos : classEntry.getTypeName() + " & " + methodEntry.getSymbolName();
Expand All @@ -817,7 +817,7 @@ public void setAbstractInlineMethodIndex(ClassEntry classEntry, MethodEntry meth
public int getAbstractInlineMethodIndex(ClassEntry classEntry, MethodEntry methodEntry) {
DwarfClassProperties classProperties = lookupClassProperties(classEntry);
assert classProperties.getTypeEntry() == classEntry;
HashMap<MethodEntry, Integer> abstractInlineMethodIndex = classProperties.abstractInlineMethodIndex;
EconomicMap<MethodEntry, Integer> abstractInlineMethodIndex = classProperties.abstractInlineMethodIndex;
assert abstractInlineMethodIndex != null : classEntry.getTypeName() + " & " + methodEntry.getSymbolName();
assert abstractInlineMethodIndex.get(methodEntry) != null : classEntry.getTypeName() + " & " + methodEntry.getSymbolName();
return abstractInlineMethodIndex.get(methodEntry);
Expand All @@ -829,10 +829,10 @@ public int getAbstractInlineMethodIndex(ClassEntry classEntry, MethodEntry metho
*/

static final class DwarfLocalProperties {
private HashMap<DebugLocalInfo, Integer> locals;
private EconomicMap<DebugLocalInfo, Integer> locals;

private DwarfLocalProperties() {
locals = new HashMap<>();
locals = EconomicMap.create();
}

int getIndex(DebugLocalInfo localInfo) {
Expand All @@ -855,15 +855,15 @@ private DwarfLocalProperties addRangeLocalProperties(Range range) {
}

public DwarfLocalProperties lookupLocalProperties(ClassEntry classEntry, MethodEntry methodEntry) {
HashMap<MethodEntry, DwarfLocalProperties> map;
EconomicMap<MethodEntry, DwarfLocalProperties> map;
if (classEntry == null) {
map = methodLocalPropertiesIndex;
} else {
DwarfClassProperties classProperties = lookupClassProperties(classEntry);
assert classProperties != null;
map = classProperties.methodLocalPropertiesIndex;
if (map == null) {
map = classProperties.methodLocalPropertiesIndex = new HashMap<>();
map = classProperties.methodLocalPropertiesIndex = EconomicMap.create();
}
}
DwarfLocalProperties localProperties = map.get(methodEntry);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ private int writeClassLayout(DebugContext context, ClassEntry classEntry, byte[]
} else {
/* Inherit layout from object header. */
superName = OBJECT_HEADER_STRUCT_NAME;
TypeEntry headerType = lookupType(null);
TypeEntry headerType = headerType();
superTypeOffset = getTypeIndex(headerType);
}
/* Now write the child fields. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;

Expand Down Expand Up @@ -689,9 +688,7 @@ protected Stream<ArrayTypeEntry> arrayTypeStream() {
* @return the unique object header type notified via the DebugTypeInfo API.
*/
protected HeaderTypeEntry headerType() {
Optional<HeaderTypeEntry> optHeader = typeStream().filter(TypeEntry::isHeader).map(entry -> ((HeaderTypeEntry) entry)).findFirst();
assert optHeader.isPresent();
return optHeader.get();
return dwarfSections.lookupHeaderType();
}

/**
Expand All @@ -705,8 +702,8 @@ protected Stream<ClassEntry> instanceClassStream() {
}

/**
* Retrieve an iterable for all all instance classes, including interfaces and enums, notified
* via the DebugTypeInfo API.
* Retrieve an iterable for all instance classes, including interfaces and enums, notified via
* the DebugTypeInfo API.
*
* @return an iterable for all instance classes notified via the DebugTypeInfo API.
*/
Expand All @@ -729,7 +726,7 @@ protected TypeEntry lookupType(ResolvedJavaType type) {
return dwarfSections.lookupTypeEntry(type);
}

protected TypeEntry lookupObjectClass() {
protected ClassEntry lookupObjectClass() {
return dwarfSections.lookupObjectClass();
}

Expand Down

0 comments on commit 5160df9

Please sign in to comment.