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

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

Issue 448943004: Refactor and simplify the dart2dart renamer. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix minifying name generation Created 6 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 side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart
index ff5b28a05e2af362616b1a05d976464ffcd8fee1..37e9b478ac51e1a5e8a43ce01d8bdce1e57250d2 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart
@@ -7,257 +7,222 @@ part of dart_backend;
Comparator get _compareNodes =>
compareBy((n) => n.getBeginToken().charOffset);
-typedef String _Renamer(Renamable renamable);
-
-abstract class Renamable {
+abstract class Renamable implements Comparable {
final int RENAMABLE_TYPE_ELEMENT = 1;
final int RENAMABLE_TYPE_MEMBER = 2;
final int RENAMABLE_TYPE_LOCAL = 3;
final Set<Node> nodes;
- final _Renamer renamer;
- Renamable(this.nodes, this.renamer);
+ Renamable(this.nodes);
int compareTo(Renamable other) {
int nodesDiff = other.nodes.length.compareTo(this.nodes.length);
if (nodesDiff != 0) return nodesDiff;
- int typeDiff = this.getTypeId().compareTo(other.getTypeId());
+ int typeDiff = this.kind.compareTo(other.kind);
return typeDiff != 0 ? typeDiff : compareInternals(other);
}
int compareInternals(Renamable other);
- int getTypeId();
+ int get kind;
- String rename() => renamer(this);
+ String createNewName(PlaceholderRenamer placeholderRenamer);
}
-class ElementRenamable extends Renamable {
- final Element element;
+class GlobalRenamable extends Renamable {
+ final Entity entity;
- ElementRenamable(this.element, Set<Node> nodes, _Renamer renamer)
- : super(nodes, renamer);
+ GlobalRenamable(this.entity, Set<Node> nodes)
+ : super(nodes);
- int compareInternals(ElementRenamable other) =>
- compareElements(this.element, other.element);
- int getTypeId() => RENAMABLE_TYPE_ELEMENT;
+ int compareInternals(GlobalRenamable other) =>
+ compareElements(this.entity, other.entity);
+ int get kind => RENAMABLE_TYPE_ELEMENT;
+ String createNewName(PlaceholderRenamer placeholderRenamer) {
+ return placeholderRenamer._renameGlobal(entity);
+ }
}
class MemberRenamable extends Renamable {
final String identifier;
- MemberRenamable(this.identifier, Set<Node> nodes, _Renamer renamer)
- : super(nodes, renamer);
+ MemberRenamable(this.identifier, Set<Node> nodes)
+ : super(nodes);
int compareInternals(MemberRenamable other) =>
this.identifier.compareTo(other.identifier);
- int getTypeId() => RENAMABLE_TYPE_MEMBER;
+ int get kind => RENAMABLE_TYPE_MEMBER;
+ String createNewName(PlaceholderRenamer placeholderRenamer) {
+ return placeholderRenamer._generateMemberName(identifier);
+ }
}
class LocalRenamable extends Renamable {
- LocalRenamable(Set<Node> nodes, _Renamer renamer) : super(nodes, renamer);
+ LocalRenamable(Set<Node> nodes)
+ : super(nodes);
int compareInternals(LocalRenamable other) =>
_compareNodes(sorted(this.nodes, _compareNodes)[0],
sorted(other.nodes, _compareNodes)[0]);
- int getTypeId() => RENAMABLE_TYPE_LOCAL;
+ int get kind => RENAMABLE_TYPE_LOCAL;
+ String createNewName(PlaceholderRenamer placeholderRenamer) {
+ return placeholderRenamer._generateUniqueTopLevelName("");
+ }
}
/**
- * Renames only top-level elements that would let to ambiguity if not renamed.
+ * Renames only top-level elements that would lead to ambiguity if not renamed.
*/
-void renamePlaceholders(
- Compiler compiler,
- PlaceholderCollector placeholderCollector,
- Map<Node, String> renames,
- Map<LibraryElement, String> imports,
- Set<String> fixedMemberNames,
- Map<Element, LibraryElement> reexportingLibraries,
- bool cutDeclarationTypes,
- {bool uniqueGlobalNaming: false}) {
- final Map<LibraryElement, Map<String, String>> renamed
- = new Map<LibraryElement, Map<String, String>>();
-
- renameNodes(Iterable<Node> nodes, renamer) {
+class PlaceholderRenamer {
+ /// After running [computeRenames] this will contain the computed renames.
+ final Map<Node, String> renames = new Map<Node, String>();
+ /// After running [computeRenames] this will contain the used platform
+ /// libraries.
+ final Set<LibraryElement> platformImports = new Set<LibraryElement>();
+
+ final Compiler _compiler;
+ final Set<String> fixedMemberNames;
+ final Map<Element, LibraryElement> reexportingLibraries;
+ final bool cutDeclarationTypes;
+
+ final Map<Entity, String> _renamedCache = new Map<Entity, String>();
+ final Map<Entity, Map<String, String>> _privateCache =
+ new Map<Entity, Map<String, String>>();
+
+ // Identifiers that has already been used, or are reserved by the
+ // language/platform.
+ Set<String> _forbiddenIdentifiers;
+ Set<String> _allNamedParameterIdentifiers;
+
+ Generator _generator;
+
+ PlaceholderRenamer(this._compiler, this.fixedMemberNames,
+ this.reexportingLibraries, {this.cutDeclarationTypes}) ;
+
+ void _renameNodes(Iterable<Node> nodes, String renamer(Node node)) {
for (Node node in sorted(nodes, _compareNodes)) {
renames[node] = renamer(node);
}
}
- sortedForEach(Map<Element, dynamic> map, f) {
- for (Element element in sortElements(map.keys)) {
- f(element, map[element]);
- }
+ String _generateUniqueTopLevelName(originalName) {
+ String newName = _generator.generate(originalName, (name) {
+ return _forbiddenIdentifiers.contains(name) ||
+ _allNamedParameterIdentifiers.contains(name);
+ });
+ _forbiddenIdentifiers.add(newName);
+ return newName;
}
- String renameType(DartType type, Function renameElement) {
- if (type.isDynamic) return 'dynamic';
- // TODO(smok): Do not rename type if it is in platform library or
- // js-helpers.
- StringBuffer result = new StringBuffer(renameElement(type.element));
- if (type is GenericType && !type.treatAsRaw) {
- result.write('<');
- List<DartType> arguments = type.typeArguments;
- result.write(renameType(arguments.first, renameElement));
- for (int index = 1; index < arguments.length; index++) {
- result.write(',');
- result.write(renameType(arguments[index], renameElement));
- }
- result.write('>');
- }
- return result.toString();
+ String _generateMemberName(String original) {
+ return _generator.generate(original, _forbiddenIdentifiers.contains);
}
- String renameConstructor(Element element, ConstructorPlaceholder placeholder,
- Function renameString, Function renameElement) {
- assert(element.isConstructor);
- StringBuffer result = new StringBuffer();
- String name = element.name;
- if (element.name != '') {
- // Named constructor or factory. Is there a more reliable way to check
- // this case?
- if (!placeholder.isRedirectingCall) {
- result.write(renameType(placeholder.type, renameElement));
- result.write('.');
- }
- if (!element.library.isPlatformLibrary) {
- name = renameString(element.library, name);
- }
- result.write(name);
- } else {
- assert(!placeholder.isRedirectingCall);
- result.write(renameType(placeholder.type, renameElement));
- }
- return result.toString();
+ /// Looks up [originalName] in the [_privateCache] cache of [library].
+ /// If [originalName] was not renamed before, generate a new name.
+ String _getPrivateName(LibraryElement library, String originalName) {
+ return _privateCache.putIfAbsent(library, () => new Map<String, String>())
+ .putIfAbsent(originalName,
+ () => _generateUniqueTopLevelName(originalName));
+ }
+
+ String _renameConstructor(ConstructorPlaceholder placeholder) {
+ String name = placeholder.element.name;
+ if (name == '') return "";
+ String result = _renameGlobal(placeholder.element);
+ return result;
}
- Function makeElementRenamer(rename, generateUniqueName) => (element) {
- assert(Elements.isErroneousElement(element) ||
- Elements.isStaticOrTopLevel(element) ||
- element is TypeVariableElement);
+ String _renameGlobal(Entity entity) {
+ assert(entity is! Element ||
+ Elements.isErroneousElement(entity) ||
+ Elements.isStaticOrTopLevel(entity) ||
+ entity is TypeVariableElement);
// TODO(smok): We may want to reuse class static field and method names.
- String originalName = element.name;
- LibraryElement library = element.library;
- if (identical(element.library, compiler.coreLibrary)) {
- return originalName;
- }
- if (library.isPlatformLibrary) {
- assert(element.isTopLevel);
- if (reexportingLibraries.containsKey(element)) {
- library = reexportingLibraries[element];
+ if (entity is Element) {
+ LibraryElement library = entity.library;
+ if (reexportingLibraries.containsKey(entity)) {
+ library = reexportingLibraries[entity];
}
- if (!library.isInternalLibrary) {
- final prefix =
- imports.putIfAbsent(library, () => generateUniqueName('p'));
- return '$prefix.$originalName';
+ if (library.isPlatformLibrary) {
+ if (library != _compiler.coreLibrary) {
+ platformImports.add(library);
+ }
+ if (library.isInternalLibrary) {
+ throw new SpannableAssertionFailure(entity,
+ "Internal library $library should never have been imported from "
+ "the code compiled by dart2dart.");
+ }
+ return entity.name;
}
}
-
- return rename(library, originalName);
- };
-
- Function makeRenamer(generateUniqueName) =>
- (library, originalName) =>
- renamed.putIfAbsent(library, () => {})
- .putIfAbsent(originalName,
- () => generateUniqueName(originalName));
-
- // Renamer function that takes library and original name and returns a new
- // name for given identifier.
- Function rename;
- Function renameElement;
- // A function that takes original identifier name and generates a new unique
- // identifier.
- Function generateUniqueName;
-
- Set<String> allNamedParameterIdentifiers = new Set<String>();
- for (var functionScope in placeholderCollector.functionScopes.values) {
- allNamedParameterIdentifiers.addAll(functionScope.parameterIdentifiers);
+ String name = _renamedCache.putIfAbsent(entity,
+ () => _generateUniqueTopLevelName(entity.name));
+ // Look up in [_renamedCache] for a name for [entity] .
+ // If it was not renamed before, generate a new name.
+ return name;
}
- if (compiler.enableMinification) {
- MinifyingGenerator generator = new MinifyingGenerator();
- Set<String> forbiddenIdentifiers = new Set<String>.from(['main']);
- forbiddenIdentifiers.addAll(Keyword.keywords.keys);
- forbiddenIdentifiers.addAll(fixedMemberNames);
- generateUniqueName = (_) =>
- generator.generate((name) =>
- forbiddenIdentifiers.contains(name)
- || allNamedParameterIdentifiers.contains(name));
- rename = makeRenamer(generateUniqueName);
- renameElement = makeElementRenamer(rename, generateUniqueName);
-
- List<Set<Node>> allLocals = new List<Set<Node>>();
+ void _computeMinifiedRenames(PlaceholderCollector placeholderCollector) {
+ _generator = new MinifyingGenerator();
// Build a list sorted by usage of local nodes that will be renamed to
// the same identifier. So the top-used local variables in all functions
// will be renamed first and will all share the same new identifier.
- for (var functionScope in placeholderCollector.functionScopes.values) {
+ int maxLength = placeholderCollector.functionScopes.values.fold(0,
+ (a, b) => max(a, b.localPlaceholders.length));
+
+ List<Set<Node>> allLocals = new List<Set<Node>>
+ .generate(maxLength, (_) => new Set<Node>());
+
+ for (FunctionScope functionScope
+ in placeholderCollector.functionScopes.values) {
// Add current sorted local identifiers to the whole sorted list
// of all local identifiers for all functions.
List<LocalPlaceholder> currentSortedPlaceholders =
sorted(functionScope.localPlaceholders,
compareBy((LocalPlaceholder ph) => -ph.nodes.length));
- List<Set<Node>> currentSortedNodes =
- currentSortedPlaceholders.map((ph) => ph.nodes).toList();
- // Make room in all sorted locals list for new stuff.
- while (currentSortedNodes.length > allLocals.length) {
- allLocals.add(new Set<Node>());
- }
+
+ List<Set<Node>> currentSortedNodes = currentSortedPlaceholders
+ .map((LocalPlaceholder ph) => ph.nodes).toList();
+
for (int i = 0; i < currentSortedNodes.length; i++) {
allLocals[i].addAll(currentSortedNodes[i]);
}
}
- // Rename elements, members and locals together based on their usage count,
- // otherwise when we rename elements first there will be no good identifiers
- // left for members even if they are used often.
- String elementRenamer(ElementRenamable elementRenamable) =>
- renameElement(elementRenamable.element);
- String memberRenamer(MemberRenamable memberRenamable) =>
- generator.generate(forbiddenIdentifiers.contains);
- Function localRenamer = generateUniqueName;
- List<Renamable> renamables = [];
+ // Rename elements, members and locals together based on their usage
+ // count, otherwise when we rename elements first there will be no good
+ // identifiers left for members even if they are used often.
+ List<Renamable> renamables = new List<Renamable>();
placeholderCollector.elementNodes.forEach(
(Element element, Set<Node> nodes) {
- renamables.add(new ElementRenamable(element, nodes, elementRenamer));
+ renamables.add(new GlobalRenamable(element, nodes));
});
placeholderCollector.memberPlaceholders.forEach(
(String memberName, Set<Identifier> identifiers) {
- renamables.add(
- new MemberRenamable(memberName, identifiers, memberRenamer));
+ renamables.add(new MemberRenamable(memberName, identifiers));
});
for (Set<Node> localIdentifiers in allLocals) {
- renamables.add(new LocalRenamable(localIdentifiers, localRenamer));
+ renamables.add(new LocalRenamable(localIdentifiers));
}
- renamables.sort((Renamable renamable1, Renamable renamable2) =>
- renamable1.compareTo(renamable2));
+ renamables.sort();
for (Renamable renamable in renamables) {
- String newName = renamable.rename();
- renameNodes(renamable.nodes, (_) => newName);
+ String newName = renamable.createNewName(this);
+ _renameNodes(renamable.nodes, (_) => newName);
}
- } else {
- // Never rename anything to 'main'.
- final usedTopLevelOrMemberIdentifiers = new Set<String>();
- usedTopLevelOrMemberIdentifiers.add('main');
- usedTopLevelOrMemberIdentifiers.addAll(fixedMemberNames);
- generateUniqueName = (originalName) {
- String newName = conservativeGenerator(
- originalName, (name) =>
- usedTopLevelOrMemberIdentifiers.contains(name)
- || allNamedParameterIdentifiers.contains(name));
- usedTopLevelOrMemberIdentifiers.add(newName);
- return newName;
- };
- rename = makeRenamer(generateUniqueName);
- renameElement = makeElementRenamer(rename, generateUniqueName);
+ }
+
+ void _computeNonMinifiedRenames(PlaceholderCollector placeholderCollector) {
+ _generator = new ConservativeGenerator();
// Rename elements.
- sortedForEach(placeholderCollector.elementNodes,
+ placeholderCollector.elementNodes.forEach(
(Element element, Set<Node> nodes) {
- renameNodes(nodes, (_) => renameElement(element));
+ _renameNodes(nodes, (_) => _renameGlobal(element));
});
// Rename locals.
- sortedForEach(placeholderCollector.functionScopes,
+ placeholderCollector.functionScopes.forEach(
(functionElement, functionScope) {
- Set<LocalPlaceholder> placeholders = functionScope.localPlaceholders;
+
Set<String> memberIdentifiers = new Set<String>();
+ Set<LocalPlaceholder> placeholders = functionScope.localPlaceholders;
if (functionElement.enclosingClass != null) {
functionElement.enclosingClass.forEachMember(
(enclosingClass, member) {
@@ -266,46 +231,75 @@ void renamePlaceholders(
}
Set<String> usedLocalIdentifiers = new Set<String>();
for (LocalPlaceholder placeholder in placeholders) {
- String nextId =
- conservativeGenerator(placeholder.identifier, (name) =>
- functionScope.parameterIdentifiers.contains(name)
- || usedTopLevelOrMemberIdentifiers.contains(name)
- || usedLocalIdentifiers.contains(name)
- || memberIdentifiers.contains(name));
+ String nextId = _generator.generate(placeholder.identifier, (name) {
+ return functionScope.parameterIdentifiers.contains(name)
+ || _forbiddenIdentifiers.contains(name)
+ || usedLocalIdentifiers.contains(name)
+ || memberIdentifiers.contains(name);
+ });
usedLocalIdentifiers.add(nextId);
- renameNodes(placeholder.nodes, (_) => nextId);
+ _renameNodes(placeholder.nodes, (_) => nextId);
}
});
- final usedMemberIdentifiers = new Set<String>.from(fixedMemberNames);
// Do not rename members to top-levels, that allows to avoid renaming
// members to constructors.
- usedMemberIdentifiers.addAll(usedTopLevelOrMemberIdentifiers);
placeholderCollector.memberPlaceholders.forEach((identifier, nodes) {
- String newIdentifier = conservativeGenerator(
- identifier, usedMemberIdentifiers.contains);
- renameNodes(nodes, (_) => newIdentifier);
+ String newIdentifier = _generateMemberName(identifier);
+ _renameNodes(nodes, (_) => newIdentifier);
});
}
- // Rename constructors.
- sortedForEach(placeholderCollector.constructorPlaceholders,
- (Element constructor, List<ConstructorPlaceholder> placeholders) {
- for (ConstructorPlaceholder ph in placeholders) {
- renames[ph.node] =
- renameConstructor(constructor, ph, rename, renameElement);
- }
- });
- sortedForEach(placeholderCollector.privateNodes, (library, nodes) {
- renameNodes(nodes, (node) => rename(library, node.source));
- });
- renameNodes(placeholderCollector.unresolvedNodes,
- (_) => generateUniqueName('Unresolved'));
- renameNodes(placeholderCollector.nullNodes, (_) => '');
- if (cutDeclarationTypes) {
- for (DeclarationTypePlaceholder placeholder in
- placeholderCollector.declarationTypePlaceholders) {
- renames[placeholder.typeNode] = placeholder.requiresVar ? 'var' : '';
+ /// Finds renamings for all the placeholders in [placeholderCollector] and
+ /// stores them in [renames].
+ /// Also adds to [platformImports] all the platform-libraries that are used.
+ void computeRenames(PlaceholderCollector placeholderCollector) {
+ _allNamedParameterIdentifiers = new Set<String>();
+ for (FunctionScope functionScope in
+ placeholderCollector.functionScopes.values) {
+ _allNamedParameterIdentifiers.addAll(functionScope.parameterIdentifiers);
+ }
+
+ _forbiddenIdentifiers = new Set<String>.from(fixedMemberNames);
+ _forbiddenIdentifiers.addAll(Keyword.keywords.keys);
+ _forbiddenIdentifiers.add('main');
+
+ if (_compiler.enableMinification) {
+ _computeMinifiedRenames(placeholderCollector);
+ } else {
+ _computeNonMinifiedRenames(placeholderCollector);
+ }
+
+ // Rename constructors.
+ for (ConstructorPlaceholder placeholder in
+ placeholderCollector.constructorPlaceholders) {
+ renames[placeholder.node] =
+ _renameConstructor(placeholder);
+ };
+
+ // Rename private identifiers uniquely for each library.
+ placeholderCollector.privateNodes.forEach(
+ (LibraryElement library, Set<Identifier> identifiers) {
+ for (Identifier identifier in identifiers) {
+ renames[identifier] = _getPrivateName(library, identifier.source);
+ }
+ });
+
+ // Rename unresolved nodes, to make sure they still do not resolve.
+ for (Node node in placeholderCollector.unresolvedNodes) {
+ renames[node] = _generateUniqueTopLevelName('Unresolved');
+ }
+
+ // Erase prefixes that are now not needed.
+ for (Node node in placeholderCollector.prefixNodesToErase) {
+ renames[node] = '';
+ }
+
+ if (cutDeclarationTypes) {
+ for (DeclarationTypePlaceholder placeholder in
+ placeholderCollector.declarationTypePlaceholders) {
+ renames[placeholder.typeNode] = placeholder.requiresVar ? 'var' : '';
+ }
}
}
}
@@ -335,25 +329,29 @@ String generateMiniId(int index) {
return resultBuilder.toString();
}
+abstract class Generator {
+ String generate(String originalName, bool isForbidden(String name));
+}
-/** Always tries to return original identifier name unless it is forbidden. */
-String conservativeGenerator(String name, bool isForbidden(String name)) {
- String result = name;
- int index = 0;
- while (isForbidden(result)) {
- result = '${generateMiniId(index++)}_$name';
+/// Always tries to return original identifier name unless it is forbidden.
+class ConservativeGenerator implements Generator {
+ String generate(String originalName, bool isForbidden(String name)) {
+ String result = originalName;
+ int index = 0;
+ while (isForbidden(result) ){ //|| result == originalName) {
+ result = '${originalName}_${generateMiniId(index++)}';
+ }
+ return result;
}
- return result;
}
-
-/** Always tries to generate the most compact identifier. */
-class MinifyingGenerator {
+/// Always tries to generate the most compact identifier.
+class MinifyingGenerator implements Generator {
int index = 0;
MinifyingGenerator();
- String generate(bool isForbidden(String name)) {
+ String generate(String originalName, bool isForbidden(String name)) {
String result;
do {
result = generateMiniId(index++);

Powered by Google App Engine
This is Rietveld 408576698