From a43f6a9775e271890432bd6c6910180fe4a46f6e Mon Sep 17 00:00:00 2001 From: mirkosertic Date: Fri, 19 Apr 2024 18:12:43 +0200 Subject: [PATCH] Wasm code generation performance optimizations --- .../core/backend/wasm/WasmBackend.java | 18 ++++--- ...asmStructuredControlflowCodeGenerator.java | 25 +++++---- .../backend/wasm/ast/ExportableFunction.java | 4 +- .../core/backend/wasm/ast/ExportsSection.java | 5 +- .../core/backend/wasm/ast/Function.java | 4 +- .../core/backend/wasm/ast/FunctionIndex.java | 17 +++--- .../backend/wasm/ast/FunctionsSection.java | 4 +- .../core/backend/wasm/ast/Importable.java | 2 +- .../core/backend/wasm/ast/ImportsSection.java | 4 +- .../core/backend/wasm/ast/Module.java | 52 +++++++++++++++++-- .../core/backend/wasm/ast/NameSection.java | 5 +- .../ast/WeakFunctionReferenceCallable.java | 4 +- .../wasm/ast/WeakFunctionTableReference.java | 4 +- .../mirkosertic/bytecoder/core/ir/Graph.java | 27 +++++----- 14 files changed, 115 insertions(+), 60 deletions(-) diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/WasmBackend.java b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/WasmBackend.java index 9a3b3f097..273ca22d1 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/WasmBackend.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/WasmBackend.java @@ -32,6 +32,7 @@ import de.mirkosertic.bytecoder.core.backend.wasm.ast.ExportableFunction; import de.mirkosertic.bytecoder.core.backend.wasm.ast.Exporter; import de.mirkosertic.bytecoder.core.backend.wasm.ast.Function; +import de.mirkosertic.bytecoder.core.backend.wasm.ast.FunctionIndex; import de.mirkosertic.bytecoder.core.backend.wasm.ast.FunctionType; import de.mirkosertic.bytecoder.core.backend.wasm.ast.FunctionsSection; import de.mirkosertic.bytecoder.core.backend.wasm.ast.Global; @@ -584,6 +585,8 @@ public WasmType apply(final Type argument) { final OpaqueTypesAdapterMethods adapterMethods = new OpaqueTypesAdapterMethods(); final GeneratedMethodsRegistry generatedMethodsRegistry = new GeneratedMethodsRegistry(); + final FunctionIndex functionIndex = module.functionIndex(); + for (final ResolvedClass cl : resolvedClasses) { // Class objects for @@ -656,7 +659,8 @@ public WasmType apply(final Type argument) { compileUnit, objectTypeMappings, rtTypeMappings, - ConstExpressions.call(delegateFunction, callArgs) + ConstExpressions.call(delegateFunction, callArgs), + functionIndex )); break; } @@ -795,7 +799,8 @@ public WasmType apply(final Type argument) { compileUnit, objectTypeMappings, rtTypeMappings, - ConstExpressions.call(delegateFunction, callArgs))); + ConstExpressions.call(delegateFunction, callArgs), + functionIndex)); break; } default: { @@ -825,7 +830,7 @@ public WasmType apply(final Type argument) { final DominatorTree dt = new DominatorTree(g); try { - new Sequencer(g, dt, new WasmStructuredControlflowCodeGenerator(compileUnit, module, rtTypeMappings, objectTypeMappings, implFunction, toWASMType, toFunctionType, methodToIDMapper, g, resolvedClasses, vTableResolver, generatedMethodsRegistry)); + new Sequencer(g, dt, new WasmStructuredControlflowCodeGenerator(compileUnit, module, rtTypeMappings, objectTypeMappings, implFunction, toWASMType, toFunctionType, methodToIDMapper, g, resolvedClasses, vTableResolver, generatedMethodsRegistry, functionIndex)); } catch (final CodeGenerationFailure e) { throw e; } catch (final RuntimeException e) { @@ -868,7 +873,7 @@ public WasmType apply(final Type argument) { "typeId" ) ); - initArgs.add(ConstExpressions.ref.ref(module.functionIndex().firstByLabel(WasmHelpers.generateClassName(stringClass.type) + "_vt"))); + initArgs.add(ConstExpressions.ref.ref(functionIndex.findByLabel(WasmHelpers.generateClassName(stringClass.type) + "_vt"))); initArgs.add(ConstExpressions.getLocal(newStringFunction.localByLabel("str"))); final Global stringGlobal = module.getGlobals().globalsIndex().globalByLabel(WasmHelpers.generateClassName(stringClass.type) + "_cls"); @@ -909,7 +914,7 @@ public WasmType apply(final Type argument) { ConstExpressions.call(stringInitFunction, new ArrayList<>()), "factoryFor" )); - initArgs.add(ConstExpressions.ref.ref(module.functionIndex().firstByLabel(WasmHelpers.generateClassName(stringClass.type) + "_vt"))); + initArgs.add(ConstExpressions.ref.ref(functionIndex.findByLabel(WasmHelpers.generateClassName(stringClass.type) + "_vt"))); final Global stringGlobal = module.getGlobals().globalsIndex().globalByLabel(WasmHelpers.generateClassName(stringClass.type) + "_cls"); @@ -994,7 +999,8 @@ public WasmType apply(final Type argument) { compileUnit, objectTypeMappings, rtTypeMappings, - ConstExpressions.getLocal(callback.localByLabel("event")) + ConstExpressions.getLocal(callback.localByLabel("event")), + functionIndex )); } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/WasmStructuredControlflowCodeGenerator.java b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/WasmStructuredControlflowCodeGenerator.java index 166055662..502c29b05 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/WasmStructuredControlflowCodeGenerator.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/WasmStructuredControlflowCodeGenerator.java @@ -30,6 +30,7 @@ import de.mirkosertic.bytecoder.core.backend.wasm.ast.Container; import de.mirkosertic.bytecoder.core.backend.wasm.ast.ExportableFunction; import de.mirkosertic.bytecoder.core.backend.wasm.ast.Expressions; +import de.mirkosertic.bytecoder.core.backend.wasm.ast.FunctionIndex; import de.mirkosertic.bytecoder.core.backend.wasm.ast.FunctionType; import de.mirkosertic.bytecoder.core.backend.wasm.ast.Global; import de.mirkosertic.bytecoder.core.backend.wasm.ast.HostType; @@ -240,6 +241,8 @@ public NestingLevelTry(final NestingLevel parent, final Expressions activeFlo private final GeneratedMethodsRegistry generatedMethodsRegistry; + private final FunctionIndex functionIndex; + public WasmStructuredControlflowCodeGenerator(final CompileUnit compileUnit, final Module module, final Map rtMappings, final Map objectTypeMappings, @@ -250,7 +253,8 @@ public WasmStructuredControlflowCodeGenerator(final CompileUnit compileUnit, fin final Graph graph, final List resolvedClasses, final VTableResolver vTableResolver, - final GeneratedMethodsRegistry generatedMethodsRegistry) { + final GeneratedMethodsRegistry generatedMethodsRegistry, + final FunctionIndex functionIndex) { this.compileUnit = compileUnit; this.module = module; this.exportableFunction = exportableFunction; @@ -265,6 +269,7 @@ public WasmStructuredControlflowCodeGenerator(final CompileUnit compileUnit, fin this.resolvedClasses = resolvedClasses; this.vTableResolver = vTableResolver; this.generatedMethodsRegistry = generatedMethodsRegistry; + this.functionIndex = functionIndex; } @Override @@ -463,7 +468,8 @@ public static WasmValue createNewInstanceOf(final Type instanceType, final CompileUnit compileUnit, final Map objectTypeMappings, final Map rtMappings, - final WasmValue externRef) { + final WasmValue externRef, + final FunctionIndex functionIndex) { final ResolvedClass cl = compileUnit.findClass(instanceType); if (cl == null) { throw new IllegalArgumentException("Cannot find resolved class for " + instanceType); @@ -485,7 +491,7 @@ public static WasmValue createNewInstanceOf(final Type instanceType, ) ); - initArgs.add(ConstExpressions.ref.ref(module.functionIndex().firstByLabel(WasmHelpers.generateClassName(cl.type) + "_vt"))); + initArgs.add(ConstExpressions.ref.ref(functionIndex.findByLabel(WasmHelpers.generateClassName(cl.type) + "_vt"))); initArgs.add(externRef); @@ -530,7 +536,7 @@ public static WasmValue createNewInstanceOf(final Type instanceType, private WasmValue toWasmValue(final New value) { return createNewInstanceOf(value.type, - module, compileUnit, objectTypeMappings, rtMappings, ConstExpressions.ref.externNullRef()); + module, compileUnit, objectTypeMappings, rtMappings, ConstExpressions.ref.externNullRef(), functionIndex); } private WasmValue toWasmValue(final ReadInstanceField value) { @@ -1102,7 +1108,7 @@ private WasmValue generateInvokeDynamicLambdaMetaFactoryInvocation(final InvokeD lambdaMethod.flow.setLocal(objInstance, createNewInstanceOf(implementationMethod.owner.type, - module, compileUnit, objectTypeMappings, rtMappings, ConstExpressions.ref.externNullRef())); + module, compileUnit, objectTypeMappings, rtMappings, ConstExpressions.ref.externNullRef(), functionIndex)); arguments.add(0, ConstExpressions.getLocal(objInstance)); @@ -1249,7 +1255,7 @@ public void generateCode(final PrintWriter pw, final int index) { ConstExpressions.getGlobal(stringGlobal), "factoryFor" )); - initArgs.add(ConstExpressions.ref.ref(module.functionIndex().firstByLabel(WasmHelpers.generateClassName(stringClass.type) + "_vt"))); + initArgs.add(ConstExpressions.ref.ref(functionIndex.findByLabel(WasmHelpers.generateClassName(stringClass.type) + "_vt"))); initArgs.add(ConstExpressions.call(concatFunction, arguments)); @@ -1386,7 +1392,7 @@ public void generateCode(final PrintWriter pw, final int index) { ConstExpressions.getGlobal(stringGlobal), "factoryFor" )); - initArgs.add(ConstExpressions.ref.ref(module.functionIndex().firstByLabel(WasmHelpers.generateClassName(stringClass.type) + "_vt"))); + initArgs.add(ConstExpressions.ref.ref(functionIndex.findByLabel(WasmHelpers.generateClassName(stringClass.type) + "_vt"))); initArgs.add(ConstExpressions.call(concatFunction, arguments)); @@ -1792,7 +1798,7 @@ private WasmValue toWasmValue(final NewArray value) { final Global global = module.getGlobals().globalsIndex().globalByLabel(arrayClsName + "_cls"); initArguments.add(ConstExpressions.i32.c(resolvedClasses.indexOf(arrayCls))); - initArguments.add(ConstExpressions.ref.ref(module.functionIndex().firstByLabel(WasmHelpers.generateClassName(arrayClass) + "_vt"))); + initArguments.add(ConstExpressions.ref.ref(functionIndex.findByLabel(WasmHelpers.generateClassName(arrayClass) + "_vt"))); initArguments.add(ConstExpressions.ref.externNullRef()); initArguments.add(ConstExpressions.struct.get( rtMappings.get(arrayCls), @@ -2058,7 +2064,8 @@ private WasmValue toWasmValue(final Cast value) { objectTypeMappings.get(compileUnit.findClass(Type.getType(Object.class))), toWasmValue((Value) value.incomingDataFlows[0]), "nativeObject" - ) + ), + functionIndex ); } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/ExportableFunction.java b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/ExportableFunction.java index a15b9efab..0b5450f06 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/ExportableFunction.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/ExportableFunction.java @@ -114,7 +114,7 @@ public Local newLocal(final String label, final WasmType type) { } @Override - public void writeTo(final TextWriter textWriter, final Module aModule) throws IOException { + public void writeTo(final TextWriter textWriter, final Module aModule, final WasmValue.ExportContext exportContext) throws IOException { textWriter.opening(); textWriter.write("func"); textWriter.space(); @@ -145,7 +145,7 @@ public void writeTo(final TextWriter textWriter, final Module aModule) throws IO local.writeTo(textWriter); textWriter.newLine(); } - final DefaultExportContext context = new DefaultExportContext(this, getModule().functionIndex()); + final DefaultExportContext context = new DefaultExportContext(this, exportContext.functionIndex()); for (final WasmExpression expression : getChildren()) { expression.writeTo(textWriter, context); } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/ExportsSection.java b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/ExportsSection.java index 74fd987f3..5f9648f7d 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/ExportsSection.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/ExportsSection.java @@ -46,8 +46,7 @@ public void writeTo(final TextWriter textWriter) { } } - public void writeTo(final BinaryWriter binaryWriter, final List memoryIndex) throws IOException { - final FunctionIndex functionIndex = getModule().functionIndex(); + public void writeTo(final BinaryWriter binaryWriter, final List memoryIndex, final WasmValue.ExportContext exportContext) throws IOException { final TagIndex tagIndex = getModule().tagIndex(); try (final BinaryWriter.SectionWriter exportWriter = binaryWriter.exportsSection()) { exportWriter.writeUnsignedLeb128(exports.size()); @@ -56,7 +55,7 @@ public void writeTo(final BinaryWriter binaryWriter, final List memoryIn final Exportable value = entry.getValue(); if (value instanceof ExportableFunction) { exportWriter.writeByte(ExternalKind.EXTERNAL_KIND_FUNCTION); - exportWriter.writeUnsignedLeb128(functionIndex.indexOf((Function) value)); + exportWriter.writeUnsignedLeb128(exportContext.functionIndex().indexOf((Function) value)); } else if (value instanceof Memory) { exportWriter.writeByte(ExternalKind.EXTERNAL_KIND_MEMORY); exportWriter.writeUnsignedLeb128(memoryIndex.indexOf(value)); diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/Function.java b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/Function.java index 6ab464be0..b38d89745 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/Function.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/Function.java @@ -51,7 +51,7 @@ public class Function extends Container implements Importable, Callable { } @Override - public void writeTo(final TextWriter textWriter, final Module aModule) throws IOException { + public void writeTo(final TextWriter textWriter, final Module aModule, final WasmValue.ExportContext exportContext) throws IOException { textWriter.opening(); textWriter.write("func"); textWriter.space(); @@ -96,6 +96,6 @@ public WasmType resolveResultType(final WasmValue.ExportContext context) { @Override public int resolveIndex(final WasmValue.ExportContext context) { - return module.functionIndex().indexOf(this); + return context.functionIndex().indexOf(this); } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/FunctionIndex.java b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/FunctionIndex.java index 1bc14eeb2..15aa50bf8 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/FunctionIndex.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/FunctionIndex.java @@ -16,15 +16,19 @@ package de.mirkosertic.bytecoder.core.backend.wasm.ast; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; public class FunctionIndex { private final List functions; + private final Map labelToFunction; FunctionIndex() { functions = new ArrayList<>(); + labelToFunction = new HashMap<>(); } public int size() { @@ -37,6 +41,7 @@ public Function get(final int aIndex) { public void add(final Function function) { functions.add(function); + labelToFunction.put(function.getLabel().toLowerCase(), function); } public int indexOf(final Function value) { @@ -47,12 +52,12 @@ public List exportableFunctions() { return functions.stream().filter(t -> t instanceof ExportableFunction).map(t -> (ExportableFunction) t).collect(Collectors.toList()); } - public T firstByLabel(final String label) { - for (final Function function : functions) { - if (label.equalsIgnoreCase(function.getLabel())) { - return (T) function; - } + public T findByLabel(final String label) { + final String key = label.toLowerCase(); + final T result = (T) labelToFunction.get(key); + if (result == null) { + throw new IllegalArgumentException("No such method : " + label); } - throw new IllegalArgumentException("No such method : " + label); + return result; } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/FunctionsSection.java b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/FunctionsSection.java index ad4b3227d..fd7985e62 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/FunctionsSection.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/FunctionsSection.java @@ -57,9 +57,9 @@ public ExportableFunction newFunction(final String label) { return function; } - public void writeTo(final TextWriter textWriter) throws IOException { + public void writeTo(final TextWriter textWriter, final WasmValue.ExportContext exportContext) throws IOException { for (final Function function : functions) { - function.writeTo(textWriter, getModule()); + function.writeTo(textWriter, getModule(), exportContext); textWriter.newLine(); } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/Importable.java b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/Importable.java index 1ac8d88dd..cd1dee992 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/Importable.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/Importable.java @@ -18,5 +18,5 @@ import java.io.IOException; public interface Importable { - void writeTo(TextWriter textWriter, Module aModule) throws IOException; + void writeTo(TextWriter textWriter, Module aModule, final WasmValue.ExportContext exportContext) throws IOException; } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/ImportsSection.java b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/ImportsSection.java index dc55e62fb..db1a621fc 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/ImportsSection.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/ImportsSection.java @@ -69,7 +69,7 @@ public Function importFunction(final ImportReference importReference, final Stri return function; } - public void writeTo(final TextWriter textWriter) throws IOException { + public void writeTo(final TextWriter textWriter, final WasmValue.ExportContext exportContext) throws IOException { for (final ImportEntry entry : imports) { final ImportReference ref = entry.getReference(); @@ -81,7 +81,7 @@ public void writeTo(final TextWriter textWriter) throws IOException { textWriter.space(); textWriter.writeText(ref.getObjectName()); textWriter.space(); - entry.getImportable().writeTo(textWriter, getModule()); + entry.getImportable().writeTo(textWriter, getModule(), exportContext); textWriter.closing(); textWriter.newLine(); } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/Module.java b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/Module.java index 3a7a7bcad..11d901fab 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/Module.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/Module.java @@ -52,20 +52,61 @@ public Module(final String label, final String sourcemapFileName) { } public void writeTo(final TextWriter writer, final boolean enableDebug) throws IOException { + + final FunctionIndex functionIndex = functionIndex(); + writer.opening(); writer.write("module"); writer.space(); writer.writeLabel(label); writer.newLine(); + final WasmValue.ExportContext context = new WasmValue.ExportContext() { + + @Override + public Container owningContainer() { + return null; + } + + @Override + public FunctionIndex functionIndex() { + return functionIndex; + } + + @Override + public GlobalsIndex globalsIndex() { + return Module.this.globalsIndex(); + } + + @Override + public LocalIndex localIndex() { + return null; + } + + @Override + public TagIndex tagIndex() { + return Module.this.tagIndex(); + } + + @Override + public WasmValue.ExportContext subWith(final Container container) { + return null; + } + + @Override + public TablesSection.AnyFuncTable anyFuncTable() { + return Module.this.getTables().funcTable(); + } + }; + types.writeTo(writer); - imports.writeTo(writer); + imports.writeTo(writer, context); mems.writeTo(writer); globals.writeTo(writer); tags.writeCodeTo(writer); tables.writeTo(writer); elements.writeTo(writer); - functions.writeTo(writer); + functions.writeTo(writer, context); exports.writeTo(writer); writer.closing(); } @@ -97,6 +138,7 @@ public void writeTo(final BinaryWriter writer, final boolean enableDebug) throws mems.addMemoriesToIndex(memoryIndex); final WasmValue.ExportContext context = new WasmValue.ExportContext() { + @Override public Container owningContainer() { return null; @@ -104,7 +146,7 @@ public Container owningContainer() { @Override public FunctionIndex functionIndex() { - return Module.this.functionIndex(); + return functionIndex; } @Override @@ -141,11 +183,11 @@ public TablesSection.AnyFuncTable anyFuncTable() { mems.writeTo(writer); tags.writeCodeTo(writer); globals.writeTo(writer, context); - exports.writeTo(writer, memoryIndex); + exports.writeTo(writer, memoryIndex, context); elements.writeTo(writer, functionIndex); functions.writeCodeTo(writer, functionIndex); if (enableDebug) { - names.writeCodeTo(writer); + names.writeCodeTo(writer, context); } // Disabled, as source maps are currently not generated for Wasm diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/NameSection.java b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/NameSection.java index 2a65680af..1885adf8e 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/NameSection.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/wasm/ast/NameSection.java @@ -25,14 +25,14 @@ public NameSection(final Module module) { super(module); } - public void writeCodeTo(final BinaryWriter writer) throws IOException { + public void writeCodeTo(final BinaryWriter writer, final WasmValue.ExportContext exportContext) throws IOException { try (final BinaryWriter.SectionWriter sectionWriter = writer.customSection()) { sectionWriter.writeUTF8("name"); try (final BinaryWriter.SectionWriter moduleSection = sectionWriter.subSection((byte) 0)) { moduleSection.writeUTF8(getModule().getLabel()); } + final FunctionIndex functions = exportContext.functionIndex(); try (final BinaryWriter.SectionWriter functionSection = sectionWriter.subSection((byte) 1)) { - final FunctionIndex functions = getModule().functionIndex(); functionSection.writeUnsignedLeb128(functions.size()); for (int i=0;i typeReferences; + private int importLabelCounter = 0; public Graph(final Logger logger) { @@ -50,6 +52,7 @@ public Graph(final Logger logger) { this.translations = new HashMap<>(); this.fixups = new ArrayList<>(); this.labeledRegions = new HashMap<>(); + this.typeReferences = new HashMap<>(); this.logger = logger; } @@ -61,6 +64,7 @@ public Node[] outgoingDataFlowsFor(final Node n) { final Set result = new HashSet<>(); for (final Node t : nodes) { final Node[] incoming = t.incomingDataFlows; + for (int i = 0; i (TypeReference) register(new TypeReference(Graph.this, t))); } public New newNew(final Type type) { @@ -371,6 +367,9 @@ public SetClassField newSetClassField(final ResolvedField resolvedField) { public void deleteNode(final Node node) { nodes.remove(node); + if (node.nodeType == NodeType.TypeReference) { + typeReferences.remove(((TypeReference) node).type); + } } public PrimitiveFloat newFloat(final float constant) { @@ -463,9 +462,6 @@ void deleteFromControlFlowInternally(final ControlTokenConsumer consumer) { if (consumer.hasIncomingBackEdges()) { throw new IllegalStateException("Cannot delete node with incoming back edges! Node Type is " + consumer.nodeType + " #" + consumer.owner.nodes.indexOf(consumer)); } - if (consumer.controlComingFrom.size() != 1) { -// throw new IllegalStateException("Can only delete nodes with exactly one incoming edge! Node Type is " + consumer.nodeType + " #" + consumer.owner.nodes.indexOf(consumer)); - } if (consumer.controlFlowsTo.size() != 1) { throw new IllegalStateException("Can only delete nodes with exactly one outgoing edge! Node Type is " + consumer.nodeType + " #" + consumer.owner.nodes.indexOf(consumer)); } @@ -477,9 +473,10 @@ void deleteFromControlFlowInternally(final ControlTokenConsumer consumer) { for (final Map.Entry entry : new HashSet<>(pred.controlFlowsTo.entrySet())) { if (entry.getValue() == consumer) { for (final Map.Entry to : consumer.controlFlowsTo.entrySet()) { - pred.controlFlowsTo.put(entry.getKey(), to.getValue()); - to.getValue().controlComingFrom.remove(consumer); - to.getValue().controlComingFrom.add(pred); + final ControlTokenConsumer toTarget = to.getValue(); + pred.controlFlowsTo.put(entry.getKey(), toTarget); + toTarget.controlComingFrom.remove(consumer); + toTarget.controlComingFrom.add(pred); } } }