diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/sequencer/Sequencer.java b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/sequencer/Sequencer.java index 0d7687550e..bee89c3be7 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/backend/sequencer/Sequencer.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/backend/sequencer/Sequencer.java @@ -105,115 +105,121 @@ private void visitDominationTreeOf(final ControlTokenConsumer startNode, final S }; while (current != null) { - switch (current.nodeType) { - case TryCatch: { - // Special-Case : branching - visit((TryCatch) current, activeStack); - current = null; - break; - } - case If: { - // Special-Case : branching - visit((If) current, activeStack); - current = null; - break; - } - case TableSwitch: { - // Special-Case : branching - visit((TableSwitch) current, activeStack); - current = null; - break; - } - case LookupSwitch: { - // Special-Case : branching - visit((LookupSwitch) current, activeStack); - current = null; - break; - } - case Region: { - visit((Region) current, activeStack); - current = followUpProcessor.apply(current); - break; - } - case MethodInvocation: { - codegenerator.write((MethodInvocation) current); - current = followUpProcessor.apply(current); - break; - } - case Copy: { - codegenerator.write((Copy) current); - current = followUpProcessor.apply(current); - break; - } - case Return: { - codegenerator.write((Return) current); - // We are finished here - current = null; - break; - } - case ReturnValue: { - codegenerator.write((ReturnValue) current); - // We are finished here - current = null; - break; - } - case SetInstanceField: { - codegenerator.write((SetInstanceField) current); - current = followUpProcessor.apply(current); - break; - } - case ArrayStore: { - codegenerator.write((ArrayStore) current); - current = followUpProcessor.apply(current); - break; - } - case SetClassField: { - codegenerator.write((SetClassField) current); - current = followUpProcessor.apply(current); - break; - } - case LineNumberDebugInfo: { - codegenerator.write((LineNumberDebugInfo) current); - current = followUpProcessor.apply(current); - break; - } - case FrameDebugInfo: { - codegenerator.write((FrameDebugInfo) current); - current = followUpProcessor.apply(current); - break; - } - case Goto: { - codegenerator.write((Goto) current); - current = followUpProcessor.apply(current); - break; - } - case MonitorEnter: { - codegenerator.write((MonitorEnter) current); - current = followUpProcessor.apply(current); - break; - } - case MonitorExit: { - codegenerator.write((MonitorExit) current); - current = followUpProcessor.apply(current); - break; - } - case Unwind: { - codegenerator.write((Unwind) current); - // We are finished here - current = null; - break; - } - case ClassInitialization: { - codegenerator.write((ClassInitialization) current); - current = followUpProcessor.apply(current); - break; - } - case Nop: { - current = followUpProcessor.apply(current); - break; + try { + switch (current.nodeType) { + case TryCatch: { + // Special-Case : branching + visit((TryCatch) current, activeStack); + current = null; + break; + } + case If: { + // Special-Case : branching + visit((If) current, activeStack); + current = null; + break; + } + case TableSwitch: { + // Special-Case : branching + visit((TableSwitch) current, activeStack); + current = null; + break; + } + case LookupSwitch: { + // Special-Case : branching + visit((LookupSwitch) current, activeStack); + current = null; + break; + } + case Region: { + visit((Region) current, activeStack); + current = followUpProcessor.apply(current); + break; + } + case MethodInvocation: { + codegenerator.write((MethodInvocation) current); + current = followUpProcessor.apply(current); + break; + } + case Copy: { + codegenerator.write((Copy) current); + current = followUpProcessor.apply(current); + break; + } + case Return: { + codegenerator.write((Return) current); + // We are finished here + current = null; + break; + } + case ReturnValue: { + codegenerator.write((ReturnValue) current); + // We are finished here + current = null; + break; + } + case SetInstanceField: { + codegenerator.write((SetInstanceField) current); + current = followUpProcessor.apply(current); + break; + } + case ArrayStore: { + codegenerator.write((ArrayStore) current); + current = followUpProcessor.apply(current); + break; + } + case SetClassField: { + codegenerator.write((SetClassField) current); + current = followUpProcessor.apply(current); + break; + } + case LineNumberDebugInfo: { + codegenerator.write((LineNumberDebugInfo) current); + current = followUpProcessor.apply(current); + break; + } + case FrameDebugInfo: { + codegenerator.write((FrameDebugInfo) current); + current = followUpProcessor.apply(current); + break; + } + case Goto: { + codegenerator.write((Goto) current); + current = followUpProcessor.apply(current); + break; + } + case MonitorEnter: { + codegenerator.write((MonitorEnter) current); + current = followUpProcessor.apply(current); + break; + } + case MonitorExit: { + codegenerator.write((MonitorExit) current); + current = followUpProcessor.apply(current); + break; + } + case Unwind: { + codegenerator.write((Unwind) current); + // We are finished here + current = null; + break; + } + case ClassInitialization: { + codegenerator.write((ClassInitialization) current); + current = followUpProcessor.apply(current); + break; + } + case Nop: { + current = followUpProcessor.apply(current); + break; + } + default: + throw new IllegalStateException("Unsupported node type : " + current.nodeType); } - default: - throw new IllegalStateException("Unsupported node type : " + current.nodeType); + } catch (final IllegalStateException e) { + throw e; + } catch (final RuntimeException e) { + throw new RuntimeException("Error processing node #" + graph.nodes().indexOf(current) + " " + current.nodeType + current.additionalDebugInfo(), e); } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Add.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Add.java index a51ed7d4c8..dfe6f620e5 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Add.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Add.java @@ -22,4 +22,9 @@ public class Add extends Value { Add(final Graph owner, final Type type) { super(owner, type, NodeType.Add); } + + @Override + public Add stampInto(final Graph target) { + return target.newAdd(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/And.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/And.java index 737fc98022..43c0cedfd0 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/And.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/And.java @@ -22,4 +22,9 @@ public class And extends Value { And(final Graph owner, final Type type) { super(owner, type, NodeType.And); } + + @Override + public And stampInto(final Graph target) { + return target.newAND(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ArrayLength.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ArrayLength.java index d52f3cc114..d67d9e4cee 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ArrayLength.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ArrayLength.java @@ -22,4 +22,9 @@ public class ArrayLength extends Value { ArrayLength(final Graph owner) { super(owner, Type.INT_TYPE, NodeType.ArrayLength); } + + @Override + public ArrayLength stampInto(final Graph target) { + return target.newArrayLength(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ArrayLoad.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ArrayLoad.java index 288af4f908..27a3c966d0 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ArrayLoad.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ArrayLoad.java @@ -22,4 +22,9 @@ public class ArrayLoad extends Value { ArrayLoad(final Graph owner, final Type type) { super(owner, type, NodeType.ArrayLoad); } + + @Override + public ArrayLoad stampInto(final Graph target) { + return target.newArrayLoad(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ArrayStore.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ArrayStore.java index 165a0b0fe1..9a7f534a48 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ArrayStore.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ArrayStore.java @@ -25,4 +25,9 @@ public class ArrayStore extends ControlTokenConsumer { public boolean hasSideSideEffect() { return true; } + + @Override + public ArrayStore stampInto(final Graph target) { + return target.newArrayStore(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/BootstrapMethod.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/BootstrapMethod.java index 89d55ca977..8ac4754912 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/BootstrapMethod.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/BootstrapMethod.java @@ -41,4 +41,9 @@ public class BootstrapMethod extends Value { public boolean isConstant() { return true; } + + @Override + public BootstrapMethod stampInto(final Graph target) { + return target.newBootstrapMethod(methodType, className, methodName, kind); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/CMP.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/CMP.java index 958fde88f3..4ffb7c21da 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/CMP.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/CMP.java @@ -22,4 +22,9 @@ public class CMP extends Value { CMP(final Graph owner) { super(owner, Type.INT_TYPE, NodeType.CMP); } + + @Override + public CMP stampInto(final Graph target) { + return target.newCMP(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Cast.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Cast.java index 274dff9f65..b8d92a8a0f 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Cast.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Cast.java @@ -22,4 +22,9 @@ public class Cast extends Value { Cast(final Graph owner, final Type type) { super(owner, type, NodeType.Cast); } + + @Override + public Cast stampInto(final Graph target) { + return target.newCast(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/CaughtException.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/CaughtException.java index b703ed305b..e0daa5c75e 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/CaughtException.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/CaughtException.java @@ -27,4 +27,9 @@ public class CaughtException extends Value { public boolean isConstant() { return true; } + + @Override + public CaughtException stampInto(final Graph target) { + return target.newCaughtException(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ClassInitialization.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ClassInitialization.java index 7ad4b5a5dd..6b3da79327 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ClassInitialization.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ClassInitialization.java @@ -26,7 +26,17 @@ public class ClassInitialization extends ControlTokenConsumer { this.type = type; } + @Override + public String additionalDebugInfo() { + return ": " + type.getClassName(); + } + public void deleteFromControlFlow() { owner.deleteFromControlFlowInternally(this); } + + @Override + public ClassInitialization stampInto(final Graph target) { + return target.newClassInitialization(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ControlTokenConsumer.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ControlTokenConsumer.java index 4d0d880581..82e7500bb2 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ControlTokenConsumer.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ControlTokenConsumer.java @@ -50,4 +50,30 @@ public boolean hasIncomingBackEdges() { } return false; } + + public void replaceInControlFlow(final ControlTokenConsumer source, final ControlTokenConsumer target) { + final Set keys = new HashSet<>(controlFlowsTo.keySet()); + for (final Projection p : keys) { + final ControlTokenConsumer t = controlFlowsTo.get(p); + if (t == source) { + controlFlowsTo.put(p, target); + } + } + target.controlComingFrom.add(this); + } + + @Override + public void sanityCheck() { + super.sanityCheck(); + for (final ControlTokenConsumer source : controlComingFrom) { + if (!owner.nodes().contains(source)) { + throw new IllegalStateException("ControlToken from " + source + " is not part of the graph!"); + } + } + for (final ControlTokenConsumer target : controlFlowsTo.values()) { + if (!owner.nodes().contains(target)) { + throw new IllegalStateException("ControlToken to " + target + " is not part of the graph!"); + } + } + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Copy.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Copy.java index 3c5d4faca4..9462183cf6 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Copy.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Copy.java @@ -24,4 +24,9 @@ public class Copy extends ControlTokenConsumer { public void deleteFromControlFlow() { owner.deleteFromControlFlowInternally(this); } + + @Override + public Copy stampInto(final Graph target) { + return target.newCopy(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Div.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Div.java index b40c695392..97430781ef 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Div.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Div.java @@ -22,4 +22,9 @@ public class Div extends Value { Div(final Graph owner, final Type type) { super(owner, type, NodeType.Div); } + + @Override + public Div stampInto(final Graph target) { + return target.newDiv(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/EnumValuesOf.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/EnumValuesOf.java index 6e79d88567..879f94c715 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/EnumValuesOf.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/EnumValuesOf.java @@ -22,4 +22,9 @@ public class EnumValuesOf extends Value { EnumValuesOf(final Graph owner, final Type type) { super(owner, type, NodeType.EnumValuesOf); } + + @Override + public EnumValuesOf stampInto(final Graph target) { + return target.newEnumValuesOf(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/FieldReference.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/FieldReference.java index 708101f912..51714030bc 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/FieldReference.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/FieldReference.java @@ -28,4 +28,9 @@ public class FieldReference extends Reference { public String additionalDebugInfo() { return ": " + resolvedField.owner.type +"." + resolvedField.name + type ; } + + @Override + public FieldReference stampInto(final Graph target) { + return target.newFieldReference(resolvedField, kind); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/FrameDebugInfo.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/FrameDebugInfo.java index 04e7a5c07b..ec0f05ab68 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/FrameDebugInfo.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/FrameDebugInfo.java @@ -23,4 +23,9 @@ public class FrameDebugInfo extends ControlTokenConsumer { super(owner, NodeType.FrameDebugInfo); this.frame = frame; } + + @Override + public FrameDebugInfo stampInto(final Graph target) { + return target.newFrameDebugInfo(frame); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Goto.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Goto.java index 5549de4552..40757afda9 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Goto.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Goto.java @@ -20,4 +20,9 @@ public class Goto extends ControlTokenConsumer { Goto(final Graph owner) { super(owner, NodeType.Goto); } + + @Override + public Goto stampInto(final Graph target) { + return target.newGoto(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Graph.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Graph.java index b065303557..a16beddb2a 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Graph.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Graph.java @@ -58,8 +58,9 @@ public Region newStartRegion() { public Node[] outgoingDataFlowsFor(final Node n) { final Set result = new HashSet<>(); for (final Node t : nodes) { - for (final Node incoming : t.incomingDataFlows) { - if (incoming == n) { + final Node[] incoming = t.incomingDataFlows; + for (int i = 0; i t.edgeType() == EdgeType.BACK)) { - throw new IllegalStateException("Can only delete nodes without outgoing back edges!"); + throw new IllegalStateException("Can only delete nodes without outgoing back edges! Node Type is " + consumer.nodeType); } for (final ControlTokenConsumer pred : consumer.controlComingFrom) { @@ -486,4 +487,18 @@ void deleteFromControlFlowInternally(final ControlTokenConsumer consumer) { consumer.controlFlowsTo.clear(); nodes.remove(consumer); } + + public void replaceInControlFlow(final ControlTokenConsumer source, final ControlTokenConsumer target) { + final Set sources = new HashSet<>(source.controlComingFrom); + for (final ControlTokenConsumer s : sources) { + s.replaceInControlFlow(source, target); + } + nodes.remove(source); + } + + public void sanityCheck() { + for (final Node n : nodes) { + n.sanityCheck(); + } + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/If.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/If.java index b4b220cb69..6350140138 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/If.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/If.java @@ -20,4 +20,9 @@ public class If extends ControlTokenConsumer { If(final Graph owner) { super(owner, NodeType.If); } + + @Override + public If stampInto(final Graph target) { + return target.newIf(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/InstanceOf.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/InstanceOf.java index 366921dc09..267365c262 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/InstanceOf.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/InstanceOf.java @@ -22,4 +22,9 @@ public class InstanceOf extends Value { InstanceOf(final Graph owner) { super(owner, Type.INT_TYPE, NodeType.InstanceOf); } + + @Override + public InstanceOf stampInto(final Graph target) { + return target.newInstanceOf(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/InvokeDynamicExpression.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/InvokeDynamicExpression.java index d35648580b..5d37810490 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/InvokeDynamicExpression.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/InvokeDynamicExpression.java @@ -23,4 +23,9 @@ public class InvokeDynamicExpression extends Value { InvokeDynamicExpression(final Graph owner, final Type type) { super(owner, type, NodeType.InvokeDynamicExpression); } + + @Override + public InvokeDynamicExpression stampInto(final Graph target) { + return target.newInvokeDynamicExpression(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/LineNumberDebugInfo.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/LineNumberDebugInfo.java index 6e74230f4e..182f18ff4a 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/LineNumberDebugInfo.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/LineNumberDebugInfo.java @@ -28,4 +28,9 @@ public class LineNumberDebugInfo extends ControlTokenConsumer { public String additionalDebugInfo() { return ": line #" + lineNumber; } + + @Override + public LineNumberDebugInfo stampInto(final Graph target) { + return target.newLineNumberDebugInfo(lineNumber); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/LookupSwitch.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/LookupSwitch.java index 9234b90966..8c7ddaed5f 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/LookupSwitch.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/LookupSwitch.java @@ -20,4 +20,9 @@ public class LookupSwitch extends ControlTokenConsumer { LookupSwitch(final Graph owner) { super(owner, NodeType.LookupSwitch); } + + @Override + public LookupSwitch stampInto(final Graph target) { + return target.newLookupSwitch(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodArgument.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodArgument.java index e118c9d3b7..08e1e3b24a 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodArgument.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodArgument.java @@ -36,4 +36,9 @@ public String additionalDebugInfo() { public boolean isConstant() { return true; } + + @Override + public MethodArgument stampInto(final Graph target) { + return target.newMethodArgument(type, index); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodInvocation.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodInvocation.java index cdf885f5cb..05ec97afd7 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodInvocation.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodInvocation.java @@ -56,4 +56,9 @@ public void changeInvocationTypeTo(final InvocationType newInvocationType) { public boolean hasSideSideEffect() { return true; } + + @Override + public MethodInvocation stampInto(final Graph target) { + return target.newMethodInvocation(invocationType, insnNode, method); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodInvocationExpression.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodInvocationExpression.java index 1b8503671e..c263f45640 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodInvocationExpression.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodInvocationExpression.java @@ -35,9 +35,9 @@ public class MethodInvocationExpression extends Value implements AbstractInvocat @Override public String additionalDebugInfo() { if (insnNode == null) { - return invocationType + " " + method.owner + "." + method.methodNode.name; + return invocationType + " " + method.owner.type + "." + method.methodNode.name; } - return invocationType + " " + method.owner + "." + method.methodNode.name + insnNode.desc; + return invocationType + " " + method.owner.type + "." + method.methodNode.name + insnNode.desc; } @Override @@ -59,4 +59,9 @@ public void changeInvocationTypeTo(final InvocationType newInvocationType) { public boolean hasSideSideEffect() { return true; } + + @Override + public MethodInvocationExpression stampInto(final Graph target) { + return target.newMethodInvocationExpression(invocationType, insnNode, method); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodReference.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodReference.java index fa0f757e4c..a9a67cf58d 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodReference.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodReference.java @@ -29,4 +29,9 @@ public class MethodReference extends Reference { public String additionalDebugInfo() { return ": " + resolvedMethod.owner.type +"." + resolvedMethod.methodNode.name + type ; } + + @Override + public MethodReference stampInto(final Graph target) { + return target.newMethodReference(resolvedMethod, kind); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodType.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodType.java index c66675f699..6897101e88 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodType.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MethodType.java @@ -23,9 +23,13 @@ public class MethodType extends PrimitiveValue { super(owner, type, NodeType.MethodType); } - @Override public String additionalDebugInfo() { return ": " + type; } + + @Override + public MethodType stampInto(final Graph target) { + return target.newMethodType(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MonitorEnter.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MonitorEnter.java index 307e606ece..a5352cbc7f 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MonitorEnter.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MonitorEnter.java @@ -20,4 +20,9 @@ public class MonitorEnter extends ControlTokenConsumer { MonitorEnter(final Graph owner) { super(owner, NodeType.MonitorEnter); } + + @Override + public MonitorEnter stampInto(final Graph target) { + return target.newMonitorEnter(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MonitorExit.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MonitorExit.java index 1ca6d41332..b56134962e 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MonitorExit.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/MonitorExit.java @@ -20,4 +20,9 @@ public class MonitorExit extends ControlTokenConsumer { MonitorExit(final Graph owner) { super(owner, NodeType.MonitorExit); } + + @Override + public MonitorExit stampInto(final Graph target) { + return target.newMonitorExit(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Mul.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Mul.java index 961704d8a2..8ab3b2cc68 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Mul.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Mul.java @@ -22,4 +22,9 @@ public class Mul extends Value { Mul(final Graph owner, final Type type) { super(owner, type, NodeType.Mul); } + + @Override + public Mul stampInto(final Graph target) { + return target.newMul(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Neg.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Neg.java index 0047710a51..fb35c7a6be 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Neg.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Neg.java @@ -22,4 +22,9 @@ public class Neg extends Value { Neg(final Graph owner, final Type type) { super(owner, type, NodeType.Neg); } + + @Override + public Neg stampInto(final Graph target) { + return target.newNEG(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/New.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/New.java index 6af420972b..85cf597994 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/New.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/New.java @@ -22,4 +22,9 @@ public class New extends Value { New(final Graph owner, final Type type) { super(owner, type, NodeType.New); } + + @Override + public New stampInto(final Graph target) { + return target.newNew(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/NewArray.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/NewArray.java index 21023fe7c1..3fddec61f4 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/NewArray.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/NewArray.java @@ -22,4 +22,9 @@ public class NewArray extends Value { NewArray(final Graph owner, final Type type) { super(owner, type, NodeType.NewArray); } + + @Override + public NewArray stampInto(final Graph target) { + return target.newNewArray(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Node.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Node.java index cc48f1e202..aa25e6a926 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Node.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Node.java @@ -86,4 +86,14 @@ public boolean hasSideSideEffect() { public boolean hasSideSideEffectRecursive() { return hasSideEffectInternal(new HashSet<>()); } + + public abstract T stampInto(final Graph target); + + public void sanityCheck() { + for (final Node incoming : incomingDataFlows) { + if (!owner.nodes().contains(incoming)) { + throw new IllegalStateException("Incoming node " + incoming + " is not part of the graph!"); + } + } + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Nop.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Nop.java index f3e6522f62..365c91972a 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Nop.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Nop.java @@ -20,4 +20,9 @@ public class Nop extends ControlTokenConsumer { Nop(final Graph owner) { super(owner, NodeType.Nop); } + + @Override + public Nop stampInto(final Graph target) { + return target.newNop(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/NullReference.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/NullReference.java index 791f3189a6..abff8f9c99 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/NullReference.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/NullReference.java @@ -27,4 +27,9 @@ public class NullReference extends Value { public boolean isConstant() { return true; } + + @Override + public NullReference stampInto(final Graph target) { + return target.newNullReference(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/NullTest.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/NullTest.java index 62548de99e..9921564e8f 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/NullTest.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/NullTest.java @@ -32,4 +32,9 @@ public enum Operation { public String additionalDebugInfo() { return ": " + operation; } + + @Override + public NullTest stampInto(final Graph target) { + return target.newNullTest(operation); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/NumericalTest.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/NumericalTest.java index 2364110904..b65bf6e2fa 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/NumericalTest.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/NumericalTest.java @@ -32,4 +32,9 @@ public enum Operation { public String additionalDebugInfo() { return ": " + operation; } + + @Override + public NumericalTest stampInto(final Graph target) { + return target.newNumericalTest(operation); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ObjectString.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ObjectString.java index 662c6a1c60..4f21cd7105 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ObjectString.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ObjectString.java @@ -35,4 +35,9 @@ public String additionalDebugInfo() { public boolean isConstant() { return true; } + + @Override + public ObjectString stampInto(final Graph target) { + return target.newObjectString(value); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Or.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Or.java index e170cadb02..5ffc793092 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Or.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Or.java @@ -22,4 +22,9 @@ public class Or extends Value { Or(final Graph owner, final Type type) { super(owner, type, NodeType.Or); } + + @Override + public Or stampInto(final Graph target) { + return target.newOR(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PHI.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PHI.java index 61a713b680..207aa5b47f 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PHI.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PHI.java @@ -22,4 +22,9 @@ public class PHI extends AbstractVar { PHI(final Graph owner, final Type type) { super(owner, type, NodeType.PHI); } + + @Override + public PHI stampInto(final Graph target) { + return target.newPHI(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveClassReference.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveClassReference.java index 9e14ce0832..4bd49e110a 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveClassReference.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveClassReference.java @@ -30,4 +30,8 @@ public boolean isConstant() { return true; } + @Override + public PrimitiveClassReference stampInto(final Graph target) { + return target.newPrimitiveClassReference(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveDouble.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveDouble.java index 4a12514e9b..50eee5912c 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveDouble.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveDouble.java @@ -26,9 +26,13 @@ public class PrimitiveDouble extends PrimitiveValue { this.value = value; } - @Override public String additionalDebugInfo() { return ": " + value; } + + @Override + public PrimitiveDouble stampInto(final Graph target) { + return target.newDouble(value); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveFloat.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveFloat.java index 90e09764f3..d64c42934c 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveFloat.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveFloat.java @@ -26,9 +26,13 @@ public class PrimitiveFloat extends PrimitiveValue { this.value = value; } - @Override public String additionalDebugInfo() { return ": " + value; } + + @Override + public PrimitiveFloat stampInto(final Graph target) { + return target.newFloat(value); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveInt.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveInt.java index b7a41d670e..a007ed9612 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveInt.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveInt.java @@ -29,4 +29,9 @@ public class PrimitiveInt extends PrimitiveValue { public String additionalDebugInfo() { return ": " + value; } + + @Override + public PrimitiveInt stampInto(final Graph target) { + return target.newInt(value); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveLong.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveLong.java index 9e05b2bd71..5247ac54a9 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveLong.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveLong.java @@ -30,4 +30,9 @@ public class PrimitiveLong extends PrimitiveValue { public String additionalDebugInfo() { return ": " + value; } + + @Override + public PrimitiveLong stampInto(final Graph target) { + return target.newLong(value); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveShort.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveShort.java index fab5820a30..e3196193b4 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveShort.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/PrimitiveShort.java @@ -26,9 +26,13 @@ public class PrimitiveShort extends PrimitiveValue { this.value = value; } - @Override public String additionalDebugInfo() { return ": " + value; } + + @Override + public PrimitiveShort stampInto(final Graph target) { + return target.newShort(value); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ReadClassField.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ReadClassField.java index d7cee66932..7e1ccfcde3 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ReadClassField.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ReadClassField.java @@ -30,4 +30,9 @@ public class ReadClassField extends Value { public String additionalDebugInfo() { return ": " + resolvedField.name; } + + @Override + public ReadClassField stampInto(final Graph target) { + return target.newClassFieldExpression(type, resolvedField); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ReadInstanceField.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ReadInstanceField.java index ed5588a3d9..9e87d36327 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ReadInstanceField.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ReadInstanceField.java @@ -30,4 +30,9 @@ public class ReadInstanceField extends Value { public String additionalDebugInfo() { return ": " + resolvedField.name; } + + @Override + public ReadInstanceField stampInto(final Graph target) { + return target.newInstanceFieldExpression(type, resolvedField); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ReferenceTest.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ReferenceTest.java index 2389dd4d07..6b90db980f 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ReferenceTest.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ReferenceTest.java @@ -32,4 +32,9 @@ public enum Operation { public String additionalDebugInfo() { return ": " + operation; } + + @Override + public ReferenceTest stampInto(final Graph target) { + return target.newReferenceTest(operation); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Region.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Region.java index 610a127f7b..1634574dd1 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Region.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Region.java @@ -30,14 +30,15 @@ public class Region extends ControlTokenConsumer { this(owner, label, NodeType.Region); } - @Override - public void addControlFlowTo(final Projection projection, final ControlTokenConsumer node) { - super.addControlFlowTo(projection, node); + public String additionalDebugInfo() { + return label; } @Override - public String additionalDebugInfo() { - return label; + public Region stampInto(final Graph target) { + final Region r = target.newRegion(label); + r.frame = frame; + return r; } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Reinterpret.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Reinterpret.java index a3f76949cd..74465052d0 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Reinterpret.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Reinterpret.java @@ -22,4 +22,9 @@ public class Reinterpret extends Value { Reinterpret(final Graph owner, final Type type) { super(owner, type, NodeType.Reinterpret); } + + @Override + public Reinterpret stampInto(final Graph target) { + return target.newReinterpret(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Rem.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Rem.java index 0394b422ee..9b93cfac1b 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Rem.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Rem.java @@ -22,4 +22,9 @@ public class Rem extends Value { Rem(final Graph owner, final Type type) { super(owner, type, NodeType.Rem); } + + @Override + public Rem stampInto(final Graph target) { + return target.newRem(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ResolveCallsite.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ResolveCallsite.java index 2f88252f28..ff720a8e24 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ResolveCallsite.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ResolveCallsite.java @@ -25,4 +25,9 @@ public class ResolveCallsite extends Value { ResolveCallsite(final Graph owner) { super(owner, Type.getType(CallSite.class), NodeType.ResolveCallsite); } + + @Override + public ResolveCallsite stampInto(final Graph target) { + return target.newResolveCallsite(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Return.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Return.java index 4dce6f7f2b..9b08996fa3 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Return.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Return.java @@ -20,4 +20,9 @@ public class Return extends ControlTokenConsumer { Return(final Graph owner) { super(owner, NodeType.Return); } + + @Override + public Return stampInto(final Graph target) { + return target.newReturnNothing(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ReturnValue.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ReturnValue.java index 27d9a515ec..213cf5757b 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ReturnValue.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/ReturnValue.java @@ -20,4 +20,9 @@ public class ReturnValue extends ControlTokenConsumer { ReturnValue(final Graph owner) { super(owner, NodeType.ReturnValue); } + + @Override + public ReturnValue stampInto(final Graph target) { + return target.newReturnValue(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/RuntimeClass.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/RuntimeClass.java index e9e2c4d057..c6ca24bda0 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/RuntimeClass.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/RuntimeClass.java @@ -32,4 +32,9 @@ public String additionalDebugInfo() { public boolean isConstant() { return true; } + + @Override + public RuntimeClass stampInto(final Graph target) { + return target.newRuntimeClass(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/RuntimeClassOf.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/RuntimeClassOf.java index 11f3c40c13..fbdc270af8 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/RuntimeClassOf.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/RuntimeClassOf.java @@ -22,4 +22,9 @@ public class RuntimeClassOf extends Value { RuntimeClassOf(final Graph owner) { super(owner, Type.getType(Class.class), NodeType.RuntimeClassOf); } + + @Override + public RuntimeClassOf stampInto(final Graph target) { + return target.newRuntimeTypeOf(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/SHL.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/SHL.java index a4e194bf29..090d11ebb6 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/SHL.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/SHL.java @@ -22,4 +22,9 @@ public class SHL extends Value { SHL(final Graph owner, final Type type) { super(owner, type, NodeType.SHL); } + + @Override + public SHL stampInto(final Graph target) { + return target.newSHL(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/SHR.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/SHR.java index 31c78fbbad..dc5c1b5381 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/SHR.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/SHR.java @@ -22,4 +22,9 @@ public class SHR extends Value { SHR(final Graph owner, final Type type) { super(owner, type, NodeType.SHR); } + + @Override + public SHR stampInto(final Graph target) { + return target.newSHR(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/SetClassField.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/SetClassField.java index 91d290278d..710aa5028e 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/SetClassField.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/SetClassField.java @@ -33,4 +33,9 @@ public String additionalDebugInfo() { public boolean hasSideSideEffect() { return true; } + + @Override + public SetClassField stampInto(final Graph target) { + return target.newSetClassField(field); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/SetInstanceField.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/SetInstanceField.java index 9f2b82d2d7..7f09abdc3e 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/SetInstanceField.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/SetInstanceField.java @@ -33,4 +33,9 @@ public String additionalDebugInfo() { public boolean hasSideSideEffect() { return true; } + + @Override + public SetInstanceField stampInto(final Graph target) { + return target.newSetInstanceField(field); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Sub.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Sub.java index 1f47e60d37..efa7c8a74c 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Sub.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Sub.java @@ -22,4 +22,9 @@ public class Sub extends Value { Sub(final Graph owner, final Type type) { super(owner, type, NodeType.Sub); } + + @Override + public Sub stampInto(final Graph target) { + return target.newSub(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/TableSwitch.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/TableSwitch.java index 1918097c3b..f5c58f0926 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/TableSwitch.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/TableSwitch.java @@ -25,4 +25,9 @@ public class TableSwitch extends ControlTokenConsumer { this.min = min; this.max = max; } + + @Override + public TableSwitch stampInto(final Graph target) { + return target.newTableSwitch(min, max); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/This.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/This.java index 61bc85ab03..78a1581d56 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/This.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/This.java @@ -32,4 +32,9 @@ public String additionalDebugInfo() { public boolean isConstant() { return true; } + + @Override + public This stampInto(final Graph target) { + return target.newThis(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/TryCatch.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/TryCatch.java index 1b1a7b75fa..f93d3a969f 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/TryCatch.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/TryCatch.java @@ -20,4 +20,11 @@ public class TryCatch extends Region { TryCatch(final Graph owner, final String label) { super(owner, label, NodeType.TryCatch); } + + @Override + public TryCatch stampInto(final Graph target) { + final TryCatch t = target.newTryCatch(label); + t.frame = frame; + return t; + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/TypeConversion.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/TypeConversion.java index 2796543ab5..675f74ae11 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/TypeConversion.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/TypeConversion.java @@ -22,4 +22,9 @@ public class TypeConversion extends Value { TypeConversion(final Graph owner, final Type type) { super(owner, type, NodeType.TypeConversion); } + + @Override + public TypeConversion stampInto(final Graph target) { + return target.newTypeConversion(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/TypeReference.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/TypeReference.java index 88e6e84cf5..71bee5b4ad 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/TypeReference.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/TypeReference.java @@ -32,4 +32,9 @@ public String additionalDebugInfo() { public boolean isConstant() { return true; } + + @Override + public TypeReference stampInto(final Graph target) { + return target.newTypeReference(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/USHR.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/USHR.java index a8df700584..8ffd279999 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/USHR.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/USHR.java @@ -22,4 +22,9 @@ public class USHR extends Value { USHR(final Graph owner, final Type type) { super(owner, type, NodeType.USHR); } + + @Override + public USHR stampInto(final Graph target) { + return target.newUSHR(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Unwind.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Unwind.java index 542ba8404b..bfd256c965 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Unwind.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Unwind.java @@ -20,4 +20,9 @@ public class Unwind extends ControlTokenConsumer { Unwind(final Graph owner) { super(owner, NodeType.Unwind); } + + @Override + public Unwind stampInto(final Graph target) { + return target.newUnwind(); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Variable.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Variable.java index c1494f9fe2..5dbfc4c0f3 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Variable.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/Variable.java @@ -22,4 +22,9 @@ public class Variable extends AbstractVar { Variable(final Graph owner, final Type value) { super(owner, value, NodeType.Variable); } + + @Override + public Variable stampInto(final Graph target) { + return target.newVariable(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/XOr.java b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/XOr.java index aa4af86f42..5756e78fb3 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/ir/XOr.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/ir/XOr.java @@ -22,4 +22,9 @@ public class XOr extends Value { XOr(final Graph owner, final Type type) { super(owner, type, NodeType.XOr); } + + @Override + public XOr stampInto(final Graph target) { + return target.newXOR(type); + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/DeleteRedundantClassInitializations.java b/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/DeleteRedundantClassInitializations.java index fe3827498c..87a71bbd9f 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/DeleteRedundantClassInitializations.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/DeleteRedundantClassInitializations.java @@ -24,6 +24,7 @@ import de.mirkosertic.bytecoder.core.ir.ResolvedMethod; import de.mirkosertic.bytecoder.core.parser.CompileUnit; +import java.util.ArrayList; import java.util.Stack; public class DeleteRedundantClassInitializations implements GlobalOptimizer { @@ -48,7 +49,7 @@ public boolean optimize(final BackendType backendType, final CompileUnit compile if (!rc.requiresClassInitializer()) { ci.deleteFromControlFlow(); } else { - for (final ClassInitialization j : workingQueue) { + for (final ClassInitialization j : new ArrayList<>(workingQueue)) { if (j != ci && ci.type.equals(j.type)) { if (dominatorTree.dominates(ci, j)) { j.deleteFromControlFlow(); diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/InlineMethodsOptimizer.java b/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/InlineMethodsOptimizer.java new file mode 100644 index 0000000000..ccd8e57f71 --- /dev/null +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/InlineMethodsOptimizer.java @@ -0,0 +1,177 @@ +/* + * Copyright 2024 Mirko Sertic + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.mirkosertic.bytecoder.core.optimizer; + +import de.mirkosertic.bytecoder.core.backend.BackendType; +import de.mirkosertic.bytecoder.core.ir.ControlTokenConsumer; +import de.mirkosertic.bytecoder.core.ir.Graph; +import de.mirkosertic.bytecoder.core.ir.InvocationType; +import de.mirkosertic.bytecoder.core.ir.MethodArgument; +import de.mirkosertic.bytecoder.core.ir.MethodInvocation; +import de.mirkosertic.bytecoder.core.ir.Node; +import de.mirkosertic.bytecoder.core.ir.NodeType; +import de.mirkosertic.bytecoder.core.ir.Projection; +import de.mirkosertic.bytecoder.core.ir.Region; +import de.mirkosertic.bytecoder.core.ir.ResolvedMethod; +import de.mirkosertic.bytecoder.core.ir.TryCatch; +import de.mirkosertic.bytecoder.core.parser.CompileUnit; + +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; + +public class InlineMethodsOptimizer implements Optimizer { + + private int labelCounter = 0; + + private Map stampInto(final Graph source, final Graph target, final Node thisRef, final Node[] arguments) { + + final Map clones = new HashMap<>(); + for (final Node n : source.nodes()) { + final Node clone; + switch (n.nodeType) { + case Region: + final Region r = (Region) n; + if (Graph.START_REGION_NAME.equals(r.label)) { + clone = target.newRegion("InlineStartProxy_" + labelCounter++); + } else { + clone = target.newRegion(r.label + "_" + labelCounter++); + } + break; + case TryCatch: + final TryCatch t = (TryCatch) n; + clone = target.newTryCatch(t.label + "_" + labelCounter++); + break; + case Return: + clone = target.newRegion("InlineReturnProxy_" + labelCounter++); + break; + case This: + clone = thisRef; + break; + case MethodArgument: + clone = arguments[((MethodArgument) n).index]; + break; + default: + clone = n.stampInto(target); + break; + } + clones.put(n, clone); + } + for (final Node n : source.nodes()) { + final Node t = clones.get(n); + for (final Node inc : n.incomingDataFlows) { + final Node mapped = clones.get(inc); + t.addIncomingData(mapped); + } + + if (n instanceof ControlTokenConsumer) { + final ControlTokenConsumer s1 = (ControlTokenConsumer) n; + final ControlTokenConsumer t1 = (ControlTokenConsumer) t; + for (final Map.Entry entry : s1.controlFlowsTo.entrySet()) { + final ControlTokenConsumer controlFlowTarget = (ControlTokenConsumer) clones.get(entry.getValue()); + t1.addControlFlowTo(entry.getKey(), controlFlowTarget); + } + } + } + return clones; + } + + private boolean isInliningCandidate(final ResolvedMethod rm) { + if (Modifier.isNative(rm.methodNode.access)) { + return false; + } + final long controlTokens = rm.methodBody.nodes().stream().filter(t -> + t.nodeType == NodeType.MonitorEnter || + t.nodeType == NodeType.Goto || + t.nodeType == NodeType.Unwind || + t.nodeType == NodeType.TableSwitch || + t.nodeType == NodeType.ReturnValue || + t.nodeType == NodeType.ClassInitialization || + t.nodeType == NodeType.SetInstanceField || + t.nodeType == NodeType.Return || + t.nodeType == NodeType.Copy || + t.nodeType == NodeType.MonitorExit || + t.nodeType == NodeType.Region || + t.nodeType == NodeType.TryCatch || + t.nodeType == NodeType.ArrayStore || + t.nodeType == NodeType.Nop || + t.nodeType == NodeType.If).count(); + //return controlTokens < 20; + return "".equals(rm.methodNode.name) && controlTokens < 20; + } + + @Override + public boolean optimize(final BackendType backendType, final CompileUnit compileUnit, final ResolvedMethod method) { + boolean changed = false; + + final Graph g = method.methodBody; + + // Variable and Constant propagation + final Stack workingQueue = new Stack<>(); + + // We search for static and direct method invocations + g.nodes().stream().filter(t -> t.nodeType == NodeType.MethodInvocation).map(t -> (MethodInvocation) t).filter(t -> t.invocationType == InvocationType.DIRECT || t.invocationType == InvocationType.STATIC).forEach(workingQueue::push); + + // We perform a recursive search across the invocation graph + while (!workingQueue.isEmpty()) { + final MethodInvocation methodInvocation = workingQueue.pop(); + final ResolvedMethod rm = methodInvocation.method; + // Check for recursion here! + if (isInliningCandidate(rm) && rm != method) { + final Node thisRef; + final Node[] arguments; + final Node[] incomingDataFlows = methodInvocation.incomingDataFlows; + + if (Modifier.isStatic(rm.methodNode.access)) { + thisRef = null; + } else { + thisRef = incomingDataFlows[0]; + } + if (incomingDataFlows.length > 1) { + arguments = new Node[incomingDataFlows.length - 1]; + System.arraycopy(incomingDataFlows, 1, arguments, 0, incomingDataFlows.length - 1); + } else { + arguments = new Node[0]; + } + + final Map importedNodes = stampInto(rm.methodBody, g, thisRef, arguments); + final ControlTokenConsumer start = (ControlTokenConsumer) importedNodes.get(rm.methodBody.regionByLabel(Graph.START_REGION_NAME)); + + g.replaceInControlFlow(methodInvocation, start); + for (final Map.Entry entry : methodInvocation.controlFlowsTo.entrySet()) { + entry.getValue().controlComingFrom.remove(methodInvocation); + } + + // Remerge the control flow + for (final Map.Entry imp : importedNodes.entrySet()) { + final Node source = imp.getKey(); + if (source.nodeType == NodeType.Return) { + final ControlTokenConsumer target = (ControlTokenConsumer) imp.getValue(); + + for (final Map.Entry entry : methodInvocation.controlFlowsTo.entrySet()) { + target.addControlFlowTo(entry.getKey(), entry.getValue()); + } + } + } + + changed = true; + } + } + + return changed; + } +} diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/Optimizations.java b/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/Optimizations.java index 16f806741b..32c9bde657 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/Optimizations.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/Optimizations.java @@ -16,6 +16,8 @@ package de.mirkosertic.bytecoder.core.optimizer; import de.mirkosertic.bytecoder.core.backend.BackendType; +import de.mirkosertic.bytecoder.core.backend.CodeGenerationFailure; +import de.mirkosertic.bytecoder.core.backend.sequencer.DominatorTree; import de.mirkosertic.bytecoder.core.ir.ResolvedMethod; import de.mirkosertic.bytecoder.core.parser.CompileUnit; @@ -32,7 +34,8 @@ public enum Optimizations implements Optimizer { new VariableIsVariable(), new CopyToRedundantVariable(), new VirtualToDirectInvocation(), - new DeleteRedundantClassInitializations() + new DeleteRedundantClassInitializations(), + new InlineMethodsOptimizer() }), ALL(new Optimizer[] { new PHIorVariableIsConstant(), @@ -40,7 +43,8 @@ public enum Optimizations implements Optimizer { new VariableIsVariable(), new CopyToRedundantVariable(), new VirtualToDirectInvocation(), - new DeleteRedundantClassInitializations() + new DeleteRedundantClassInitializations(), + new InlineMethodsOptimizer() }), ; @@ -59,18 +63,22 @@ public boolean optimize(final BackendType backendType, final CompileUnit compile // return false; //} - boolean graphchanged = false; - final Set go = Arrays.stream(optimizers).filter(t -> t instanceof GlobalOptimizer).map(t -> (GlobalOptimizer) t).collect(Collectors.toSet()); - for (final Optimizer o : optimizers) { - if (!go.contains(o)) { - graphchanged = graphchanged | o.optimize(backendType, compileUnit, method); + try { + boolean graphchanged = false; + final Set go = Arrays.stream(optimizers).filter(t -> t instanceof GlobalOptimizer).map(t -> (GlobalOptimizer) t).collect(Collectors.toSet()); + for (final Optimizer o : optimizers) { + if (!go.contains(o)) { + graphchanged = graphchanged | o.optimize(backendType, compileUnit, method); + } } - } - if (!graphchanged) { - for (final GlobalOptimizer o : go) { - o.optimize(backendType, compileUnit, method); + if (!graphchanged) { + for (final GlobalOptimizer o : go) { + o.optimize(backendType, compileUnit, method); + } } + return graphchanged; + } catch (final RuntimeException e) { + throw new CodeGenerationFailure(method, new DominatorTree(method.methodBody), e); } - return graphchanged; } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/OptimizerLogging.java b/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/OptimizerLogging.java index a26d3a25c2..a7b8a69834 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/OptimizerLogging.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/OptimizerLogging.java @@ -1,8 +1,26 @@ +/* + * Copyright 2024 Mirko Sertic + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package de.mirkosertic.bytecoder.core.optimizer; +import de.mirkosertic.bytecoder.core.backend.sequencer.DominatorTree; import de.mirkosertic.bytecoder.core.ir.ResolvedMethod; import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -19,27 +37,29 @@ public OptimizerLogging(final ResolvedMethod rm) { } public void logStep(final int step) { -/* try { - final String prefix = rm.owner.type.getClassName() + "_" + rm.methodNode.name.replace("<", "$").replace(">", "$") + "_"; - - final File generatedFilesDir = new File("."); - final String filenameDg = prefix + "optimization_debuggraph_" + step + ".dot"; - final File unoptdbf = new File(generatedFilesDir, filenameDg); - try (final FileOutputStream fos = new FileOutputStream(unoptdbf)) { - rm.methodBody.writeDebugTo(fos); - } - graphSteps.add(unoptdbf); + if ("true".equalsIgnoreCase(System.getProperty("bytecoder.logoptimizations", "false"))) { + try { + final String prefix = rm.owner.type.getClassName() + "_" + rm.methodNode.name.replace("<", "$").replace(">", "$") + "_"; + + final File generatedFilesDir = new File("."); + final String filenameDg = prefix + "optimization_debuggraph_" + step + ".dot"; + final File unoptdbf = new File(generatedFilesDir, filenameDg); + try (final FileOutputStream fos = new FileOutputStream(unoptdbf)) { + rm.methodBody.writeDebugTo(fos); + } + graphSteps.add(unoptdbf); - final String filenameDt = prefix + "optimiztation__dominatortree_" + step + ".dot"; - final File unoptdtf = new File(generatedFilesDir, filenameDt); - try (final FileOutputStream fos = new FileOutputStream(unoptdtf)) { - final DominatorTree dt = new DominatorTree(rm.methodBody); - dt.writeDebugTo(fos); + final String filenameDt = prefix + "optimiztation_dominatortree_" + step + ".dot"; + final File unoptdtf = new File(generatedFilesDir, filenameDt); + try (final FileOutputStream fos = new FileOutputStream(unoptdtf)) { + final DominatorTree dt = new DominatorTree(rm.methodBody); + dt.writeDebugTo(fos); + } + dominatorTreeSteps.add(unoptdtf); + } catch (final IOException e) { + throw new RuntimeException("Cannot write debug data", e); } - dominatorTreeSteps.add(unoptdtf); - } catch (final IOException e) { - throw new RuntimeException("Cannot write debug data", e); - }*/ + } } public void finished() { //if (!rm.owner.type.getClassName().contains("TailcallVarargs") && (!"eval".equals(rm.methodNode.name))) { diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/STATS.md b/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/STATS.md index 25d9ef2174..503eb951ee 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/STATS.md +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/STATS.md @@ -39,3 +39,8 @@ JBox2D JS CopyToRedVar 2576857 bytes LUA Wasm CopyToRedVar 493149 bytes LUA JS CopyToRedVar 2068370 bytes + + JBox2D Wasm InlineCons1 540810 bytes + JBox2D JS InlineCons1 2822585 bytes + LUA Wasm InlineCons1 502611 bytes + LUA JS InlineCons1 2259485 bytes diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/VariableIsVariable.java b/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/VariableIsVariable.java index 071884c8f0..8e38984a80 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/VariableIsVariable.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/VariableIsVariable.java @@ -56,7 +56,7 @@ public boolean optimize(final BackendType backendType, final CompileUnit compile final Node source = workingItem.incomingDataFlows[0]; // And only one outgoing dataflow // At this point we are sure it is a variable or phi - final Node target =g.outgoingDataFlowsFor(workingItem)[0]; + final Node target = g.outgoingDataFlowsFor(workingItem)[0]; g.remapDataFlow(target, source); diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/VirtualToDirectInvocation.java b/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/VirtualToDirectInvocation.java index 4628c41e0c..4e84b7f920 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/VirtualToDirectInvocation.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/optimizer/VirtualToDirectInvocation.java @@ -59,10 +59,10 @@ private boolean isMethodOverriddenInSubclass(final ResolvedClass rc, final Resol @Override public boolean optimize(final BackendType backendType, final CompileUnit compileUnit, final ResolvedMethod method) { - if (backendType == BackendType.JS) { - // Ineffizient Optimization on JS backend... + /*if (backendType == BackendType.JS) { + // Inefficient optimization on JS backend... return false; - } + }*/ final Graph g = method.methodBody; diff --git a/core/src/test/java/de/mirkosertic/bytecoder/IRExport.java b/core/src/test/java/de/mirkosertic/bytecoder/IRExport.java index be729c06c1..922f07830a 100644 --- a/core/src/test/java/de/mirkosertic/bytecoder/IRExport.java +++ b/core/src/test/java/de/mirkosertic/bytecoder/IRExport.java @@ -23,7 +23,13 @@ public class IRExport { + public static void doit(final String[] args) { + + } + public int dosomething(final int value) { + doit(new String[0]); + final IRExport dummy = new IRExport(); int x = value; for (int i = 0; i < 100; i++) { x = x + i + value; @@ -43,6 +49,8 @@ public static void main(final String[] args) throws IOException { final ResolvedMethod method = compileUnit.resolveMainMethod(invokedType, "dosomething", Type.getMethodType(Type.INT_TYPE, Type.INT_TYPE)); //final ResolvedMethod method = compileUnit.resolveMainMethod(invokedType, "need_value", Type.getMethodType(Type.BOOLEAN_TYPE, Type.INT_TYPE)); + //final ResolvedMethod method = compileUnit.resolveMainMethod(Type.getType(Buffer.class), "", Type.getMethodType(Type.VOID_TYPE)); + compileUnit.finalizeLinkingHierarchy(); compileUnit.logStatistics();