From 8896ccd3857222368ad890c04a0a0c01a77067ea Mon Sep 17 00:00:00 2001 From: Sigmund Cherem Date: Tue, 18 Aug 2015 15:44:38 -0700 Subject: [PATCH] dart2js: switch to use dart2js_info/info.dart R=het@google.com Review URL: https://codereview.chromium.org//1298553002 . --- DEPS | 3 + pkg/compiler/lib/src/dump_info.dart | 3 +- pkg/compiler/lib/src/info/info.dart | 745 ------------------ pkg/compiler/pubspec.yaml | 7 +- pkg/compiler/tool/code_deps.dart | 105 --- pkg/compiler/tool/coverage_log_server.dart | 190 ----- pkg/compiler/tool/graph.dart | 292 ------- pkg/compiler/tool/library_size_split.dart | 132 ---- pkg/compiler/tool/util.dart | 96 --- .../dart2js/analyze_unused_dart2js_test.dart | 3 - tools/deps/dartium.deps/DEPS | 3 + 11 files changed, 10 insertions(+), 1569 deletions(-) delete mode 100644 pkg/compiler/lib/src/info/info.dart delete mode 100644 pkg/compiler/tool/code_deps.dart delete mode 100644 pkg/compiler/tool/coverage_log_server.dart delete mode 100644 pkg/compiler/tool/graph.dart delete mode 100644 pkg/compiler/tool/library_size_split.dart delete mode 100644 pkg/compiler/tool/util.dart diff --git a/DEPS b/DEPS index a9d036dc1fb..e3e0fd2d2b8 100644 --- a/DEPS +++ b/DEPS @@ -49,6 +49,7 @@ vars = { "collection_rev": "@1da9a07f32efa2ba0c391b289e2037391e31da0e", "crypto_rev" : "@2df57a1e26dd88e8d0614207d4b062c73209917d", "csslib_tag" : "@0.12.0", + "dart2js_info_rev" : "@5902be71c24bbda96675f646ba7d3ff911d26eae", "dartdoc_tag" : "@v0.5.0", "dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97", "dart_style_tag": "@0.2.0", @@ -195,6 +196,8 @@ deps = { (Var("github_mirror") % "csslib") + Var("csslib_tag"), Var("dart_root") + "/third_party/pkg_tested/dart_style": (Var("github_mirror") % "dart_style") + Var("dart_style_tag"), + Var("dart_root") + "/third_party/pkg/dart2js_info": + (Var("github_mirror") % "dart2js_info") + Var("dart2js_info_rev"), Var("dart_root") + "/third_party/pkg/dartdoc": (Var("github_mirror") % "dartdoc") + Var("dartdoc_tag"), Var("dart_root") + "/third_party/pkg/dev_compiler": diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart index 5ea735862a3..2f4a30403d4 100644 --- a/pkg/compiler/lib/src/dump_info.dart +++ b/pkg/compiler/lib/src/dump_info.dart @@ -7,6 +7,8 @@ library dump_info; import 'dart:convert' show HtmlEscape, JsonEncoder, StringConversionSink, ChunkedConversionSink; +import 'package:dart2js_info/info.dart'; + import 'common/tasks.dart' show CompilerTask; import 'compiler.dart' show @@ -21,7 +23,6 @@ import 'types/types.dart' show TypeMask; import 'deferred_load.dart' show OutputUnit; -import 'info/info.dart'; import 'js_backend/js_backend.dart' show JavaScriptBackend; import 'js_emitter/full_emitter/emitter.dart' as full show diff --git a/pkg/compiler/lib/src/info/info.dart b/pkg/compiler/lib/src/info/info.dart deleted file mode 100644 index 6a6f747ef79..00000000000 --- a/pkg/compiler/lib/src/info/info.dart +++ /dev/null @@ -1,745 +0,0 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/// Data collected by the dump-info task. -library compiler.src.lib.info; - -// Note: this file intentionally doesn't import anything from the compiler. That -// should make it easier for tools to depend on this library. The idea is that -// by using this library, tools can consume the information in the same way it -// is produced by the compiler. -// TODO(sigmund): make this a proper public API (export this explicitly at the -// lib folder level.) - -/// Common interface to many pieces of information generated by the compiler. -abstract class Info { - /// An identifier for the kind of information. - InfoKind get kind; - - /// Name of the element associated with this info. - String name; - - /// An id to uniquely identify this info among infos of the same [kind]. - int get id; - - /// A globally unique id combining [kind] and [id] together. - String get serializedId; - - /// Id used by the compiler when instrumenting code for code coverage. - // TODO(sigmund): It would be nice if we could use the same id for - // serialization and for coverage. Could we unify them? - String coverageId; - - /// Bytes used in the generated code for the corresponding element. - int size; - - /// Info of the enclosing element. - Info parent; - - /// Serializes the information into a JSON format. - // TODO(sigmund): refactor and put toJson outside the class, so we can have 2 - // different serializer/deserializers at once. - Map toJson(); - - void accept(InfoVisitor visitor); -} - -/// Common information used for most kind of elements. -// TODO(sigmund): add more: -// - inputSize: bytes used in the Dart source program -abstract class BasicInfo implements Info { - final InfoKind kind; - final int id; - String coverageId; - int size; - Info parent; - - String get serializedId => '${_kindToString(kind)}/$id'; - - String name; - - /// If using deferred libraries, where the element associated with this info - /// is generated. - OutputUnitInfo outputUnit; - - BasicInfo(this.kind, this.id, this.name, this.outputUnit, this.size, - this.coverageId); - - BasicInfo._fromId(String serializedId) - : kind = _kindFromSerializedId(serializedId), - id = _idFromSerializedId(serializedId); - - Map toJson() { - var res = { - 'id': serializedId, - 'kind': _kindToString(kind), - 'name': name, - 'size': size, - }; - // TODO(sigmund): Omit this also when outputUnit.id == 0 (most code is in - // the main output unit by default). - if (outputUnit != null) res['outputUnit'] = outputUnit.serializedId; - if (coverageId != null) res['coverageId'] = coverageId; - if (parent != null) res['parent'] = parent.serializedId; - return res; - } - - String toString() => '$serializedId $name [$size]'; -} - -/// Info associated with elements containing executable code (like fields and -/// methods) -abstract class CodeInfo implements Info { - /// How does this function or field depend on others. - final List uses = []; -} - - -/// The entire information produced while compiling a program. -class AllInfo { - /// Summary information about the program. - ProgramInfo program; - - /// Information about each library processed by the compiler. - List libraries = []; - - /// Information about each function (includes methods and getters in any - /// library) - List functions = []; - - /// Information about type defs in the program. - List typedefs = []; - - /// Information about each class (in any library). - List classes = []; - - /// Information about fields (in any class). - List fields = []; - - /// Information about output units (should be just one entry if not using - /// deferred loading). - List outputUnits = []; - - /// Details about all deferred imports and what files would be loaded when the - /// import is resolved. - // TODO(sigmund): use a different format for dump-info. This currently emits - // the same map that is created for the `--deferred-map` flag. - Map> deferredFiles; - - /// A new representation of dependencies form one info to another. An entry in - /// this map indicates that an Info depends on another (e.g. a function - /// invokes another). Please note that the data in this field might not be - /// accurate yet (this is work in progress). - Map> dependencies = {}; - - /// Major version indicating breaking changes in the format. A new version - /// means that an old deserialization algorithm will not work with the new - /// format. - final int version = 3; - - /// Minor version indicating non-breaking changes in the format. A change in - /// this version number means that the json parsing in this library from a - /// previous will continue to work after the change. This is typically - /// increased when adding new entries to the file format. - // Note: the dump-info.viewer app was written using a json parser version 3.2. - final int minorVersion = 5; - - AllInfo(); - - static AllInfo parseFromJson(Map map) => new _ParseHelper().parseAll(map); - - Map _listAsJsonMap(List list) { - var map = {}; - for (var info in list) { - map['${info.id}'] = info.toJson(); - } - return map; - } - - Map _extractHoldingInfo() { - var map = {}; - void helper(CodeInfo info) { - if (info.uses.isEmpty) return; - map[info.serializedId] = info.uses.map((u) => u.toJson()).toList(); - } - functions.forEach(helper); - fields.forEach(helper); - return map; - } - - Map _extractDependencies() { - var map = {}; - dependencies.forEach((k, v) { - map[k.serializedId] = v.map((i) => i.serializedId).toList(); - }); - return map; - } - - Map toJson() => { - 'elements': { - 'library': _listAsJsonMap(libraries), - 'class': _listAsJsonMap(classes), - 'function': _listAsJsonMap(functions), - 'typedef': _listAsJsonMap(typedefs), - 'field': _listAsJsonMap(fields), - }, - 'holding': _extractHoldingInfo(), - 'dependencies': _extractDependencies(), - 'outputUnits': outputUnits.map((u) => u.toJson()).toList(), - 'dump_version': version, - 'deferredFiles': deferredFiles, - 'dump_minor_version': '$minorVersion', - // TODO(sigmund): change viewer to accept an int? - 'program': program.toJson(), - }; - - void accept(InfoVisitor visitor) => visitor.visitAll(this); -} - -class ProgramInfo { - int size; - String dart2jsVersion; - DateTime compilationMoment; - Duration compilationDuration; - // TODO(sigmund): use Duration. - int toJsonDuration; - int dumpInfoDuration; - bool noSuchMethodEnabled; - bool minified; - - ProgramInfo( - {this.size, - this.dart2jsVersion, - this.compilationMoment, - this.compilationDuration, - this.toJsonDuration, - this.dumpInfoDuration, - this.noSuchMethodEnabled, - this.minified}); - - Map toJson() => { - 'size': size, - 'dart2jsVersion': dart2jsVersion, - 'compilationMoment': '$compilationMoment', - 'compilationDuration': '${compilationDuration}', - 'toJsonDuration': toJsonDuration, - 'dumpInfoDuration': '$dumpInfoDuration', - 'noSuchMethodEnabled': noSuchMethodEnabled, - 'minified': minified, - }; - - void accept(InfoVisitor visitor) => visitor.visitProgram(this); -} - -// TODO(sigmund): add unit tests. -class _ParseHelper { - Map registry = {}; - - AllInfo parseAll(Map json) { - var result = new AllInfo(); - var elements = json['elements']; - result.libraries.addAll(elements['library'].values.map(parseLibrary)); - result.classes.addAll(elements['class'].values.map(parseClass)); - result.functions.addAll(elements['function'].values.map(parseFunction)); - result.fields.addAll(elements['field'].values.map(parseField)); - result.typedefs.addAll(elements['typedef'].values.map(parseTypedef)); - - var idMap = {}; - for (var f in result.functions) { - idMap[f.serializedId] = f; - } - for (var f in result.fields) { - idMap[f.serializedId] = f; - } - - json['holding'].forEach((k, deps) { - var src = idMap[k]; - assert (src != null); - for (var dep in deps) { - var target = idMap[dep['id']]; - assert (target != null); - src.uses.add(new DependencyInfo(target, dep['mask'])); - } - }); - - json['dependencies']?.forEach((k, deps) { - result.dependencies[idMap[k]] = deps.map((d) => idMap[d]).toList(); - }); - - result.program = parseProgram(json['program']); - // todo: version, etc - return result; - } - - LibraryInfo parseLibrary(Map json) { - LibraryInfo result = parseId(json['id']); - result..name = json['name'] - ..uri = Uri.parse(json['canonicalUri']) - ..outputUnit = parseId(json['outputUnit']) - ..size = json['size']; - for (var child in json['children'].map(parseId)) { - if (child is FunctionInfo) { - result.topLevelFunctions.add(child); - } else if (child is FieldInfo) { - result.topLevelVariables.add(child); - } else if (child is ClassInfo) { - result.classes.add(child); - } else { - assert(child is TypedefInfo); - result.typedefs.add(child); - } - } - return result; - } - - ClassInfo parseClass(Map json) { - ClassInfo result = parseId(json['id']); - result..name = json['name'] - ..parent = parseId(json['parent']) - ..outputUnit = parseId(json['outputUnit']) - ..size = json['size'] - ..isAbstract = json['modifiers']['abstract'] == true; - assert(result is ClassInfo); - for (var child in json['children'].map(parseId)) { - if (child is FunctionInfo) { - result.functions.add(child); - } else { - assert(child is FieldInfo); - result.fields.add(child); - } - } - return result; - } - - FieldInfo parseField(Map json) { - FieldInfo result = parseId(json['id']); - return result..name = json['name'] - ..parent = parseId(json['parent']) - ..coverageId = json['coverageId'] - ..outputUnit = parseId(json['outputUnit']) - ..size = json['size'] - ..type = json['type'] - ..inferredType = json['inferredType'] - ..code = json['code'] - ..closures = json['children'].map(parseId).toList(); - } - - TypedefInfo parseTypedef(Map json) { - TypedefInfo result = parseId(json['id']); - return result..name = json['name'] - ..parent = parseId(json['parent']) - ..type = json['type'] - ..size = 0; - } - - ProgramInfo parseProgram(Map json) => - new ProgramInfo()..size = json['size']; - - FunctionInfo parseFunction(Map json) { - FunctionInfo result = parseId(json['id']); - return result..name = json['name'] - ..parent = parseId(json['parent']) - ..coverageId = json['coverageId'] - ..outputUnit = parseId(json['outputUnit']) - ..size = json['size'] - ..type = json['type'] - ..returnType = json['returnType'] - ..inferredReturnType = json['inferredReturnType'] - ..parameters = json['parameters'].map(parseParameter).toList() - ..code = json['code'] - ..sideEffects = json['sideEffects'] - ..modifiers = parseModifiers(json['modifiers']) - ..closures = json['children'].map(parseId).toList(); - } - - ParameterInfo parseParameter(Map json) => - new ParameterInfo(json['name'], json['type'], json['declaredType']); - - FunctionModifiers parseModifiers(Map json) { - return new FunctionModifiers( - isStatic: json['static'] == true, - isConst: json['const'] == true, - isFactory: json['factory'] == true, - isExternal: json['external'] == true); - } - - Info parseId(String serializedId) => registry.putIfAbsent(serializedId, () { - if (serializedId == null) { - return null; - } else if (serializedId.startsWith('function/')) { - return new FunctionInfo._(serializedId); - } else if (serializedId.startsWith('library/')) { - return new LibraryInfo._(serializedId); - } else if (serializedId.startsWith('class/')) { - return new ClassInfo._(serializedId); - } else if (serializedId.startsWith('field/')) { - return new FieldInfo._(serializedId); - } else if (serializedId.startsWith('typedef/')) { - return new TypedefInfo._(serializedId); - } else if (serializedId.startsWith('outputUnit/')) { - return new OutputUnitInfo._(serializedId); - } - assert(false); - }); -} - -/// Info associated with a library element. -class LibraryInfo extends BasicInfo { - /// Canonical uri that identifies the library. - Uri uri; - - /// Top level functions defined within the library. - final List topLevelFunctions = []; - - /// Top level fields defined within the library. - final List topLevelVariables = []; - - /// Classes defined within the library. - final List classes = []; - - /// Typedefs defined within the library. - final List typedefs = []; - - static int _id = 0; - - /// Whether there is any information recorded for this library. - bool get isEmpty => - topLevelFunctions.isEmpty && topLevelVariables.isEmpty && classes.isEmpty; - - LibraryInfo(String name, this.uri, OutputUnitInfo outputUnit, int size) - : super(InfoKind.library, _id++, name, outputUnit, size, null); - - LibraryInfo._(String serializedId) : super._fromId(serializedId); - - Map toJson() => super.toJson() - ..addAll({ - 'children': [] - ..addAll(topLevelFunctions.map((f) => f.serializedId)) - ..addAll(topLevelVariables.map((v) => v.serializedId)) - ..addAll(classes.map((c) => c.serializedId)) - ..addAll(typedefs.map((t) => t.serializedId)), - 'canonicalUri': '$uri', - }); - - void accept(InfoVisitor visitor) => visitor.visitLibrary(this); -} - -/// Information about an output unit. Normally there is just one for the entire -/// program unless the application uses deferred imports, in which case there -/// would be an additional output unit per deferred chunk. -class OutputUnitInfo extends BasicInfo { - static int _ids = 0; - OutputUnitInfo(String name, int size) - : super(InfoKind.outputUnit, _ids++, name, null, size, null); - - OutputUnitInfo._(String serializedId) : super._fromId(serializedId); - - void accept(InfoVisitor visitor) => visitor.visitOutput(this); -} - -/// Information about a class element. -class ClassInfo extends BasicInfo { - /// Whether the class is abstract. - bool isAbstract; - - // TODO(sigmund): split static vs instance vs closures - /// Functions (static or instance) defined in the class. - final List functions = []; - - /// Fields defined in the class. - // TODO(sigmund): currently appears to only be populated with instance fields, - // but this should be fixed. - final List fields = []; - static int _ids = 0; - - ClassInfo( - {String name, this.isAbstract, OutputUnitInfo outputUnit, int size: 0}) - : super(InfoKind.clazz, _ids++, name, outputUnit, size, null); - - ClassInfo._(String serializedId) : super._fromId(serializedId); - - Map toJson() => super.toJson() - ..addAll({ - // TODO(sigmund): change format, include only when abstract is true. - 'modifiers': {'abstract': isAbstract}, - 'children': [] - ..addAll(fields.map((f) => f.serializedId)) - ..addAll(functions.map((m) => m.serializedId)) - }); - - void accept(InfoVisitor visitor) => visitor.visitClass(this); -} - -/// Information about a field element. -class FieldInfo extends BasicInfo with CodeInfo { - /// The type of the field. - String type; - - /// The type inferred by dart2js's whole program analysis - String inferredType; - - /// Nested closures seen in the field initializer. - List closures; - - /// The actual generated code for the field. - String code; - - static int _ids = 0; - FieldInfo( - {String name, - String coverageId, - int size: 0, - this.type, - this.inferredType, - this.closures, - this.code, - OutputUnitInfo outputUnit}) - : super(InfoKind.field, _ids++, name, outputUnit, size, coverageId); - - FieldInfo._(String serializedId) : super._fromId(serializedId); - - Map toJson() => super.toJson() - ..addAll({ - 'children': closures.map((i) => i.serializedId).toList(), - 'inferredType': inferredType, - 'code': code, - 'type': type, - }); - - void accept(InfoVisitor visitor) => visitor.visitField(this); -} - -/// Information about a typedef declaration. -class TypedefInfo extends BasicInfo { - /// The declared type. - String type; - - static int _ids = 0; - TypedefInfo(String name, this.type, OutputUnitInfo outputUnit) - : super(InfoKind.typedef, _ids++, name, outputUnit, 0, null); - - TypedefInfo._(String serializedId) : super._fromId(serializedId); - - Map toJson() => super.toJson()..['type'] = '$type'; - - void accept(InfoVisitor visitor) => visitor.visitTypedef(this); -} - -/// Information about a function or method. -class FunctionInfo extends BasicInfo with CodeInfo { - static const int TOP_LEVEL_FUNCTION_KIND = 0; - static const int CLOSURE_FUNCTION_KIND = 1; - static const int METHOD_FUNCTION_KIND = 2; - static const int CONSTRUCTOR_FUNCTION_KIND = 3; - static int _ids = 0; - - /// Kind of function (top-level function, closure, method, or constructor). - int functionKind; - - /// Modifiers applied to this function. - FunctionModifiers modifiers; - - /// Nested closures that appear within the body of this function. - List closures; - - /// The type of this function. - String type; - - /// The declared return type. - String returnType; - - /// The inferred return type. - String inferredReturnType; - - /// Name and type information for each parameter. - List parameters; - - /// Side-effects. - // TODO(sigmund): serialize more precisely, not just a string representation. - String sideEffects; - - /// How many function calls were inlined into this function. - int inlinedCount; - - /// The actual generated code. - String code; - - FunctionInfo( - {String name, - String coverageId, - OutputUnitInfo outputUnit, - int size: 0, - this.functionKind, - this.modifiers, - this.closures, - this.type, - this.returnType, - this.inferredReturnType, - this.parameters, - this.sideEffects, - this.inlinedCount, - this.code}) - : super(InfoKind.function, _ids++, name, outputUnit, size, coverageId); - - FunctionInfo._(String serializedId) : super._fromId(serializedId); - - Map toJson() => super.toJson() - ..addAll({ - 'children': closures.map((i) => i.serializedId).toList(), - 'modifiers': modifiers.toJson(), - 'returnType': returnType, - 'inferredReturnType': inferredReturnType, - 'parameters': parameters.map((p) => p.toJson()).toList(), - 'sideEffects': sideEffects, - 'inlinedCount': inlinedCount, - 'code': code, - 'type': type, - // Note: version 3.2 of dump-info serializes `uses` in a section called - // `holding` at the top-level. - }); - - void accept(InfoVisitor visitor) => visitor.visitFunction(this); -} - -/// Information about how a dependency is used. -class DependencyInfo { - /// The dependency, either a FunctionInfo or FieldInfo. - final Info target; - - /// Either a selector mask indicating how this is used, or 'inlined'. - // TODO(sigmund): split mask into an enum or something more precise to really - // describe the dependencies in detail. - final String mask; - - DependencyInfo(this.target, this.mask); - - Map toJson() => {'id': target.serializedId, 'mask': mask}; -} - -/// Name and type information about a function parameter. -class ParameterInfo { - final String name; - final String type; - final String declaredType; - - ParameterInfo(this.name, this.type, this.declaredType); - - Map toJson() => {'name': name, 'type': type, 'declaredType': declaredType}; -} - -/// Modifiers that may apply to methods. -class FunctionModifiers { - final bool isStatic; - final bool isConst; - final bool isFactory; - final bool isExternal; - - FunctionModifiers( - {this.isStatic: false, - this.isConst: false, - this.isFactory: false, - this.isExternal: false}); - - // TODO(sigmund): exclude false values (requires bumping the format version): - // Map toJson() { - // var res = {}; - // if (isStatic) res['static'] = true; - // if (isConst) res['const'] = true; - // if (isFactory) res['factory'] = true; - // if (isExternal) res['external'] = true; - // return res; - // } - Map toJson() => { - 'static': isStatic, - 'const': isConst, - 'factory': isFactory, - 'external': isExternal, - }; -} - -/// Possible values of the `kind` field in the serialied infos. -enum InfoKind { - library, - clazz, - function, - field, - outputUnit, - typedef, -} - -String _kindToString(InfoKind kind) { - switch(kind) { - case InfoKind.library: return 'library'; - case InfoKind.clazz: return 'class'; - case InfoKind.function: return 'function'; - case InfoKind.field: return 'field'; - case InfoKind.outputUnit: return 'outputUnit'; - case InfoKind.typedef: return 'typedef'; - default: return null; - } -} - -int _idFromSerializedId(String serializedId) => - int.parse(serializedId.substring(serializedId.indexOf('/') + 1)); - -InfoKind _kindFromSerializedId(String serializedId) => - _kindFromString(serializedId.substring(0, serializedId.indexOf('/'))); - -InfoKind _kindFromString(String kind) { - switch(kind) { - case 'library': return InfoKind.library; - case 'class': return InfoKind.clazz; - case 'function': return InfoKind.function; - case 'field': return InfoKind.field; - case 'outputUnit': return InfoKind.outputUnit; - case 'typedef': return InfoKind.typedef; - default: return null; - } -} - -/// A simple visitor for information produced by the dart2js compiler. -class InfoVisitor { - visitAll(AllInfo info) {} - visitProgram(ProgramInfo info) {} - visitLibrary(LibraryInfo info) {} - visitClass(ClassInfo info) {} - visitField(FieldInfo info) {} - visitFunction(FunctionInfo info) {} - visitTypedef(TypedefInfo info) {} - visitOutput(OutputUnitInfo info) {} -} - -/// A visitor that recursively walks each portion of the program. Because the -/// info representation is redundant, this visitor only walks the structure of -/// the program and skips some redundant links. For example, even though -/// visitAll contains references to functions, this visitor only recurses to -/// visit libraries, then from each library we visit functions and classes, and -/// so on. -class RecursiveInfoVisitor extends InfoVisitor { - visitAll(AllInfo info) { - // Note: we don't visit functions, fields, classes, and typedefs because - // they are reachable from the library info. - info.libraries.forEach(visitLibrary); - } - - visitLibrary(LibraryInfo info) { - info.topLevelFunctions.forEach(visitFunction); - info.topLevelVariables.forEach(visitField); - info.classes.forEach(visitClass); - info.typedefs.forEach(visitTypedef); - } - - visitClass(ClassInfo info) { - info.functions.forEach(visitFunction); - info.fields.forEach(visitField); - } - - visitField(FieldInfo info) { - info.closures.forEach(visitFunction); - } - - visitFunction(FunctionInfo info) { - info.closures.forEach(visitFunction); - } -} diff --git a/pkg/compiler/pubspec.yaml b/pkg/compiler/pubspec.yaml index aafa6a05f19..54d97b55752 100644 --- a/pkg/compiler/pubspec.yaml +++ b/pkg/compiler/pubspec.yaml @@ -10,11 +10,8 @@ dependencies: path: ../../sdk/lib/_internal/js_runtime sdk_library_metadata: path: ../../sdk/lib/_internal/sdk_library_metadata -dev_dependencies: - path: ^1.3.6 - args: ^0.13.2 - shelf: ^0.6.1+2 - yaml: ^2.1.3 + dart2js_info: ^0.0.1 + # Uncomment if running gclient, so you can depend directly on the downloaded # versions of dart2js's transitive dependencies: diff --git a/pkg/compiler/tool/code_deps.dart b/pkg/compiler/tool/code_deps.dart deleted file mode 100644 index 8050cfd9203..00000000000 --- a/pkg/compiler/tool/code_deps.dart +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/// Command-line tool to query for code dependencies. -library compiler.tool.code_deps; - -import 'dart:collection'; -import 'dart:convert'; -import 'dart:io'; - -import 'package:compiler/src/info/info.dart'; -import 'graph.dart'; -import 'util.dart'; - -main(args) { - if (args.length < 2) { - print('usage: dart tool/code_deps.dart path-to-info.json '); - print(' where can be:'); - print(' - some_path elementA elementB'); - // TODO(sigmund): add other queries, such as 'all_paths'. - exit(1); - } - - var json = JSON.decode(new File(args[0]).readAsStringSync()); - var info = AllInfo.parseFromJson(json); - var graph = graphFromInfo(info); - - var queryName = args[1]; - if (queryName == 'some_path') { - if (args.length < 4) { - print('missing arguments for `some_path`'); - exit(1); - } - var source = - info.functions.firstWhere(_longNameMatcher(new RegExp(args[2])), - orElse: () => null); - var target = - info.functions.firstWhere(_longNameMatcher(new RegExp(args[3])), - orElse: () => null); - print('query: some_path'); - if (source == null) { - print("source '${args[2]}' not found in '${args[0]}'"); - exit(1); - } - print('source: ${longName(source)}'); - if (target == null) { - print("target '${args[3]}' not found in '${args[0]}'"); - exit(1); - } - print('target: ${longName(target)}'); - var path = new SomePathQuery(source, target).run(graph); - if (path.isEmpty) { - print('result: no path found'); - } else { - print('result:'); - for (int i = 0; i < path.length; i++) { - print(' $i. ${longName(path[i])}'); - } - } - } else { - print('unrecognized query: $queryName'); - } -} - -/// A query supported by this tool. -abstract class Query { - run(Graph graph); -} - -/// Query that searches for a single path between two elements. -class SomePathQuery { - /// The info associated with the source element. - Info source; - - /// The info associated with the target element. - Info target; - - SomePathQuery(this.source, this.target); - - List run(Graph graph) { - var seen = {source: null}; - var queue = new Queue(); - queue.addLast(source); - while (queue.isNotEmpty) { - var node = queue.removeFirst(); - if (identical(node, target)) { - var result = new Queue(); - while (node != null) { - result.addFirst(node); - node = seen[node]; - } - return result.toList(); - } - for (var neighbor in graph.targetsOf(node)) { - if (seen.containsKey(neighbor)) continue; - seen[neighbor] = node; - queue.addLast(neighbor); - } - } - return []; - } -} - -_longNameMatcher(RegExp regexp) => (e) => regexp.hasMatch(longName(e)); diff --git a/pkg/compiler/tool/coverage_log_server.dart b/pkg/compiler/tool/coverage_log_server.dart deleted file mode 100644 index d2e860e46ad..00000000000 --- a/pkg/compiler/tool/coverage_log_server.dart +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/// A tool to gather coverage data from an app generated with dart2js. -/// This tool starts a server that answers to mainly 2 requests: -/// * a GET request to retrieve the application -/// * POST requests to record coverage data. -/// -/// It is intended to be used as follows: -/// * generate an app by running dart2js with the environment boolean -/// -DinstrumentForCoverage=true provided to the vm, and the --dump-info -/// flag provided to dart2js. -/// * start this server, and proxy requests from your normal frontend -/// server to this one. -library compiler.tool.coverage_log_server; - -import 'dart:convert'; -import 'dart:io'; -import 'dart:async'; -import 'package:path/path.dart' as path; -import 'package:args/args.dart'; -import 'package:shelf/shelf.dart' as shelf; -import 'package:shelf/shelf_io.dart' as shelf; - -const _DEFAULT_OUT_TEMPLATE = '.coverage.json'; - -main(argv) async { - var parser = new ArgParser() - ..addOption('port', abbr: 'p', help: 'port number', defaultsTo: "8080") - ..addOption('host', help: 'host name (use 0.0.0.0 for all interfaces)', - defaultsTo: 'localhost') - ..addFlag('help', abbr: 'h', help: 'show this help message', - negatable: false) - ..addOption('uri-prefix', - help: 'uri path prefix that will hit this server. This will be injected' - ' into the .js file', - defaultsTo: '') - ..addOption('out', abbr: 'o', help: 'output log file', - defaultsTo: _DEFAULT_OUT_TEMPLATE); - var args = parser.parse(argv); - if (args['help'] == true || args.rest.isEmpty) { - print('usage: dart coverage_logging.dart [options] ' - ' []'); - print(parser.usage); - exit(1); - } - - var jsPath = args.rest[0]; - var htmlPath = null; - if (args.rest.length > 1) { - htmlPath = args.rest[1]; - } - var outPath = args['out']; - if (outPath == _DEFAULT_OUT_TEMPLATE) outPath = '$jsPath.coverage.json'; - var server = new _Server(args['host'], int.parse(args['port']), jsPath, - htmlPath, outPath, args['uri-prefix']); - await server.run(); -} - -class _Server { - /// Server hostname, typically `localhost`, but can be `0.0.0.0`. - final String hostname; - - /// Port the server will listen to. - final int port; - - /// JS file (previously generated by dart2js) to serve. - final String jsPath; - - /// HTML file to serve, if any. - final String htmlPath; - - /// Contents of jsPath, adjusted to use the appropriate server url. - String jsCode; - - /// Location where we'll dump the coverage data. - final String outPath; - - /// Uri prefix used on all requests to this server. This will be injected into - /// the .js file. - final String prefix; - - // TODO(sigmund): add support to load also simple HTML files to test small - // simple apps. - - /// Data received so far. The data is just an array of pairs, showing the - /// hashCode and name of the element used. This can be later cross-checked - /// against dump-info data. - Map data = {}; - - String get _serializedData => new JsonEncoder.withIndent(' ').convert(data); - - _Server(this.hostname, this.port, String jsPath, this.htmlPath, - this.outPath, String prefix) - : jsPath = jsPath, - jsCode = _adjustRequestUrl(new File(jsPath).readAsStringSync(), prefix), - prefix = _normalize(prefix); - - run() async { - await shelf.serve(_handler, hostname, port); - var urlBase = "http://$hostname:$port${prefix == '' ? '/' : '/$prefix/'}"; - var htmlFilename = htmlPath == null ? '' : path.basename(htmlPath); - print("Server is listening\n" - " - html page: $urlBase$htmlFilename\n" - " - js code: $urlBase${path.basename(jsPath)}\n" - " - coverage reporting: ${urlBase}coverage\n"); - } - - _expectedPath(String tail) => prefix == '' ? tail : '$prefix/$tail'; - - _handler(shelf.Request request) async { - var urlPath = request.url.path; - print('received request: $urlPath'); - var baseJsName = path.basename(jsPath); - var baseHtmlName = htmlPath == null ? '' : path.basename(htmlPath); - - // Serve an HTML file at the default prefix, or a path matching the HTML - // file name - if (urlPath == prefix || urlPath == '$prefix/' - || urlPath == _expectedPath(baseHtmlName)) { - var contents = htmlPath == null - ? '' - : await new File(htmlPath).readAsString(); - return new shelf.Response.ok(contents, headers: HTML_HEADERS); - } - - if (urlPath == _expectedPath(baseJsName)) { - return new shelf.Response.ok(jsCode, headers: JS_HEADERS); - } - - // Handle POST requests to record coverage data, and GET requests to display - // the currently coverage resutls. - if (urlPath == _expectedPath('coverage')) { - if (request.method == 'GET') { - return new shelf.Response.ok(_serializedData, headers: TEXT_HEADERS); - } - - if (request.method == 'POST') { - _record(JSON.decode(await request.readAsString())); - return new shelf.Response.ok("Thanks!"); - } - } - - // Any other request is not supported. - return new shelf.Response.notFound('Not found: "$urlPath"'); - } - - _record(List entries) { - for (var entry in entries) { - var id = entry[0]; - data.putIfAbsent('$id', () => {'name': entry[1], 'count': 0}); - data['$id']['count']++; - } - _enqueueSave(); - } - - bool _savePending = false; - int _total = 0; - _enqueueSave() async { - if (!_savePending) { - _savePending = true; - await new Future.delayed(new Duration(seconds: 3)); - await new File(outPath).writeAsString(_serializedData); - var diff = data.length - _total; - print(diff ? ' - no new element covered' - : ' - $diff new elements covered'); - _savePending = false; - _total = data.length; - } - } -} - -/// Removes leading and trailing slashes of [uriPath]. -_normalize(String uriPath) { - if (uriPath.startsWith('/')) uriPath = uriPath.substring(1); - if (uriPath.endsWith('/')) uriPath = uriPath.substring(0, uriPath.length - 1); - return uriPath; -} - -_adjustRequestUrl(String code, String prefix) { - var newUrl = prefix == '' ? 'coverage' : '$prefix/coverage'; - return code.replaceFirst( - '"/coverage_uri_to_amend_by_server"', - '"/$newUrl" /*url-prefix updated!*/'); -} - -const HTML_HEADERS = const {'content-type': 'text/html'}; -const JS_HEADERS = const {'content-type': 'text/javascript'}; -const TEXT_HEADERS = const {'content-type': 'text/plain'}; diff --git a/pkg/compiler/tool/graph.dart b/pkg/compiler/tool/graph.dart deleted file mode 100644 index 1ef8d9e12d4..00000000000 --- a/pkg/compiler/tool/graph.dart +++ /dev/null @@ -1,292 +0,0 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/// A library to work with graphs. It contains a couple algorithms, including -/// Tarjan's algorithm to compute strongest connected components in a graph and -/// Cooper et al's dominator algorithm. -/// -/// Portions of the code in this library was adapted from -/// `package:analyzer/src/generated/collection_utilities.dart`. -// TODO(sigmund): move this into a shared place? -library compiler.tool.graph; - -import 'dart:math' as math; - -abstract class Graph { - Iterable get nodes; - bool get isEmpty; - int get nodeCount; - Iterable targetsOf(N source); - Iterable sourcesOf(N source); - - /// Run a topological sort of the graph. Since the graph may contain cycles, - /// this results in a list of strongly connected components rather than a list - /// of nodes. The nodes in each strongly connected components only have edges - /// that point to nodes in the same component or earlier components. - List> computeTopologicalSort() { - _SccFinder finder = new _SccFinder(this); - return finder.computeTopologicalSort(); - } - - /// Whether [source] can transitively reach [target]. - bool containsPath(N source, N target) { - Set seen = new Set(); - bool helper(N node) { - if (identical(node, target)) return true; - if (!seen.add(node)) return false; - return targetsOf(node).any(helper); - } - return helper(source); - } - - /// Returns all nodes reachable from [root] in post order. - List postOrder(N root) { - var seen = new Set(); - var result = []; - helper(n) { - if (!seen.add(n)) return; - targetsOf(n).forEach(helper); - result.add(n); - } - helper(root); - return result; - } - - /// Return a list of nodes that form a cycle containing the given node. If the - /// node is not part of this graph, then a list containing only the node - /// itself will be returned. - List findCycleContaining(N node) { - assert(node != null); - _SccFinder finder = new _SccFinder(this); - return finder._componentContaining(node); - } - - Graph dominatorTree(N root) { - var iDom = (new _DominatorFinder(this)..run(root)).immediateDominators; - var graph = new EdgeListGraph(); - for (N node in iDom.keys) { - if (node != root) graph.addEdge(iDom[node], node); - } - return graph; - } -} - -class EdgeListGraph extends Graph { - /// Edges in the graph. - Map> _edges = new Map>(); - - /// The reverse of _edges. - Map> _revEdges = new Map>(); - - Iterable get nodes => _edges.keys; - bool get isEmpty => _edges.isEmpty; - int get nodeCount => _edges.length; - - final _empty = new Set(); - - Iterable targetsOf(N source) => _edges[source] ?? _empty; - Iterable sourcesOf(N source) => _revEdges[source] ?? _empty; - - void addEdge(N source, N target) { - assert(source != null); - assert(target != null); - addNode(source); - addNode(target); - _edges[source].add(target); - _revEdges[target].add(source); - } - - void addNode(N node) { - assert(node != null); - _edges.putIfAbsent(node, () => new Set()); - _revEdges.putIfAbsent(node, () => new Set()); - } - - /// Remove the edge from the given [source] node to the given [target] node. - /// If there was no such edge then the graph will be unmodified: the number of - /// edges will be the same and the set of nodes will be the same (neither node - /// will either be added or removed). - void removeEdge(N source, N target) { - _edges[source]?.remove(target); - } - - /// Remove the given node from this graph. As a consequence, any edges for - /// which that node was either a head or a tail will also be removed. - void removeNode(N node) { - _edges.remove(node); - var sources = _revEdges[node]; - if (sources == null) return; - for (var source in sources) { - _edges[source].remove(node); - } - } - - /// Remove all of the given nodes from this graph. As a consequence, any edges - /// for which those nodes were either a head or a tail will also be removed. - void removeAllNodes(List nodes) => nodes.forEach(removeNode); -} - -/// Used by the [SccFinder] to maintain information about the nodes that have -/// been examined. There is an instance of this class per node in the graph. -class _NodeInfo { - /// Depth of the node corresponding to this info. - int index = 0; - - /// Depth of the first node in a cycle. - int lowlink = 0; - - /// Whether the corresponding node is on the stack. Used to remove the need - /// for searching a collection for the node each time the question needs to be - /// asked. - bool onStack = false; - - /// Component that contains the corresponding node. - List component; - - _NodeInfo(int depth) - : index = depth, lowlink = depth, onStack = false; -} - -/// Implements Tarjan's Algorithm for finding the strongly connected components -/// in a graph. -class _SccFinder { - /// The graph to process. - final Graph _graph; - - /// The index used to uniquely identify the depth of nodes. - int _index = 0; - - /// Nodes that are being visited in order to identify components. - List _stack = new List(); - - /// Information associated with each node. - Map> _info = >{}; - - /// All strongly connected components found, in topological sort order (each - /// node in a strongly connected component only has edges that point to nodes - /// in the same component or earlier components). - List> _allComponents = new List>(); - - _SccFinder(this._graph) : super(); - - /// Return a list containing the nodes that are part of the strongly connected - /// component that contains the given node. - List _componentContaining(N node) => _strongConnect(node).component; - - /// Run Tarjan's algorithm and return the resulting list of strongly connected - /// components. The list is in topological sort order (each node in a strongly - /// connected component only has edges that point to nodes in the same - /// component or earlier components). - List> computeTopologicalSort() { - for (N node in _graph.nodes) { - var nodeInfo = _info[node]; - if (nodeInfo == null) _strongConnect(node); - } - return _allComponents; - } - - /// Remove and return the top-most element from the stack. - N _pop() { - N node = _stack.removeAt(_stack.length - 1); - _info[node].onStack = false; - return node; - } - - /// Add the given node to the stack. - void _push(N node) { - _info[node].onStack = true; - _stack.add(node); - } - - /// Compute the strongly connected component that contains the given node as - /// well as any components containing nodes that are reachable from the given - /// component. - _NodeInfo _strongConnect(N v) { - // Set the depth index for v to the smallest unused index - var vInfo = new _NodeInfo(_index++); - _info[v] = vInfo; - _push(v); - - for (N w in _graph.targetsOf(v)) { - var wInfo = _info[w]; - if (wInfo == null) { - // Successor w has not yet been visited; recurse on it - wInfo = _strongConnect(w); - vInfo.lowlink = math.min(vInfo.lowlink, wInfo.lowlink); - } else if (wInfo.onStack) { - // Successor w is in stack S and hence in the current SCC - vInfo.lowlink = math.min(vInfo.lowlink, wInfo.index); - } - } - - // If v is a root node, pop the stack and generate an SCC - if (vInfo.lowlink == vInfo.index) { - var component = new List(); - N w; - do { - w = _pop(); - component.add(w); - _info[w].component = component; - } while (!identical(w, v)); - _allComponents.add(component); - } - return vInfo; - } -} - -/// Computes dominators using (Cooper, Harvey, and Kennedy's -/// algorithm)[http://www.cs.rice.edu/~keith/EMBED/dom.pdf]. -class _DominatorFinder { - final Graph _graph; - Map immediateDominators = {}; - Map postOrderId = {}; - _DominatorFinder(this._graph); - - run(N root) { - immediateDominators[root] = root; - bool changed = true; - int i = 0; - var nodesInPostOrder = _graph.postOrder(root); - for (var n in nodesInPostOrder) { - postOrderId[n] = i++; - } - var nodesInReversedPostOrder = nodesInPostOrder.reversed; - while (changed) { - changed = false; - for (var n in nodesInReversedPostOrder) { - if (n == root) continue; - bool first = true; - var idom = null; - for (var p in _graph.sourcesOf(n)) { - if (immediateDominators[p] != null) { - if (first) { - idom = p; - first = false; - } else { - idom = _intersect(p, idom); - } - } - } - if (immediateDominators[n] != idom) { - immediateDominators[n] = idom; - changed = true; - } - } - } - } - - N _intersect(N b1, N b2) { - var finger1 = b1; - var finger2 = b2; - while (finger1 != finger2) { - while (postOrderId[finger1] < postOrderId[finger2]) { - finger1 = immediateDominators[finger1]; - } - while (postOrderId[finger2] < postOrderId[finger1]) { - finger2 = immediateDominators[finger2]; - } - } - return finger1; - } -} diff --git a/pkg/compiler/tool/library_size_split.dart b/pkg/compiler/tool/library_size_split.dart deleted file mode 100644 index dcfaefeb22a..00000000000 --- a/pkg/compiler/tool/library_size_split.dart +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/// Command-line tool to show the size distribution of generated code among -/// libraries. Libraries can be grouped using regular expressions. See -/// [defaultGrouping] for an example. -library compiler.tool.library_size_split; - -import 'dart:convert'; -import 'dart:io'; -import 'dart:math' show max; - -import 'package:compiler/src/info/info.dart'; -import 'package:yaml/yaml.dart'; - -main(args) { - if (args.length < 1) { - print('usage: dart tool/library_size_split.dart ' - 'path-to-info.json [grouping.yaml]'); - exit(1); - } - - var filename = args[0]; - var json = JSON.decode(new File(filename).readAsStringSync()); - var info = AllInfo.parseFromJson(json); - - var groupingText = args.length > 1 - ? new File(args[1]).readAsStringSync() : defaultGrouping; - var groupingYaml = loadYaml(groupingText); - var groups = []; - for (var group in groupingYaml['groups']) { - groups.add(new _Group(group['name'], - new RegExp(group['regexp']), - group['cluster'] ?? 0)); - } - - var sizes = {}; - for (LibraryInfo lib in info.libraries) { - groups.forEach((group) { - var match = group.matcher.firstMatch('${lib.uri}'); - if (match != null) { - var name = group.name; - if (name == null && match.groupCount > 0) name = match.group(1); - if (name == null) name = match.group(0); - sizes.putIfAbsent(name, () => new _SizeEntry(name, group.cluster)); - sizes[name].size += lib.size; - } - }); - } - - var all = sizes.keys.toList(); - all.sort((a, b) => sizes[a].compareTo(sizes[b])); - var realTotal = info.program.size; - var longest = all.fold(0, (count, value) => max(count, value.length)); - longest = max(longest, 'Program Size'.length); - var lastCluster = 0; - for (var name in all) { - var entry = sizes[name]; - if (lastCluster < entry.cluster) { - print(' ' + ('-' * (longest + 18))); - lastCluster = entry.cluster; - } - var size = entry.size; - var percent = (size * 100 / realTotal).toStringAsFixed(2); - print(' ${_pad(name, longest + 1, right: true)}' - ' ${_pad(size, 8)} ${_pad(percent, 6)}%'); - } - print(' ${_pad("Program Size", longest + 1, right: true)}' - ' ${_pad(realTotal, 8)} ${_pad(100, 6)}%'); -} - -/// A group defined in the configuration. -class _Group { - /// Name of the group. May be null if the name is derived from the matcher. In - /// that case, the name would be group(1) of the matched expression if it - /// exist, or group(0) otherwise. - final String name; - - /// Regular expression matching members of the group. - final RegExp matcher; - - /// Index used to cluster groups together. Useful when the grouping - /// configuration describes some coarser groups than orders (e.g. summary of - /// packages would be in a different cluster than a summary of libraries). - final int cluster; - - _Group(this.name, this.matcher, this.cluster); -} - -class _SizeEntry { - final String name; - final int cluster; - int size = 0; - - _SizeEntry(this.name, this.cluster); - - int compareTo(_SizeEntry other) => - cluster == other.cluster ? size - other.size : cluster - other.cluster; -} - -_pad(value, n, {bool right: false}) { - var s = '$value'; - if (s.length >= n) return s; - var pad = ' ' * (n - s.length); - return right ? '$s$pad' : '$pad$s'; -} - -/// Example grouping specification: a yaml format containing a list of -/// group specifications. A group is specified by 3 parameters: -/// - name: the name that will be shown in the table of results -/// - regexp: a regexp used to match entries that belong to the group -/// - cluster: a clustering index, the higher the value, the later it will be -/// shown in the results. -/// Both cluster and name are optional. If cluster is omitted, the default value -/// is 0. If the name is omitted, it is extracted from the regexp, either as -/// group(1) if it is available or group(0) otherwise. -final defaultGrouping = """ -groups: -- { name: "Total (excludes preambles, statics & consts)", regexp: ".*", cluster: 3} -- { name: "Loose files", regexp: "file://.*", cluster: 2} -- { name: "All packages", regexp: "package:.*", cluster: 2} -- { name: "Core libs", regexp: "dart:.*", cluster: 2} -# We omitted `name` to extract the group name from the regexp directly. -# Here the name is the name of the package: -- { regexp: "package:([^/]*)", cluster: 1} -# Here the name is the url of the package and dart core libraries: -- { regexp: "package:.*"} -- { regexp: "dart:.*"} -# Here the name is the relative path of loose files: -- { regexp: "file://${Directory.current.path}/(.*)" } -"""; diff --git a/pkg/compiler/tool/util.dart b/pkg/compiler/tool/util.dart deleted file mode 100644 index c3091f5b9f6..00000000000 --- a/pkg/compiler/tool/util.dart +++ /dev/null @@ -1,96 +0,0 @@ -library compiler.tool.util; - -import 'package:compiler/src/info/info.dart'; -import 'graph.dart'; - -/// Computes a graph of dependencies from [info]. -Graph graphFromInfo(AllInfo info) { - // Note: currently we build two graphs to debug the differences between to - // places where we collect this information in dump-info. - // TODO(sigmund): fix inconsistencies between graphs, stick with one of them. - // TODO(sigmund): create a concrete implementation of InfoGraph, instead of - // using the EdgeListGraph. - var g1 = new EdgeListGraph(); - var g2 = new EdgeListGraph(); - var g3 = new EdgeListGraph(); - for (var f in info.functions) { - g1.addNode(f); - g3.addNode(f); - for (var g in f.uses) { - g1.addEdge(f, g.target); - g3.addEdge(f, g.target); - } - g2.addNode(f); - if (info.dependencies[f] != null) { - for (var g in info.dependencies[f]) { - g2.addEdge(f, g); - g3.addEdge(f, g); - } - } - } - - for (var f in info.fields) { - g1.addNode(f); - g3.addNode(f); - for (var g in f.uses) { - g1.addEdge(f, g.target); - g3.addEdge(f, g.target); - } - g2.addNode(f); - if (info.dependencies[f] != null) { - for (var g in info.dependencies[f]) { - g2.addEdge(f, g); - g3.addEdge(f, g); - } - } - } - - // Note: these checks right now show that 'uses' links are computed - // differently than 'deps' links - int more1 = 0; - int more2 = 0; - int more1b = 0; - int more2b = 0; - _sameEdges(f) { - var targets1 = g1.targetsOf(f).toSet(); - var targets2 = g2.targetsOf(f).toSet(); - var len1 = targets1.length; - var len2 = targets2.length; - if (len1 > len2) more1b++; - if (len1 < len2) more2b++; - var diff1 = targets1.difference(targets2); - var diff2 = targets2.difference(targets1); - if (diff1.isNotEmpty) { - more1++; - } - if (diff2.isNotEmpty) { - more2++; - } - return true; - } - info.functions.forEach(_sameEdges); - info.fields.forEach(_sameEdges); - if (more1 > 0 || more2 > 0 || more1b > 0 || more2b > 0) { - print("Dep graph is not consistent: $more1 $more2"); - } - - return g3; -} - -/// Provide a unique long name associated with [info]. -// TODO(sigmund): guarantee that the name is actually unique. -String longName(Info info) { - var sb = new StringBuffer(); - helper(i) { - if (i.parent == null) { - // TODO(sigmund): ensure `i is LibraryInfo`, we still don't set parents - // for closure classes correctly. - sb.write('${i.name}..'); - } else { - helper(i.parent); - sb.write('.${i.name}'); - } - } - helper(info); - return sb.toString(); -} diff --git a/tests/compiler/dart2js/analyze_unused_dart2js_test.dart b/tests/compiler/dart2js/analyze_unused_dart2js_test.dart index ae21bd30e4a..b1eaf6e1683 100644 --- a/tests/compiler/dart2js/analyze_unused_dart2js_test.dart +++ b/tests/compiler/dart2js/analyze_unused_dart2js_test.dart @@ -44,9 +44,6 @@ const Map> WHITE_LIST = const { "accept", "FunctionExpression", "CreateFunction" ], - // AllInfo.fromJson and visit methods are not used yet. - "lib/src/info/info.dart": const [ "is never" ], - "lib/src/universe/universe.dart": const [ "The method 'getterInvocationsByName' is never called.", "The method 'setterInvocationsByName' is never called."], diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS index 3869a2095bd..a7c3ff93de5 100644 --- a/tools/deps/dartium.deps/DEPS +++ b/tools/deps/dartium.deps/DEPS @@ -21,6 +21,7 @@ vars.update({ "collection_rev": "@1da9a07f32efa2ba0c391b289e2037391e31da0e", "crypto_rev" : "@2df57a1e26dd88e8d0614207d4b062c73209917d", "csslib_tag" : "@0.12.0", + "dart2js_info_rev" : "@5902be71c24bbda96675f646ba7d3ff911d26eae", "glob_rev": "@704cf75e4f26b417505c5c611bdaacd8808467dd", "html_tag" : "@0.12.1+1", "http_rev" : "@9b93e1542c753090c50b46ef1592d44bc858bfe7", @@ -93,6 +94,8 @@ deps.update({ "https://github.com/dart-lang/crypto.git" + Var("crypto_rev"), "src/dart/third_party/pkg/csslib": "https://github.com/dart-lang/csslib.git" + Var("csslib_tag"), + "src/dart/third_party/pkg/dart2js_info": + "https://github.com/dart-lang/dart2js_info.git" + Var("dart2js_info_rev"), "src/dart/third_party/pkg/collection": "https://github.com/dart-lang/collection.git" + Var("collection_rev"), "src/dart/third_party/pkg/glob":