Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(540)

Unified Diff: pkg/compiler/lib/src/info/info.dart

Issue 1253763004: dart2js: represent dump-info explicitly, so we can easily create tools that process the data (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« pkg/compiler/lib/src/dump_info.dart ('K') | « pkg/compiler/lib/src/dump_info.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/info/info.dart
diff --git a/pkg/compiler/lib/src/info/info.dart b/pkg/compiler/lib/src/info/info.dart
new file mode 100644
index 0000000000000000000000000000000000000000..addaff824fb5c2ba13d7f909f404c4ccff8135b9
--- /dev/null
+++ b/pkg/compiler/lib/src/info/info.dart
@@ -0,0 +1,399 @@
+// 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.
+ String get kind;
+
+ /// An unique id used to create references to this info.
+ int get id;
+
+ /// Serializes the information into a JSON format.
+ Map toJson();
+}
+
+/// Common information used for most kind of elements.
+// TODO(sigmund): add more:
+// - inputSize: bytes used in the Dart source program
+// - transitiveSize: bytes including the size of dependencies that are only
+// retained because of this element.
+class BasicInfo implements Info {
+ final String kind;
+ final int id;
+
+ /// Bytes used in the generated code for the corresponding element.
+ int size;
+
+ String get serializedId => '$kind/$id';
+
+ // TODO(sigmund): make final (currently not final because we amend the name in
Johnni Winther 2015/07/27 10:14:42 'name in of' -> 'name of'
Siggi Cherem (dart-lang) 2015/07/27 20:10:59 Done.
+ // of nested closures to record their enclosing element).
+ String name;
+
+ /// If using deferred libraries, where the element associated with this info
+ /// is generated.
+ final OutputUnitInfo outputUnit;
+
+ BasicInfo(this.kind, this.id, this.name, this.outputUnit, [this.size = 0]);
+
+ Map toJson() {
+ var res = {'id': serializedId, 'kind': kind, 'name': name, 'size': size};
+ // TODO(sigmund): omit this also when outputUnit.id == 0
+ // (most code is by default in the main output unit)
+ if (outputUnit != null) res['outputUnit'] = outputUnit.serializedId;
+ return res;
+ }
+}
+
+/// 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<LibraryInfo> libraries = [];
+
+ /// Information about each function (includes methods and getters in any
+ /// library)
+ List<FunctionInfo> functions = [];
+
+ /// Information about type defs in the program.
+ List<TypedefInfo> typedefs = [];
+
+ /// Information about each class (in any library).
+ List<ClassInfo> classes = [];
+
+ /// Information about fields (in any class).
+ List<FieldInfo> fields = [];
+
+ /// Information about output units (should be just one entry if not using
+ /// deferred loading).
+ List<OutputUnitInfo> 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<String, Map<String, dynamic>> deferredFiles;
+
+ /// 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 = 3;
+
+ AllInfo();
+
+ factory AllInfo.fromJson(Map map) {
+ // TODO(sigmund): implement
+ throw UnimplementedError('deserialization of dump-info not implemented');
+ }
+
+ Map _listAsJsonMap(List<Info> list) {
+ var map = <String, Map>{};
+ for (var info in list) {
+ map['${info.id}'] = info.toJson();
+ }
+ return map;
+ }
+
+ Map _extractHoldingInfo() {
+ var map = <String, List>{};
+ for (var f in functions) {
+ if (f.uses.isEmpty) continue;
+ map[f.serializedId] = f.uses.map((u) => u.toJson()).toList();
+ }
+ return map;
+ }
+
+ Map toJson() => {
+ 'elements': {
Siggi Cherem (dart-lang) 2015/07/24 01:07:58 seems wasteful that this is indented so much by th
+ 'library': _listAsJsonMap(libraries),
+ 'class': _listAsJsonMap(classes),
+ 'function': _listAsJsonMap(functions),
+ 'typedef': _listAsJsonMap(typedefs),
+ 'field': _listAsJsonMap(fields),
+ },
+ 'holding': _extractHoldingInfo(),
+ '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(),
+ };
+}
+
+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,
+ };
+}
+
+class LibraryInfo extends BasicInfo {
+ final Uri uri;
+ final List<FunctionInfo> topLevelFunctions = [];
+ final List<FieldInfo> topLevelVariables = [];
+ final List<ClassInfo> classes = [];
+
+ static int _id = 0;
+
+ bool get isEmpty =>
+ topLevelFunctions.isEmpty && topLevelVariables.isEmpty && classes.isEmpty;
+
+ LibraryInfo(String name, this.uri, OutputUnitInfo outputUnit, int size)
+ : super('library', _id++, name, outputUnit, size);
+
+ Map toJson() => super.toJson()
+ ..addAll({
+ 'children': []
+ ..addAll(topLevelFunctions.map((f) => f.serializedId))
+ ..addAll(topLevelVariables.map((v) => v.serializedId))
+ ..addAll(classes.map((c) => c.serializedId)),
+ 'canonicalUri': '$uri',
+ });
+}
+
+class OutputUnitInfo extends BasicInfo {
+ static int _ids = 0;
+ OutputUnitInfo(String name, int size)
+ : super('outputUnit', _ids++, name, null, size);
+}
+
+class ClassInfo extends BasicInfo {
+ final bool isAbstract;
+
+ // TODO(sigmund): split static vs instance vs closures
+ final List<FunctionInfo> functions = [];
+ final List<FieldInfo> fields = [];
+ static int _ids = 0;
+
+ ClassInfo(
+ {String name, this.isAbstract, OutputUnitInfo outputUnit, int size: 0})
+ : super('class', _ids++, name, outputUnit, size);
+
+ 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))
+ });
+}
+
+class FieldInfo extends BasicInfo {
+ String type;
+ String inferredType;
+ List<FunctionInfo> closures;
+ String code;
+
+ static int _ids = 0;
+ FieldInfo(
+ {String name,
+ int size,
+ this.type,
+ this.inferredType,
+ this.closures,
+ this.code,
+ OutputUnitInfo outputUnit})
+ : super('field', _ids++, name, outputUnit, size);
+
+ Map toJson() => super.toJson()
+ ..addAll({
+ 'children': closures.map((i) => i.serializedId).toList(),
+ 'inferredType': inferredType,
+ 'code': code,
+ 'type': type,
+ });
+}
+
+class TypedefInfo extends BasicInfo {
+ String type;
+
+ static int _ids = 0;
+ TypedefInfo(String name, this.type, OutputUnitInfo outputUnit)
+ : super('typedef', _ids++, name, outputUnit);
+
+ Map toJson() => super.toJson()..['type'] = '$type';
+}
+
+class FunctionInfo extends BasicInfo {
+ 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).
+ final int functionKind;
+
+ /// Modifiers applied to this function.
+ final FunctionModifiers modifiers;
+
+ /// Nested closures that appear within the body of this function.
+ List<FunctionInfo> 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<ParameterInfo> 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;
+
+ /// How does this function depend on other functions or fields.
+ List<DependencyInfo> uses = [];
karlklose 2015/07/24 07:08:22 Please add type arguments to literals (several pla
Siggi Cherem (dart-lang) 2015/07/27 20:10:59 Done. We should chat more about this long term - i
+
+ FunctionInfo(
+ {String name,
+ OutputUnitInfo outputUnit,
+ int size,
+ this.functionKind,
+ this.modifiers,
+ this.closures,
+ this.type,
+ this.returnType,
+ this.inferredReturnType,
+ this.parameters,
+ this.sideEffects,
+ this.inlinedCount,
+ this.code})
+ : super('function', _ids++, name, outputUnit, size);
+
+ 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.
+ });
+}
+
+/// 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'.
+ final String mask;
karlklose 2015/07/24 07:08:22 Preferably we would have an enum that describes ex
Siggi Cherem (dart-lang) 2015/07/27 20:10:58 good point. I added a TODO for now. I'm thinking t
+
+ 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});
+
+ factory FunctionModifiers.fromJson(Map<String, bool> json) {
+ return new FunctionModifiers(
+ isStatic: json['static'] == true,
+ isConst: json['const'] == true,
+ isFactory: json['factory'] == true,
+ isExternal: json['external'] == true);
+ }
+
+ // TODO(sigmund): exclude false values (requires bumping the format version):
+ // Map toJson() {
+ // var res = <String, bool>{};
+ // 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,
+ };
+}
« pkg/compiler/lib/src/dump_info.dart ('K') | « pkg/compiler/lib/src/dump_info.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698