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' show | 7 import 'dart:convert' show |
8 HtmlEscape, | 8 HtmlEscape, |
9 JsonEncoder, | 9 JsonEncoder, |
10 StringConversionSink, | 10 StringConversionSink, |
11 ChunkedConversionSink; | 11 ChunkedConversionSink; |
12 | 12 |
13 import 'elements/elements.dart'; | 13 import 'elements/elements.dart'; |
14 import 'elements/visitor.dart'; | 14 import 'elements/visitor.dart'; |
15 import 'dart2jslib.dart' show | 15 import 'dart2jslib.dart' show |
16 Backend, | 16 Backend, |
17 CodeBuffer, | 17 CodeBuffer, |
18 Compiler, | 18 Compiler, |
19 CompilerTask, | 19 CompilerTask, |
20 MessageKind; | 20 MessageKind; |
21 import 'types/types.dart' show TypeMask; | 21 import 'types/types.dart' show TypeMask; |
22 import 'deferred_load.dart' show OutputUnit; | 22 import 'deferred_load.dart' show OutputUnit; |
23 import 'js_backend/js_backend.dart' show JavaScriptBackend; | 23 import 'js_backend/js_backend.dart' show JavaScriptBackend; |
24 import 'js/js.dart' as jsAst; | 24 import 'js/js.dart' as jsAst; |
25 import 'universe/universe.dart' show Selector, UniverseSelector; | 25 import 'universe/universe.dart' show Selector; |
26 import 'util/util.dart' show NO_LOCATION_SPANNABLE; | 26 import 'util/util.dart' show NO_LOCATION_SPANNABLE; |
27 | 27 |
28 /// Maps objects to an id. Supports lookups in | 28 /// Maps objects to an id. Supports lookups in |
29 /// both directions. | 29 /// both directions. |
30 class IdMapper<T>{ | 30 class IdMapper<T>{ |
31 Map<int, T> _idToElement = {}; | 31 Map<int, T> _idToElement = {}; |
32 Map<T, int> _elementToId = {}; | 32 Map<T, int> _elementToId = {}; |
33 int _idCounter = 0; | 33 int _idCounter = 0; |
34 final String name; | 34 final String name; |
35 | 35 |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 'inlinedCount': inlinedCount, | 382 'inlinedCount': inlinedCount, |
383 'code': emittedCode == null ? null : '$emittedCode', | 383 'code': emittedCode == null ? null : '$emittedCode', |
384 'type': element.type.toString(), | 384 'type': element.type.toString(), |
385 'outputUnit': mapper._outputUnit.add(outputUnit) | 385 'outputUnit': mapper._outputUnit.add(outputUnit) |
386 }; | 386 }; |
387 } | 387 } |
388 } | 388 } |
389 | 389 |
390 class Selection { | 390 class Selection { |
391 final Element selectedElement; | 391 final Element selectedElement; |
392 final TypeMask mask; | 392 final Selector selector; |
393 Selection(this.selectedElement, this.mask); | 393 Selection(this.selectedElement, this.selector); |
394 } | 394 } |
395 | 395 |
396 class DumpInfoTask extends CompilerTask { | 396 class DumpInfoTask extends CompilerTask { |
397 DumpInfoTask(Compiler compiler) | 397 DumpInfoTask(Compiler compiler) |
398 : super(compiler); | 398 : super(compiler); |
399 | 399 |
400 String get name => "Dump Info"; | 400 String get name => "Dump Info"; |
401 | 401 |
402 ElementToJsonVisitor infoCollector; | 402 ElementToJsonVisitor infoCollector; |
403 | 403 |
404 /// The size of the generated output. | 404 /// The size of the generated output. |
405 int _programSize; | 405 int _programSize; |
406 | 406 |
407 // A set of javascript AST nodes that we care about the size of. | 407 // A set of javascript AST nodes that we care about the size of. |
408 // This set is automatically populated when registerElementAst() | 408 // This set is automatically populated when registerElementAst() |
409 // is called. | 409 // is called. |
410 final Set<jsAst.Node> _tracking = new Set<jsAst.Node>(); | 410 final Set<jsAst.Node> _tracking = new Set<jsAst.Node>(); |
411 // A mapping from Dart Elements to Javascript AST Nodes. | 411 // A mapping from Dart Elements to Javascript AST Nodes. |
412 final Map<Element, List<jsAst.Node>> _elementToNodes = | 412 final Map<Element, List<jsAst.Node>> _elementToNodes = |
413 <Element, List<jsAst.Node>>{}; | 413 <Element, List<jsAst.Node>>{}; |
414 // A mapping from Javascript AST Nodes to the size of their | 414 // A mapping from Javascript AST Nodes to the size of their |
415 // pretty-printed contents. | 415 // pretty-printed contents. |
416 final Map<jsAst.Node, int> _nodeToSize = <jsAst.Node, int>{}; | 416 final Map<jsAst.Node, int> _nodeToSize = <jsAst.Node, int>{}; |
417 | 417 |
418 final Map<Element, Set<UniverseSelector>> selectorsFromElement = {}; | 418 final Map<Element, Set<Selector>> selectorsFromElement = {}; |
419 final Map<Element, int> inlineCount = <Element, int>{}; | 419 final Map<Element, int> inlineCount = <Element, int>{}; |
420 // A mapping from an element to a list of elements that are | 420 // A mapping from an element to a list of elements that are |
421 // inlined inside of it. | 421 // inlined inside of it. |
422 final Map<Element, List<Element>> inlineMap = <Element, List<Element>>{}; | 422 final Map<Element, List<Element>> inlineMap = <Element, List<Element>>{}; |
423 | 423 |
424 /// Register the size of the generated output. | 424 /// Register the size of the generated output. |
425 void reportSize(int programSize) { | 425 void reportSize(int programSize) { |
426 _programSize = programSize; | 426 _programSize = programSize; |
427 } | 427 } |
428 | 428 |
429 void registerInlined(Element element, Element inlinedFrom) { | 429 void registerInlined(Element element, Element inlinedFrom) { |
430 inlineCount.putIfAbsent(element, () => 0); | 430 inlineCount.putIfAbsent(element, () => 0); |
431 inlineCount[element] += 1; | 431 inlineCount[element] += 1; |
432 inlineMap.putIfAbsent(inlinedFrom, () => new List<Element>()); | 432 inlineMap.putIfAbsent(inlinedFrom, () => new List<Element>()); |
433 inlineMap[inlinedFrom].add(element); | 433 inlineMap[inlinedFrom].add(element); |
434 } | 434 } |
435 | 435 |
436 /** | 436 /** |
437 * Registers that a function uses a selector in the | 437 * Registers that a function uses a selector in the |
438 * function body | 438 * function body |
439 */ | 439 */ |
440 void elementUsesSelector(Element element, UniverseSelector selector) { | 440 void elementUsesSelector(Element element, Selector selector) { |
441 if (compiler.dumpInfo) { | 441 if (compiler.dumpInfo) { |
442 selectorsFromElement | 442 selectorsFromElement |
443 .putIfAbsent(element, () => new Set<UniverseSelector>()) | 443 .putIfAbsent(element, () => new Set<Selector>()) |
444 .add(selector); | 444 .add(selector); |
445 } | 445 } |
446 } | 446 } |
447 | 447 |
448 /** | 448 /** |
449 * Returns an iterable of [Selection]s that are used by | 449 * Returns an iterable of [Selection]s that are used by |
450 * [element]. Each [Selection] contains an element that is | 450 * [element]. Each [Selection] contains an element that is |
451 * used and the selector that selected the element. | 451 * used and the selector that selected the element. |
452 */ | 452 */ |
453 Iterable<Selection> getRetaining(Element element) { | 453 Iterable<Selection> getRetaining(Element element) { |
454 if (!selectorsFromElement.containsKey(element)) { | 454 if (!selectorsFromElement.containsKey(element)) { |
455 return const <Selection>[]; | 455 return const <Selection>[]; |
456 } else { | 456 } else { |
457 return selectorsFromElement[element].expand( | 457 return selectorsFromElement[element].expand( |
458 (UniverseSelector selector) { | 458 (selector) { |
459 return compiler.world.allFunctions.filter( | 459 return compiler.world.allFunctions.filter(selector).map((element) { |
460 selector.selector, selector.mask) | 460 return new Selection(element, selector); |
461 .map((element) { | |
462 return new Selection(element, selector.mask); | |
463 }); | 461 }); |
464 }); | 462 }); |
465 } | 463 } |
466 } | 464 } |
467 | 465 |
468 // Returns true if we care about tracking the size of | 466 // Returns true if we care about tracking the size of |
469 // this node. | 467 // this node. |
470 bool isTracking(jsAst.Node code) { | 468 bool isTracking(jsAst.Node code) { |
471 if (compiler.dumpInfo) { | 469 if (compiler.dumpInfo) { |
472 return _tracking.contains(code); | 470 return _tracking.contains(code); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 // Don't bother recording an empty list of dependencies. | 556 // Don't bother recording an empty list of dependencies. |
559 if (pulling.length > 0) { | 557 if (pulling.length > 0) { |
560 String fnId = infoCollector.idOf(fn); | 558 String fnId = infoCollector.idOf(fn); |
561 // Some dart2js builtin functions are not | 559 // Some dart2js builtin functions are not |
562 // recorded. Don't register these. | 560 // recorded. Don't register these. |
563 if (fnId != null) { | 561 if (fnId != null) { |
564 holding[fnId] = pulling | 562 holding[fnId] = pulling |
565 .map((selection) { | 563 .map((selection) { |
566 return <String, String>{ | 564 return <String, String>{ |
567 "id": infoCollector.idOf(selection.selectedElement), | 565 "id": infoCollector.idOf(selection.selectedElement), |
568 "mask": selection.mask.toString() | 566 "mask": selection.selector.mask.toString() |
569 }; | 567 }; |
570 }) | 568 }) |
571 // Filter non-null ids for the same reason as above. | 569 // Filter non-null ids for the same reason as above. |
572 .where((a) => a['id'] != null) | 570 .where((a) => a['id'] != null) |
573 .toList(); | 571 .toList(); |
574 } | 572 } |
575 } | 573 } |
576 } | 574 } |
577 | 575 |
578 // Track dependencies that come from inlining. | 576 // Track dependencies that come from inlining. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 ChunkedConversionSink<Object> sink = | 632 ChunkedConversionSink<Object> sink = |
635 encoder.startChunkedConversion( | 633 encoder.startChunkedConversion( |
636 new StringConversionSink.fromStringSink(buffer)); | 634 new StringConversionSink.fromStringSink(buffer)); |
637 sink.add(outJson); | 635 sink.add(outJson); |
638 compiler.reportInfo(NO_LOCATION_SPANNABLE, | 636 compiler.reportInfo(NO_LOCATION_SPANNABLE, |
639 const MessageKind( | 637 const MessageKind( |
640 "View the dumped .info.json file at " | 638 "View the dumped .info.json file at " |
641 "https://dart-lang.github.io/dump-info-visualizer")); | 639 "https://dart-lang.github.io/dump-info-visualizer")); |
642 } | 640 } |
643 } | 641 } |
OLD | NEW |