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

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: additional fixes Created 5 years, 4 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
« no previous file with comments | « 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..5aa06f2665d707202012ab70c0b58a060ec51e0e
--- /dev/null
+++ b/pkg/compiler/lib/src/info/info.dart
@@ -0,0 +1,405 @@
+// 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;
+
+ /// 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;
+
+ /// Bytes used in the generated code for the corresponding element.
+ int size;
+
+ /// 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();
+}
+
+/// 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 String kind;
+ final int id;
+ int size;
+
+ String get serializedId => '$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);
+
+ 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;
+ }
+
+ 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<DependencyInfo> uses = <DependencyInfo>[];
+}
+
+
+/// 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 = <LibraryInfo>[];
+
+ /// Information about each function (includes methods and getters in any
+ /// library)
+ List<FunctionInfo> functions = <FunctionInfo>[];
+
+ /// Information about type defs in the program.
+ List<TypedefInfo> typedefs = <TypedefInfo>[];
+
+ /// Information about each class (in any library).
+ List<ClassInfo> classes = <ClassInfo>[];
+
+ /// Information about fields (in any class).
+ List<FieldInfo> fields = <FieldInfo>[];
+
+ /// Information about output units (should be just one entry if not using
+ /// deferred loading).
+ List<OutputUnitInfo> outputUnits = <OutputUnitInfo>[];
+
+ /// 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();
+
+ 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>{};
+ 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;
+ }
+
+ // TODO(sigmund): implement fromJson
+ Map toJson() => {
+ 'elements': {
+ '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 {
+ Uri uri;
+ final List<FunctionInfo> topLevelFunctions = <FunctionInfo>[];
+ final List<FieldInfo> topLevelVariables = <FieldInfo>[];
+ final List<ClassInfo> classes = <ClassInfo>[];
+ final List<TypedefInfo> typedefs = <TypedefInfo>[];
+
+ 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))
+ ..addAll(typedefs.map((t) => t.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 {
+ bool isAbstract;
+
+ // TODO(sigmund): split static vs instance vs closures
+ final List<FunctionInfo> functions = <FunctionInfo>[];
+ final List<FieldInfo> fields = <FieldInfo>[];
+ 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 with CodeInfo {
+ String type;
+ String inferredType;
+ List<FunctionInfo> closures;
+ String code;
+
+ static int _ids = 0;
+ FieldInfo(
+ {String name,
+ int size: 0,
+ 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, 0);
+
+ Map toJson() => super.toJson()..['type'] = '$type';
+}
+
+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).
+ 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;
+
+ FunctionInfo(
+ {String name,
+ 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('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'.
+ // 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 = <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,
+ };
+}
« no previous file with comments | « 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