Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/dump_info.dart

Issue 90713003: Dart2js option to dump info about compilation (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library dump_types;
6
7 import 'elements/elements.dart';
8 import 'elements/visitor.dart';
9 import 'dart:convert' show HtmlEscape;
10 import 'dart2jslib.dart'
11 show Compiler,
ahe 2013/12/02 15:20:26 Put show on previous line and indent by four.
sigurdm 2013/12/05 09:19:44 Done.
12 CompilerTask,
13 CodeBuffer;
14 import 'dart_types.dart' show DartType;
15
16 // TODO (sigurdm): A search function.
17 // TODO (sigurdm): Output size of classes.
18 // TODO (sigurdm): Print that we dumped the HTML-file.
19 // TODO (sigurdm): Include why a given element was included in the output.
20 // TODO (sigurdm): Include how much output grew because of mirror support.
21 // TODO (sigurdm): Write each function with parameter names.
22 // TODO (sigurdm): Write how much space the boilerplate takes.
23
24 class CodeSizeCounter {
25 final Map<Element, int> generatedSize = new Map<Element, int>();
26
27 int getGeneratedSizeOf(Element element) {
28 int result = generatedSize[element];
29 return result == null ? 0 : result;
30 }
31
32 void countCode(Element element, int added) {
33 int before = generatedSize.putIfAbsent(element, () => 0);
34 generatedSize[element] = before + added;
35 }
36 }
37
38 class ElementInfo {
ahe 2013/12/02 15:20:26 I'd put a line between each member.
sigurdm 2013/12/05 09:19:44 Done.
39 final String name;
40 final String kind;
41 final String type;
42 final String modifiers;
43 final String generatedCode;
44 // How to present this piece of information
ahe 2013/12/02 15:20:26 What does this comment apply to? Is it a TODO?
sigurdm 2013/12/05 09:19:44 Done.
45 // As "element" or "code"
ahe 2013/12/02 15:20:26 Is this a sentence by itself or a continuation of
46 final String presentation;
47 final int size; // How many bytes does this take in the output
ahe 2013/12/02 15:20:26 Is this supposed to be a documentation comment?
sigurdm 2013/12/05 09:19:44 yes
48 List<ElementInfo> contents;
49 ElementInfo({this.name: "",
50 this.kind: "",
51 this.type: "",
52 this.modifiers: "",
53 this.size,
54 this.generatedCode,
55 this.presentation: "element",
56 this.contents});
57 }
58
59 class ProgramInfo {
ahe 2013/12/02 15:20:26 I'd put a line between each member.
sigurdm 2013/12/05 09:19:44 Done.
60 final String name;
61 final String presentation;
62 final List<ElementInfo> libraries;
63 final int size; // How many bytes is the output
ahe 2013/12/02 15:20:26 Documentation comment?
sigurdm 2013/12/05 09:19:44 Done.
64 final DateTime compilationMoment;
65 final int compilationDuration;
66 final String dart2jsVersion;
67
68 ProgramInfo({String this.name,
69 this.presentation,
70 this.libraries,
71 this.size, DateTime this.compilationMoment,
72 this.compilationDuration, String this.dart2jsVersion});
73 }
74
75 class InfoDumpVisitor extends ElementVisitor<ElementInfo> {
76
ahe 2013/12/02 15:20:26 Extra line.
sigurdm 2013/12/05 09:19:44 Done.
77 Compiler compiler;
78
79 InfoDumpVisitor(Compiler this.compiler);
80
81 ElementInfo visitElement(Element element) {
82 compiler.internalError("This element of kind ${element.kind} "
83 "does not support dumping of types",
84 token: element.position());
85 }
86
87 ElementInfo visitLibraryElement(LibraryElement element) {
88 List<ElementInfo> contents = new List<ElementInfo>();
89 int size = compiler.dumpInfoTask.codeSizeCounter
90 .getGeneratedSizeOf(element);
91 if (size == 0) return null;
92 element.forEachLocalMember((Element member) {
93 ElementInfo info = member.accept(this);
94 if (info != null) {
95 contents.add(info);
96 }
97 });
98
99 String nameString = element.getLibraryName() == ""
100 ? "<unnamed>"
101 : element.getLibraryName();
102 contents.sort((ElementInfo e1, ElementInfo e2) {
103 return e1.name.compareTo(e2.name);
104 });
105 return new ElementInfo(
106 type: element.canonicalUri.toString(),
107 kind: "library",
108 name: nameString,
109 size: size,
110 modifiers: "",
111 contents: contents);
112 }
113
114 ElementInfo visitTypedefElement(TypedefElement element) {
115 return element.thisType == null
116 ? null
117 : new ElementInfo(
118 type: element.thisType.toString(),
119 kind: "typedef",
120 name: element.name);
121 }
122
123 ElementInfo visitVariableElement(VariableElement element) {
124 DartType type = element.computeType(compiler);
125 if (type == null) return null;
126 String modifiersString = element.modifiers.toString() == ""
127 ? ""
128 : element.modifiers.toString()+" ";
129 List inferredType = [new ElementInfo(
ahe 2013/12/02 15:20:26 I don't understand why an inferredType is a list.
sigurdm 2013/12/05 09:19:44 Done.
130 kind: "inferred type",
131 name: "",
132 type: compiler.typesTask.getGuaranteedTypeOfElement(element).toString(),
133 modifiers: "")];
134 return new ElementInfo(
135 kind: "field",
136 type: type.toString(),
137 name: element.name,
138 modifiers: modifiersString,
139 contents: inferredType);
140 }
141
142 ElementInfo visitClassElement(ClassElement element) {
143 String modifiersString = element.modifiers.toString() == ""
144 ? ""
145 : element.modifiers.toString()+" ";
146 if (!element.isResolved) return null;
147 String supersString = element.allSupertypes == null ? "" :
148 "implements ${element.allSupertypes}";
149 List contents = [];
150 element.forEachLocalMember((Element member) {
151 ElementInfo info = member.accept(this);
152 if (info != null) {
153 contents.add(info);
154 }
155 });
156 if (contents.isEmpty) {
157 return null;
158 }
159 contents.sort((ElementInfo m1, ElementInfo m2) {
160 return m1.name.compareTo(m2.name);
161 });
162 return new ElementInfo(
163 kind: "class",
164 name: element.name,
165 type: supersString,
166 modifiers: modifiersString,
167 contents: contents);
168 }
169
170 ElementInfo visitFunctionElement(FunctionElement element) {
171 CodeBuffer emittedCode = compiler.backend.codeOf(element);
172 if (emittedCode == null) {
173 return null;
174 }
175 String modifiersString = element.modifiers.toString() == ""
176 ? ""
177 : element.modifiers.toString()+" ";
178 String kindString = "function";
179 String nameString = element.name;
180 if (element.isConstructor()) {
181 nameString = element.name == "" ? "${element.enclosingElement.name}()" :
182 "${element.enclosingElement.name}.${element.name}";
183 kindString = "constructor";
184 }
185 List contents = [];
186 FunctionSignature signature = element.computeSignature(compiler);
187 signature.forEachParameter((parameter) {
188 contents.add(new ElementInfo(
189 kind: "inferred",
190 name: parameter.name,
191 modifiers: "parameter type",
192 type: compiler.typesTask
193 .getGuaranteedTypeOfElement(parameter).toString()));
194 });
195 contents.add(new ElementInfo(
196 kind: "inferred",
197 modifiers: "return type",
198 type: compiler.typesTask
199 .getGuaranteedReturnTypeOfElement(element).toString()));
200 contents.add(new ElementInfo(
201 kind: "inferred",
202 modifiers: "side effects",
203 type: compiler.world.getSideEffectsOfElement(element).toString()));
204 contents.add(new ElementInfo(
205 name: "Generated code",
206 presentation: "code",
207 generatedCode: emittedCode.getText()));
208 return new ElementInfo(
209 type: element.type.toString(),
210 kind: kindString,
211 name: nameString,
212 size: emittedCode.length,
213 modifiers: modifiersString,
214 contents: contents);
215 }
216 }
217
218 class DumpInfoTask extends CompilerTask {
219 DumpInfoTask(Compiler compiler) :
220 super(compiler),
221 infoDumpVisitor = new InfoDumpVisitor(compiler);
222
223 String name = "Dump Info";
224
225 final CodeSizeCounter codeSizeCounter = new CodeSizeCounter();
226
227 final InfoDumpVisitor infoDumpVisitor;
228
229 void dumpInfo() {
230 measure(() {
231 ProgramInfo info = collectDumpInfo();
232 StringBuffer buffer = new StringBuffer();
233 dumpInfoHtml(info, buffer);
234 compiler.outputProvider('', 'info.html')
235 ..add(buffer.toString())
236 ..close();
237 });
238 }
239
240 ProgramInfo collectDumpInfo() {
241 List<LibraryElement> sortedLibraries = compiler.libraries.values.toList();
242 sortedLibraries.sort((LibraryElement l1, LibraryElement l2) {
243 if (l1.isPlatformLibrary && !l2.isPlatformLibrary) {
244 return 1;
245 } else if (!l1.isPlatformLibrary && l2.isPlatformLibrary) {
246 return -1;
247 }
248 return l1.getLibraryName().compareTo(l2.getLibraryName());
249 });
250
251 List<ElementInfo> libraryInfos = new List<ElementInfo>();
252 libraryInfos.addAll(sortedLibraries
253 .map((library) => infoDumpVisitor.visit(library))
254 .where((library) => library != null));
255
256 return new ProgramInfo(
257 compilationDuration: compiler.totalCompileTime.elapsedTicks,
258 // TODO (sigurdm): Also count the size of deferred code
259 size: compiler.assembledCode.length,
260 libraries: libraryInfos,
261 compilationMoment: new DateTime.now(),
262 dart2jsVersion: compiler.hasBuildId ? compiler.buildId : null);
263 }
264
265 void dumpInfoHtml(ProgramInfo info, StringSink buffer) {
266 tag(String element) {
267 return (String content, {String cls}) {
268 String classString = cls == null ? '' : ' class="$cls"';
269 return '<$element$classString>$content</$element>';
270 };
271 }
272 var div = tag('div');
273 var span = tag('span');
274 var code = tag('code');
275 var h2 = tag('h2');
276 int totalSize = info.size;
277 void dumpElement(ElementInfo description) {
278 var esc = const HtmlEscape().convert;
279 if (description.presentation == 'code') {
280 buffer.write(div(description.name, cls: 'kind') +
281 code(esc(description.generatedCode)));
282 } else {
283 String kind = span(esc(description.kind), cls: 'kind');
284 String modifiers = span(esc(description.modifiers), cls: "modifiers");
285 String size = '';
286 if (description.size != null) {
287 size = 'Size: ' +
288 span('${description.size} bytes '
289 '(${description.size * 100 ~/ totalSize})%',
290 cls: "size");
291 }
292 String name = span(esc(description.name), cls: 'name');
293 String type = span(esc(description.type), cls: 'type');
294 String describe = [kind, modifiers, name, size, type].join(' ');
295
296 if (description.contents != null) {
297 buffer.write(div("+$describe", cls: "container"));
298 String contents = "No Members";
299 buffer.write('<div class="contained">');
300 if (description.contents.isEmpty) {
301 buffer.writeln("No members");
302 }
303 for (Object subElementDescription in description.contents) {
304 dumpElement(subElementDescription);
305 }
306 buffer.write("</div>");
307 } else {
308 buffer.writeln(describe);
309 }
310 }
311 }
312 buffer.writeln("""
313 <html>
314 <head>
315 <title>Dart2JS compilation information</title>
316 <style>
317 div.show {display:block;}
318 code {margin-left: 20px; display: block;}
319 div.contained {margin-left: 20px;}
320 div {margin-top:0px;
321 margin-bottom: 0px;
322 white-space: pre; /*border: 1px solid;*/}
323 span.kind {font-weight:bold;}
324 span.modifiers {font-weight:bold;}
325 span.name {font-style:italic}
326 span.type {color:blue;}
327 </style>
328 </head>
329 <body>
330 <h1>Dart2js compilation information</h1>""");
331 buffer.writeln(h2('Compilation took place: '
332 '${info.compilationMoment}'));
333 buffer.writeln(h2('Compilation took: '
334 '${info.compilationDuration/1000000} seconds'));
335 buffer.writeln(h2('Output size: ${info.size} bytes'));
336 if (info.dart2jsVersion != null) {
337 buffer.writeln(h2('Dart2js version: ${info.dart2jsVersion}'));
338 }
339
340 info.libraries.forEach(dumpElement);
341
342 // TODO (sigurdm): This script should be written in dart
343 buffer.writeln(r"""
344 <script type="text/javascript">
345 function toggler(element) {
346 return function(e) {
347 element.hidden = !element.hidden;
348 };
349 }
350 var containers = document.getElementsByClassName('container');
351 for (var i = 0; i < containers.length; i++) {
352 var container = containers[i];
353 container.addEventListener('click',
354 toggler(container.nextElementSibling), false);
355 container.nextElementSibling.hidden = true;
356 };
357 </script>
358 </body>
359 </html>""");
360 }
361 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698