From 77863ad6fd07b1f9f06b759241ebcdc02e33867b Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Fri, 13 Mar 2015 15:55:02 +0400 Subject: [PATCH] Perform better preordering before decompilation --- .../java/org/teavm/common/GraphIndexer.java | 85 +++++++++++++++++-- .../java/org/teavm/javascript/Decompiler.java | 6 +- 2 files changed, 82 insertions(+), 9 deletions(-) diff --git a/teavm-core/src/main/java/org/teavm/common/GraphIndexer.java b/teavm-core/src/main/java/org/teavm/common/GraphIndexer.java index 7fba32a06..21f1b94c6 100644 --- a/teavm-core/src/main/java/org/teavm/common/GraphIndexer.java +++ b/teavm-core/src/main/java/org/teavm/common/GraphIndexer.java @@ -18,7 +18,10 @@ package org.teavm.common; import com.carrotsearch.hppc.IntOpenHashSet; import com.carrotsearch.hppc.IntSet; import com.carrotsearch.hppc.cursors.IntCursor; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.List; /** * @@ -30,18 +33,19 @@ public class GraphIndexer { static final byte VISITED = 2; private int[] indexToNode; private int[] nodeToIndex; - private byte[] state; private Graph graph; private DominatorTree domTree; private int lastIndex; + private int[] weights; - public GraphIndexer(Graph graph) { + public GraphIndexer(Graph graph, int[] weights) { int sz = graph.size(); + this.weights = weights; + propagateWeights(graph, weights); indexToNode = new int[sz + 1]; nodeToIndex = new int[sz + 1]; Arrays.fill(nodeToIndex, -1); Arrays.fill(indexToNode, -1); - state = new byte[sz]; this.graph = graph; domTree = GraphUtils.buildDominatorTree(graph); sort(graph); @@ -66,8 +70,38 @@ public class GraphIndexer { this.graph = sorted.build(); } + private void propagateWeights(Graph graph, int[] weights) { + int sz = graph.size(); + byte[] state = new byte[sz]; + IntegerStack stack = new IntegerStack(sz * 2); + stack.push(0); + while (!stack.isEmpty()) { + int node = stack.pop(); + switch (state[node]) { + case VISITING: + state[node] = VISITED; + for (int succ : graph.outgoingEdges(node)) { + if (state[node] == VISITED) { + weights[node] += weights[succ]; + } + } + break; + case NONE: + state[node] = VISITING; + stack.push(node); + for (int succ : graph.outgoingEdges(node)) { + if (state[succ] == NONE) { + stack.push(succ); + } + } + break; + } + } + } + private void sort(Graph graph) { int sz = graph.size(); + byte[] state = new byte[sz]; IntegerStack stack = new IntegerStack(sz * 2); stack.push(0); while (!stack.isEmpty()) { @@ -88,25 +122,45 @@ public class GraphIndexer { } } int[] successors = graph.outgoingEdges(node); + List succList = new ArrayList<>(successors.length); + IntegerArray orderedSuccessors = new IntegerArray(successors.length); if (terminalNodes.size() > 0) { IntSet loopNodes = IntOpenHashSet.from(findNaturalLoop(node, terminalNodes.getAll())); - IntegerArray orderedSuccessors = new IntegerArray(successors.length); for (int succ : successors) { if (loopNodes.contains(succ)) { - orderedSuccessors.add(succ); + succList.add(new WeightedNode(succ, weights[succ])); } } + Collections.sort(succList); + for (WeightedNode wnode : succList) { + orderedSuccessors.add(wnode.index); + } + IntSet outerSuccessors = new IntOpenHashSet(successors.length); + succList.clear(); for (IntCursor loopNode : loopNodes) { for (int succ : graph.outgoingEdges(loopNode.value)) { if (!loopNodes.contains(succ)) { - outerSuccessors.add(succ); + if (outerSuccessors.add(succ)) { + succList.add(new WeightedNode(succ, weights[succ])); + } } } } - orderedSuccessors.addAll(outerSuccessors.toArray()); - successors = orderedSuccessors.getAll(); + Collections.sort(succList); + for (WeightedNode wnode : succList) { + orderedSuccessors.add(wnode.index); + } + } else { + for (int succ : successors) { + succList.add(new WeightedNode(succ, weights[succ])); + } + Collections.sort(succList); + for (WeightedNode wnode : succList) { + orderedSuccessors.add(wnode.index); + } } + successors = orderedSuccessors.getAll(); for (int succ : successors) { if (state[succ] == NONE) { stack.push(succ); @@ -152,4 +206,19 @@ public class GraphIndexer { public Graph getGraph() { return graph; } + + static class WeightedNode implements Comparable { + int index; + int weight; + + public WeightedNode(int index, int weight) { + this.index = index; + this.weight = weight; + } + + @Override + public int compareTo(WeightedNode o) { + return Integer.compare(weight, o.weight); + } + } } diff --git a/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java b/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java index d3d16f0d0..31a430daa 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java @@ -246,7 +246,11 @@ public class Decompiler { AsyncMethodPart result = new AsyncMethodPart(); lastBlockId = 1; graph = ProgramUtils.buildControlFlowGraph(program); - indexer = new GraphIndexer(graph); + int[] weights = new int[graph.size()]; + for (int i = 0; i < weights.length; ++i) { + weights[i] = program.basicBlockAt(i).getInstructions().size(); + } + indexer = new GraphIndexer(graph, weights); graph = indexer.getGraph(); loopGraph = new LoopGraph(this.graph); unflatCode();