Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dump_info; | 5 library dump_info; |
| 6 | 6 |
| 7 import 'dart:convert' | 7 import 'dart:convert' |
| 8 show HtmlEscape, JsonEncoder, StringConversionSink, ChunkedConversionSink; | 8 show HtmlEscape, JsonEncoder, StringConversionSink, ChunkedConversionSink; |
| 9 | 9 |
| 10 import 'package:dart2js_info/info.dart'; | 10 import 'package:dart2js_info/info.dart'; |
| 11 | 11 |
| 12 import 'common.dart'; | 12 import 'common.dart'; |
| 13 import 'common/tasks.dart' show | 13 import 'common/tasks.dart' show CompilerTask; |
| 14 CompilerTask; | 14 import 'constants/values.dart' show ConstantValue, InterceptorConstantValue; |
| 15 import 'constants/values.dart' show ConstantValue; | 15 import 'compiler.dart' show Compiler; |
| 16 import 'compiler.dart' show | |
| 17 Compiler; | |
| 18 import 'elements/elements.dart'; | 16 import 'elements/elements.dart'; |
| 19 import 'elements/visitor.dart'; | 17 import 'elements/visitor.dart'; |
| 20 import 'types/types.dart' show | 18 import 'types/types.dart' show TypeMask; |
| 21 TypeMask; | 19 import 'deferred_load.dart' show OutputUnit; |
| 22 import 'deferred_load.dart' show | 20 import 'js_backend/js_backend.dart' show JavaScriptBackend; |
| 23 OutputUnit; | 21 import 'js_emitter/full_emitter/emitter.dart' as full show Emitter; |
| 24 import 'js_backend/js_backend.dart' show | |
| 25 JavaScriptBackend; | |
| 26 import 'js_emitter/full_emitter/emitter.dart' as full show | |
| 27 Emitter; | |
| 28 import 'js/js.dart' as jsAst; | 22 import 'js/js.dart' as jsAst; |
| 29 import 'universe/universe.dart' show | 23 import 'universe/universe.dart' show UniverseSelector; |
| 30 UniverseSelector; | |
| 31 import 'info/send_info.dart' show collectSendMeasurements; | 24 import 'info/send_info.dart' show collectSendMeasurements; |
| 32 | 25 |
| 33 class ElementInfoCollector extends BaseElementVisitor<Info, dynamic> { | 26 class ElementInfoCollector extends BaseElementVisitor<Info, dynamic> { |
| 34 final Compiler compiler; | 27 final Compiler compiler; |
| 35 | 28 |
| 36 final AllInfo result = new AllInfo(); | 29 final AllInfo result = new AllInfo(); |
| 37 final Map<Element, Info> _elementToInfo = <Element, Info>{}; | 30 final Map<Element, Info> _elementToInfo = <Element, Info>{}; |
| 38 final Map<ConstantValue, Info> _constantToInfo = <ConstantValue, Info>{}; | 31 final Map<ConstantValue, Info> _constantToInfo = <ConstantValue, Info>{}; |
| 39 final Map<OutputUnit, OutputUnitInfo> _outputToInfo = {}; | 32 final Map<OutputUnit, OutputUnitInfo> _outputToInfo = {}; |
| 40 | 33 |
| 41 ElementInfoCollector(this.compiler); | 34 ElementInfoCollector(this.compiler); |
| 42 | 35 |
| 43 void run() { | 36 void run() { |
| 44 compiler.dumpInfoTask._constantToNode.forEach((constant, node) { | 37 compiler.dumpInfoTask._constantToNode.forEach((constant, node) { |
| 45 // TODO(sigmund): add dependencies on other constants | 38 // TODO(sigmund): add dependencies on other constants |
| 46 var size = compiler.dumpInfoTask._nodeToSize[node]; | 39 var size = compiler.dumpInfoTask._nodeToSize[node]; |
| 47 var code = jsAst.prettyPrint(node, compiler).getText(); | 40 var code = jsAst.prettyPrint(node, compiler).getText(); |
| 48 var info = new ConstantInfo(size: size, code: code); | 41 var info = new ConstantInfo( |
| 42 size: size, code: code, outputUnit: _unitInfoForConstant(constant)); | |
| 49 _constantToInfo[constant] = info; | 43 _constantToInfo[constant] = info; |
| 50 result.constants.add(info); | 44 result.constants.add(info); |
| 51 | |
| 52 }); | 45 }); |
| 53 compiler.libraryLoader.libraries.forEach(visit); | 46 compiler.libraryLoader.libraries.forEach(visit); |
| 54 } | 47 } |
| 55 | 48 |
| 56 Info visit(Element e, [_]) => e.accept(this, null); | 49 Info visit(Element e, [_]) => e.accept(this, null); |
| 57 | 50 |
| 58 /// Whether to emit information about [element]. | 51 /// Whether to emit information about [element]. |
| 59 /// | 52 /// |
| 60 /// By default we emit information for any element that contributes to the | 53 /// By default we emit information for any element that contributes to the |
| 61 /// output size. Either becuase the it is a function being emitted or inlined, | 54 /// output size. Either becuase the it is a function being emitted or inlined, |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 75 Info visitElement(Element element, _) => null; | 68 Info visitElement(Element element, _) => null; |
| 76 | 69 |
| 77 FunctionInfo visitConstructorBodyElement(ConstructorBodyElement e, _) { | 70 FunctionInfo visitConstructorBodyElement(ConstructorBodyElement e, _) { |
| 78 return visitFunctionElement(e.constructor, _); | 71 return visitFunctionElement(e.constructor, _); |
| 79 } | 72 } |
| 80 | 73 |
| 81 LibraryInfo visitLibraryElement(LibraryElement element, _) { | 74 LibraryInfo visitLibraryElement(LibraryElement element, _) { |
| 82 String libname = element.hasLibraryName ? element.libraryName : "<unnamed>"; | 75 String libname = element.hasLibraryName ? element.libraryName : "<unnamed>"; |
| 83 int size = compiler.dumpInfoTask.sizeOf(element); | 76 int size = compiler.dumpInfoTask.sizeOf(element); |
| 84 LibraryInfo info = | 77 LibraryInfo info = |
| 85 new LibraryInfo(libname, element.canonicalUri, null, size); | 78 new LibraryInfo(libname, element.canonicalUri, null, size); |
| 86 _elementToInfo[element] = info; | 79 _elementToInfo[element] = info; |
| 87 | 80 |
| 88 LibraryElement realElement = element.isPatched ? element.patch : element; | 81 LibraryElement realElement = element.isPatched ? element.patch : element; |
| 89 realElement.forEachLocalMember((Element member) { | 82 realElement.forEachLocalMember((Element member) { |
| 90 Info child = this.process(member); | 83 Info child = this.process(member); |
| 91 if (child is ClassInfo) { | 84 if (child is ClassInfo) { |
| 92 info.classes.add(child); | 85 info.classes.add(child); |
| 93 child.parent = info; | 86 child.parent = info; |
| 94 } else if (child is FunctionInfo) { | 87 } else if (child is FunctionInfo) { |
| 95 info.topLevelFunctions.add(child); | 88 info.topLevelFunctions.add(child); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 106 } | 99 } |
| 107 }); | 100 }); |
| 108 | 101 |
| 109 if (info.isEmpty && !shouldKeep(element)) return null; | 102 if (info.isEmpty && !shouldKeep(element)) return null; |
| 110 result.libraries.add(info); | 103 result.libraries.add(info); |
| 111 return info; | 104 return info; |
| 112 } | 105 } |
| 113 | 106 |
| 114 TypedefInfo visitTypedefElement(TypedefElement element, _) { | 107 TypedefInfo visitTypedefElement(TypedefElement element, _) { |
| 115 if (!element.isResolved) return null; | 108 if (!element.isResolved) return null; |
| 116 TypedefInfo info = new TypedefInfo(element.name, '${element.alias}', | 109 TypedefInfo info = new TypedefInfo( |
| 117 _unitInfoForElement(element)); | 110 element.name, '${element.alias}', _unitInfoForElement(element)); |
| 118 _elementToInfo[element] = info; | 111 _elementToInfo[element] = info; |
| 119 result.typedefs.add(info); | 112 result.typedefs.add(info); |
| 120 return info; | 113 return info; |
| 121 } | 114 } |
| 122 | 115 |
| 123 FieldInfo visitFieldElement(FieldElement element, _) { | 116 FieldInfo visitFieldElement(FieldElement element, _) { |
| 124 TypeMask inferredType = | 117 TypeMask inferredType = |
| 125 compiler.typesTask.getGuaranteedTypeOfElement(element); | 118 compiler.typesTask.getGuaranteedTypeOfElement(element); |
| 126 // If a field has an empty inferred type it is never used. | 119 // If a field has an empty inferred type it is never used. |
| 127 if (inferredType == null || inferredType.isEmpty) return null; | 120 if (inferredType == null || inferredType.isEmpty) return null; |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 277 } | 270 } |
| 278 String inferredReturnType = | 271 String inferredReturnType = |
| 279 '${compiler.typesTask.getGuaranteedReturnTypeOfElement(element)}'; | 272 '${compiler.typesTask.getGuaranteedReturnTypeOfElement(element)}'; |
| 280 String sideEffects = '${compiler.world.getSideEffectsOfElement(element)}'; | 273 String sideEffects = '${compiler.world.getSideEffectsOfElement(element)}'; |
| 281 | 274 |
| 282 int inlinedCount = compiler.dumpInfoTask.inlineCount[element]; | 275 int inlinedCount = compiler.dumpInfoTask.inlineCount[element]; |
| 283 if (inlinedCount == null) inlinedCount = 0; | 276 if (inlinedCount == null) inlinedCount = 0; |
| 284 | 277 |
| 285 FunctionInfo info = new FunctionInfo( | 278 FunctionInfo info = new FunctionInfo( |
| 286 name: name, | 279 name: name, |
| 280 functionKind: kind, | |
| 287 // We use element.hashCode because it is globally unique and it is | 281 // We use element.hashCode because it is globally unique and it is |
| 288 // available while we are doing codegen. | 282 // available while we are doing codegen. |
| 289 coverageId: '${element.hashCode}', | 283 coverageId: '${element.hashCode}', |
| 290 modifiers: modifiers, | 284 modifiers: modifiers, |
| 291 size: size, | 285 size: size, |
| 292 returnType: returnType, | 286 returnType: returnType, |
| 293 inferredReturnType: inferredReturnType, | 287 inferredReturnType: inferredReturnType, |
| 294 parameters: parameters, | 288 parameters: parameters, |
| 295 sideEffects: sideEffects, | 289 sideEffects: sideEffects, |
| 296 inlinedCount: inlinedCount, | 290 inlinedCount: inlinedCount, |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 318 info.closures = nestedClosures; | 312 info.closures = nestedClosures; |
| 319 result.functions.add(info); | 313 result.functions.add(info); |
| 320 if (const bool.fromEnvironment('send_stats')) { | 314 if (const bool.fromEnvironment('send_stats')) { |
| 321 info.measurements = collectSendMeasurements(element, compiler); | 315 info.measurements = collectSendMeasurements(element, compiler); |
| 322 } | 316 } |
| 323 return info; | 317 return info; |
| 324 } | 318 } |
| 325 | 319 |
| 326 OutputUnitInfo _unitInfoForElement(Element element) { | 320 OutputUnitInfo _unitInfoForElement(Element element) { |
| 327 OutputUnit outputUnit = | 321 OutputUnit outputUnit = |
| 328 compiler.deferredLoadTask.outputUnitForElement(element); | 322 compiler.deferredLoadTask.outputUnitForElement(element); |
| 329 return _outputToInfo.putIfAbsent(outputUnit, () { | 323 return _outputToInfo.putIfAbsent(outputUnit, () { |
| 330 // Dump-info currently only works with the full emitter. If another | 324 // Dump-info currently only works with the full emitter. If another |
| 331 // emitter is used it will fail here. | 325 // emitter is used it will fail here. |
| 326 JavaScriptBackend backend = compiler.backend; | |
| 327 full.Emitter emitter = backend.emitter.emitter; | |
| 328 OutputUnitInfo info = new OutputUnitInfo( | |
| 329 outputUnit.name, emitter.outputBuffers[outputUnit].length); | |
| 330 result.outputUnits.add(info); | |
| 331 return info; | |
| 332 }); | |
| 333 } | |
| 334 | |
| 335 OutputUnitInfo _unitInfoForConstant(ConstantValue constant) { | |
| 336 OutputUnit outputUnit = | |
| 337 compiler.deferredLoadTask.outputUnitForConstant(constant); | |
| 338 if (outputUnit == null) { | |
| 339 assert(constant is InterceptorConstantValue); | |
| 340 return null; | |
| 341 } | |
| 342 return _outputToInfo.putIfAbsent(outputUnit, () { | |
|
Siggi Cherem (dart-lang)
2015/11/03 02:30:18
nit: let's factor out this common part of the code
Harry Terkelsen
2015/11/03 02:43:34
Done.
| |
| 343 // Dump-info currently only works with the full emitter. If another | |
| 344 // emitter is used it will fail here. | |
| 332 JavaScriptBackend backend = compiler.backend; | 345 JavaScriptBackend backend = compiler.backend; |
| 333 full.Emitter emitter = backend.emitter.emitter; | 346 full.Emitter emitter = backend.emitter.emitter; |
| 334 OutputUnitInfo info = new OutputUnitInfo( | 347 OutputUnitInfo info = new OutputUnitInfo( |
| 335 outputUnit.name, emitter.outputBuffers[outputUnit].length); | 348 outputUnit.name, emitter.outputBuffers[outputUnit].length); |
| 336 result.outputUnits.add(info); | 349 result.outputUnits.add(info); |
| 337 return info; | 350 return info; |
| 338 }); | 351 }); |
| 339 } | 352 } |
| 340 } | 353 } |
| 341 | 354 |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 540 outerInfo.uses.add(new DependencyInfo(inlinedInfo, 'inlined')); | 553 outerInfo.uses.add(new DependencyInfo(inlinedInfo, 'inlined')); |
| 541 } | 554 } |
| 542 } | 555 } |
| 543 | 556 |
| 544 AllInfo result = infoCollector.result; | 557 AllInfo result = infoCollector.result; |
| 545 | 558 |
| 546 for (Element element in _dependencies.keys) { | 559 for (Element element in _dependencies.keys) { |
| 547 var a = infoCollector._elementToInfo[element]; | 560 var a = infoCollector._elementToInfo[element]; |
| 548 if (a == null) continue; | 561 if (a == null) continue; |
| 549 result.dependencies[a] = _dependencies[element] | 562 result.dependencies[a] = _dependencies[element] |
| 550 .map((o) => infoCollector._elementToInfo[o]) | 563 .map((o) => infoCollector._elementToInfo[o]) |
| 551 .where((o) => o != null) | 564 .where((o) => o != null) |
| 552 .toList(); | 565 .toList(); |
| 553 } | 566 } |
| 554 | 567 |
| 555 result.deferredFiles = compiler.deferredLoadTask.computeDeferredMap(); | 568 result.deferredFiles = compiler.deferredLoadTask.computeDeferredMap(); |
| 556 stopwatch.stop(); | 569 stopwatch.stop(); |
| 557 result.program = new ProgramInfo( | 570 result.program = new ProgramInfo( |
| 558 entrypoint: infoCollector._elementToInfo[compiler.mainFunction], | 571 entrypoint: infoCollector._elementToInfo[compiler.mainFunction], |
| 559 size: _programSize, | 572 size: _programSize, |
| 560 dart2jsVersion: compiler.hasBuildId ? compiler.buildId : null, | 573 dart2jsVersion: compiler.hasBuildId ? compiler.buildId : null, |
| 561 compilationMoment: new DateTime.now(), | 574 compilationMoment: new DateTime.now(), |
| 562 compilationDuration: compiler.totalCompileTime.elapsed, | 575 compilationDuration: compiler.totalCompileTime.elapsed, |
| 563 toJsonDuration: stopwatch.elapsedMilliseconds, | 576 toJsonDuration: stopwatch.elapsedMilliseconds, |
| 564 dumpInfoDuration: this.timing, | 577 dumpInfoDuration: this.timing, |
| 565 noSuchMethodEnabled: compiler.backend.enabledNoSuchMethod, | 578 noSuchMethodEnabled: compiler.backend.enabledNoSuchMethod, |
| 566 minified: compiler.enableMinification); | 579 minified: compiler.enableMinification); |
| 567 | 580 |
| 568 ChunkedConversionSink<Object> sink = encoder.startChunkedConversion( | 581 ChunkedConversionSink<Object> sink = encoder.startChunkedConversion( |
| 569 new StringConversionSink.fromStringSink(buffer)); | 582 new StringConversionSink.fromStringSink(buffer)); |
| 570 sink.add(new AllInfoJsonCodec().encode(result)); | 583 sink.add(new AllInfoJsonCodec().encode(result)); |
| 571 reporter.reportInfo(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, { | 584 reporter.reportInfo(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, { |
| 572 'text': "View the dumped .info.json file at " | 585 'text': "View the dumped .info.json file at " |
| 573 "https://dart-lang.github.io/dump-info-visualizer" | 586 "https://dart-lang.github.io/dump-info-visualizer" |
| 574 }); | 587 }); |
| 575 } | 588 } |
| 576 } | 589 } |
| OLD | NEW |