src/share/classes/com/sun/tools/javac/util/GraphUtils.java

changeset 3080
75296d8d5125
parent 2047
5f915a0c9615
child 3295
859dc787b52b
     1.1 --- a/src/share/classes/com/sun/tools/javac/util/GraphUtils.java	Mon Jan 25 08:48:11 2016 +0000
     1.2 +++ b/src/share/classes/com/sun/tools/javac/util/GraphUtils.java	Tue Jan 26 21:08:18 2016 +0000
     1.3 @@ -103,34 +103,60 @@
     1.4       * directed graph in linear time. Works on TarjanNode.
     1.5       */
     1.6      public static <D, N extends TarjanNode<D>> List<? extends List<? extends N>> tarjan(Iterable<? extends N> nodes) {
     1.7 -        ListBuffer<List<N>> cycles = new ListBuffer<>();
     1.8 +        Tarjan<D, N> tarjan = new Tarjan<>();
     1.9 +        return tarjan.findSCC(nodes);
    1.10 +    }
    1.11 +
    1.12 +    //where
    1.13 +    private static class Tarjan<D, N extends TarjanNode<D>> {
    1.14 +
    1.15 +        /** Unique node identifier. */
    1.16 +        int index = 0;
    1.17 +
    1.18 +        /** List of SCCs found so far. */
    1.19 +        ListBuffer<List<N>> sccs = new ListBuffer<>();
    1.20 +
    1.21 +        /** Stack of all reacheable nodes from given root. */
    1.22          ListBuffer<N> stack = new ListBuffer<>();
    1.23 -        int index = 0;
    1.24 -        for (N node: nodes) {
    1.25 -            if (node.index == -1) {
    1.26 -                index += tarjan(node, index, stack, cycles);
    1.27 +
    1.28 +        private List<? extends List<? extends N>> findSCC(Iterable<? extends N> nodes) {
    1.29 +            for (N node : nodes) {
    1.30 +                if (node.index == -1) {
    1.31 +                    findSCC(node);
    1.32 +                }
    1.33 +            }
    1.34 +            return sccs.toList();
    1.35 +        }
    1.36 +
    1.37 +        private void findSCC(N v) {
    1.38 +            visitNode(v);
    1.39 +            for (TarjanNode<D> tn : v.getAllDependencies()) {
    1.40 +                @SuppressWarnings("unchecked")
    1.41 +                N n = (N)tn;
    1.42 +                if (n.index == -1) {
    1.43 +                    //it's the first time we see this node
    1.44 +                    findSCC(n);
    1.45 +                    v.lowlink = Math.min(v.lowlink, n.lowlink);
    1.46 +                } else if (stack.contains(n)) {
    1.47 +                    //this node is already reachable from current root
    1.48 +                    v.lowlink = Math.min(v.lowlink, n.index);
    1.49 +                }
    1.50 +            }
    1.51 +            if (v.lowlink == v.index) {
    1.52 +                //v is the root of a SCC
    1.53 +                addSCC(v);
    1.54              }
    1.55          }
    1.56 -        return cycles.toList();
    1.57 -    }
    1.58  
    1.59 -    private static <D, N extends TarjanNode<D>> int tarjan(N v, int index, ListBuffer<N> stack, ListBuffer<List<N>> cycles) {
    1.60 -        v.index = index;
    1.61 -        v.lowlink = index;
    1.62 -        index++;
    1.63 -        stack.prepend(v);
    1.64 -        v.active = true;
    1.65 -        for (TarjanNode<D> nd: v.getAllDependencies()) {
    1.66 -            @SuppressWarnings("unchecked")
    1.67 -            N n = (N)nd;
    1.68 -            if (n.index == -1) {
    1.69 -                tarjan(n, index, stack, cycles);
    1.70 -                v.lowlink = Math.min(v.lowlink, n.lowlink);
    1.71 -            } else if (stack.contains(n)) {
    1.72 -                v.lowlink = Math.min(v.lowlink, n.index);
    1.73 -            }
    1.74 +        private void visitNode(N n) {
    1.75 +            n.index = index;
    1.76 +            n.lowlink = index;
    1.77 +            index++;
    1.78 +            stack.prepend(n);
    1.79 +            n.active = true;
    1.80          }
    1.81 -        if (v.lowlink == v.index) {
    1.82 +
    1.83 +        private void addSCC(N v) {
    1.84              N n;
    1.85              ListBuffer<N> cycle = new ListBuffer<>();
    1.86              do {
    1.87 @@ -138,9 +164,8 @@
    1.88                  n.active = false;
    1.89                  cycle.add(n);
    1.90              } while (n != v);
    1.91 -            cycles.add(cycle.toList());
    1.92 +            sccs.add(cycle.toList());
    1.93          }
    1.94 -        return index;
    1.95      }
    1.96  
    1.97      /**

mercurial