diff --git a/src/main/java/dk/camelot64/kickc/model/CallGraph.java b/src/main/java/dk/camelot64/kickc/model/CallGraph.java index a2fa131b0..2b0a5d54d 100644 --- a/src/main/java/dk/camelot64/kickc/model/CallGraph.java +++ b/src/main/java/dk/camelot64/kickc/model/CallGraph.java @@ -5,10 +5,7 @@ import dk.camelot64.kickc.model.values.ProcedureRef; import dk.camelot64.kickc.model.values.ScopeRef; import dk.camelot64.kickc.passes.PassNCallGraphAnalysis; -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.List; +import java.util.*; /** * The call graph for the entire control flow graph. @@ -312,6 +309,19 @@ public class CallGraph { return out.toString(); } + @Override + public boolean equals(Object o) { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + Call call = (Call) o; + return Objects.equals(callStatementIdx, call.callStatementIdx) && + Objects.equals(procedure, call.procedure); + } + + @Override + public int hashCode() { + return Objects.hash(callStatementIdx, procedure); + } } } diff --git a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java index 02b0f347a..f9e271b4e 100644 --- a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java +++ b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java @@ -232,6 +232,19 @@ public class LiveRangeVariablesEffective { public Pass2AliasElimination.Aliases getInnerAliases() { return innerAliases; } + + @Override + public boolean equals(Object o) { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + CallPath callPath = (CallPath) o; + return Objects.equals(path, callPath.path); + } + + @Override + public int hashCode() { + return Objects.hash(path); + } } /** @@ -258,11 +271,29 @@ public class LiveRangeVariablesEffective { */ private Pass2AliasElimination.Aliases callAliases; + /** Effective alive variables for each call path. */ + private Map> effectiveAliveAtStmt; + + public AliveCombinations(CallPaths callPaths, Collection referencedInProcedure, Collection aliveAtStmt, Pass2AliasElimination.Aliases callAliases) { this.callPaths = callPaths; this.referencedInProcedure = referencedInProcedure; this.aliveAtStmt = aliveAtStmt; this.callAliases = callAliases; + // Initialize the effective alive at statment per call-path + this.effectiveAliveAtStmt = new LinkedHashMap<>(); + for(CallPath callPath : callPaths.getCallPaths()) { + // Add alive at call + LinkedHashSet effectiveAlive = new LinkedHashSet<>(); + // Add alive through the call path + effectiveAlive.addAll(callPath.getAlive()); + // Clear out any variables referenced in the method + effectiveAlive.removeAll(referencedInProcedure); + // Add alive at statement + effectiveAlive.addAll(aliveAtStmt); + // Store the effective alive vars + effectiveAliveAtStmt.put(callPath, effectiveAlive); + } } public CallPaths getCallPaths() { @@ -276,13 +307,7 @@ public class LiveRangeVariablesEffective { * @return All variables effectively alive at the statement on the call-path */ public Collection getEffectiveAliveAtStmt(CallPath callPath) { - // Add alive at call - LinkedHashSet effectiveAlive = new LinkedHashSet<>(callPath.getAlive()); - // Clear out any variables referenced in the method - effectiveAlive.removeAll(referencedInProcedure); - // Add alive at statement - effectiveAlive.addAll(aliveAtStmt); - return effectiveAlive; + return effectiveAliveAtStmt.get(callPath); } public Pass2AliasElimination.Aliases getEffectiveAliasesAtStmt(CallPath callPath) { diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 04dabae5a..eaf2c0e2c 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -12,6 +12,9 @@ import org.junit.BeforeClass; import org.junit.Test; import java.io.*; +import java.lang.management.GarbageCollectorMXBean; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryUsage; import java.net.URISyntaxException; import java.nio.file.FileAlreadyExistsException; import java.nio.file.Files; @@ -32,6 +35,7 @@ public class TestPrograms { public TestPrograms() { } + @Test public void testRobozzleLabelProblem() throws IOException, URISyntaxException { compileAndCompare("robozzle64-label-problem", log()); @@ -2013,6 +2017,43 @@ public class TestPrograms { public static void tearDown() { CompileLog log = log(); AsmFragmentTemplateUsages.logUsages(log, false, false, false, false, false, false); + + printGCStats(); + + } + + public static void printGCStats() { + long totalGarbageCollections = 0; + long garbageCollectionTime = 0; + + for(GarbageCollectorMXBean gc : + ManagementFactory.getGarbageCollectorMXBeans()) { + + long count = gc.getCollectionCount(); + + if(count >= 0) { + totalGarbageCollections += count; + } + + long time = gc.getCollectionTime(); + + if(time >= 0) { + garbageCollectionTime += time; + } + } + + System.out.println("Total Garbage Collections: " + + totalGarbageCollections); + System.out.println("Total Garbage Collection Time (ms): " + + garbageCollectionTime); + + MemoryUsage heapMemoryUsage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); + MemoryUsage nonHeapMemoryUsage = ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage(); + System.out.println("Heap Memory Usage: " + + heapMemoryUsage.toString()); + System.out.println("Non-Heap Memory Usage: " + + nonHeapMemoryUsage.toString()); + } private static CompileLog log() {