| 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 ChunkedConversionSink, JsonEncoder, StringConversionSink; | 8 show ChunkedConversionSink, JsonEncoder, StringConversionSink; |
| 9 | 9 |
| 10 import 'package:dart2js_info/info.dart'; | 10 import 'package:dart2js_info/info.dart'; |
| 11 | 11 |
| 12 import 'closure.dart'; | 12 import 'closure.dart'; |
| 13 import 'common/tasks.dart' show CompilerTask; | 13 import 'common/tasks.dart' show CompilerTask; |
| 14 import 'common.dart'; | 14 import 'common.dart'; |
| 15 import 'compiler.dart' show Compiler; | 15 import 'compiler.dart' show Compiler; |
| 16 import 'constants/values.dart' show ConstantValue, InterceptorConstantValue; | 16 import 'constants/values.dart' show ConstantValue, InterceptorConstantValue; |
| 17 import 'deferred_load.dart' show OutputUnit; | 17 import 'deferred_load.dart' show OutputUnit; |
| 18 import 'elements/elements.dart'; | 18 import 'elements/elements.dart'; |
| 19 import 'elements/visitor.dart'; | 19 import 'elements/visitor.dart'; |
| 20 import 'js/js.dart' as jsAst; | 20 import 'js/js.dart' as jsAst; |
| 21 import 'js_backend/js_backend.dart' show JavaScriptBackend; | 21 import 'js_backend/js_backend.dart' show JavaScriptBackend; |
| 22 import 'js_emitter/full_emitter/emitter.dart' as full show Emitter; | 22 import 'js_emitter/full_emitter/emitter.dart' as full show Emitter; |
| 23 import 'types/types.dart' show TypeMask; | 23 import 'types/types.dart' show TypeMask; |
| 24 import 'universe/world_builder.dart' show ReceiverConstraint; | 24 import 'universe/world_builder.dart' show ReceiverConstraint; |
| 25 import 'universe/world_impact.dart' | 25 import 'universe/world_impact.dart' |
| 26 show ImpactUseCase, WorldImpact, WorldImpactVisitorImpl; | 26 show ImpactUseCase, WorldImpact, WorldImpactVisitorImpl; |
| 27 import 'world.dart' show ClosedWorld; |
| 27 | 28 |
| 28 class ElementInfoCollector extends BaseElementVisitor<Info, dynamic> { | 29 class ElementInfoCollector extends BaseElementVisitor<Info, dynamic> { |
| 29 final Compiler compiler; | 30 final Compiler compiler; |
| 31 final ClosedWorld closedWorld; |
| 30 | 32 |
| 31 final AllInfo result = new AllInfo(); | 33 final AllInfo result = new AllInfo(); |
| 32 final Map<Element, Info> _elementToInfo = <Element, Info>{}; | 34 final Map<Element, Info> _elementToInfo = <Element, Info>{}; |
| 33 final Map<ConstantValue, Info> _constantToInfo = <ConstantValue, Info>{}; | 35 final Map<ConstantValue, Info> _constantToInfo = <ConstantValue, Info>{}; |
| 34 final Map<OutputUnit, OutputUnitInfo> _outputToInfo = {}; | 36 final Map<OutputUnit, OutputUnitInfo> _outputToInfo = {}; |
| 35 | 37 |
| 36 ElementInfoCollector(this.compiler); | 38 ElementInfoCollector(this.compiler, this.closedWorld); |
| 37 | 39 |
| 38 void run() { | 40 void run() { |
| 39 compiler.dumpInfoTask._constantToNode.forEach((constant, node) { | 41 compiler.dumpInfoTask._constantToNode.forEach((constant, node) { |
| 40 // TODO(sigmund): add dependencies on other constants | 42 // TODO(sigmund): add dependencies on other constants |
| 41 var size = compiler.dumpInfoTask._nodeToSize[node]; | 43 var size = compiler.dumpInfoTask._nodeToSize[node]; |
| 42 var code = jsAst.prettyPrint(node, compiler); | 44 var code = jsAst.prettyPrint(node, compiler); |
| 43 var info = new ConstantInfo( | 45 var info = new ConstantInfo( |
| 44 size: size, code: code, outputUnit: _unitInfoForConstant(constant)); | 46 size: size, code: code, outputUnit: _unitInfoForConstant(constant)); |
| 45 _constantToInfo[constant] = info; | 47 _constantToInfo[constant] = info; |
| 46 result.constants.add(info); | 48 result.constants.add(info); |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 signature.forEachParameter((parameter) { | 255 signature.forEachParameter((parameter) { |
| 254 parameters.add(new ParameterInfo(parameter.name, | 256 parameters.add(new ParameterInfo(parameter.name, |
| 255 '${_resultOf(parameter).type}', '${parameter.node.type}')); | 257 '${_resultOf(parameter).type}', '${parameter.node.type}')); |
| 256 }); | 258 }); |
| 257 } | 259 } |
| 258 | 260 |
| 259 String returnType = null; | 261 String returnType = null; |
| 260 // TODO(sigmund): why all these checks? | 262 // TODO(sigmund): why all these checks? |
| 261 if (element.isInstanceMember && | 263 if (element.isInstanceMember && |
| 262 !element.isAbstract && | 264 !element.isAbstract && |
| 263 compiler.closedWorld.allFunctions.contains(element)) { | 265 closedWorld.allFunctions.contains(element)) { |
| 264 returnType = '${element.type.returnType}'; | 266 returnType = '${element.type.returnType}'; |
| 265 } | 267 } |
| 266 String inferredReturnType = '${_resultOf(element).returnType}'; | 268 String inferredReturnType = '${_resultOf(element).returnType}'; |
| 267 String sideEffects = | 269 String sideEffects = '${closedWorld.getSideEffectsOfElement(element)}'; |
| 268 '${compiler.closedWorld.getSideEffectsOfElement(element)}'; | |
| 269 | 270 |
| 270 int inlinedCount = compiler.dumpInfoTask.inlineCount[element]; | 271 int inlinedCount = compiler.dumpInfoTask.inlineCount[element]; |
| 271 if (inlinedCount == null) inlinedCount = 0; | 272 if (inlinedCount == null) inlinedCount = 0; |
| 272 | 273 |
| 273 FunctionInfo info = new FunctionInfo( | 274 FunctionInfo info = new FunctionInfo( |
| 274 name: name, | 275 name: name, |
| 275 functionKind: kind, | 276 functionKind: kind, |
| 276 // We use element.hashCode because it is globally unique and it is | 277 // We use element.hashCode because it is globally unique and it is |
| 277 // available while we are doing codegen. | 278 // available while we are doing codegen. |
| 278 coverageId: '${element.hashCode}', | 279 coverageId: '${element.hashCode}', |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 | 436 |
| 436 void unregisterImpact(var impactSource) { | 437 void unregisterImpact(var impactSource) { |
| 437 impacts.remove(impactSource); | 438 impacts.remove(impactSource); |
| 438 } | 439 } |
| 439 | 440 |
| 440 /** | 441 /** |
| 441 * Returns an iterable of [Selection]s that are used by | 442 * Returns an iterable of [Selection]s that are used by |
| 442 * [element]. Each [Selection] contains an element that is | 443 * [element]. Each [Selection] contains an element that is |
| 443 * used and the selector that selected the element. | 444 * used and the selector that selected the element. |
| 444 */ | 445 */ |
| 445 Iterable<Selection> getRetaining(Element element) { | 446 Iterable<Selection> getRetaining(Element element, ClosedWorld closedWorld) { |
| 446 WorldImpact impact = impacts[element]; | 447 WorldImpact impact = impacts[element]; |
| 447 if (impact == null) return const <Selection>[]; | 448 if (impact == null) return const <Selection>[]; |
| 448 | 449 |
| 449 var selections = <Selection>[]; | 450 var selections = <Selection>[]; |
| 450 compiler.impactStrategy.visitImpact( | 451 compiler.impactStrategy.visitImpact( |
| 451 element, | 452 element, |
| 452 impact, | 453 impact, |
| 453 new WorldImpactVisitorImpl(visitDynamicUse: (dynamicUse) { | 454 new WorldImpactVisitorImpl(visitDynamicUse: (dynamicUse) { |
| 454 selections.addAll(compiler.closedWorld.allFunctions | 455 selections.addAll(closedWorld.allFunctions |
| 455 .filter(dynamicUse.selector, dynamicUse.mask) | 456 .filter(dynamicUse.selector, dynamicUse.mask) |
| 456 .map((e) => new Selection(e, dynamicUse.mask))); | 457 .map((e) => new Selection(e, dynamicUse.mask))); |
| 457 }, visitStaticUse: (staticUse) { | 458 }, visitStaticUse: (staticUse) { |
| 458 selections.add(new Selection(staticUse.element, null)); | 459 selections.add(new Selection(staticUse.element, null)); |
| 459 }), | 460 }), |
| 460 IMPACT_USE); | 461 IMPACT_USE); |
| 461 return selections; | 462 return selections; |
| 462 } | 463 } |
| 463 | 464 |
| 464 // Returns true if we care about tracking the size of | 465 // Returns true if we care about tracking the size of |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 List<jsAst.Node> code = _elementToNodes[element]; | 522 List<jsAst.Node> code = _elementToNodes[element]; |
| 522 if (code == null) return null; | 523 if (code == null) return null; |
| 523 // Concatenate rendered ASTs. | 524 // Concatenate rendered ASTs. |
| 524 StringBuffer sb = new StringBuffer(); | 525 StringBuffer sb = new StringBuffer(); |
| 525 for (jsAst.Node ast in code) { | 526 for (jsAst.Node ast in code) { |
| 526 sb.writeln(jsAst.prettyPrint(ast, compiler)); | 527 sb.writeln(jsAst.prettyPrint(ast, compiler)); |
| 527 } | 528 } |
| 528 return sb.toString(); | 529 return sb.toString(); |
| 529 } | 530 } |
| 530 | 531 |
| 531 void dumpInfo() { | 532 void dumpInfo(ClosedWorld closedWorld) { |
| 532 measure(() { | 533 measure(() { |
| 533 infoCollector = new ElementInfoCollector(compiler)..run(); | 534 infoCollector = new ElementInfoCollector(compiler, closedWorld)..run(); |
| 534 StringBuffer jsonBuffer = new StringBuffer(); | 535 StringBuffer jsonBuffer = new StringBuffer(); |
| 535 dumpInfoJson(jsonBuffer); | 536 dumpInfoJson(jsonBuffer, closedWorld); |
| 536 compiler.outputProvider('', 'info.json') | 537 compiler.outputProvider('', 'info.json') |
| 537 ..add(jsonBuffer.toString()) | 538 ..add(jsonBuffer.toString()) |
| 538 ..close(); | 539 ..close(); |
| 539 }); | 540 }); |
| 540 } | 541 } |
| 541 | 542 |
| 542 void dumpInfoJson(StringSink buffer) { | 543 void dumpInfoJson(StringSink buffer, ClosedWorld closedWorld) { |
| 543 JsonEncoder encoder = const JsonEncoder.withIndent(' '); | 544 JsonEncoder encoder = const JsonEncoder.withIndent(' '); |
| 544 Stopwatch stopwatch = new Stopwatch(); | 545 Stopwatch stopwatch = new Stopwatch(); |
| 545 stopwatch.start(); | 546 stopwatch.start(); |
| 546 | 547 |
| 547 // Recursively build links to function uses | 548 // Recursively build links to function uses |
| 548 Iterable<Element> functionElements = | 549 Iterable<Element> functionElements = |
| 549 infoCollector._elementToInfo.keys.where((k) => k is FunctionElement); | 550 infoCollector._elementToInfo.keys.where((k) => k is FunctionElement); |
| 550 for (FunctionElement element in functionElements) { | 551 for (FunctionElement element in functionElements) { |
| 551 FunctionInfo info = infoCollector._elementToInfo[element]; | 552 FunctionInfo info = infoCollector._elementToInfo[element]; |
| 552 Iterable<Selection> uses = getRetaining(element); | 553 Iterable<Selection> uses = getRetaining(element, closedWorld); |
| 553 // Don't bother recording an empty list of dependencies. | 554 // Don't bother recording an empty list of dependencies. |
| 554 for (Selection selection in uses) { | 555 for (Selection selection in uses) { |
| 555 // Don't register dart2js builtin functions that are not recorded. | 556 // Don't register dart2js builtin functions that are not recorded. |
| 556 Info useInfo = infoCollector._elementToInfo[selection.selectedElement]; | 557 Info useInfo = infoCollector._elementToInfo[selection.selectedElement]; |
| 557 if (useInfo == null) continue; | 558 if (useInfo == null) continue; |
| 558 info.uses.add(new DependencyInfo(useInfo, '${selection.mask}')); | 559 info.uses.add(new DependencyInfo(useInfo, '${selection.mask}')); |
| 559 } | 560 } |
| 560 } | 561 } |
| 561 // Notify the impact strategy impacts are no longer needed for dump info. | 562 // Notify the impact strategy impacts are no longer needed for dump info. |
| 562 compiler.impactStrategy.onImpactUsed(IMPACT_USE); | 563 compiler.impactStrategy.onImpactUsed(IMPACT_USE); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 | 601 |
| 601 ChunkedConversionSink<Object> sink = encoder.startChunkedConversion( | 602 ChunkedConversionSink<Object> sink = encoder.startChunkedConversion( |
| 602 new StringConversionSink.fromStringSink(buffer)); | 603 new StringConversionSink.fromStringSink(buffer)); |
| 603 sink.add(new AllInfoJsonCodec().encode(result)); | 604 sink.add(new AllInfoJsonCodec().encode(result)); |
| 604 compiler.reporter.reportInfo(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, { | 605 compiler.reporter.reportInfo(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, { |
| 605 'text': "View the dumped .info.json file at " | 606 'text': "View the dumped .info.json file at " |
| 606 "https://dart-lang.github.io/dump-info-visualizer" | 607 "https://dart-lang.github.io/dump-info-visualizer" |
| 607 }); | 608 }); |
| 608 } | 609 } |
| 609 } | 610 } |
| OLD | NEW |