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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart

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

Powered by Google App Engine
This is Rietveld 408576698