| Index: pkg/kernel/test/type_propagation_dump.dart
|
| diff --git a/pkg/kernel/test/type_propagation_dump.dart b/pkg/kernel/test/type_propagation_dump.dart
|
| deleted file mode 100644
|
| index 5af3f105a194d4b8d01ca35d21e430189ab19e47..0000000000000000000000000000000000000000
|
| --- a/pkg/kernel/test/type_propagation_dump.dart
|
| +++ /dev/null
|
| @@ -1,188 +0,0 @@
|
| -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -library kernel.type_propagation.dump;
|
| -
|
| -import 'package:kernel/kernel.dart';
|
| -import 'package:kernel/text/ast_to_text.dart';
|
| -import 'package:kernel/type_propagation/builder.dart';
|
| -import 'package:kernel/type_propagation/solver.dart';
|
| -import 'package:kernel/type_propagation/visualizer.dart';
|
| -import 'package:kernel/type_propagation/constraints.dart';
|
| -import 'package:kernel/type_propagation/type_propagation.dart';
|
| -import 'package:args/args.dart';
|
| -import 'dart:io';
|
| -
|
| -ArgParser parser = new ArgParser()
|
| - ..addFlag('graph', help: 'Generate graphviz dot files')
|
| - ..addOption('graph-filter',
|
| - valueHelp: 'name',
|
| - help: 'Only print graph for members whose name contains the given string')
|
| - ..addFlag('text', help: 'Generate annotated kernel text files')
|
| - ..addFlag('escape', help: 'Dump information from escape analysis')
|
| - ..addFlag('stats',
|
| - help: 'Print times and constraint system size', defaultsTo: true)
|
| - ..addFlag('solve', help: 'Solve the constraint system', defaultsTo: true);
|
| -
|
| -String get usage => """
|
| -Usage: dump [options] FILE.dill
|
| -
|
| -Options:
|
| -${parser.usage}
|
| -""";
|
| -
|
| -const String outputDir = 'typegraph';
|
| -
|
| -main(List<String> args) {
|
| - if (args.length == 0) {
|
| - print(usage);
|
| - exit(1);
|
| - }
|
| - ArgResults options = parser.parse(args);
|
| - if (options.rest.length != 1) {
|
| - print('Exactly one file must be given');
|
| - exit(1);
|
| - }
|
| - String path = options.rest.single;
|
| -
|
| - bool printGraphviz = options['graph'];
|
| - bool printText = options['text'];
|
| - bool printEscape = options['escape'];
|
| - bool useVisualizer = printGraphviz || printText || printEscape;
|
| -
|
| - Program program = loadProgramFromBinary(path);
|
| - Stopwatch watch = new Stopwatch()..start();
|
| - Visualizer visualizer = useVisualizer ? new Visualizer(program) : null;
|
| - Builder builder = new Builder(program, visualizer: visualizer, verbose: true);
|
| - int buildTime = watch.elapsedMilliseconds;
|
| -
|
| - watch.reset();
|
| - var solver = new Solver(builder);
|
| - if (options['solve']) {
|
| - solver.solve();
|
| - }
|
| - int solveTime = watch.elapsedMilliseconds;
|
| - visualizer?.solver = solver;
|
| - ConstraintSystem constraints = builder.constraints;
|
| -
|
| - if (printEscape) {
|
| - for (int value = 0; value <= constraints.numberOfValues; ++value) {
|
| - TreeNode node;
|
| - if (value < builder.hierarchy.classes.length) {
|
| - node = builder.hierarchy.classes[value];
|
| - } else {
|
| - FunctionNode function = visualizer.getFunctionFromValue(value);
|
| - if (function == null || function.parent is! Member) continue;
|
| - node = function.parent;
|
| - }
|
| - int escape = solver.getEscapeContext(value);
|
| - String escapeString = (escape == constraints.latticePointOfValue[value])
|
| - ? 'no escape'
|
| - : visualizer.getLatticePointName(escape);
|
| - print('$node -> $escapeString');
|
| - }
|
| - }
|
| -
|
| - if (printText) {
|
| - print('Printing kernel text files...');
|
| - new Directory(outputDir).createSync();
|
| - StringBuffer buffer = new StringBuffer();
|
| - Printer printer =
|
| - new Printer(buffer, annotator: visualizer.getTextAnnotator());
|
| - printer.writeProgramFile(program);
|
| - String path = '$outputDir/program.txt';
|
| - new File(path).writeAsStringSync('$buffer');
|
| - }
|
| -
|
| - if (printGraphviz) {
|
| - print('Printing graphviz dot files...');
|
| - String filter = options['graph-filter'];
|
| - new Directory(outputDir).createSync();
|
| - void dumpMember(Member member) {
|
| - if (filter != null && !'$member'.contains(filter)) return;
|
| - String name = sanitizeFilename('$member');
|
| - String path = '$outputDir/$name.dot';
|
| - String dotCode = visualizer.dumpMember(member);
|
| - new File(path).writeAsStringSync(dotCode);
|
| - }
|
| -
|
| - for (var library in program.libraries) {
|
| - library.members.forEach(dumpMember);
|
| - for (var class_ in library.classes) {
|
| - class_.members.forEach(dumpMember);
|
| - }
|
| - }
|
| - }
|
| -
|
| - if (options['stats']) {
|
| - var constraints = solver.constraints;
|
| - int numberOfConstraints = constraints.numberOfAssignments +
|
| - constraints.numberOfLoads +
|
| - constraints.numberOfStores;
|
| - int numberOfTransfers = numberOfConstraints * solver.iterations;
|
| - double transfersPerSecond =
|
| - (numberOfConstraints * solver.iterations) / (solveTime / 1000);
|
| - Iterable<int> outputVariables = [
|
| - builder.global.fields.values,
|
| - builder.global.returns.values,
|
| - builder.global.parameters.values
|
| - ].expand((x) => x);
|
| - int outputCount = outputVariables.length;
|
| - int inferredUnknown = 0;
|
| - int inferredNothing = 0;
|
| - int inferredNullable = 0;
|
| - int inferredNonNullable = 0;
|
| - int inferredOnlyNull = 0;
|
| - for (int variable in outputVariables) {
|
| - int values = solver.getVariableValue(variable);
|
| - int bitmask = solver.getVariableBitmask(variable);
|
| - if (values == Solver.bottom && bitmask == 0) {
|
| - ++inferredNothing;
|
| - } else if (values == Solver.bottom && bitmask == ValueBit.null_) {
|
| - ++inferredOnlyNull;
|
| - } else if (values == Solver.rootClass && bitmask == ValueBit.all) {
|
| - ++inferredUnknown;
|
| - } else if (bitmask & ValueBit.null_ != 0) {
|
| - ++inferredNullable;
|
| - } else {
|
| - ++inferredNonNullable;
|
| - }
|
| - }
|
| - print("""
|
| -Build time: $buildTime ms
|
| -Solve time: $solveTime ms
|
| -Iterations: ${solver.iterations}
|
| -
|
| -Classes: ${builder.hierarchy.classes.length}
|
| -Values: ${constraints.numberOfValues}
|
| -Unions: ${constraints.numberOfLatticePoints}
|
| -Variables: ${constraints.numberOfVariables}
|
| -Fields: ${builder.fieldNames.length}
|
| -Assignments: ${constraints.numberOfAssignments}
|
| -Loads: ${constraints.numberOfLoads}
|
| -Stores: ${constraints.numberOfStores}
|
| -
|
| -Transfers: $numberOfTransfers (${(transfersPerSecond / 1000000).toStringAsFixed(1)} M/s)
|
| -
|
| -Outputs: $outputCount
|
| -Unknown: $inferredUnknown (${percent(inferredUnknown, outputCount)})
|
| -Nullable: $inferredNullable (${percent(inferredNullable, outputCount)})
|
| -Non-nullable: $inferredNonNullable (${percent(inferredNonNullable, outputCount)})
|
| -Only null: $inferredOnlyNull (${percent(inferredOnlyNull, outputCount)})
|
| -Nothing: $inferredNothing (${percent(inferredNothing, outputCount)})
|
| - """);
|
| - }
|
| -}
|
| -
|
| -String percent(int amount, int total) {
|
| - if (total == 0) return '0%';
|
| - return (amount / total * 100).toStringAsFixed(1) + '%';
|
| -}
|
| -
|
| -String sanitizeFilename(String name) {
|
| - return name
|
| - .replaceAll('::', '.')
|
| - .replaceAll('/', r'$div')
|
| - .replaceAll('(', '')
|
| - .replaceAll(')', '');
|
| -}
|
|
|