| 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' show |
| 8 show HtmlEscape, JsonEncoder, StringConversionSink, ChunkedConversionSink; | 8 ChunkedConversionSink, |
| 9 HtmlEscape, |
| 10 JsonEncoder, |
| 11 StringConversionSink; |
| 9 | 12 |
| 10 import 'package:dart2js_info/info.dart'; | 13 import 'package:dart2js_info/info.dart'; |
| 11 | 14 |
| 12 import 'common.dart'; | 15 import 'common.dart'; |
| 13 import 'common/tasks.dart' show CompilerTask; | 16 import 'common/tasks.dart' show |
| 14 import 'constants/values.dart' show ConstantValue, InterceptorConstantValue; | 17 CompilerTask; |
| 15 import 'compiler.dart' show Compiler; | 18 import 'constants/values.dart' show |
| 19 ConstantValue, |
| 20 InterceptorConstantValue; |
| 21 import 'compiler.dart' show |
| 22 Compiler; |
| 23 import 'deferred_load.dart' show |
| 24 OutputUnit; |
| 16 import 'elements/elements.dart'; | 25 import 'elements/elements.dart'; |
| 17 import 'elements/visitor.dart'; | 26 import 'elements/visitor.dart'; |
| 18 import 'types/types.dart' show TypeMask; | 27 import 'info/send_info.dart' show |
| 19 import 'deferred_load.dart' show OutputUnit; | 28 collectSendMeasurements; |
| 20 import 'js_backend/js_backend.dart' show JavaScriptBackend; | 29 import 'js_backend/js_backend.dart' show |
| 21 import 'js_emitter/full_emitter/emitter.dart' as full show Emitter; | 30 JavaScriptBackend; |
| 31 import 'js_emitter/full_emitter/emitter.dart' as full show |
| 32 Emitter; |
| 22 import 'js/js.dart' as jsAst; | 33 import 'js/js.dart' as jsAst; |
| 23 import 'universe/universe.dart' show ReceiverConstraint; | 34 import 'types/types.dart' show |
| 24 import 'universe/world_impact.dart' show WorldImpact; | 35 TypeMask; |
| 25 import 'info/send_info.dart' show collectSendMeasurements; | 36 import 'universe/universe.dart' show |
| 37 ReceiverConstraint; |
| 38 import 'universe/world_impact.dart' show |
| 39 ImpactUseCase, |
| 40 WorldImpact, |
| 41 WorldImpactVisitorImpl; |
| 26 | 42 |
| 27 class ElementInfoCollector extends BaseElementVisitor<Info, dynamic> { | 43 class ElementInfoCollector extends BaseElementVisitor<Info, dynamic> { |
| 28 final Compiler compiler; | 44 final Compiler compiler; |
| 29 | 45 |
| 30 final AllInfo result = new AllInfo(); | 46 final AllInfo result = new AllInfo(); |
| 31 final Map<Element, Info> _elementToInfo = <Element, Info>{}; | 47 final Map<Element, Info> _elementToInfo = <Element, Info>{}; |
| 32 final Map<ConstantValue, Info> _constantToInfo = <ConstantValue, Info>{}; | 48 final Map<ConstantValue, Info> _constantToInfo = <ConstantValue, Info>{}; |
| 33 final Map<OutputUnit, OutputUnitInfo> _outputToInfo = {}; | 49 final Map<OutputUnit, OutputUnitInfo> _outputToInfo = {}; |
| 34 | 50 |
| 35 ElementInfoCollector(this.compiler); | 51 ElementInfoCollector(this.compiler); |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 /// we can emit them in the dump-info task. | 375 /// we can emit them in the dump-info task. |
| 360 // TODO(sigmund,het): move more features here. Ideally the dump-info task | 376 // TODO(sigmund,het): move more features here. Ideally the dump-info task |
| 361 // shouldn't reach into internals of other parts of the compiler. For example, | 377 // shouldn't reach into internals of other parts of the compiler. For example, |
| 362 // we currently reach into the full emitter and as a result we don't support | 378 // we currently reach into the full emitter and as a result we don't support |
| 363 // dump-info when using the startup-emitter (issue #24190). | 379 // dump-info when using the startup-emitter (issue #24190). |
| 364 abstract class InfoReporter { | 380 abstract class InfoReporter { |
| 365 void reportInlined(Element element, Element inlinedFrom); | 381 void reportInlined(Element element, Element inlinedFrom); |
| 366 } | 382 } |
| 367 | 383 |
| 368 class DumpInfoTask extends CompilerTask implements InfoReporter { | 384 class DumpInfoTask extends CompilerTask implements InfoReporter { |
| 385 static const ImpactUseCase IMPACT_USE = const ImpactUseCase('Dump info'); |
| 386 |
| 369 DumpInfoTask(Compiler compiler) : super(compiler); | 387 DumpInfoTask(Compiler compiler) : super(compiler); |
| 370 | 388 |
| 371 String get name => "Dump Info"; | 389 String get name => "Dump Info"; |
| 372 | 390 |
| 373 ElementInfoCollector infoCollector; | 391 ElementInfoCollector infoCollector; |
| 374 | 392 |
| 375 /// The size of the generated output. | 393 /// The size of the generated output. |
| 376 int _programSize; | 394 int _programSize; |
| 377 | 395 |
| 378 // A set of javascript AST nodes that we care about the size of. | 396 // A set of javascript AST nodes that we care about the size of. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 void registerDependency(Element source, Element target) { | 429 void registerDependency(Element source, Element target) { |
| 412 _dependencies.putIfAbsent(source, () => new Set()).add(target); | 430 _dependencies.putIfAbsent(source, () => new Set()).add(target); |
| 413 } | 431 } |
| 414 | 432 |
| 415 void registerImpact(Element element, WorldImpact impact) { | 433 void registerImpact(Element element, WorldImpact impact) { |
| 416 if (compiler.dumpInfo) { | 434 if (compiler.dumpInfo) { |
| 417 impacts[element] = impact; | 435 impacts[element] = impact; |
| 418 } | 436 } |
| 419 } | 437 } |
| 420 | 438 |
| 439 void unregisterImpact(Element element) { |
| 440 impacts.remove(element); |
| 441 } |
| 442 |
| 421 /** | 443 /** |
| 422 * Returns an iterable of [Selection]s that are used by | 444 * Returns an iterable of [Selection]s that are used by |
| 423 * [element]. Each [Selection] contains an element that is | 445 * [element]. Each [Selection] contains an element that is |
| 424 * used and the selector that selected the element. | 446 * used and the selector that selected the element. |
| 425 */ | 447 */ |
| 426 Iterable<Selection> getRetaining(Element element) { | 448 Iterable<Selection> getRetaining(Element element) { |
| 427 var impact = impacts[element]; | 449 WorldImpact impact = impacts[element]; |
| 428 if (impact == null) return const <Selection>[]; | 450 if (impact == null) return const <Selection>[]; |
| 429 | 451 |
| 430 var selections = <Selection>[]; | 452 var selections = <Selection>[]; |
| 431 selections.addAll(impact.dynamicUses.expand((dynamicUse) { | 453 compiler.impactStrategy.visitImpact( |
| 432 return compiler.world.allFunctions | 454 element, |
| 433 .filter(dynamicUse.selector, dynamicUse.mask) | 455 impact, |
| 434 .map((e) => new Selection(e, dynamicUse.mask)); | 456 new WorldImpactVisitorImpl( |
| 435 })); | 457 visitDynamicUse: (dynamicUse) { |
| 436 selections.addAll(impact.staticUses | 458 selections.addAll(compiler.world.allFunctions |
| 437 .map((staticUse) => new Selection(staticUse.element, null))); | 459 .filter(dynamicUse.selector, dynamicUse.mask) |
| 460 .map((e) => new Selection(e, dynamicUse.mask))); |
| 461 }, |
| 462 visitStaticUse: (staticUse) { |
| 463 selections.add(new Selection(staticUse.element, null)); |
| 464 } |
| 465 ), |
| 466 IMPACT_USE); |
| 438 return selections; | 467 return selections; |
| 439 } | 468 } |
| 440 | 469 |
| 441 // Returns true if we care about tracking the size of | 470 // Returns true if we care about tracking the size of |
| 442 // this node. | 471 // this node. |
| 443 bool isTracking(jsAst.Node code) { | 472 bool isTracking(jsAst.Node code) { |
| 444 if (compiler.dumpInfo) { | 473 if (compiler.dumpInfo) { |
| 445 return _tracking.contains(code); | 474 return _tracking.contains(code); |
| 446 } else { | 475 } else { |
| 447 return false; | 476 return false; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 FunctionInfo info = infoCollector._elementToInfo[element]; | 557 FunctionInfo info = infoCollector._elementToInfo[element]; |
| 529 Iterable<Selection> uses = getRetaining(element); | 558 Iterable<Selection> uses = getRetaining(element); |
| 530 // Don't bother recording an empty list of dependencies. | 559 // Don't bother recording an empty list of dependencies. |
| 531 for (Selection selection in uses) { | 560 for (Selection selection in uses) { |
| 532 // Don't register dart2js builtin functions that are not recorded. | 561 // Don't register dart2js builtin functions that are not recorded. |
| 533 Info useInfo = infoCollector._elementToInfo[selection.selectedElement]; | 562 Info useInfo = infoCollector._elementToInfo[selection.selectedElement]; |
| 534 if (useInfo == null) continue; | 563 if (useInfo == null) continue; |
| 535 info.uses.add(new DependencyInfo(useInfo, '${selection.mask}')); | 564 info.uses.add(new DependencyInfo(useInfo, '${selection.mask}')); |
| 536 } | 565 } |
| 537 } | 566 } |
| 567 // Notify the impact strategy impacts are no longer needed for dump info. |
| 568 compiler.impactStrategy.onImpactUsed(IMPACT_USE); |
| 538 | 569 |
| 539 // Track dependencies that come from inlining. | 570 // Track dependencies that come from inlining. |
| 540 for (Element element in inlineMap.keys) { | 571 for (Element element in inlineMap.keys) { |
| 541 CodeInfo outerInfo = infoCollector._elementToInfo[element]; | 572 CodeInfo outerInfo = infoCollector._elementToInfo[element]; |
| 542 if (outerInfo == null) continue; | 573 if (outerInfo == null) continue; |
| 543 for (Element inlined in inlineMap[element]) { | 574 for (Element inlined in inlineMap[element]) { |
| 544 Info inlinedInfo = infoCollector._elementToInfo[inlined]; | 575 Info inlinedInfo = infoCollector._elementToInfo[inlined]; |
| 545 if (inlinedInfo == null) continue; | 576 if (inlinedInfo == null) continue; |
| 546 outerInfo.uses.add(new DependencyInfo(inlinedInfo, 'inlined')); | 577 outerInfo.uses.add(new DependencyInfo(inlinedInfo, 'inlined')); |
| 547 } | 578 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 573 | 604 |
| 574 ChunkedConversionSink<Object> sink = encoder.startChunkedConversion( | 605 ChunkedConversionSink<Object> sink = encoder.startChunkedConversion( |
| 575 new StringConversionSink.fromStringSink(buffer)); | 606 new StringConversionSink.fromStringSink(buffer)); |
| 576 sink.add(new AllInfoJsonCodec().encode(result)); | 607 sink.add(new AllInfoJsonCodec().encode(result)); |
| 577 reporter.reportInfo(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, { | 608 reporter.reportInfo(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, { |
| 578 'text': "View the dumped .info.json file at " | 609 'text': "View the dumped .info.json file at " |
| 579 "https://dart-lang.github.io/dump-info-visualizer" | 610 "https://dart-lang.github.io/dump-info-visualizer" |
| 580 }); | 611 }); |
| 581 } | 612 } |
| 582 } | 613 } |
| OLD | NEW |