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 ChunkedConversionSink, JsonEncoder, StringConversionSink; | 8 show ChunkedConversionSink, JsonEncoder, StringConversionSink; |
| 9 | 9 |
| 10 import 'package:dart2js_info/info.dart'; | 10 import 'package:dart2js_info/info.dart'; |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 411 final Map<Element, List<Element>> inlineMap = <Element, List<Element>>{}; | 411 final Map<Element, List<Element>> inlineMap = <Element, List<Element>>{}; |
| 412 | 412 |
| 413 final Map<Element, WorldImpact> impacts = <Element, WorldImpact>{}; | 413 final Map<Element, WorldImpact> impacts = <Element, WorldImpact>{}; |
| 414 | 414 |
| 415 /// Register the size of the generated output. | 415 /// Register the size of the generated output. |
| 416 void reportSize(int programSize) { | 416 void reportSize(int programSize) { |
| 417 _programSize = programSize; | 417 _programSize = programSize; |
| 418 } | 418 } |
| 419 | 419 |
| 420 void reportInlined(Element element, Element inlinedFrom) { | 420 void reportInlined(Element element, Element inlinedFrom) { |
| 421 if (element.isPatch) { | |
|
Johnni Winther
2017/02/22 13:29:38
Equivalent to `element = element.declaration`.
Harry Terkelsen
2017/02/22 20:53:14
Done.
| |
| 422 element = element.origin; | |
| 423 } | |
| 424 if (inlinedFrom.isPatch) { | |
| 425 inlinedFrom = inlinedFrom.origin; | |
| 426 } | |
| 421 inlineCount.putIfAbsent(element, () => 0); | 427 inlineCount.putIfAbsent(element, () => 0); |
| 422 inlineCount[element] += 1; | 428 inlineCount[element] += 1; |
| 423 inlineMap.putIfAbsent(inlinedFrom, () => new List<Element>()); | 429 inlineMap.putIfAbsent(inlinedFrom, () => new List<Element>()); |
| 424 inlineMap[inlinedFrom].add(element); | 430 inlineMap[inlinedFrom].add(element); |
| 425 } | 431 } |
| 426 | 432 |
| 427 final Map<Element, Set<Element>> _dependencies = {}; | |
| 428 void registerDependency(Element target) { | |
| 429 if (compiler.options.dumpInfo) { | |
| 430 _dependencies | |
| 431 .putIfAbsent(compiler.currentElement, () => new Set()) | |
| 432 .add(target); | |
| 433 } | |
| 434 } | |
| 435 | |
| 436 void registerImpact(Element element, WorldImpact impact) { | 433 void registerImpact(Element element, WorldImpact impact) { |
| 437 if (compiler.options.dumpInfo) { | 434 if (compiler.options.dumpInfo) { |
| 438 impacts[element] = impact; | 435 impacts[element] = impact; |
| 439 } | 436 } |
| 440 } | 437 } |
| 441 | 438 |
| 442 void unregisterImpact(var impactSource) { | 439 void unregisterImpact(var impactSource) { |
| 443 impacts.remove(impactSource); | 440 impacts.remove(impactSource); |
| 444 } | 441 } |
| 445 | 442 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 543 ..add(jsonBuffer.toString()) | 540 ..add(jsonBuffer.toString()) |
| 544 ..close(); | 541 ..close(); |
| 545 }); | 542 }); |
| 546 } | 543 } |
| 547 | 544 |
| 548 void dumpInfoJson(StringSink buffer, ClosedWorld closedWorld) { | 545 void dumpInfoJson(StringSink buffer, ClosedWorld closedWorld) { |
| 549 JsonEncoder encoder = const JsonEncoder.withIndent(' '); | 546 JsonEncoder encoder = const JsonEncoder.withIndent(' '); |
| 550 Stopwatch stopwatch = new Stopwatch(); | 547 Stopwatch stopwatch = new Stopwatch(); |
| 551 stopwatch.start(); | 548 stopwatch.start(); |
| 552 | 549 |
| 550 AllInfo result = infoCollector.result; | |
| 551 | |
| 553 // Recursively build links to function uses | 552 // Recursively build links to function uses |
| 554 Iterable<Element> functionElements = | 553 Iterable<Element> functionElements = |
| 555 infoCollector._elementToInfo.keys.where((k) => k is FunctionElement); | 554 infoCollector._elementToInfo.keys.where((k) => k is FunctionElement); |
| 556 for (FunctionElement element in functionElements) { | 555 for (FunctionElement element in functionElements) { |
| 557 FunctionInfo info = infoCollector._elementToInfo[element]; | 556 FunctionInfo info = infoCollector._elementToInfo[element]; |
| 558 Iterable<Selection> uses = getRetaining(element, closedWorld); | 557 Iterable<Selection> uses = getRetaining(element, closedWorld); |
| 559 // Don't bother recording an empty list of dependencies. | 558 // Don't bother recording an empty list of dependencies. |
| 560 for (Selection selection in uses) { | 559 for (Selection selection in uses) { |
| 561 // Don't register dart2js builtin functions that are not recorded. | 560 // Don't register dart2js builtin functions that are not recorded. |
| 562 Info useInfo = infoCollector._elementToInfo[selection.selectedElement]; | 561 Info useInfo = infoCollector._elementToInfo[selection.selectedElement]; |
| 563 if (useInfo == null) continue; | 562 if (useInfo == null) continue; |
| 564 info.uses.add(new DependencyInfo(useInfo, '${selection.mask}')); | 563 info.uses.add(new DependencyInfo(useInfo, '${selection.mask}')); |
| 565 } | 564 } |
| 566 } | 565 } |
| 566 | |
| 567 // Recursively build links to field uses | |
| 568 Iterable<Element> fieldElements = | |
| 569 infoCollector._elementToInfo.keys.where((k) => k is FieldElement); | |
| 570 for (FieldElement element in fieldElements) { | |
| 571 FieldInfo info = infoCollector._elementToInfo[element]; | |
| 572 Iterable<Selection> uses = getRetaining(element, closedWorld); | |
| 573 // Don't bother recording an empty list of dependencies. | |
| 574 for (Selection selection in uses) { | |
| 575 Info useInfo = infoCollector._elementToInfo[selection.selectedElement]; | |
| 576 if (useInfo == null) continue; | |
| 577 info.uses.add(new DependencyInfo(useInfo, '${selection.mask}')); | |
| 578 } | |
| 579 } | |
| 580 | |
| 567 // Notify the impact strategy impacts are no longer needed for dump info. | 581 // Notify the impact strategy impacts are no longer needed for dump info. |
| 568 compiler.impactStrategy.onImpactUsed(IMPACT_USE); | 582 compiler.impactStrategy.onImpactUsed(IMPACT_USE); |
| 569 | 583 |
| 570 // Track dependencies that come from inlining. | 584 // Track dependencies that come from inlining. |
| 571 for (Element element in inlineMap.keys) { | 585 for (Element element in inlineMap.keys) { |
| 572 CodeInfo outerInfo = infoCollector._elementToInfo[element]; | 586 CodeInfo outerInfo = infoCollector._elementToInfo[element]; |
| 573 if (outerInfo == null) continue; | 587 if (outerInfo == null) continue; |
| 574 for (Element inlined in inlineMap[element]) { | 588 for (Element inlined in inlineMap[element]) { |
| 575 Info inlinedInfo = infoCollector._elementToInfo[inlined]; | 589 Info inlinedInfo = infoCollector._elementToInfo[inlined]; |
| 576 if (inlinedInfo == null) continue; | 590 if (inlinedInfo == null) continue; |
| 577 outerInfo.uses.add(new DependencyInfo(inlinedInfo, 'inlined')); | 591 outerInfo.uses.add(new DependencyInfo(inlinedInfo, 'inlined')); |
| 578 } | 592 } |
| 579 } | 593 } |
| 580 | 594 |
| 581 AllInfo result = infoCollector.result; | |
| 582 | |
| 583 for (Element element in _dependencies.keys) { | |
| 584 var a = infoCollector._elementToInfo[element]; | |
| 585 if (a == null) continue; | |
| 586 result.dependencies[a] = _dependencies[element] | |
| 587 .map((o) => infoCollector._elementToInfo[o]) | |
| 588 .where((o) => o != null) | |
| 589 .toList(); | |
| 590 } | |
| 591 | |
| 592 result.deferredFiles = compiler.deferredLoadTask.computeDeferredMap(); | 595 result.deferredFiles = compiler.deferredLoadTask.computeDeferredMap(); |
| 593 stopwatch.stop(); | 596 stopwatch.stop(); |
| 594 result.program = new ProgramInfo( | 597 result.program = new ProgramInfo( |
| 595 entrypoint: infoCollector._elementToInfo[compiler.mainFunction], | 598 entrypoint: infoCollector._elementToInfo[compiler.mainFunction], |
| 596 size: _programSize, | 599 size: _programSize, |
| 597 dart2jsVersion: | 600 dart2jsVersion: |
| 598 compiler.options.hasBuildId ? compiler.options.buildId : null, | 601 compiler.options.hasBuildId ? compiler.options.buildId : null, |
| 599 compilationMoment: new DateTime.now(), | 602 compilationMoment: new DateTime.now(), |
| 600 compilationDuration: compiler.measurer.wallClock.elapsed, | 603 compilationDuration: compiler.measurer.wallClock.elapsed, |
| 601 toJsonDuration: | 604 toJsonDuration: |
| 602 new Duration(milliseconds: stopwatch.elapsedMilliseconds), | 605 new Duration(milliseconds: stopwatch.elapsedMilliseconds), |
| 603 dumpInfoDuration: new Duration(milliseconds: this.timing), | 606 dumpInfoDuration: new Duration(milliseconds: this.timing), |
| 604 noSuchMethodEnabled: compiler.backend.enabledNoSuchMethod, | 607 noSuchMethodEnabled: compiler.backend.enabledNoSuchMethod, |
| 605 minified: compiler.options.enableMinification); | 608 minified: compiler.options.enableMinification); |
| 606 | 609 |
| 607 ChunkedConversionSink<Object> sink = encoder.startChunkedConversion( | 610 ChunkedConversionSink<Object> sink = encoder.startChunkedConversion( |
| 608 new StringConversionSink.fromStringSink(buffer)); | 611 new StringConversionSink.fromStringSink(buffer)); |
| 609 sink.add(new AllInfoJsonCodec().encode(result)); | 612 sink.add(new AllInfoJsonCodec().encode(result)); |
| 610 compiler.reporter.reportInfo(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, { | 613 compiler.reporter.reportInfo(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, { |
| 611 'text': "View the dumped .info.json file at " | 614 'text': "View the dumped .info.json file at " |
| 612 "https://dart-lang.github.io/dump-info-visualizer" | 615 "https://dart-lang.github.io/dump-info-visualizer" |
| 613 }); | 616 }); |
| 614 } | 617 } |
| 615 } | 618 } |
| OLD | NEW |