OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 /// Tool used mainly by dart2js developers to debug the generated info and check | 5 /// Tool used mainly by dart2js developers to debug the generated info and check |
6 /// that it is consistent and that it covers all the data we expect it to cover. | 6 /// that it is consistent and that it covers all the data we expect it to cover. |
7 library dart2js_info.bin.debug_info; | 7 library dart2js_info.bin.debug_info; |
8 | 8 |
9 import 'dart:convert'; | 9 import 'dart:convert'; |
10 import 'dart:io'; | 10 import 'dart:io'; |
11 | 11 |
12 import 'package:dart2js_info/info.dart'; | 12 import 'package:dart2js_info/info.dart'; |
13 import 'package:dart2js_info/src/graph.dart'; | 13 import 'package:dart2js_info/src/graph.dart'; |
| 14 import 'package:dart2js_info/src/util.dart'; |
14 | 15 |
15 main(args) { | 16 main(args) { |
16 if (args.length < 1) { | 17 if (args.length < 1) { |
17 print('usage: dart tool/debug_info.dart path-to-info.json ' | 18 print('usage: dart tool/debug_info.dart path-to-info.json ' |
18 '[--show-library libname]'); | 19 '[--show-library libname]'); |
19 exit(1); | 20 exit(1); |
20 } | 21 } |
21 | 22 |
22 var filename = args[0]; | 23 var filename = args[0]; |
23 var json = JSON.decode(new File(filename).readAsStringSync()); | 24 var json = JSON.decode(new File(filename).readAsStringSync()); |
24 var info = new AllInfoJsonCodec().decode(json); | 25 var info = new AllInfoJsonCodec().decode(json); |
25 var debugLibName; | 26 var debugLibName; |
26 | 27 |
27 if (args.length > 2 && args[1] == '--show-library') { | 28 if (args.length > 2 && args[1] == '--show-library') { |
28 debugLibName = args[2]; | 29 debugLibName = args[2]; |
29 } | 30 } |
30 | 31 |
| 32 validateSize(info, debugLibName); |
| 33 compareGraphs(info); |
| 34 verifyDeps(info); |
| 35 } |
| 36 |
| 37 /// Validates that codesize of elements adds up to total codesize. |
| 38 validateSize(AllInfo info, String debugLibName) { |
31 // Gather data from visiting all info elements. | 39 // Gather data from visiting all info elements. |
32 var tracker = new _SizeTracker(debugLibName); | 40 var tracker = new _SizeTracker(debugLibName); |
33 info.accept(tracker); | 41 info.accept(tracker); |
34 | 42 |
35 // Validate that listed elements include elements of each library. | 43 // Validate that listed elements include elements of each library. |
36 Set<Info> listed = new Set()..addAll(info.functions)..addAll(info.fields); | 44 Set<Info> listed = new Set()..addAll(info.functions)..addAll(info.fields); |
37 // For our sanity we do some validation of dump-info invariants | 45 // For our sanity we do some validation of dump-info invariants |
38 var diff1 = listed.difference(tracker.discovered); | 46 var diff1 = listed.difference(tracker.discovered); |
39 var diff2 = tracker.discovered.difference(listed); | 47 var diff2 = tracker.discovered.difference(listed); |
40 if (diff1.length == 0 || diff2.length == 0) { | 48 if (diff1.length == 0 || diff2.length == 0) { |
(...skipping 19 matching lines...) Expand all Loading... |
60 var percent = | 68 var percent = |
61 ((realTotal - accounted) * 100 / realTotal).toStringAsFixed(2); | 69 ((realTotal - accounted) * 100 / realTotal).toStringAsFixed(2); |
62 _fail('$percent% size missing: $accounted (all libs + consts) ' | 70 _fail('$percent% size missing: $accounted (all libs + consts) ' |
63 '< $realTotal (total)'); | 71 '< $realTotal (total)'); |
64 } | 72 } |
65 var missingTotal = tracker.missing.values.fold(0, (a, b) => a + b); | 73 var missingTotal = tracker.missing.values.fold(0, (a, b) => a + b); |
66 if (missingTotal > 0) { | 74 if (missingTotal > 0) { |
67 var percent = (missingTotal * 100 / realTotal).toStringAsFixed(2); | 75 var percent = (missingTotal * 100 / realTotal).toStringAsFixed(2); |
68 _fail('$percent% size missing in libraries (sum of elements > lib.size)'); | 76 _fail('$percent% size missing in libraries (sum of elements > lib.size)'); |
69 } | 77 } |
70 | |
71 // Validate dependency data. | |
72 compareGraphs(info); | |
73 } | 78 } |
74 | 79 |
75 class _SizeTracker extends RecursiveInfoVisitor { | 80 class _SizeTracker extends RecursiveInfoVisitor { |
76 /// A library name for which to print debugging information (if not null). | 81 /// A library name for which to print debugging information (if not null). |
77 final String _debugLibName; | 82 final String _debugLibName; |
78 | 83 |
79 _SizeTracker(this._debugLibName); | 84 _SizeTracker(this._debugLibName); |
80 | 85 |
81 /// [FunctionInfo]s and [FieldInfo]s transitively reachable from [LibraryInfo] | 86 /// [FunctionInfo]s and [FieldInfo]s transitively reachable from [LibraryInfo] |
82 /// elements. | 87 /// elements. |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 } | 206 } |
202 } | 207 } |
203 } | 208 } |
204 | 209 |
205 class _State { | 210 class _State { |
206 int _count = 0; | 211 int _count = 0; |
207 int _totalSize = 0; | 212 int _totalSize = 0; |
208 int _bodySize = 0; | 213 int _bodySize = 0; |
209 } | 214 } |
210 | 215 |
| 216 /// Validates that both forms of dependency information match. |
211 void compareGraphs(AllInfo info) { | 217 void compareGraphs(AllInfo info) { |
212 var g1 = new EdgeListGraph<Info>(); | 218 var g1 = new EdgeListGraph<Info>(); |
213 var g2 = new EdgeListGraph<Info>(); | 219 var g2 = new EdgeListGraph<Info>(); |
214 for (var f in info.functions) { | 220 for (var f in info.functions) { |
215 g1.addNode(f); | 221 g1.addNode(f); |
216 for (var g in f.uses) { | 222 for (var g in f.uses) { |
217 g1.addEdge(f, g.target); | 223 g1.addEdge(f, g.target); |
218 } | 224 } |
219 g2.addNode(f); | 225 g2.addNode(f); |
220 if (info.dependencies[f] != null) { | 226 if (info.dependencies[f] != null) { |
(...skipping 30 matching lines...) Expand all Loading... |
251 info.fields.forEach(_sameEdges); | 257 info.fields.forEach(_sameEdges); |
252 if (inUsesNotInDependencies == 0 && inDependenciesNotInUses == 0) { | 258 if (inUsesNotInDependencies == 0 && inDependenciesNotInUses == 0) { |
253 _pass('dependency data is consistent'); | 259 _pass('dependency data is consistent'); |
254 } else { | 260 } else { |
255 _fail('inconsistencies in dependency data:\n' | 261 _fail('inconsistencies in dependency data:\n' |
256 ' $inUsesNotInDependencies edges missing from "dependencies" graph\n' | 262 ' $inUsesNotInDependencies edges missing from "dependencies" graph\n' |
257 ' $inDependenciesNotInUses edges missing from "uses" graph'); | 263 ' $inDependenciesNotInUses edges missing from "uses" graph'); |
258 } | 264 } |
259 } | 265 } |
260 | 266 |
| 267 // Validates that all elements are reachable from `main` in the dependency |
| 268 // graph. |
| 269 verifyDeps(AllInfo info) { |
| 270 var graph = graphFromInfo(info); |
| 271 var entrypoint = info.program.entrypoint; |
| 272 var reachables = new Set.from(graph.preOrder(entrypoint)); |
| 273 |
| 274 var functionsAndFields = []..addAll(info.functions)..addAll(info.fields); |
| 275 var unreachables = |
| 276 functionsAndFields.where((func) => !reachables.contains(func)); |
| 277 if (unreachables.isNotEmpty) { |
| 278 _fail('${unreachables.length} elements are unreachable from the ' |
| 279 'entrypoint'); |
| 280 } else { |
| 281 _pass('all elements are reachable from the entrypoint'); |
| 282 } |
| 283 } |
| 284 |
261 _pass(String msg) => print('\x1b[32mPASS\x1b[0m: $msg'); | 285 _pass(String msg) => print('\x1b[32mPASS\x1b[0m: $msg'); |
262 _fail(String msg) => print('\x1b[31mFAIL\x1b[0m: $msg'); | 286 _fail(String msg) => print('\x1b[31mFAIL\x1b[0m: $msg'); |
OLD | NEW |