langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/GraphUtils.java
changeset 31839 e0bf9644a930
parent 25874 83c19f00452c
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/GraphUtils.java	Wed Jul 05 20:42:39 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/GraphUtils.java	Fri Jul 17 12:46:07 2015 +0100
@@ -151,32 +151,57 @@
      * directed graph in linear time. Works on TarjanNode.
      */
     public static <D, N extends TarjanNode<D, N>> List<? extends List<? extends N>> tarjan(Iterable<? extends N> nodes) {
-        ListBuffer<List<N>> cycles = new ListBuffer<>();
-        ListBuffer<N> stack = new ListBuffer<>();
+        Tarjan<D, N> tarjan = new Tarjan<>();
+        return tarjan.findSCC(nodes);
+    }
+    //where
+    private static class Tarjan<D, N extends TarjanNode<D, N>> {
+
+        /** Unique node identifier. */
         int index = 0;
-        for (N node: nodes) {
-            if (node.index == -1) {
-                index += tarjan(node, index, stack, cycles);
+
+        /** List of SCCs found fso far. */
+        ListBuffer<List<N>> sccs = new ListBuffer<>();
+
+        /** Stack of all reacheable nodes from given root. */
+        ListBuffer<N> stack = new ListBuffer<>();
+
+        private List<? extends List<? extends N>> findSCC(Iterable<? extends N> nodes) {
+            for (N node : nodes) {
+                if (node.index == -1) {
+                    findSCC(node);
+                }
+            }
+            return sccs.toList();
+        }
+
+        private void findSCC(N v) {
+            visitNode(v);
+            for (N n: v.getAllDependencies()) {
+                if (n.index == -1) {
+                    //it's the first time we see this node
+                    findSCC(n);
+                    v.lowlink = Math.min(v.lowlink, n.lowlink);
+                } else if (stack.contains(n)) {
+                    //this node is already reachable from current root
+                    v.lowlink = Math.min(v.lowlink, n.index);
+                }
+            }
+            if (v.lowlink == v.index) {
+                //v is the root of a SCC
+                addSCC(v);
             }
         }
-        return cycles.toList();
-    }
 
-    private static <D, N extends TarjanNode<D, N>> int tarjan(N v, int index, ListBuffer<N> stack, ListBuffer<List<N>> cycles) {
-        v.index = index;
-        v.lowlink = index;
-        index++;
-        stack.prepend(v);
-        v.active = true;
-        for (N n: v.getAllDependencies()) {
-            if (n.index == -1) {
-                tarjan(n, index, stack, cycles);
-                v.lowlink = Math.min(v.lowlink, n.lowlink);
-            } else if (stack.contains(n)) {
-                v.lowlink = Math.min(v.lowlink, n.index);
-            }
+        private void visitNode(N n) {
+            n.index = index;
+            n.lowlink = index;
+            index++;
+            stack.prepend(n);
+            n.active = true;
         }
-        if (v.lowlink == v.index) {
+
+        private void addSCC(N v) {
             N n;
             ListBuffer<N> cycle = new ListBuffer<>();
             do {
@@ -184,9 +209,8 @@
                 n.active = false;
                 cycle.add(n);
             } while (n != v);
-            cycles.add(cycle.toList());
+            sccs.add(cycle.toList());
         }
-        return index;
     }
 
     /**