| 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 |