| 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 HtmlEscape; | 7 import 'dart:convert' show |
| 8 HtmlEscape, |
| 9 JsonEncoder, |
| 10 StringConversionSink, |
| 11 ChunkedConversionSink; |
| 8 | 12 |
| 9 import 'elements/elements.dart'; | 13 import 'elements/elements.dart'; |
| 10 import 'elements/visitor.dart'; | 14 import 'elements/visitor.dart'; |
| 11 import 'dart2jslib.dart' show | 15 import 'dart2jslib.dart' show |
| 12 Compiler, | 16 Compiler, |
| 13 CompilerTask, | 17 CompilerTask, |
| 14 CodeBuffer; | 18 CodeBuffer; |
| 15 import 'dart_types.dart' show DartType; | 19 import 'dart_types.dart' show DartType; |
| 16 import 'types/types.dart' show TypeMask; | 20 import 'types/types.dart' show TypeMask; |
| 17 import 'util/util.dart' show modifiersToString; | 21 import 'util/util.dart' show modifiersToString; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 var esc = const HtmlEscape().convert; | 76 var esc = const HtmlEscape().convert; |
| 73 | 77 |
| 74 String sizeDescription(int size, ProgramInfo programInfo) { | 78 String sizeDescription(int size, ProgramInfo programInfo) { |
| 75 if (size == null) { | 79 if (size == null) { |
| 76 return ''; | 80 return ''; |
| 77 } | 81 } |
| 78 return span(span(size.toString(), cls: 'value') + | 82 return span(span(size.toString(), cls: 'value') + |
| 79 ' bytes (${size * 100 ~/ programInfo.size}%)', cls: 'size'); | 83 ' bytes (${size * 100 ~/ programInfo.size}%)', cls: 'size'); |
| 80 } | 84 } |
| 81 | 85 |
| 86 String sizePercent(int size, ProgramInfo programInfo) { |
| 87 if (size == null) { |
| 88 return "0.000%"; |
| 89 } else { |
| 90 return (100 * size / programInfo.size).toStringAsFixed(3) + "%"; |
| 91 } |
| 92 } |
| 93 |
| 82 /// An [InfoNode] holds information about a part the program. | 94 /// An [InfoNode] holds information about a part the program. |
| 83 abstract class InfoNode { | 95 abstract class InfoNode { |
| 84 String get name; | 96 String get name; |
| 85 | 97 |
| 86 int get size; | 98 int get size; |
| 87 | 99 |
| 88 void emitHtml(ProgramInfo programInfo, StringSink buffer, | 100 void emitHtml(ProgramInfo programInfo, StringSink buffer, |
| 89 [String indentation = '']); | 101 [String indentation = '']); |
| 102 |
| 103 Map<String, dynamic> toJson(ProgramInfo programInfo); |
| 90 } | 104 } |
| 91 | 105 |
| 92 /// An [ElementNode] holds information about an [Element] | 106 /// An [ElementNode] holds information about an [Element] |
| 93 class ElementInfoNode implements InfoNode { | 107 class ElementInfoNode implements InfoNode { |
| 94 /// The name of the represented [Element]. | 108 /// The name of the represented [Element]. |
| 95 final String name; | 109 final String name; |
| 96 | 110 |
| 97 /// The kind of the [Element] represented. This is presented to the | 111 /// The kind of the [Element] represented. This is presented to the |
| 98 /// user, so it might be more specific than [element.kind]. | 112 /// user, so it might be more specific than [element.kind]. |
| 99 final String kind; | 113 final String kind; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 123 | 137 |
| 124 ElementInfoNode({this.name: "", | 138 ElementInfoNode({this.name: "", |
| 125 this.kind: "", | 139 this.kind: "", |
| 126 this.type, | 140 this.type, |
| 127 this.modifiers: "", | 141 this.modifiers: "", |
| 128 this.size, | 142 this.size, |
| 129 this.contents, | 143 this.contents, |
| 130 this.extra: "", | 144 this.extra: "", |
| 131 this.outputUnitId}); | 145 this.outputUnitId}); |
| 132 | 146 |
| 147 Map<String, dynamic> toJson(ProgramInfo programInfo) { |
| 148 Map<String, dynamic> json = <String, dynamic>{ |
| 149 'kind': this.kind, |
| 150 'modifiers': this.modifiers, |
| 151 'name': this.name, |
| 152 'type': this.type, |
| 153 'size': this.size, |
| 154 'sizePercent': sizePercent(this.size, programInfo), |
| 155 'extra': this.extra |
| 156 }; |
| 157 |
| 158 if (this.contents != null) { |
| 159 json['children'] = |
| 160 this.contents.map((c) => c.toJson(programInfo)).toList(); |
| 161 } |
| 162 |
| 163 return json; |
| 164 } |
| 165 |
| 133 void emitHtml(ProgramInfo programInfo, StringSink buffer, | 166 void emitHtml(ProgramInfo programInfo, StringSink buffer, |
| 134 [String indentation = '']) { | 167 [String indentation = '']) { |
| 135 String kindString = span(esc(kind), cls: 'kind'); | 168 String kindString = span(esc(kind), cls: 'kind'); |
| 136 String modifiersString = span(esc(modifiers), cls: "modifiers"); | 169 String modifiersString = span(esc(modifiers), cls: "modifiers"); |
| 137 | 170 |
| 138 String nameString = span(esc(name), cls: 'name'); | 171 String nameString = span(esc(name), cls: 'name'); |
| 139 String typeString = type == null | 172 String typeString = type == null |
| 140 ? '' | 173 ? '' |
| 141 : span('/* ' + esc(type) + ' */', cls: 'type'); | 174 : span('/* ' + esc(type) + ' */', cls: 'type'); |
| 142 String extraString = span(esc(extra), cls: 'type'); | 175 String extraString = span(esc(extra), cls: 'type'); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 | 223 |
| 191 void emitHtml(ProgramInfo programInfo, StringBuffer buffer, | 224 void emitHtml(ProgramInfo programInfo, StringBuffer buffer, |
| 192 [String indentation = '']) { | 225 [String indentation = '']) { |
| 193 buffer.write(indentation); | 226 buffer.write(indentation); |
| 194 buffer.write(div(description + ' ' + | 227 buffer.write(div(description + ' ' + |
| 195 sizeDescription(generatedCode.length, programInfo), | 228 sizeDescription(generatedCode.length, programInfo), |
| 196 cls: 'kind') + | 229 cls: 'kind') + |
| 197 code(esc(generatedCode))); | 230 code(esc(generatedCode))); |
| 198 buffer.write('\n'); | 231 buffer.write('\n'); |
| 199 } | 232 } |
| 233 |
| 234 Map<String, dynamic> toJson(ProgramInfo programInfo) { |
| 235 return <String, dynamic>{ |
| 236 'kind': 'code', |
| 237 'description': description, |
| 238 'code': generatedCode, |
| 239 'size': generatedCode.length, |
| 240 'sizePercent': sizePercent(generatedCode.length, programInfo) |
| 241 }; |
| 242 } |
| 200 } | 243 } |
| 201 | 244 |
| 202 /// Instances represent information inferred about the program such as | 245 /// Instances represent information inferred about the program such as |
| 203 /// inferred type information or inferred side effects. | 246 /// inferred type information or inferred side effects. |
| 204 class InferredInfoNode implements InfoNode { | 247 class InferredInfoNode implements InfoNode { |
| 205 /// Text describing the represented information. | 248 /// Text describing the represented information. |
| 206 final String description; | 249 final String description; |
| 207 | 250 |
| 208 /// The name of the entity this information is inferred about (for example the | 251 /// The name of the entity this information is inferred about (for example the |
| 209 /// name of a parameter). | 252 /// name of a parameter). |
| 210 final String name; | 253 final String name; |
| 211 | 254 |
| 212 /// The inferred type/side effect. | 255 /// The inferred type/side effect. |
| 213 final String type; | 256 final String type; |
| 214 | 257 |
| 215 get size => 0; | 258 get size => 0; |
| 216 | 259 |
| 217 InferredInfoNode({this.name: "", this.description, this.type}); | 260 InferredInfoNode({this.name: "", this.description, this.type}); |
| 218 | 261 |
| 262 Map<String, dynamic> toJson(ProgramInfo programInfo) { |
| 263 return <String, dynamic>{ |
| 264 'kind': 'inferred', |
| 265 'name': name, |
| 266 'type': type, |
| 267 'desc': description |
| 268 }; |
| 269 } |
| 270 |
| 219 void emitHtml(ProgramInfo programInfo, StringBuffer buffer, | 271 void emitHtml(ProgramInfo programInfo, StringBuffer buffer, |
| 220 [String indentation = '']) { | 272 [String indentation = '']) { |
| 221 buffer.write(indentation); | 273 buffer.write(indentation); |
| 222 buffer.write( | 274 buffer.write( |
| 223 div('${span("Inferred " + description, cls: "kind")} ' | 275 div('${span("Inferred " + description, cls: "kind")} ' |
| 224 '${span(esc(name), cls: "name")} ' | 276 '${span(esc(name), cls: "name")} ' |
| 225 '${span(esc(type), cls: "type")} ', | 277 '${span(esc(type), cls: "type")} ', |
| 226 cls: "attr")); | 278 cls: "attr")); |
| 227 buffer.write('\n'); | 279 buffer.write('\n'); |
| 228 } | 280 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 246 final String dart2jsVersion; | 298 final String dart2jsVersion; |
| 247 | 299 |
| 248 final Map<OutputUnit, int> outputUnitNumbering; | 300 final Map<OutputUnit, int> outputUnitNumbering; |
| 249 | 301 |
| 250 ProgramInfo({this.libraries, | 302 ProgramInfo({this.libraries, |
| 251 this.size, | 303 this.size, |
| 252 this.compilationMoment, | 304 this.compilationMoment, |
| 253 this.compilationDuration, | 305 this.compilationDuration, |
| 254 this.dart2jsVersion, | 306 this.dart2jsVersion, |
| 255 this.outputUnitNumbering: null}); | 307 this.outputUnitNumbering: null}); |
| 308 |
| 309 Map<String, dynamic> toJson() { |
| 310 return <String, dynamic>{ |
| 311 'program_size': size, |
| 312 'compile_time': compilationMoment.toString(), |
| 313 'compile_duration': compilationDuration.toString(), |
| 314 'dart2js_version': dart2jsVersion |
| 315 }; |
| 316 } |
| 256 } | 317 } |
| 257 | 318 |
| 258 class InfoDumpVisitor extends ElementVisitor<InfoNode> { | 319 class InfoDumpVisitor extends ElementVisitor<InfoNode> { |
| 259 final Compiler compiler; | 320 final Compiler compiler; |
| 260 | 321 |
| 261 /// Contains the elements visited on the path from the library to here. | 322 /// Contains the elements visited on the path from the library to here. |
| 262 final List<Element> stack = new List<Element>(); | 323 final List<Element> stack = new List<Element>(); |
| 263 | 324 |
| 264 final Map<OutputUnit, int> outputUnitNumbering = new Map<OutputUnit, int>(); | 325 final Map<OutputUnit, int> outputUnitNumbering = new Map<OutputUnit, int>(); |
| 265 | 326 |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 CodeBuffer codeOf(Element element) { | 586 CodeBuffer codeOf(Element element) { |
| 526 jsAst.Expression code = _generatedCode[element]; | 587 jsAst.Expression code = _generatedCode[element]; |
| 527 return code != null | 588 return code != null |
| 528 ? jsAst.prettyPrint(code, compiler) | 589 ? jsAst.prettyPrint(code, compiler) |
| 529 : compiler.backend.codeOf(element); | 590 : compiler.backend.codeOf(element); |
| 530 } | 591 } |
| 531 | 592 |
| 532 void dumpInfo() { | 593 void dumpInfo() { |
| 533 measure(() { | 594 measure(() { |
| 534 ProgramInfo info = infoDumpVisitor.collectDumpInfo(); | 595 ProgramInfo info = infoDumpVisitor.collectDumpInfo(); |
| 535 StringBuffer buffer = new StringBuffer(); | 596 |
| 536 dumpInfoHtml(info, buffer); | 597 StringBuffer htmlBuffer = new StringBuffer(); |
| 598 dumpInfoHtml(info, htmlBuffer); |
| 537 compiler.outputProvider('', 'info.html') | 599 compiler.outputProvider('', 'info.html') |
| 538 ..add(buffer.toString()) | 600 ..add(htmlBuffer.toString()) |
| 601 ..close(); |
| 602 |
| 603 StringBuffer jsonBuffer = new StringBuffer(); |
| 604 dumpInfoJson(info, jsonBuffer); |
| 605 compiler.outputProvider('', 'info.json') |
| 606 ..add(jsonBuffer.toString()) |
| 539 ..close(); | 607 ..close(); |
| 540 }); | 608 }); |
| 541 } | 609 } |
| 542 | 610 |
| 611 void dumpInfoJson(ProgramInfo info, StringSink buffer) { |
| 612 Map<String, dynamic> entire = <String, dynamic>{ |
| 613 'program': info.toJson(), |
| 614 'libs': info.libraries.map((lib) => lib.toJson(info)).toList() |
| 615 }; |
| 616 |
| 617 JsonEncoder encoder = const JsonEncoder(); |
| 618 ChunkedConversionSink<Object> sink = |
| 619 encoder.startChunkedConversion( |
| 620 new StringConversionSink.fromStringSink(buffer)); |
| 621 sink.add(entire); |
| 622 } |
| 623 |
| 543 void dumpInfoHtml(ProgramInfo info, StringSink buffer) { | 624 void dumpInfoHtml(ProgramInfo info, StringSink buffer) { |
| 544 int totalSize = info.size; | 625 int totalSize = info.size; |
| 545 | 626 |
| 546 buffer.writeln(""" | 627 buffer.writeln(""" |
| 547 <html> | 628 <html> |
| 548 <head> | 629 <head> |
| 549 <title>Dart2JS compilation information</title> | 630 <title>Dart2JS compilation information</title> |
| 550 <style> | 631 <style> |
| 551 code {margin-left: 20px; display: block; white-space: pre; } | 632 code {margin-left: 20px; display: block; white-space: pre; } |
| 552 div.container, div.contained, div.element, div.attr { | 633 div.container, div.contained, div.element, div.attr { |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 678 } | 759 } |
| 679 document.querySelector('.sort_by_size').addEventListener('click', | 760 document.querySelector('.sort_by_size').addEventListener('click', |
| 680 function() { | 761 function() { |
| 681 sortBySize(); | 762 sortBySize(); |
| 682 }, false); | 763 }, false); |
| 683 </script> | 764 </script> |
| 684 </body> | 765 </body> |
| 685 </html>"""); | 766 </html>"""); |
| 686 } | 767 } |
| 687 } | 768 } |
| OLD | NEW |