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 Compiler, | 16 Compiler, |
17 CompilerTask, | 17 CompilerTask, |
18 CodeBuffer; | 18 CodeBuffer; |
19 import 'dart_types.dart' show DartType; | 19 import 'dart_types.dart' show DartType; |
20 import 'types/types.dart' show TypeMask; | 20 import 'types/types.dart' show TypeMask; |
21 import 'util/util.dart' show modifiersToString; | 21 import 'util/util.dart' show modifiersToString, SpannableAssertionFailure; |
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 'compilation_info.dart' show CompilationInformation; | 25 import 'dependency_info.dart' show DependencyInformation; |
26 | 26 |
27 /// Maps elements to an id. Supports lookups in | 27 /// Maps elements to an id. Supports lookups in |
28 /// both directions. | 28 /// both directions. |
29 class ElementMapper { | 29 class ElementMapper { |
30 Map<int, Element> _idToElement = {}; | 30 Map<int, Element> _idToElement = {}; |
31 Map<Element, int> _elementToId = {}; | 31 Map<Element, int> _elementToId = {}; |
32 int _idCounter = 0; | 32 int _idCounter = 0; |
33 String name; | 33 String name; |
34 | 34 |
35 ElementMapper(this.name); | 35 ElementMapper(this.name); |
36 | 36 |
| 37 Iterable<Element> get elements => _elementToId.keys; |
| 38 |
37 String add(Element e) { | 39 String add(Element e) { |
38 if (_elementToId.containsKey(e)) { | 40 if (_elementToId.containsKey(e)) { |
39 return name + "/${_elementToId[e]}"; | 41 return name + "/${_elementToId[e]}"; |
40 } | 42 } |
41 | 43 |
42 _idToElement[_idCounter] = e; | 44 _idToElement[_idCounter] = e; |
43 _elementToId[e] = _idCounter; | 45 _elementToId[e] = _idCounter; |
44 _idCounter += 1; | 46 _idCounter += 1; |
45 return name + "/${_idCounter - 1}"; | 47 return name + "/${_idCounter - 1}"; |
46 } | 48 } |
47 } | 49 } |
48 | 50 |
49 class DividedElementMapper { | 51 class DividedElementMapper { |
50 // Mappers for specific kinds of elements. | 52 // Mappers for specific kinds of elements. |
51 ElementMapper _library = new ElementMapper('library'); | 53 ElementMapper _library = new ElementMapper('library'); |
52 ElementMapper _typedef = new ElementMapper('typedef'); | 54 ElementMapper _typedef = new ElementMapper('typedef'); |
53 ElementMapper _field = new ElementMapper('field'); | 55 ElementMapper _field = new ElementMapper('field'); |
54 ElementMapper _class = new ElementMapper('class'); | 56 ElementMapper _class = new ElementMapper('class'); |
55 ElementMapper _function = new ElementMapper('function'); | 57 ElementMapper _function = new ElementMapper('function'); |
56 | 58 |
| 59 Iterable<Element> get functions => _function.elements; |
| 60 |
57 // Convert this database of elements into JSON for rendering | 61 // Convert this database of elements into JSON for rendering |
58 Map<String, dynamic> _toJson(ElementToJsonVisitor elementToJson) { | 62 Map<String, dynamic> _toJson(ElementToJsonVisitor elementToJson) { |
59 Map<String, dynamic> json = {}; | 63 Map<String, dynamic> json = {}; |
60 var m = [_library, _typedef, _field, _class, _function]; | 64 var m = [_library, _typedef, _field, _class, _function]; |
61 for (ElementMapper mapper in m) { | 65 for (ElementMapper mapper in m) { |
62 Map<String, dynamic> innerMapper = {}; | 66 Map<String, dynamic> innerMapper = {}; |
63 mapper._idToElement.forEach((k, v) { | 67 mapper._idToElement.forEach((k, v) { |
64 // All these elements are already cached in the | 68 // All these elements are already cached in the |
65 // jsonCache, so this is just an access. | 69 // jsonCache, so this is just an access. |
66 var elementJson = elementToJson.process(v); | 70 var elementJson = elementToJson.process(v); |
67 if (elementJson != null) { | 71 if (elementJson != null) { |
68 innerMapper["$k"] = elementJson; | 72 innerMapper["$k"] = elementJson; |
69 } | 73 } |
70 }); | 74 }); |
71 json[mapper.name] = innerMapper; | 75 json[mapper.name] = innerMapper; |
72 } | 76 } |
73 return json; | 77 return json; |
74 } | 78 } |
75 } | 79 } |
76 | 80 |
77 class ElementToJsonVisitor extends ElementVisitor<Map<String, dynamic>> { | 81 class ElementToJsonVisitor extends ElementVisitor<Map<String, dynamic>> { |
78 DividedElementMapper mapper = new DividedElementMapper(); | 82 DividedElementMapper mapper = new DividedElementMapper(); |
79 Compiler compiler; | 83 Compiler compiler; |
80 | 84 |
81 CompilationInformation compilationInfo; | 85 DependencyInformation dependencyInfo; |
82 | 86 |
83 Map<Element, Map<String, dynamic>> jsonCache = {}; | 87 Map<Element, Map<String, dynamic>> jsonCache = {}; |
84 Map<Element, jsAst.Expression> codeCache; | 88 Map<Element, jsAst.Expression> codeCache; |
85 | 89 |
86 int programSize; | 90 int programSize; |
87 DateTime compilationMoment; | 91 DateTime compilationMoment; |
88 String dart2jsVersion; | 92 String dart2jsVersion; |
89 Duration compilationDuration; | 93 Duration compilationDuration; |
90 Duration dumpInfoDuration; | 94 Duration dumpInfoDuration; |
91 | 95 |
92 ElementToJsonVisitor(Compiler compiler) { | 96 ElementToJsonVisitor(Compiler compiler) { |
93 this.compiler = compiler; | 97 this.compiler = compiler; |
94 this.compilationInfo = compiler.enqueuer.codegen.compilationInfo; | 98 this.dependencyInfo = compiler.enqueuer.codegen.dependencyInfo; |
95 | 99 |
96 programSize = compiler.assembledCode.length; | 100 programSize = compiler.assembledCode.length; |
97 compilationMoment = new DateTime.now(); | 101 compilationMoment = new DateTime.now(); |
98 dart2jsVersion = compiler.hasBuildId ? compiler.buildId : null; | 102 dart2jsVersion = compiler.hasBuildId ? compiler.buildId : null; |
99 compilationDuration = compiler.totalCompileTime.elapsed; | 103 compilationDuration = compiler.totalCompileTime.elapsed; |
100 | 104 |
101 for (var library in compiler.libraryLoader.libraries.toList()) { | 105 for (var library in compiler.libraryLoader.libraries.toList()) { |
102 library.accept(this); | 106 library.accept(this); |
103 } | 107 } |
104 | 108 |
105 dumpInfoDuration = new DateTime.now().difference(compilationMoment); | 109 dumpInfoDuration = new DateTime.now().difference(compilationMoment); |
106 } | 110 } |
107 | 111 |
108 // If keeping the element is in question (like if a function has a size | 112 // If keeping the element is in question (like if a function has a size |
109 // of zero), only keep it if it holds dependencies to elsewhere. | 113 // of zero), only keep it if it holds dependencies to elsewhere. |
110 bool shouldKeep(Element element) { | 114 bool shouldKeep(Element element) { |
111 return compilationInfo.addsToWorkListMap.containsKey(element) || | 115 return dependencyInfo.selectorsFromElement.containsKey(element); |
112 compilationInfo.enqueuesMap.containsKey(element); | |
113 } | 116 } |
114 | 117 |
115 Map<String, dynamic> toJson() { | 118 Map<String, dynamic> toJson() { |
116 return mapper._toJson(this); | 119 return mapper._toJson(this); |
117 } | 120 } |
118 | 121 |
119 // Memoization of the JSON creating process. | 122 // Memoization of the JSON creating process. |
120 Map<String, dynamic> process(Element element) { | 123 Map<String, dynamic> process(Element element) { |
121 return jsonCache.putIfAbsent(element, () => element.accept(this)); | 124 return jsonCache.putIfAbsent(element, () => element.accept(this)); |
122 } | 125 } |
123 | 126 |
| 127 String idOf(Element element) { |
| 128 if (jsonCache.containsKey(element) && jsonCache[element] != null) { |
| 129 return jsonCache[element]['id']; |
| 130 } else { |
| 131 return null; |
| 132 } |
| 133 } |
| 134 |
124 Map<String, dynamic> visitElement(Element element) { | 135 Map<String, dynamic> visitElement(Element element) { |
125 return null; | 136 return null; |
126 } | 137 } |
127 | 138 |
128 Map<String, dynamic> visitConstructorBodyElement(ConstructorBodyElement e) { | 139 Map<String, dynamic> visitConstructorBodyElement(ConstructorBodyElement e) { |
129 return visitFunctionElement(e.constructor); | 140 return visitFunctionElement(e.constructor); |
130 } | 141 } |
131 | 142 |
132 Map<String, dynamic> visitLibraryElement(LibraryElement element) { | 143 Map<String, dynamic> visitLibraryElement(LibraryElement element) { |
133 var id = mapper._library.add(element); | 144 var id = mapper._library.add(element); |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 compiler.outputProvider('', 'info.json') | 468 compiler.outputProvider('', 'info.json') |
458 ..add(jsonBuffer.toString()) | 469 ..add(jsonBuffer.toString()) |
459 ..close(); | 470 ..close(); |
460 }); | 471 }); |
461 } | 472 } |
462 | 473 |
463 | 474 |
464 void dumpInfoJson(StringSink buffer) { | 475 void dumpInfoJson(StringSink buffer) { |
465 JsonEncoder encoder = const JsonEncoder(); | 476 JsonEncoder encoder = const JsonEncoder(); |
466 | 477 |
467 // `A` uses and depends on the functions `Bs`. | |
468 // A Bs | |
469 Map<String, List<String>> holding = <String, List<String>>{}; | |
470 | |
471 DateTime startToJsonTime = new DateTime.now(); | 478 DateTime startToJsonTime = new DateTime.now(); |
472 | 479 |
473 CompilationInformation compilationInfo = | 480 DependencyInformation dependencyInfo = |
474 infoCollector.compiler.enqueuer.codegen.compilationInfo; | 481 infoCollector.compiler.enqueuer.codegen.dependencyInfo; |
475 compilationInfo.addsToWorkListMap.forEach((func, deps) { | |
476 if (func != null) { | |
477 var funcJson = infoCollector.process(func); | |
478 if (funcJson != null) { | |
479 var funcId = funcJson['id']; | |
480 | 482 |
481 List<String> heldList = <String>[]; | 483 Map<String, List<String>> holding = <String, List<String>>{}; |
482 | 484 for (Element fn in infoCollector.mapper.functions) { |
483 for (var held in deps) { | 485 Iterable<Element> pulling = dependencyInfo.getRetaining(fn, compiler); |
484 // "process" to get the ids of the elements. | 486 if (pulling.length > 0) { |
485 var heldJson = infoCollector.process(held); | 487 String fnId = infoCollector.idOf(fn); |
486 if (heldJson != null) { | 488 if (fnId != null) { |
487 var heldId = heldJson['id']; | 489 holding[fnId] = pulling |
488 heldList.add(heldId); | 490 .map((a) => infoCollector.idOf(a)) |
489 } | 491 .where((a) => a != null) |
490 } | 492 .toList(); |
491 holding[funcId] = heldList; | |
492 } | 493 } |
493 } | 494 } |
494 }); | 495 } |
495 | 496 |
496 Map<String, dynamic> outJson = { | 497 Map<String, dynamic> outJson = { |
497 'elements': infoCollector.toJson(), | 498 'elements': infoCollector.toJson(), |
498 'holding': holding, | 499 'holding': holding, |
499 'dump_version': 1, | 500 'dump_version': 1, |
500 }; | 501 }; |
501 | 502 |
502 Duration toJsonDuration = new DateTime.now().difference(startToJsonTime); | 503 Duration toJsonDuration = new DateTime.now().difference(startToJsonTime); |
503 | 504 |
504 Map<String, dynamic> generalProgramInfo = <String, dynamic> { | 505 Map<String, dynamic> generalProgramInfo = <String, dynamic> { |
505 'size': infoCollector.programSize, | 506 'size': infoCollector.programSize, |
506 'dart2jsVersion': infoCollector.dart2jsVersion, | 507 'dart2jsVersion': infoCollector.dart2jsVersion, |
507 'compilationMoment': infoCollector.compilationMoment.toString(), | 508 'compilationMoment': infoCollector.compilationMoment.toString(), |
508 'compilationDuration': infoCollector.compilationDuration.toString(), | 509 'compilationDuration': infoCollector.compilationDuration.toString(), |
509 'toJsonDuration': toJsonDuration.toString(), | 510 'toJsonDuration': toJsonDuration.toString(), |
510 'dumpInfoDuration': infoCollector.dumpInfoDuration.toString(), | 511 'dumpInfoDuration': infoCollector.dumpInfoDuration.toString(), |
511 'noSuchMethodEnabled': compiler.enabledNoSuchMethod | 512 'noSuchMethodEnabled': compiler.enabledNoSuchMethod |
512 }; | 513 }; |
513 | 514 |
514 outJson['program'] = generalProgramInfo; | 515 outJson['program'] = generalProgramInfo; |
515 | 516 |
516 ChunkedConversionSink<Object> sink = | 517 ChunkedConversionSink<Object> sink = |
517 encoder.startChunkedConversion( | 518 encoder.startChunkedConversion( |
518 new StringConversionSink.fromStringSink(buffer)); | 519 new StringConversionSink.fromStringSink(buffer)); |
519 sink.add(outJson); | 520 sink.add(outJson); |
520 } | 521 } |
521 } | 522 } |
OLD | NEW |