anchor.diff:      _preds = preds;
     }
   
  -  // "A Simple, Fast Dominance Algorithm"
  -  // Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy
  +  static int _eval(int v,
  +                   Uint32List ancestor,
  +                   Uint32List semi,
  +                   Uint32List label,
  +                   Uint32List stackNode,
  +                   Uint8List stackState) {
  +    if (ancestor[v] == 0) {
  +      return label[v];
  +    } else {
  +      {
  +        // Inlined 'compress' with an explicit stack to prevent JS stack
  +        // overflow.
  +        var top = 0;
  +        stackNode[top] = v;
  +        stackState[top] = 0;
  +        while (top >= 0) {
  +          var v = stackNode[top];
  +          var state = stackState[top];
  +          if (state == 0) {
  +            assert(ancestor[v] != 0);
  +            if (ancestor[ancestor[v]] != 0) {
  +              stackState[top] = 1;
  +              // Recurse with ancestor[v]
  +              top++;
  +              stackNode[top] = ancestor[v];
  +              stackState[top] = 0;
  +            } else {
  +              top--;
  +            }
  +          } else {
  +            assert(state == 1);
  +            if (semi[label[ancestor[v]]] < semi[label[v]]) {
  +              label[v] = label[ancestor[v]];
  +            }
  +            ancestor[v] = ancestor[ancestor[v]];
  +            top--;
  +          }
  +        }
  +      }
  +
  +      if (semi[label[ancestor[v]]] >= semi[label[v]]) {
  +        return label[v];
  +      } else {
  +        return label[ancestor[v]];
  +      }
  +    }
  +  }
  +
  +  // Note the version in the main text of Lengauer & Tarjan incorrectly
  +  // uses parent instead of ancestor. The correct version is in Appendix B.
  +  static void _link(int v,
  +                    int w,
  +                    Uint32List size,
  +                    Uint32List label,
  +                    Uint32List semi,
  +                    Uint32List child,
  +                    Uint32List ancestor) {
  +    assert(size[0] == 0);
  +    assert(label[0] == 0);
  +    assert(semi[0] == 0);
  +    var s = w;
  +    while (semi[label[w]] < semi[label[child[s]]]) {
  +      if (size[s] + size[child[child[s]]] >= 2 * size[child[s]]) {
  +        ancestor[child[s]] = s;
  +        child[s] = child[child[s]];
  +      } else {
  +        size[child[s]] = size[s];
  +        s = ancestor[s] = child[s];
  +      }
  +    }
  +    label[s] = label[w];
  +    size[v] = size[v] + size[w];
  +    if (size[v] < 2 * size[w]) {
  +      var tmp = s;
  +      s = child[v];
  +      child[v] = tmp;
  +    }
  +    while (s != 0) {
  +      ancestor[s] = v;
  +      s = child[s];
  +    }
  +  }
  +
  +  // T. Lengauer and R. E. Tarjan. "A Fast Algorithm for Finding Dominators
  +  // in a Flowgraph."
     void _buildDominators() {
       var N = _N;
   
  -    var postOrder = _postOrderOrdinals;
  -    var postOrderIndex = _postOrderIndices;
  +    var vertex = _vertex;
  +    var semi = _semi;
  +    var parent = _parent;
       var firstPreds = _firstPreds;
       var preds = _preds;
   
       var root = 1;
  -    var rootPostOrderIndex = postOrderIndex[root];
  -    var domByPOI = new Uint32List(N + 1);
  -
  -    domByPOI[rootPostOrderIndex] = rootPostOrderIndex;
  -
  -    var iteration = 0;
  -    var changed = true;
  -    while (changed) {
  -      changed = false;
  -      Logger.root.info("Find dominators iteration $iteration");
  -      iteration++; // dart2js heaps typically converge in 10 iterations.
  -
  -      // Visit the nodes, except the root, in reverse post order (top down).
  -      for (var curPostOrderIndex = rootPostOrderIndex - 1;
  -           curPostOrderIndex > 1;
  -           curPostOrderIndex--) {
  -        if (domByPOI[curPostOrderIndex] == rootPostOrderIndex)
  -          continue;
  -
  -        var nodeOrdinal = postOrder[curPostOrderIndex];
  -        var newDomIndex = 0; // 0 = undefined
  -
  -        // Intersect the DOM sets of the node's precedessors.
  -        var beginPredIndex = firstPreds[nodeOrdinal];
  -        var endPredIndex = firstPreds[nodeOrdinal + 1];
  -        for (var predIndex = beginPredIndex;
  -             predIndex < endPredIndex;
  -             predIndex++) {
  -          var predOrdinal = preds[predIndex];
  -          var predPostOrderIndex = postOrderIndex[predOrdinal];
  -          if (domByPOI[predPostOrderIndex] != 0) {
  -            if (newDomIndex == 0) {
  -              newDomIndex = predPostOrderIndex;
  -            } else {
  -              // Note this two finger algorithm to find the DOM intersection
  -              // relies on comparing nodes by their post order index.
  -              while (predPostOrderIndex != newDomIndex) {
  -                while(predPostOrderIndex < newDomIndex)
  -                  predPostOrderIndex = domByPOI[predPostOrderIndex];
  -                while (newDomIndex < predPostOrderIndex)
  -                  newDomIndex = domByPOI[newDomIndex];
  -              }
  -            }
  -            if (newDomIndex == rootPostOrderIndex) {
  -              break;
  -            }
  -          }
  +    var dom = new Uint32List(N + 1);
  +
  +    var ancestor = new Uint32List(N + 1);
  +    var label = new Uint32List(N + 1);
  +    for (var i = 1; i <= N; i++) {
  +      label[i] = i;
  +    }
  +    var buckets = new List(N + 1);
  +    var child = new Uint32List(N + 1);
  +    var size = new Uint32List(N + 1);
  +    for (var i = 1; i <= N; i++) {
  +      size[i] = 1;
  +    }
  +    var stackNode = new Uint32List(N + 1);
  +    var stackState = new Uint8List(N + 1);
  +
  +    for (var i = N; i > 1; i--) {
  +      var w = vertex[i];
  +      assert(w != root);
  +
  +      // Lengauer & Tarjan Step 2.
  +      var startPred = firstPreds[w];
  +      var limitPred = firstPreds[w + 1];
  +      for (var predIndex = startPred;
  +           predIndex < limitPred;
  +           predIndex++) {
  +        var v = preds[predIndex];
  +        var u = _eval(v, ancestor, semi, label, stackNode, stackState);
  +        if (semi[u] < semi[w]) {
  +          semi[w] = semi[u];
           }
  -        if (newDomIndex != 0 && domByPOI[curPostOrderIndex] != newDomIndex) {
  -          domByPOI[curPostOrderIndex] = newDomIndex;
  -          changed = true;
  +      }
  +
  +      // w.semi.bucket.add(w);
  +      var tmp = vertex[semi[w]];
  +      if (buckets[tmp] == null) {
  +        buckets[tmp] = new List();
  +      }
  +      buckets[tmp].add(w);
  +
  +      _link(parent[w], w, size, label, semi, child, ancestor);
  +
  +      // Lengauer & Tarjan Step 3.
  +      tmp = parent[w];
  +      var bucket = buckets[tmp];
  +      buckets[tmp] = null;
  +      if (bucket != null) {
  +        for (var v in bucket) {
  +          var u = _eval(v, ancestor, semi, label, stackNode, stackState);
  +          dom[v] = semi[u] < semi[v] ? u : parent[w];
           }
         }
       }
  -
  -    Logger.root.info("Start remap dominators");
  -
  -    // Reindex doms by id instead of post order index so we can throw away
  -    // the post order arrays.
  -    var domById = new Uint32List(N + 1);
  -    for (var id = 1; id <= N; id++) {
  -      domById[id] = postOrder[domByPOI[postOrderIndex[id]]];
  -    }
  -
  -    Logger.root.info("End remap dominators");
  -
  -    domById[root] = 0;
  -
  -    _doms = domById;
  +    for (var i = 1; i <= N; i++) {
  +      assert(buckets[i] == null);
  +    }
  +    // Lengauer & Tarjan Step 4.
  +    for (var i = 2; i <= N; i++) {
  +      var w = vertex[i];
  +      if (dom[w] != vertex[semi[w]]) {
  +        dom[w] = dom[dom[w]];
  +      }
  +    }
  +
  +    _doms = dom;
     }
   
     void _calculateRetainedSizes() {
  
positive.code:     _addrToId = null;
      _chunks = null;
  
      statusReporter.add("Finding post order...");
      await new Future(() => _buildPostOrder());
  
      statusReporter.add("Finding predecessors...");
      await new Future(() => _buildPredecessors());
  
negative.code: 
    // Intermediates.
    AddressMapper _addrToId;
    Uint32List _vertex;
    Uint32List _parent;
    Uint32List _semi;
    Uint32List _firstPreds; // Offset into preds.
    Uint32List _preds;
  
  