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

Unified Diff: pkg/compiler/lib/src/dump_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 | « no previous file | pkg/compiler/lib/src/info/info.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/dump_info.dart
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 3b8f8bce2ae20e3e9706acfda1458e90fc9531bc..5e0d4fe05f83c052f82c3e1f32a4b9aecf00e62f 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -4,188 +4,98 @@
library dump_info;
-import 'dart:convert' show
- HtmlEscape,
- JsonEncoder,
- StringConversionSink,
- ChunkedConversionSink;
+import 'dart:convert'
+ show HtmlEscape, JsonEncoder, StringConversionSink, ChunkedConversionSink;
import 'elements/elements.dart';
import 'elements/visitor.dart';
-import 'dart2jslib.dart' show
- Backend,
- CodeBuffer,
- Compiler,
- CompilerTask,
- MessageKind;
+import 'dart2jslib.dart'
+ show Backend, CodeBuffer, Compiler, CompilerTask, MessageKind;
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 Emitter;
import 'js/js.dart' as jsAst;
import 'universe/universe.dart' show Selector, UniverseSelector;
import 'util/util.dart' show NO_LOCATION_SPANNABLE;
-/// Maps objects to an id. Supports lookups in
-/// both directions.
-class IdMapper<T>{
- Map<int, T> _idToElement = {};
- Map<T, int> _elementToId = {};
- int _idCounter = 0;
- final String name;
-
- IdMapper(this.name);
-
- Iterable<T> get elements => _elementToId.keys;
-
- String add(T e) {
- if (_elementToId.containsKey(e)) {
- return name + "/${_elementToId[e]}";
- }
-
- _idToElement[_idCounter] = e;
- _elementToId[e] = _idCounter;
- _idCounter += 1;
- return name + "/${_idCounter - 1}";
- }
-}
-
-class GroupedIdMapper {
- // Mappers for specific kinds of elements.
- IdMapper<LibraryElement> _library = new IdMapper('library');
- IdMapper<TypedefElement> _typedef = new IdMapper('typedef');
- IdMapper<FieldElement> _field = new IdMapper('field');
- IdMapper<ClassElement> _class = new IdMapper('class');
- IdMapper<FunctionElement> _function = new IdMapper('function');
- IdMapper<OutputUnit> _outputUnit = new IdMapper('outputUnit');
-
- Iterable<Element> get functions => _function.elements;
-
- // Convert this database of elements into JSON for rendering
- Map<String, dynamic> _toJson(ElementToJsonVisitor elementToJson) {
- Map<String, dynamic> json = {};
- var m = [_library, _typedef, _field, _class, _function];
- for (IdMapper mapper in m) {
- Map<String, dynamic> innerMapper = {};
- mapper._idToElement.forEach((k, v) {
- // All these elements are already cached in the
- // jsonCache, so this is just an access.
- var elementJson = elementToJson.process(v);
- if (elementJson != null) {
- innerMapper["$k"] = elementJson;
- }
- });
- json[mapper.name] = innerMapper;
- }
- return json;
- }
-}
-
-class ElementToJsonVisitor
- extends BaseElementVisitor<Map<String, dynamic>, dynamic> {
- final GroupedIdMapper mapper = new GroupedIdMapper();
+class ElementInfoCollector extends BaseElementVisitor<Info, dynamic> {
final Compiler compiler;
- final Map<Element, Map<String, dynamic>> jsonCache = {};
-
- String dart2jsVersion;
+ final AllInfo result = new AllInfo();
+ final Map<Element, Info> _elementToInfo = <Element, Info>{};
+ final Map<OutputUnit, OutputUnitInfo> _outputToInfo = {};
- ElementToJsonVisitor(this.compiler);
+ ElementInfoCollector(this.compiler);
- void run() {
- dart2jsVersion = compiler.hasBuildId ? compiler.buildId : null;
+ void run() => compiler.libraryLoader.libraries.forEach(visit);
- for (LibraryElement library in compiler.libraryLoader.libraries.toList()) {
- visit(library);
- }
- }
-
- Map<String, dynamic> visit(Element e, [_]) => e.accept(this, null);
+ Info visit(Element e, [_]) => e.accept(this, null);
- // If keeping the element is in question (like if a function has a size
- // of zero), only keep it if it holds dependencies to elsewhere.
+ /// Whether to emit information about [element].
+ ///
+ /// By default we emit information for any element that contributes to the
+ /// output size. Either becuase the it is a function being emitted or inlined,
+ /// or because it is an element that holds dependencies to other elements.
bool shouldKeep(Element element) {
- return compiler.dumpInfoTask.selectorsFromElement.containsKey(element)
- || compiler.dumpInfoTask.inlineCount.containsKey(element);
- }
-
- Map<String, dynamic> toJson() {
- return mapper._toJson(this);
+ return compiler.dumpInfoTask.selectorsFromElement.containsKey(element) ||
+ compiler.dumpInfoTask.inlineCount.containsKey(element);
}
- // Memoization of the JSON creating process.
- Map<String, dynamic> process(Element element) {
- return jsonCache.putIfAbsent(element, () => visit(element));
+ /// Visits [element] and produces it's corresponding info.
+ Info process(Element element) {
+ // TODO(sigmund): change the visit order to eliminate the need to check
+ // whether or not an element has been processed.
+ return _elementToInfo.putIfAbsent(element, () => visit(element));
}
- // Returns the id of an [element] if it has already been processed.
- // If the element has not been processed, this function does not
- // process it, and simply returns null instead.
- String idOf(Element element) {
- if (jsonCache.containsKey(element) && jsonCache[element] != null) {
- return jsonCache[element]['id'];
- } else {
- return null;
- }
- }
-
- Map<String, dynamic> visitElement(Element element, _) {
- return null;
- }
+ Info visitElement(Element element, _) => null;
- Map<String, dynamic> visitConstructorBodyElement(
- ConstructorBodyElement e, _) {
+ FunctionInfo visitConstructorBodyElement(ConstructorBodyElement e, _) {
return visitFunctionElement(e.constructor, _);
}
- Map<String, dynamic> visitLibraryElement(LibraryElement element, _) {
- var id = mapper._library.add(element);
- List<String> children = <String>[];
-
+ LibraryInfo visitLibraryElement(LibraryElement element, _) {
String libname = element.getLibraryName();
libname = libname == "" ? "<unnamed>" : libname;
-
int size = compiler.dumpInfoTask.sizeOf(element);
-
- LibraryElement contentsOfLibrary = element.isPatched
- ? element.patch : element;
- contentsOfLibrary.forEachLocalMember((Element member) {
- Map<String, dynamic> childJson = this.process(member);
- if (childJson == null) return;
- children.add(childJson['id']);
+ LibraryInfo info =
+ new LibraryInfo(libname, element.canonicalUri, null, size);
+ _elementToInfo[element] = info;
+
+ LibraryElement realElement = element.isPatched ? element.patch : element;
+ realElement.forEachLocalMember((Element member) {
+ Info child = this.process(member);
+ if (child is ClassInfo) {
+ info.classes.add(child);
+ } else if (child is FunctionInfo) {
+ info.topLevelFunctions.add(child);
+ } else if (child is FieldInfo) {
+ info.topLevelVariables.add(child);
+ } else if (child is TypedefInfo) {
+ info.typedefs.add(child);
+ } else if (child != null) {
+ print('unexpected child of $info: $child ==> ${child.runtimeType}');
+ assert(false);
+ }
});
- if (children.length == 0 && !shouldKeep(element)) {
- return null;
- }
-
- return {
- 'kind': 'library',
- 'name': libname,
- 'size': size,
- 'id': id,
- 'children': children,
- 'canonicalUri': element.canonicalUri.toString()
- };
+ if (info.isEmpty && !shouldKeep(element)) return null;
+ result.libraries.add(info);
+ return info;
}
- Map<String, dynamic> visitTypedefElement(TypedefElement element, _) {
- String id = mapper._typedef.add(element);
- return element.alias == null
- ? null
- : {
- 'id': id,
- 'type': element.alias.toString(),
- 'kind': 'typedef',
- 'name': element.name
- };
+ TypedefInfo visitTypedefElement(TypedefElement element, _) {
+ if (element.alias == null) return null;
+ TypedefInfo info = new TypedefInfo(element.name, '${element.alias}',
+ _unitInfoForElement(element));
+ _elementToInfo[element] = info;
+ result.typedefs.add(info);
+ return info;
}
- Map<String, dynamic> visitFieldElement(FieldElement element, _) {
- String id = mapper._field.add(element);
- List<String> children = [];
- StringBuffer emittedCode = compiler.dumpInfoTask.codeOf(element);
-
+ FieldInfo visitFieldElement(FieldElement element, _) {
TypeMask inferredType =
compiler.typesTask.getGuaranteedTypeOfElement(element);
// If a field has an empty inferred type it is never used.
@@ -195,196 +105,197 @@ class ElementToJsonVisitor
int size = compiler.dumpInfoTask.sizeOf(element);
String code;
-
+ StringBuffer emittedCode = compiler.dumpInfoTask.codeOf(element);
if (emittedCode != null) {
size += emittedCode.length;
code = emittedCode.toString();
}
+ FieldInfo info = new FieldInfo(
+ name: element.name,
+ type: '${element.type}',
+ inferredType: '$inferredType',
+ size: size,
+ code: code,
+ outputUnit: _unitInfoForElement(element));
+ _elementToInfo[element] = info;
+
+ List<FunctionInfo> nestedClosures = <FunctionInfo>[];
for (Element closure in element.nestedClosures) {
- var childJson = this.process(closure);
- if (childJson != null) {
- children.add(childJson['id']);
- if (childJson.containsKey('size')) {
- size += childJson['size'];
+ Info child = this.process(closure);
+ if (child != null) {
+ ClassInfo parent = this.process(closure.enclosingElement);
+ if (parent != null) {
+ child.name = "${parent.name}.${child.name}";
}
+ nestedClosures.add(child);
+ size += child.size;
}
}
-
- OutputUnit outputUnit =
- compiler.deferredLoadTask.outputUnitForElement(element);
-
- return {
- 'id': id,
- 'kind': 'field',
- 'type': element.type.toString(),
- 'inferredType': inferredType.toString(),
- 'name': element.name,
- 'children': children,
- 'size': size,
- 'code': code,
- 'outputUnit': mapper._outputUnit.add(outputUnit)
- };
+ info.closures = nestedClosures;
+ result.fields.add(info);
+ return info;
}
- Map<String, dynamic> visitClassElement(ClassElement element, _) {
- String id = mapper._class.add(element);
- List<String> children = [];
+ ClassInfo visitClassElement(ClassElement element, _) {
+ ClassInfo classInfo = new ClassInfo(
+ name: element.name,
+ isAbstract: element.isAbstract,
+ outputUnit: _unitInfoForElement(element));
+ _elementToInfo[element] = classInfo;
int size = compiler.dumpInfoTask.sizeOf(element);
- JavaScriptBackend backend = compiler.backend;
-
- Map<String, dynamic> modifiers = { 'abstract': element.isAbstract };
-
element.forEachLocalMember((Element member) {
- Map<String, dynamic> childJson = this.process(member);
- if (childJson != null) {
- children.add(childJson['id']);
-
- // Closures are placed in the library namespace, but
- // we want to attribute them to a function, and by
- // extension, this class. Process and add the sizes
- // here.
- if (member is MemberElement) {
- for (Element closure in member.nestedClosures) {
- Map<String, dynamic> child = this.process(closure);
-
- // Look for the parent element of this closure which should
- // be a class. If it exists, set the display name to
- // the name of the class + the name of the closure function.
- Element parent = closure.enclosingElement;
- Map<String, dynamic> processedParent = this.process(parent);
- if (processedParent != null) {
- child['name'] = "${processedParent['name']}.${child['name']}";
- }
-
- if (child != null) {
- size += child['size'];
- }
+ Info info = this.process(member);
+ if (info == null) return;
+ if (info is FieldInfo) {
+ classInfo.fields.add(info);
+ } else {
+ assert(info is FunctionInfo);
+ classInfo.functions.add(info);
+ }
+
+ // Closures are placed in the library namespace, but we want to attribute
+ // them to a function, and by extension, this class. Process and add the
+ // sizes here.
+ if (member is MemberElement) {
+ for (Element closure in member.nestedClosures) {
+ FunctionInfo closureInfo = this.process(closure);
+ if (closureInfo == null) continue;
+
+ // TODO(sigmund): remove this legacy update on the name, represent the
+ // information explicitly in the info format.
+ // Look for the parent element of this closure might be the enclosing
+ // class or an enclosing function.
+ Element parent = closure.enclosingElement;
+ ClassInfo parentInfo = this.process(parent);
+ if (parentInfo != null) {
+ closureInfo.name = "${parentInfo.name}.${closureInfo.name}";
}
+ size += closureInfo.size;
}
}
});
+ classInfo.size = size;
+
// Omit element if it is not needed.
+ JavaScriptBackend backend = compiler.backend;
if (!backend.emitter.neededClasses.contains(element) &&
- children.length == 0) {
+ classInfo.fields.isEmpty &&
+ classInfo.functions.isEmpty) {
return null;
}
-
- OutputUnit outputUnit =
- compiler.deferredLoadTask.outputUnitForElement(element);
-
- return {
- 'name': element.name,
- 'size': size,
- 'kind': 'class',
- 'modifiers': modifiers,
- 'children': children,
- 'id': id,
- 'outputUnit': mapper._outputUnit.add(outputUnit)
- };
+ result.classes.add(classInfo);
+ return classInfo;
}
- Map<String, dynamic> visitFunctionElement(FunctionElement element, _) {
- String id = mapper._function.add(element);
- String name = element.name;
- String kind = "function";
- List<String> children = [];
- List<Map<String, dynamic>> parameters = [];
- String inferredReturnType = null;
- String returnType = null;
- String sideEffects = null;
-
- StringBuffer emittedCode = compiler.dumpInfoTask.codeOf(element);
+ FunctionInfo visitFunctionElement(FunctionElement element, _) {
int size = compiler.dumpInfoTask.sizeOf(element);
+ if (size == 0 && !shouldKeep(element)) return null;
- Map<String, dynamic> modifiers = {
- 'static': element.isStatic,
- 'const': element.isConst,
- 'factory': element.isFactoryConstructor,
- 'external': element.isPatched
- };
-
+ String name = element.name;
+ int kind = FunctionInfo.TOP_LEVEL_FUNCTION_KIND;
var enclosingElement = element.enclosingElement;
if (enclosingElement.isField ||
enclosingElement.isFunction ||
element.isClosure ||
enclosingElement.isConstructor) {
- kind = "closure";
+ kind = FunctionInfo.CLOSURE_FUNCTION_KIND;
name = "<unnamed>";
- } else if (modifiers['static']) {
- kind = 'function';
+ } else if (element.isStatic) {
+ kind = FunctionInfo.TOP_LEVEL_FUNCTION_KIND;
} else if (enclosingElement.isClass) {
- kind = 'method';
+ kind = FunctionInfo.METHOD_FUNCTION_KIND;
}
if (element.isConstructor) {
- name == ""
- ? "${element.enclosingElement.name}"
- : "${element.enclosingElement.name}.${element.name}";
- kind = "constructor";
+ name = name == ""
+ ? "${element.enclosingElement.name}"
+ : "${element.enclosingElement.name}.${element.name}";
+ kind = FunctionInfo.CONSTRUCTOR_FUNCTION_KIND;
}
+ FunctionModifiers modifiers = new FunctionModifiers(
+ isStatic: element.isStatic,
+ isConst: element.isConst,
+ isFactory: element.isFactoryConstructor,
+ isExternal: element.isPatched);
+ StringBuffer emittedCode = compiler.dumpInfoTask.codeOf(element);
+ String code = emittedCode == null ? null : '$emittedCode';
+
+ List<ParameterInfo> parameters = <ParameterInfo>[];
if (element.hasFunctionSignature) {
FunctionSignature signature = element.functionSignature;
signature.forEachParameter((parameter) {
- parameters.add({
- 'name': parameter.name,
- 'type': '${compiler.typesTask.getGuaranteedTypeOfElement(parameter)}',
- 'declaredType': '${parameter.node.type}'
- });
+ parameters.add(new ParameterInfo(
+ parameter.name,
+ '${compiler.typesTask.getGuaranteedTypeOfElement(parameter)}',
+ '${parameter.node.type}'));
});
}
- if (element.isInstanceMember && !element.isAbstract &&
+ String returnType = null;
+ // TODO(sigmund): why all these checks?
+ if (element.isInstanceMember &&
+ !element.isAbstract &&
compiler.world.allFunctions.contains(element)) {
returnType = '${element.type.returnType}';
}
- inferredReturnType =
+ String inferredReturnType =
'${compiler.typesTask.getGuaranteedReturnTypeOfElement(element)}';
- sideEffects = compiler.world.getSideEffectsOfElement(element).toString();
+ String sideEffects = '${compiler.world.getSideEffectsOfElement(element)}';
+ int inlinedCount = compiler.dumpInfoTask.inlineCount[element];
+ if (inlinedCount == null) inlinedCount = 0;
+
+ FunctionInfo info = new FunctionInfo(
+ name: name,
+ modifiers: modifiers,
+ size: size,
+ returnType: returnType,
+ inferredReturnType: inferredReturnType,
+ parameters: parameters,
+ sideEffects: sideEffects,
+ inlinedCount: inlinedCount,
+ code: code,
+ type: element.type.toString(),
+ outputUnit: _unitInfoForElement(element));
+ _elementToInfo[element] = info;
+
+ List<FunctionInfo> nestedClosures = <FunctionInfo>[];
if (element is MemberElement) {
MemberElement member = element as MemberElement;
for (Element closure in member.nestedClosures) {
- Map<String, dynamic> child = this.process(closure);
+ Info child = this.process(closure);
if (child != null) {
- child['kind'] = 'closure';
- children.add(child['id']);
- size += child['size'];
+ BasicInfo parent = this.process(closure.enclosingElement);
+ if (parent != null) {
+ child.name = "${parent.name}.${child.name}";
+ }
+ nestedClosures.add(child);
+ size += child.size;
}
}
}
+ info.closures = nestedClosures;
+ result.functions.add(info);
+ return info;
+ }
- if (size == 0 && !shouldKeep(element)) {
- return null;
- }
-
- int inlinedCount = compiler.dumpInfoTask.inlineCount[element];
- if (inlinedCount == null) {
- inlinedCount = 0;
- }
-
+ OutputUnitInfo _unitInfoForElement(Element element) {
OutputUnit outputUnit =
- compiler.deferredLoadTask.outputUnitForElement(element);
-
- return {
- 'kind': kind,
- 'name': name,
- 'id': id,
- 'modifiers': modifiers,
- 'children': children,
- 'size': size,
- 'returnType': returnType,
- 'inferredReturnType': inferredReturnType,
- 'parameters': parameters,
- 'sideEffects': sideEffects,
- 'inlinedCount': inlinedCount,
- 'code': emittedCode == null ? null : '$emittedCode',
- 'type': element.type.toString(),
- 'outputUnit': mapper._outputUnit.add(outputUnit)
- };
+ compiler.deferredLoadTask.outputUnitForElement(element);
+ return _outputToInfo.putIfAbsent(outputUnit, () {
+ // Dump-info currently only works with the full emitter. If another
+ // emitter is used it will fail here.
+ JavaScriptBackend backend = compiler.backend;
+ full.Emitter emitter = backend.emitter.emitter;
+ OutputUnitInfo info = new OutputUnitInfo(
+ outputUnit.name, emitter.outputBuffers[outputUnit].length);
+ result.outputUnits.add(info);
+ return info;
+ });
}
}
@@ -395,12 +306,11 @@ class Selection {
}
class DumpInfoTask extends CompilerTask {
- DumpInfoTask(Compiler compiler)
- : super(compiler);
+ DumpInfoTask(Compiler compiler) : super(compiler);
String get name => "Dump Info";
- ElementToJsonVisitor infoCollector;
+ ElementInfoCollector infoCollector;
/// The size of the generated output.
int _programSize;
@@ -411,7 +321,7 @@ class DumpInfoTask extends CompilerTask {
final Set<jsAst.Node> _tracking = new Set<jsAst.Node>();
// A mapping from Dart Elements to Javascript AST Nodes.
final Map<Element, List<jsAst.Node>> _elementToNodes =
- <Element, List<jsAst.Node>>{};
+ <Element, List<jsAst.Node>>{};
// A mapping from Javascript AST Nodes to the size of their
// pretty-printed contents.
final Map<jsAst.Node, int> _nodeToSize = <jsAst.Node, int>{};
@@ -455,14 +365,13 @@ class DumpInfoTask extends CompilerTask {
if (!selectorsFromElement.containsKey(element)) {
return const <Selection>[];
} else {
- return selectorsFromElement[element].expand(
- (UniverseSelector selector) {
- return compiler.world.allFunctions.filter(
- selector.selector, selector.mask)
- .map((element) {
- return new Selection(element, selector.mask);
- });
+ return selectorsFromElement[element].expand((UniverseSelector selector) {
+ return compiler.world.allFunctions
+ .filter(selector.selector, selector.mask)
+ .map((element) {
+ return new Selection(element, selector.mask);
});
+ });
}
}
@@ -481,8 +390,8 @@ class DumpInfoTask extends CompilerTask {
void registerElementAst(Element element, jsAst.Node code) {
if (compiler.dumpInfo) {
_elementToNodes
- .putIfAbsent(element, () => new List<jsAst.Node>())
- .add(code);
+ .putIfAbsent(element, () => new List<jsAst.Node>())
+ .add(code);
_tracking.add(code);
}
}
@@ -501,9 +410,7 @@ class DumpInfoTask extends CompilerTask {
// code was produced, return 0.
int sizeOf(Element element) {
if (_elementToNodes.containsKey(element)) {
- return _elementToNodes[element]
- .map(sizeOfNode)
- .fold(0, (a, b) => a + b);
+ return _elementToNodes[element].map(sizeOfNode).fold(0, (a, b) => a + b);
} else {
return 0;
}
@@ -529,7 +436,7 @@ class DumpInfoTask extends CompilerTask {
}
void collectInfo() {
- infoCollector = new ElementToJsonVisitor(compiler)..run();
+ infoCollector = new ElementInfoCollector(compiler)..run();
}
void dumpInfo() {
@@ -546,103 +453,56 @@ class DumpInfoTask extends CompilerTask {
});
}
-
void dumpInfoJson(StringSink buffer) {
JsonEncoder encoder = const JsonEncoder.withIndent(' ');
Stopwatch stopwatch = new Stopwatch();
stopwatch.start();
- Map<String, List<Map<String, String>>> holding =
- <String, List<Map<String, String>>>{};
- for (Element fn in infoCollector.mapper.functions) {
- Iterable<Selection> pulling = getRetaining(fn);
+ // Recursively build links to function uses
+ Iterable<FunctionElement> functionElements =
+ infoCollector._elementToInfo.keys.where((k) => k is FunctionElement);
+ for (FunctionElement element in functionElements) {
+ FunctionInfo info = infoCollector._elementToInfo[element];
+ Iterable<Selection> uses = getRetaining(element);
// Don't bother recording an empty list of dependencies.
- if (pulling.length > 0) {
- String fnId = infoCollector.idOf(fn);
- // Some dart2js builtin functions are not
- // recorded. Don't register these.
- if (fnId != null) {
- holding[fnId] = pulling
- .map((selection) {
- return <String, String>{
- "id": infoCollector.idOf(selection.selectedElement),
- "mask": selection.mask.toString()
- };
- })
- // Filter non-null ids for the same reason as above.
- .where((a) => a['id'] != null)
- .toList();
- }
+ for (Selection selection in uses) {
+ // Don't register dart2js builtin functions that are not recorded.
+ Info useInfo = infoCollector._elementToInfo[selection.selectedElement];
+ if (useInfo == null) continue;
+ info.uses.add(new DependencyInfo(useInfo, '${selection.mask}'));
}
}
// Track dependencies that come from inlining.
for (Element element in inlineMap.keys) {
- String keyId = infoCollector.idOf(element);
- if (keyId != null) {
- for (Element held in inlineMap[element]) {
- String valueId = infoCollector.idOf(held);
- if (valueId != null) {
- holding.putIfAbsent(keyId, () => new List<Map<String, String>>())
- .add(<String, String>{
- "id": valueId,
- "mask": "inlined"
- });
- }
- }
+ FunctionInfo functionInfo = infoCollector._elementToInfo[element];
+ if (functionInfo == null) continue;
+ for (Element held in inlineMap[element]) {
+ Info heldInfo = infoCollector._elementToInfo[held];
+ if (heldInfo == null) continue;
+ functionInfo.uses.add(new DependencyInfo(heldInfo, 'inlined'));
}
}
- List<Map<String, dynamic>> outputUnits =
- new List<Map<String, dynamic>>();
-
- JavaScriptBackend backend = compiler.backend;
- // Dump-info currently only works with the full emitter. If another
- // emitter is used it will fail here.
- full.Emitter fullEmitter = backend.emitter.emitter;
-
- for (OutputUnit outputUnit in
- infoCollector.mapper._outputUnit._elementToId.keys) {
- String id = infoCollector.mapper._outputUnit.add(outputUnit);
- outputUnits.add(<String, dynamic> {
- 'id': id,
- 'name': outputUnit.name,
- 'size': fullEmitter.outputBuffers[outputUnit].length,
- });
- }
-
- Map<String, dynamic> outJson = {
- 'elements': infoCollector.toJson(),
- 'holding': holding,
- 'outputUnits': outputUnits,
- 'dump_version': 3,
- 'deferredFiles': compiler.deferredLoadTask.computeDeferredMap(),
- // This increases when new information is added to the map, but the viewer
- // still is compatible.
- 'dump_minor_version': '2'
- };
-
- Map<String, dynamic> generalProgramInfo = <String, dynamic> {
- 'size': _programSize,
- 'dart2jsVersion': infoCollector.dart2jsVersion,
- 'compilationMoment': new DateTime.now().toString(),
- 'compilationDuration': compiler.totalCompileTime.elapsed.toString(),
- 'toJsonDuration': stopwatch.elapsedMilliseconds,
- 'dumpInfoDuration': this.timing.toString(),
- 'noSuchMethodEnabled': backend.enabledNoSuchMethod,
- 'minified': compiler.enableMinification
- };
-
- outJson['program'] = generalProgramInfo;
-
- ChunkedConversionSink<Object> sink =
- encoder.startChunkedConversion(
- new StringConversionSink.fromStringSink(buffer));
- sink.add(outJson);
- compiler.reportInfo(
- NO_LOCATION_SPANNABLE,
- MessageKind.GENERIC,
- {'text': "View the dumped .info.json file at "
- "https://dart-lang.github.io/dump-info-visualizer"});
+ AllInfo result = infoCollector.result;
+ result.deferredFiles = compiler.deferredLoadTask.computeDeferredMap();
+ stopwatch.stop();
+ result.program = new ProgramInfo(
+ size: _programSize,
+ dart2jsVersion: compiler.hasBuildId ? compiler.buildId : null,
+ compilationMoment: new DateTime.now(),
+ compilationDuration: compiler.totalCompileTime.elapsed,
+ toJsonDuration: stopwatch.elapsedMilliseconds,
+ dumpInfoDuration: this.timing,
+ noSuchMethodEnabled: compiler.backend.enabledNoSuchMethod,
+ minified: compiler.enableMinification);
+
+ ChunkedConversionSink<Object> sink = encoder.startChunkedConversion(
+ new StringConversionSink.fromStringSink(buffer));
+ sink.add(result.toJson());
+ compiler.reportInfo(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, {
+ 'text': "View the dumped .info.json file at "
+ "https://dart-lang.github.io/dump-info-visualizer"
+ });
}
}
« no previous file with comments | « no previous file | pkg/compiler/lib/src/info/info.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698