anchor.diff:  
     DumpInfoStateData();
   }
  +
  +class LocalFunctionInfo {
  +  final ir.LocalFunction localFunction;
  +  final List<ir.TreeNode> hierarchy;
  +  final String name;
  +  bool isInvoked = false;
  +
  +  LocalFunctionInfo._(this.localFunction, this.hierarchy, this.name);
  +
  +  factory LocalFunctionInfo(ir.LocalFunction localFunction) {
  +    String name = '';
  +    ir.TreeNode node = localFunction;
  +    final hierarchy = <ir.TreeNode>[];
  +    bool inClosure = false;
  +    while (node != null) {
  +      // Only consider nodes used for resolving a closure's full name.
  +      if (node is ir.FunctionDeclaration) {
  +        hierarchy.add(node);
  +        name = '_${node.variable.name}' + name;
  +        inClosure = false;
  +      } else if (node is ir.FunctionExpression) {
  +        hierarchy.add(node);
  +        name = (inClosure ? '_' : '_closure') + name;
  +        inClosure = true;
  +      } else if (node is ir.Member) {
  +        hierarchy.add(node);
  +        var cleanName = node.toStringInternal();
  +        if (cleanName.endsWith('.'))
  +          cleanName = cleanName.substring(0, cleanName.length - 1);
  +        final isFactory = node is ir.Procedure && node.isFactory;
  +        if (isFactory) {
  +          cleanName = cleanName.replaceAll('.', '\$');
  +          cleanName = '${node.enclosingClass.toStringInternal()}_' + cleanName;
  +        } else {
  +          cleanName = cleanName.replaceAll('.', '_');
  +        }
  +        name = cleanName + name;
  +        inClosure = false;
  +      }
  +      node = node.parent;
  +    }
  +
  +    return LocalFunctionInfo._(localFunction, hierarchy, name);
  +  }
  +}
  +
  +class LocalFunctionInfoCollector extends ir.RecursiveVisitor<void> {
  +  final localFunctions = <ir.LocalFunction, LocalFunctionInfo>{};
  +
  +  @override
  +  void visitFunctionExpression(ir.FunctionExpression node) {
  +    assert(localFunctions[node] == null);
  +    localFunctions[node] = LocalFunctionInfo(node);
  +    defaultExpression(node);
  +  }
  +
  +  @override
  +  void visitFunctionDeclaration(ir.FunctionDeclaration node) {
  +    assert(localFunctions[node] == null);
  +    localFunctions[node] = LocalFunctionInfo(node);
  +    defaultStatement(node);
  +  }
  +
  +  @override
  +  void visitLocalFunctionInvocation(ir.LocalFunctionInvocation node) {
  +    if (localFunctions[node.localFunction] == null)
  +      visitFunctionDeclaration(node.localFunction);
  +    localFunctions[node.localFunction].isInvoked = true;
  +  }
  +}
  
positive.code:   }
  
    ClosureInfo visitClosureClass(ClassEntity element) {
      ClosureInfo closureInfo = ClosureInfo(
          name: element.name,
          outputUnit: _unitInfoForClass(element),
          size: dumpInfoTask.sizeOf(element));
      kernelInfo.state.entityToInfo[element] = closureInfo;
  
      FunctionEntity callMethod = closedWorld.elementEnvironment
          .lookupClassMember(element, Identifiers.call);
  
      FunctionInfo functionInfo = visitFunction(callMethod, element.name);
      if (functionInfo == null) return null;
  
      closureInfo.function = functionInfo;
      functionInfo.parent = closureInfo;
      closureInfo.treeShakenStatus = TreeShakenStatus.Live;
  
      kernelInfo.state.info.closures.add(closureInfo);
      return closureInfo;
    }
  
    // TODO(markzipan): [parentName] is used for disambiguation, but this might
  
negative.code:   int _addClosureInfo(BasicInfo info, MemberEntity member) {
      assert(info is FunctionInfo || info is FieldInfo);
      int size = 0;
      environment.forEachNestedClosure(member, (closure) {
        ClosureInfo closureInfo = visitClosureClass(closure.enclosingClass);
        if (closureInfo != null) {
          closureInfo.treeShakenStatus = TreeShakenStatus.Live;
          size += closureInfo.size;
        }
      });
      return size;
    }
  
  