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

Unified Diff: pkg/compiler/lib/src/js_backend/namer.dart

Issue 1428853004: Use better names for captured variables in closures. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Address comments Created 5 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 side-by-side diff with in-line comments
Download patch
Index: pkg/compiler/lib/src/js_backend/namer.dart
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 26dd37605963a441cf14f8e5ab68a69565dfa0d9..78966e3d53a6377f8f0ba3dbbae4f16b52a515d3 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -370,7 +370,7 @@ class Namer {
/// Although global names are distributed across a number of global objects,
/// (see [globalObjectFor]), we currently use a single namespace for all these
/// names.
- final Set<String> usedGlobalNames = new Set<String>();
+ final NamingScope globalScope = new NamingScope();
final Map<Element, jsAst.Name> userGlobals =
new HashMap<Element, jsAst.Name>();
final Map<String, jsAst.Name> internalGlobals =
@@ -379,7 +379,7 @@ class Namer {
/// Used disambiguated names in the instance namespace, issued by
/// [_disambiguateMember], [_disambiguateInternalMember],
/// [_disambiguateOperator], and [reservePublicMemberName].
- final Set<String> usedInstanceNames = new Set<String>();
+ final NamingScope instanceScope = new NamingScope();
final Map<String, jsAst.Name> userInstanceMembers =
new HashMap<String, jsAst.Name>();
final Map<Element, jsAst.Name> internalInstanceMembers =
@@ -388,18 +388,11 @@ class Namer {
new HashMap<String, jsAst.Name>();
/// Used to disambiguate names for constants in [constantName].
- final Set<String> usedConstantNames = new Set<String>();
+ final NamingScope constantScope = new NamingScope();
- Set<String> getUsedNames(NamingScope scope) {
- if (scope == NamingScope.global) {
- return usedGlobalNames;
- } else if (scope == NamingScope.instance){
- return usedInstanceNames;
- } else {
- assert(scope == NamingScope.constant);
- return usedConstantNames;
- }
- }
+ /// Used to store scopes for instances of [PrivatelyNamedJsEntity]
+ final Map<Entity, NamingScope> _privateNamingScopes =
+ new Map<Entity, NamingScope>();
final Map<String, int> popularNameCounters = <String, int>{};
@@ -417,28 +410,9 @@ class Namer {
final Map<String, LibraryElement> shortPrivateNameOwners =
<String, LibraryElement>{};
- /// Maps proposed names to *suggested* disambiguated names.
- ///
- /// Suggested names are hints to the [MinifyNamer], suggesting that a specific
- /// names be given to the first item with the given proposed name.
- ///
- /// This is currently used in [MinifyNamer] to assign very short minified
- /// names to things that tend to be used very often.
final Map<String, String> suggestedGlobalNames = <String, String>{};
final Map<String, String> suggestedInstanceNames = <String, String>{};
- Map<String, String> getSuggestedNames(NamingScope scope) {
- if (scope == NamingScope.global) {
- return suggestedGlobalNames;
- } else if (scope == NamingScope.instance) {
- return suggestedInstanceNames;
- } else {
- assert(scope == NamingScope.constant);
- return const {};
- }
- }
-
-
/// Used to store unique keys for library names. Keys are not used as names,
/// nor are they visible in the output. The only serve as an internal
/// key into maps.
@@ -476,6 +450,11 @@ class Namer {
String get closureInvocationSelectorName => Identifiers.call;
bool get shouldMinify => false;
+ NamingScope _getPrivateScopeFor(PrivatelyNamedJSEntity entity) {
+ return _privateNamingScopes.putIfAbsent(entity.rootOfScope,
+ () => new NamingScope());
+ }
+
/// Returns the string that is to be used as the result of a call to
/// [JS_GET_NAME] at [node] with argument [name].
jsAst.Name getNameForJsGetName(Node node, JsGetName name) {
@@ -545,7 +524,7 @@ class Namer {
jsAst.Name result = constantNames[constant];
if (result == null) {
String longName = constantLongName(constant);
- result = getFreshName(NamingScope.constant, longName);
+ result = getFreshName(constantScope, longName);
constantNames[constant] = result;
}
return _newReference(result);
@@ -799,14 +778,16 @@ class Namer {
return new StringBackedName(backend.getFixedBackendName(element));
}
- // Instances of BoxFieldElement are special. They are already created with
- // a unique and safe name. However, as boxes are not really instances of
- // classes, the usual naming scheme that tries to avoid name clashes with
- // super classes does not apply. We still do not mark the name as a
- // fixedBackendName, as we want to allow other namers to do something more
- // clever with them.
- if (element is BoxFieldElement) {
- return new StringBackedName(element.name);
+ // Some elements, like e.g. instances of BoxFieldElement are special.
+ // They are created with a unique and safe name for the element model.
+ // While their name is unique, it is not very readable. So we try to
+ // preserve the original, proposed name.
+ // However, as boxes are not really instances of classes, the usual naming
+ // scheme that tries to avoid name clashes with super classes does not
+ // apply. So we can directly grab a name.
+ if (element is JSEntity) {
+ return _disambiguateInternalMember(element,
+ () => element.declaredEntity.name);
}
// If the name of the field might clash with another field,
@@ -882,7 +863,7 @@ class Namer {
jsAst.Name _disambiguateInternalGlobal(String name) {
jsAst.Name newName = internalGlobals[name];
if (newName == null) {
- newName = getFreshName(NamingScope.global, name);
+ newName = getFreshName(globalScope, name);
internalGlobals[name] = newName;
}
return _newReference(newName);
@@ -929,7 +910,7 @@ class Namer {
jsAst.Name newName = userGlobals[element];
if (newName == null) {
String proposedName = _proposeNameForGlobal(element);
- newName = getFreshName(NamingScope.global, proposedName);
+ newName = getFreshName(globalScope, proposedName);
userGlobals[element] = newName;
}
return _newReference(newName);
@@ -969,7 +950,7 @@ class Namer {
// proposed name must be a valid identifier, but not necessarily unique.
proposedName += r'$' + suffixes.join(r'$');
}
- newName = getFreshName(NamingScope.instance, proposedName,
+ newName = getFreshName(instanceScope, proposedName,
sanitizeForAnnotations: true);
userInstanceMembers[key] = newName;
}
@@ -992,7 +973,7 @@ class Namer {
jsAst.Name newName = userInstanceMembers[key];
if (newName == null) {
String name = proposeName();
- newName = getFreshName(NamingScope.instance, name,
+ newName = getFreshName(instanceScope, name,
sanitizeForAnnotations: true);
userInstanceMembers[key] = newName;
}
@@ -1014,9 +995,9 @@ class Namer {
String suffix = ''; // We don't need any suffixes.
String key = '$libraryPrefix@$originalName@$suffix';
assert(!userInstanceMembers.containsKey(key));
- assert(!usedInstanceNames.contains(disambiguatedName));
+ assert(!instanceScope.isUsed(disambiguatedName));
userInstanceMembers[key] = new StringBackedName(disambiguatedName);
- usedInstanceNames.add(disambiguatedName);
+ instanceScope.registerUse(disambiguatedName);
}
/// Disambiguated name unique to [element].
@@ -1030,11 +1011,21 @@ class Namer {
jsAst.Name newName = internalInstanceMembers[element];
if (newName == null) {
String name = proposeName();
- bool mayClashNative = _isUserClassExtendingNative(element.enclosingClass);
- newName = getFreshName(NamingScope.instance, name,
- sanitizeForAnnotations: true,
- sanitizeForNatives: mayClashNative);
- internalInstanceMembers[element] = newName;
+
+ if (element is PrivatelyNamedJSEntity) {
+ NamingScope scope = _getPrivateScopeFor(element);
+ newName = getFreshName(scope, name,
+ sanitizeForAnnotations: true,
+ sanitizeForNatives: false);
+ internalInstanceMembers[element] = newName;
+ } else {
+ bool mayClashNative =
+ _isUserClassExtendingNative(element.enclosingClass);
+ newName = getFreshName(instanceScope, name,
+ sanitizeForAnnotations: true,
+ sanitizeForNatives: mayClashNative);
+ internalInstanceMembers[element] = newName;
+ }
}
return _newReference(newName);
}
@@ -1048,15 +1039,14 @@ class Namer {
jsAst.Name _disambiguateOperator(String operatorIdentifier) {
jsAst.Name newName = userInstanceOperators[operatorIdentifier];
if (newName == null) {
- newName = getFreshName(NamingScope.instance, operatorIdentifier);
+ newName = getFreshName(instanceScope, operatorIdentifier);
userInstanceOperators[operatorIdentifier] = newName;
}
return _newReference(newName);
}
String _generateFreshStringForName(String proposedName,
- Set<String> usedNames,
- Map<String, String> suggestedNames,
+ NamingScope scope,
{bool sanitizeForAnnotations: false,
bool sanitizeForNatives: false}) {
if (sanitizeForAnnotations) {
@@ -1067,18 +1057,18 @@ class Namer {
}
proposedName = _sanitizeForKeywords(proposedName);
String candidate;
- if (!usedNames.contains(proposedName)) {
+ if (scope.isUnused(proposedName)) {
candidate = proposedName;
} else {
int counter = popularNameCounters[proposedName];
int i = (counter == null) ? 0 : counter;
- while (usedNames.contains("$proposedName$i")) {
+ while (scope.isUsed("$proposedName$i")) {
i++;
}
popularNameCounters[proposedName] = i + 1;
candidate = "$proposedName$i";
}
- usedNames.add(candidate);
+ scope.registerUse(candidate);
return candidate;
}
@@ -1100,8 +1090,7 @@ class Namer {
bool sanitizeForNatives: false}) {
String candidate =
_generateFreshStringForName(proposedName,
- getUsedNames(scope),
- getSuggestedNames(scope),
+ scope,
sanitizeForAnnotations:
sanitizeForAnnotations,
sanitizeForNatives: sanitizeForNatives);
@@ -1436,7 +1425,7 @@ class Namer {
jsAst.Name getFunctionTypeName(FunctionType functionType) {
return functionTypeNameMap.putIfAbsent(functionType, () {
String proposedName = functionTypeNamer.computeName(functionType);
- return getFreshName(NamingScope.instance, proposedName);
+ return getFreshName(instanceScope, proposedName);
});
}
@@ -1572,7 +1561,6 @@ class Namer {
void forgetElement(Element element) {
jsAst.Name globalName = userGlobals[element];
invariant(element, globalName != null, message: 'No global name.');
- usedGlobalNames.remove(globalName);
userGlobals.remove(element);
}
}
@@ -2028,8 +2016,29 @@ class FunctionTypeNamer extends BaseDartTypeVisitor {
}
}
-enum NamingScope {
- global,
- instance,
- constant
+
+class NamingScope {
+ /// Maps proposed names to *suggested* disambiguated names.
+ ///
+ /// Suggested names are hints to the [MinifyNamer], suggesting that a specific
+ /// names be given to the first item with the given proposed name.
+ ///
+ /// This is currently used in [MinifyNamer] to assign very short minified
+ /// names to things that tend to be used very often.
+ final Map<String, String> _suggestedNames = new Map<String, String>();
+ final Set<String> _usedNames = new Set<String>();
+
+ bool isUsed(String name) => _usedNames.contains(name);
+ bool isUnused(String name) => !_usedNames.contains(name);
+ bool registerUse(String name) => _usedNames.add(name);
+
+ String suggestName(String original) => _suggestedNames[original];
+ void addSuggestion(String original, String suggestion) {
+ assert(!_suggestedNames.containsKey(original));
+ _suggestedNames[original] = suggestion;
+ }
+ bool hasSuggestion(String original) => _suggestedNames.containsKey(original);
+ bool isSuggestion(String candidate) {
+ return _suggestedNames.containsValue(candidate);
+ }
}
« no previous file with comments | « pkg/compiler/lib/src/js_backend/minify_namer.dart ('k') | tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698