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 |