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

Side by Side Diff: pkg/compiler/lib/src/dart_backend/renamer.dart

Issue 2213673002: Delete dart_backend from compiler. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 4 months 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
OLDNEW
(Empty)
1 // Copyright (c) 2012, 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 part of dart_backend;
6
7 Comparator get _compareNodes => compareBy((n) => n.getBeginToken().charOffset);
8
9 abstract class Renamable implements Comparable {
10 final int RENAMABLE_TYPE_ELEMENT = 1;
11 final int RENAMABLE_TYPE_MEMBER = 2;
12 final int RENAMABLE_TYPE_LOCAL = 3;
13
14 final Set<Node> nodes;
15
16 Renamable(this.nodes);
17 int compareTo(Renamable other) {
18 int nodesDiff = other.nodes.length.compareTo(this.nodes.length);
19 if (nodesDiff != 0) return nodesDiff;
20 int typeDiff = this.kind.compareTo(other.kind);
21 return typeDiff != 0 ? typeDiff : compareInternals(other);
22 }
23
24 int compareInternals(Renamable other);
25 int get kind;
26
27 String createNewName(PlaceholderRenamer placeholderRenamer);
28 }
29
30 class GlobalRenamable extends Renamable {
31 final Entity entity;
32
33 GlobalRenamable(this.entity, Set<Node> nodes) : super(nodes);
34
35 int compareInternals(GlobalRenamable other) =>
36 compareElements(this.entity, other.entity);
37 int get kind => RENAMABLE_TYPE_ELEMENT;
38 String createNewName(PlaceholderRenamer placeholderRenamer) {
39 return placeholderRenamer._renameGlobal(entity);
40 }
41 }
42
43 class MemberRenamable extends Renamable {
44 final String identifier;
45 MemberRenamable(this.identifier, Set<Node> nodes) : super(nodes);
46 int compareInternals(MemberRenamable other) =>
47 this.identifier.compareTo(other.identifier);
48 int get kind => RENAMABLE_TYPE_MEMBER;
49 String createNewName(PlaceholderRenamer placeholderRenamer) {
50 return placeholderRenamer._generateMemberName(identifier);
51 }
52 }
53
54 class LocalRenamable extends Renamable {
55 LocalRenamable(Set<Node> nodes) : super(nodes);
56 int compareInternals(LocalRenamable other) => _compareNodes(
57 sorted(this.nodes, _compareNodes)[0],
58 sorted(other.nodes, _compareNodes)[0]);
59 int get kind => RENAMABLE_TYPE_LOCAL;
60 String createNewName(PlaceholderRenamer placeholderRenamer) {
61 return placeholderRenamer._generateUniqueTopLevelName("");
62 }
63 }
64
65 /**
66 * Renames only top-level elements that would lead to ambiguity if not renamed.
67 */
68 class PlaceholderRenamer {
69 /// After running [computeRenames] this will contain the computed renames.
70 final Map<Node, String> renames = new Map<Node, String>();
71
72 /// After running [computeRenames] this will map the used platform
73 /// libraries to their respective prefixes.
74 final Map<LibraryElement, String> platformImports =
75 <LibraryElement, String>{};
76
77 final bool enableMinification;
78 final Set<String> fixedDynamicNames;
79 final Set<String> fixedStaticNames;
80 final Map<Element, LibraryElement> reexportingLibraries;
81 final bool cutDeclarationTypes;
82
83 final Map<Entity, String> _renamedCache = new Map<Entity, String>();
84 final Map<Entity, Map<String, String>> _privateCache =
85 new Map<Entity, Map<String, String>>();
86
87 // Identifiers that has already been used, or are reserved by the
88 // language/platform.
89 Set<String> _forbiddenIdentifiers;
90 Set<String> _allNamedParameterIdentifiers;
91
92 Generator _generator;
93
94 PlaceholderRenamer(
95 this.fixedDynamicNames, this.fixedStaticNames, this.reexportingLibraries,
96 {this.enableMinification, this.cutDeclarationTypes});
97
98 void _renameNodes(Iterable<Node> nodes, String renamer(Node node)) {
99 for (Node node in sorted(nodes, _compareNodes)) {
100 renames[node] = renamer(node);
101 }
102 }
103
104 String _generateUniqueTopLevelName(String originalName) {
105 String newName = _generator.generate(originalName, (name) {
106 return _forbiddenIdentifiers.contains(name) ||
107 _allNamedParameterIdentifiers.contains(name);
108 });
109 _forbiddenIdentifiers.add(newName);
110 return newName;
111 }
112
113 String _generateMemberName(String original) {
114 return _generator.generate(original, _forbiddenIdentifiers.contains);
115 }
116
117 /// Looks up [originalName] in the [_privateCache] cache of [library].
118 /// If [originalName] was not renamed before, generate a new name.
119 String _getPrivateName(LibraryElement library, String originalName) {
120 return _privateCache
121 .putIfAbsent(library, () => new Map<String, String>())
122 .putIfAbsent(
123 originalName, () => _generateUniqueTopLevelName(originalName));
124 }
125
126 String _renameConstructor(ConstructorPlaceholder placeholder) {
127 String name = placeholder.element.name;
128 if (name == '') return "";
129 String result = _renameGlobal(placeholder.element);
130 return result;
131 }
132
133 String _renameGlobal(Entity entity) {
134 assert(entity is! Element ||
135 Elements.isMalformed(entity) ||
136 Elements.isStaticOrTopLevel(entity) ||
137 entity is TypeVariableElement);
138 // TODO(smok): We may want to reuse class static field and method names.
139 if (entity is Element) {
140 LibraryElement library = entity.library;
141 if (reexportingLibraries.containsKey(entity)) {
142 library = reexportingLibraries[entity];
143 }
144 if (library.isPlatformLibrary) {
145 // TODO(johnniwinther): Handle prefixes for dart:core.
146 if (library.canonicalUri == Uris.dart_core) return entity.name;
147 if (library.isInternalLibrary) {
148 throw new SpannableAssertionFailure(
149 entity,
150 "Internal library $library should never have been imported from "
151 "the code compiled by dart2dart.");
152 }
153
154 String prefix = platformImports.putIfAbsent(library, () => null);
155 if (entity.isTopLevel && fixedDynamicNames.contains(entity.name)) {
156 if (prefix == null) {
157 prefix = _generateUniqueTopLevelName('');
158 platformImports[library] = prefix;
159 }
160 return '$prefix.${entity.name}';
161 }
162 return entity.name;
163 }
164 }
165 String name = _renamedCache.putIfAbsent(
166 entity, () => _generateUniqueTopLevelName(entity.name));
167 // Look up in [_renamedCache] for a name for [entity] .
168 // If it was not renamed before, generate a new name.
169 return name;
170 }
171
172 void _computeMinifiedRenames(PlaceholderCollector placeholderCollector) {
173 _generator = new MinifyingGenerator();
174
175 // Build a list sorted by usage of local nodes that will be renamed to
176 // the same identifier. So the top-used local variables in all functions
177 // will be renamed first and will all share the same new identifier.
178 int maxLength = placeholderCollector.functionScopes.values
179 .fold(0, (a, b) => max(a, b.localPlaceholders.length));
180
181 List<Set<Node>> allLocals =
182 new List<Set<Node>>.generate(maxLength, (_) => new Set<Node>());
183
184 for (FunctionScope functionScope
185 in placeholderCollector.functionScopes.values) {
186 // Add current sorted local identifiers to the whole sorted list
187 // of all local identifiers for all functions.
188 List<LocalPlaceholder> currentSortedPlaceholders = sorted(
189 functionScope.localPlaceholders,
190 compareBy((LocalPlaceholder ph) => -ph.nodes.length));
191
192 List<Set<Node>> currentSortedNodes = currentSortedPlaceholders
193 .map((LocalPlaceholder ph) => ph.nodes)
194 .toList();
195
196 for (int i = 0; i < currentSortedNodes.length; i++) {
197 allLocals[i].addAll(currentSortedNodes[i]);
198 }
199 }
200
201 // Rename elements, members and locals together based on their usage
202 // count, otherwise when we rename elements first there will be no good
203 // identifiers left for members even if they are used often.
204 List<Renamable> renamables = new List<Renamable>();
205 placeholderCollector.elementNodes
206 .forEach((Element element, Set<Node> nodes) {
207 renamables.add(new GlobalRenamable(element, nodes));
208 });
209 placeholderCollector.memberPlaceholders
210 .forEach((String memberName, Set<Identifier> identifiers) {
211 renamables.add(new MemberRenamable(memberName, identifiers));
212 });
213 for (Set<Node> localIdentifiers in allLocals) {
214 renamables.add(new LocalRenamable(localIdentifiers));
215 }
216 renamables.sort();
217 for (Renamable renamable in renamables) {
218 String newName = renamable.createNewName(this);
219 _renameNodes(renamable.nodes, (_) => newName);
220 }
221 }
222
223 void _computeNonMinifiedRenames(PlaceholderCollector placeholderCollector) {
224 _generator = new ConservativeGenerator();
225 // Rename elements.
226 placeholderCollector.elementNodes
227 .forEach((Element element, Set<Node> nodes) {
228 _renameNodes(nodes, (_) => _renameGlobal(element));
229 });
230
231 // Rename locals.
232 placeholderCollector.functionScopes
233 .forEach((functionElement, functionScope) {
234 Set<String> memberIdentifiers = new Set<String>();
235 Set<LocalPlaceholder> placeholders = functionScope.localPlaceholders;
236 if (functionElement != null && functionElement.enclosingClass != null) {
237 functionElement.enclosingClass.forEachMember((enclosingClass, member) {
238 memberIdentifiers.add(member.name);
239 });
240 }
241 Set<String> usedLocalIdentifiers = new Set<String>();
242 for (LocalPlaceholder placeholder in placeholders) {
243 String nextId = _generator.generate(placeholder.identifier, (name) {
244 return functionScope.parameterIdentifiers.contains(name) ||
245 _forbiddenIdentifiers.contains(name) ||
246 usedLocalIdentifiers.contains(name) ||
247 memberIdentifiers.contains(name);
248 });
249 usedLocalIdentifiers.add(nextId);
250 _renameNodes(placeholder.nodes, (_) => nextId);
251 }
252 });
253
254 // Do not rename members to top-levels, that allows to avoid renaming
255 // members to constructors.
256 placeholderCollector.memberPlaceholders.forEach((identifier, nodes) {
257 String newIdentifier = _generateMemberName(identifier);
258 _renameNodes(nodes, (_) => newIdentifier);
259 });
260 }
261
262 /// Finds renamings for all the placeholders in [placeholderCollector] and
263 /// stores them in [renames].
264 /// Also adds to [platformImports] all the platform-libraries that are used.
265 void computeRenames(PlaceholderCollector placeholderCollector) {
266 _allNamedParameterIdentifiers = new Set<String>();
267 for (FunctionScope functionScope
268 in placeholderCollector.functionScopes.values) {
269 _allNamedParameterIdentifiers.addAll(functionScope.parameterIdentifiers);
270 }
271
272 _forbiddenIdentifiers = new Set<String>.from(fixedDynamicNames);
273 _forbiddenIdentifiers.addAll(fixedStaticNames);
274 _forbiddenIdentifiers.addAll(Keyword.keywords.keys);
275 _forbiddenIdentifiers.add('main');
276
277 if (enableMinification) {
278 _computeMinifiedRenames(placeholderCollector);
279 } else {
280 _computeNonMinifiedRenames(placeholderCollector);
281 }
282
283 // Rename constructors.
284 for (ConstructorPlaceholder placeholder
285 in placeholderCollector.constructorPlaceholders) {
286 renames[placeholder.node] = _renameConstructor(placeholder);
287 }
288 ;
289
290 // Rename private identifiers uniquely for each library.
291 placeholderCollector.privateNodes
292 .forEach((LibraryElement library, Set<Identifier> identifiers) {
293 for (Identifier identifier in identifiers) {
294 renames[identifier] = _getPrivateName(library, identifier.source);
295 }
296 });
297
298 // Rename unresolved nodes, to make sure they still do not resolve.
299 for (Node node in placeholderCollector.unresolvedNodes) {
300 renames[node] = _generateUniqueTopLevelName('Unresolved');
301 }
302
303 // Erase prefixes that are now not needed.
304 for (Node node in placeholderCollector.prefixNodesToErase) {
305 renames[node] = '';
306 }
307
308 if (cutDeclarationTypes) {
309 for (DeclarationTypePlaceholder placeholder
310 in placeholderCollector.declarationTypePlaceholders) {
311 renames[placeholder.typeNode] = placeholder.requiresVar ? 'var' : '';
312 }
313 }
314 }
315 }
316
317 /**
318 * Generates mini ID based on index.
319 * In other words, it converts index to visual representation
320 * as if digits are given characters.
321 */
322 String generateMiniId(int index) {
323 const String firstCharAlphabet =
324 r'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
325 const String otherCharsAlphabet =
326 r'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$';
327 // It's like converting index in decimal to [chars] radix.
328 if (index < firstCharAlphabet.length) return firstCharAlphabet[index];
329 StringBuffer resultBuilder = new StringBuffer();
330 resultBuilder.writeCharCode(
331 firstCharAlphabet.codeUnitAt(index % firstCharAlphabet.length));
332 index ~/= firstCharAlphabet.length;
333 int length = otherCharsAlphabet.length;
334 while (index >= length) {
335 resultBuilder.writeCharCode(otherCharsAlphabet.codeUnitAt(index % length));
336 index ~/= length;
337 }
338 resultBuilder.write(otherCharsAlphabet[index]);
339 return resultBuilder.toString();
340 }
341
342 abstract class Generator {
343 String generate(String originalName, bool isForbidden(String name));
344 }
345
346 /// Always tries to return original identifier name unless it is forbidden.
347 class ConservativeGenerator implements Generator {
348 String generate(String originalName, bool isForbidden(String name)) {
349 String result = originalName;
350 int index = 0;
351 while (isForbidden(result)) {
352 //|| result == originalName) {
353 result = '${originalName}_${generateMiniId(index++)}';
354 }
355 return result;
356 }
357 }
358
359 /// Always tries to generate the most compact identifier.
360 class MinifyingGenerator implements Generator {
361 int index = 0;
362
363 MinifyingGenerator();
364
365 String generate(String originalName, bool isForbidden(String name)) {
366 String result;
367 do {
368 result = generateMiniId(index++);
369 } while (isForbidden(result));
370 return result;
371 }
372 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/dart_backend/placeholder_collector.dart ('k') | pkg/compiler/lib/src/diagnostics/messages.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698