| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library dominator_tree; | |
| 6 | |
| 7 // Flowgraph dominators in O(m log n) time. Implements the algorithm from | |
| 8 // [Lengauer & Tarjan 1979] | |
| 9 // T. Lengauer and R.E. Tarjan, | |
| 10 // "A fast algorithm for finding dominators in a flowgraph", | |
| 11 // ACM Transactions on Programming Language and Systems, 1(1):121-141, 1979. | |
| 12 | |
| 13 // Internal vertex information used inside 'Dominator'. | |
| 14 // Field names mostly follow naming in [Lengauer & Tarjan 1979]. | |
| 15 class _Vertex { | |
| 16 final Object id; | |
| 17 _Vertex dom; | |
| 18 _Vertex parent; | |
| 19 _Vertex ancestor; | |
| 20 _Vertex label; | |
| 21 int semi; | |
| 22 final List<_Vertex> pred = new List<_Vertex>(); | |
| 23 final List<_Vertex> bucket = new List<_Vertex>(); | |
| 24 // TODO(koda): Avoid duplication by having an interface for 'id' with | |
| 25 // access to outgoing edges, and/or clearing 'succ' after constructing | |
| 26 // inverse graph in 'pred'. | |
| 27 final List<_Vertex> succ = new List<_Vertex>(); | |
| 28 _Vertex(this.id) { label = this; } | |
| 29 } | |
| 30 | |
| 31 // Utility to compute immediate dominators. Usage: | |
| 32 // 1. Build the flowgraph using 'addEdges'. | |
| 33 // 2. Call 'computeDominatorTree' once. | |
| 34 // 3. Use 'dominator' to access result. | |
| 35 // The instance can only be used once. | |
| 36 class Dominator { | |
| 37 final Map<Object, _Vertex> _idToVertex = new Map<Object, _Vertex>(); | |
| 38 final List<_Vertex> _vertex = new List<_Vertex>(); | |
| 39 | |
| 40 void addEdges(Object u, Iterable<Object> vs) { | |
| 41 _asVertex(u).succ.addAll(vs.map(_asVertex)); | |
| 42 } | |
| 43 | |
| 44 // Returns the immediate dominator of 'v', or null if 'v' is the root. | |
| 45 Object dominator(Object v) { | |
| 46 _Vertex dom = _asVertex(v).dom; | |
| 47 return dom == null ? null : dom.id; | |
| 48 } | |
| 49 | |
| 50 _Vertex _asVertex(Object u) { | |
| 51 return _idToVertex.putIfAbsent(u, () => new _Vertex(u)); | |
| 52 } | |
| 53 | |
| 54 void _dfs(_Vertex v) { | |
| 55 v.semi = _vertex.length; | |
| 56 _vertex.add(v); | |
| 57 for (_Vertex w in v.succ) { | |
| 58 if (w.semi == null) { | |
| 59 w.parent = v; | |
| 60 _dfs(w); | |
| 61 } | |
| 62 w.pred.add(v); | |
| 63 } | |
| 64 } | |
| 65 | |
| 66 void _compress(_Vertex v) { | |
| 67 if (v.ancestor.ancestor != null) { | |
| 68 _compress(v.ancestor); | |
| 69 if (v.ancestor.label.semi < v.label.semi) { | |
| 70 v.label = v.ancestor.label; | |
| 71 } | |
| 72 v.ancestor = v.ancestor.ancestor; | |
| 73 } | |
| 74 } | |
| 75 | |
| 76 _Vertex _eval(_Vertex v) { | |
| 77 if (v.ancestor == null) { | |
| 78 return v; | |
| 79 } else { | |
| 80 _compress(v); | |
| 81 return v.label; | |
| 82 } | |
| 83 } | |
| 84 | |
| 85 void _link(_Vertex v, _Vertex w) { | |
| 86 w.ancestor = v; | |
| 87 } | |
| 88 | |
| 89 void computeDominatorTree(Object root) { | |
| 90 _Vertex r = _asVertex(root); | |
| 91 int n = _idToVertex.length; | |
| 92 _dfs(r); | |
| 93 if (_vertex.length != n) { | |
| 94 throw new StateError("Not a flowgraph: " | |
| 95 "only ${_vertex.length} of $n vertices reachable"); | |
| 96 } | |
| 97 for (int i = n - 1; i >= 1; --i) { | |
| 98 _Vertex w = _vertex[i]; | |
| 99 for (_Vertex v in w.pred) { | |
| 100 _Vertex u = _eval(v); | |
| 101 if (u.semi < w.semi) { | |
| 102 w.semi = u.semi; | |
| 103 } | |
| 104 } | |
| 105 _vertex[w.semi].bucket.add(w); | |
| 106 _link(w.parent, w); | |
| 107 for (_Vertex v in w.parent.bucket) { | |
| 108 _Vertex u = _eval(v); | |
| 109 v.dom = u.semi < v.semi ? u : w.parent; | |
| 110 } | |
| 111 w.parent.bucket.clear(); | |
| 112 } | |
| 113 for (int i = 1; i < n; ++i) { | |
| 114 _Vertex w = _vertex[i]; | |
| 115 if (w.dom != _vertex[w.semi]) { | |
| 116 w.dom = w.dom.dom; | |
| 117 } | |
| 118 } | |
| 119 r.dom = null; | |
| 120 } | |
| 121 } | |
| OLD | NEW |