OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 library dart2js.inferrer.type_graph_dump; | 4 library dart2js.inferrer.type_graph_dump; |
5 | 5 |
6 import '../../compiler_new.dart'; | 6 import '../../compiler_new.dart'; |
7 import '../elements/elements.dart'; | 7 import '../elements/elements.dart'; |
| 8 import '../elements/entities.dart'; |
8 import '../types/types.dart'; | 9 import '../types/types.dart'; |
9 import 'inferrer_engine.dart'; | 10 import 'inferrer_engine.dart'; |
10 import 'type_graph_nodes.dart'; | 11 import 'type_graph_nodes.dart'; |
11 import 'debug.dart'; | 12 import 'debug.dart'; |
12 | 13 |
13 /// Dumps the type inference graph in Graphviz Dot format into the `typegraph` | 14 /// Dumps the type inference graph in Graphviz Dot format into the `typegraph` |
14 /// subfolder of the current working directory. Each function body is dumped in | 15 /// subfolder of the current working directory. Each function body is dumped in |
15 /// a separate file. | 16 /// a separate file. |
16 /// | 17 /// |
17 /// The resulting .dot files must be processed using the Graphviz `dot` command, | 18 /// The resulting .dot files must be processed using the Graphviz `dot` command, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 Set<TypeInformation> copy = node.assignments.toSet(); | 56 Set<TypeInformation> copy = node.assignments.toSet(); |
56 if (!copy.isEmpty) { | 57 if (!copy.isEmpty) { |
57 assignmentsBeforeTracing[node] = copy; | 58 assignmentsBeforeTracing[node] = copy; |
58 } | 59 } |
59 } | 60 } |
60 } | 61 } |
61 | 62 |
62 /// Dumps the entire graph. | 63 /// Dumps the entire graph. |
63 void afterAnalysis() { | 64 void afterAnalysis() { |
64 // Group all the type nodes by their context member. | 65 // Group all the type nodes by their context member. |
65 Map<MemberElement, List<TypeInformation>> nodes = | 66 Map<MemberEntity, List<TypeInformation>> nodes = |
66 <MemberElement, List<TypeInformation>>{}; | 67 <MemberEntity, List<TypeInformation>>{}; |
67 for (TypeInformation node in inferrer.types.allTypes) { | 68 for (TypeInformation node in inferrer.types.allTypes) { |
68 if (node.contextMember != null) { | 69 if (node.contextMember != null) { |
69 nodes | 70 nodes |
70 .putIfAbsent(node.contextMember, () => <TypeInformation>[]) | 71 .putIfAbsent(node.contextMember, () => <TypeInformation>[]) |
71 .add(node); | 72 .add(node); |
72 } | 73 } |
73 } | 74 } |
74 // Print every group separately. | 75 // Print every group separately. |
75 for (MemberElement element in nodes.keys) { | 76 for (MemberEntity element in nodes.keys) { |
76 OutputSink output; | 77 OutputSink output; |
77 try { | 78 try { |
78 String name = filenameFromElement(element); | 79 String name = filenameFromElement(element); |
79 output = inferrer.compiler | 80 output = inferrer.compiler |
80 .outputProvider('$outputDir/$name', 'dot', OutputType.debug); | 81 .outputProvider('$outputDir/$name', 'dot', OutputType.debug); |
81 _GraphGenerator visitor = new _GraphGenerator(this, element, output); | 82 _GraphGenerator visitor = new _GraphGenerator(this, element, output); |
82 for (TypeInformation node in nodes[element]) { | 83 for (TypeInformation node in nodes[element]) { |
83 visitor.visit(node); | 84 visitor.visit(node); |
84 } | 85 } |
85 visitor.addMissingNodes(); | 86 visitor.addMissingNodes(); |
86 visitor.finish(); | 87 visitor.finish(); |
87 } finally { | 88 } finally { |
88 if (output != null) { | 89 if (output != null) { |
89 output.close(); | 90 output.close(); |
90 } | 91 } |
91 } | 92 } |
92 } | 93 } |
93 } | 94 } |
94 | 95 |
95 /// Returns the filename (without extension) in which to dump the type | 96 /// Returns the filename (without extension) in which to dump the type |
96 /// graph for [element]. | 97 /// graph for [element]. |
97 /// | 98 /// |
98 /// Will never return the a given filename more than once, even if called with | 99 /// Will never return the a given filename more than once, even if called with |
99 /// the same element. | 100 /// the same element. |
100 String filenameFromElement(Element element) { | 101 String filenameFromElement(MemberElement element) { |
101 // The toString method of elements include characters that are unsuitable | 102 // The toString method of elements include characters that are unsuitable |
102 // for URIs and file systems. | 103 // for URIs and file systems. |
103 List<String> parts = <String>[]; | 104 List<String> parts = <String>[]; |
104 parts.add(element.library?.libraryName); | 105 parts.add(element.library?.libraryName); |
105 parts.add(element.enclosingClass?.name); | 106 parts.add(element.enclosingClass?.name); |
106 Element namedElement = | 107 if (element.isGetter) { |
107 element is LocalElement ? element.executableContext : element; | 108 parts.add('get-${element.name}'); |
108 if (namedElement.isGetter) { | 109 } else if (element.isSetter) { |
109 parts.add('get-${namedElement.name}'); | 110 parts.add('set-${element.name}'); |
110 } else if (namedElement.isSetter) { | 111 } else if (element.isConstructor) { |
111 parts.add('set-${namedElement.name}'); | 112 if (element.name.isEmpty) { |
112 } else if (namedElement.isConstructor) { | |
113 if (namedElement.name.isEmpty) { | |
114 parts.add('-constructor'); | 113 parts.add('-constructor'); |
115 } else { | 114 } else { |
116 parts.add(namedElement.name); | 115 parts.add(element.name); |
117 } | 116 } |
118 } else if (namedElement.isOperator) { | 117 } else if (element.isOperator) { |
119 parts.add(Elements | 118 parts.add(Elements |
120 .operatorNameToIdentifier(namedElement.name) | 119 .operatorNameToIdentifier(element.name) |
121 .replaceAll(r'$', '-')); | 120 .replaceAll(r'$', '-')); |
122 } else { | 121 } else { |
123 parts.add(namedElement.name); | 122 parts.add(element.name); |
124 } | 123 } |
125 if (namedElement != element) { | 124 if (element != element) { |
126 if (element.name.isEmpty) { | 125 if (element.name.isEmpty) { |
127 parts.add('anon${element.sourcePosition.begin}'); | 126 parts.add('anon${element.sourcePosition.begin}'); |
128 } else { | 127 } else { |
129 parts.add(element.name); | 128 parts.add(element.name); |
130 } | 129 } |
131 } | 130 } |
132 String filename = parts.where((x) => x != null && x != '').join('.'); | 131 String filename = parts.where((x) => x != null && x != '').join('.'); |
133 if (usedFilenames.add(filename)) return filename; | 132 if (usedFilenames.add(filename)) return filename; |
134 // The filename has already been used by another method. Append a serial | 133 // The filename has already been used by another method. Append a serial |
135 // number to ensure we don't overwrite it. | 134 // number to ensure we don't overwrite it. |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 String value = formatType(type.valueType); | 453 String value = formatType(type.valueType); |
455 return '$container<$key,$value>'; | 454 return '$container<$key,$value>'; |
456 } | 455 } |
457 if (type is ValueTypeMask) { | 456 if (type is ValueTypeMask) { |
458 String baseType = formatType(type.forwardTo); | 457 String baseType = formatType(type.forwardTo); |
459 String value = type.value.toStructuredText(); | 458 String value = type.value.toStructuredText(); |
460 return '$baseType=$value'; | 459 return '$baseType=$value'; |
461 } | 460 } |
462 return '$type'; // Fall back on toString if not supported here. | 461 return '$type'; // Fall back on toString if not supported here. |
463 } | 462 } |
OLD | NEW |