diff --git a/teavm-core/src/main/java/org/teavm/common/DJGraph.java b/teavm-core/src/main/java/org/teavm/common/DJGraph.java new file mode 100644 index 000000000..0ece52948 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/common/DJGraph.java @@ -0,0 +1,89 @@ +/* + * Copyright 2015 Alexey Andreev. + * + * 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 org.teavm.common; + +/** + * + * @author Alexey Andreev + */ +public class DJGraph { + private DominatorTree domTree; + private Graph graph; + private Graph backEdges; + + public DJGraph(Graph src) { + domTree = GraphUtils.buildDominatorTree(src); + buildGraph(src); + dfs(); + } + + private void buildGraph(Graph graph) { + GraphBuilder builder = new GraphBuilder(graph.size()); + for (int i = 0; i < graph.size(); ++i) { + for (int j : graph.outgoingEdges(i)) { + builder.addEdge(i, j); + } + } + for (int i = 1; i < graph.size(); ++i) { + int j = domTree.immediateDominatorOf(i); + boolean needsDomEdge = true; + for (int k : graph.incomingEdges(i)) { + if (k == j) { + needsDomEdge = false; + break; + } + } + if (needsDomEdge) { + builder.addEdge(j, i); + } + } + graph = builder.build(); + } + + private void dfs() { + GraphBuilder builder = new GraphBuilder(); + boolean[] visited = new boolean[graph.size()]; + IntegerStack stack = new IntegerStack(graph.size() * 2); + stack.push(0); + stack.push(-1); + while (!stack.isEmpty()) { + int node = stack.pop(); + int source = stack.pop(); + if (visited[node]) { + builder.addEdge(node, source); + continue; + } + visited[node] = true; + for (int succ : graph.outgoingEdges(node)) { + stack.push(node); + stack.push(succ); + } + } + backEdges = builder.build(); + } + + public DominatorTree getDomTree() { + return domTree; + } + + public Graph getGraph() { + return graph; + } + + public int[] getSpanningTreeBackEdges(int node) { + return backEdges.outgoingEdges(node); + } +} diff --git a/teavm-core/src/main/java/org/teavm/model/util/IrreducibleGraphConverter.java b/teavm-core/src/main/java/org/teavm/model/util/IrreducibleGraphConverter.java new file mode 100644 index 000000000..8f9190aa9 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/model/util/IrreducibleGraphConverter.java @@ -0,0 +1,47 @@ +/* + * Copyright 2015 Alexey Andreev. + * + * 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 org.teavm.model.util; + +import java.util.ArrayList; +import java.util.List; +import org.teavm.common.DisjointSet; +import org.teavm.common.Graph; +import org.teavm.common.MutableGraphNode; + +/** + * + * @author Alexey Andreev + */ +public class IrreducibleGraphConverter { + List nodes = new ArrayList<>(); + DisjointSet nodeClasses = new DisjointSet(); + + public void convertToReducible(Graph graph) { + buildMutableCFG(graph); + } + + private void buildMutableCFG(Graph graph) { + nodes.clear(); + for (int i = 0; i < graph.size(); ++i) { + nodes.add(new MutableGraphNode(i)); + } + for (int i = 0; i < graph.size(); ++i) { + for (int j : graph.outgoingEdges(i)) { + nodes.get(i).connect(nodes.get(j)); + } + } + } +}