Index: sdk/lib/_internal/compiler/implementation/js_backend/namer.dart |
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart |
index 691d73babc3d4a780a6ab4cddbff5339d7e1a17c..f10f29857b1eb1c15396b31f3ea096329b297fa5 100644 |
--- a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart |
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart |
@@ -8,6 +8,8 @@ part of js_backend; |
* Assigns JavaScript identifiers to Dart variables, class-names and members. |
*/ |
class Namer { |
+ final Compiler compiler; |
+ |
static Set<String> _jsReserved = null; |
Set<String> get jsReserved { |
if (_jsReserved == null) { |
@@ -18,22 +20,15 @@ class Namer { |
return _jsReserved; |
} |
- final String CURRENT_ISOLATE = r'$'; |
- |
/** |
* Map from top-level or static elements to their unique identifiers provided |
* by [getName]. |
* |
* Invariant: Keys must be declaration elements. |
*/ |
- final Compiler compiler; |
final Map<Element, String> globals; |
+ final Map<String, int> usedGlobals; |
final Map<String, LibraryElement> shortPrivateNameOwners; |
- final Set<String> usedGlobalNames; |
- final Set<String> usedInstanceNames; |
- final Map<String, String> instanceNameMap; |
- final Map<String, String> globalNameMap; |
- final Map<String, int> popularNameCounters; |
/** |
* A cache of names used for bailout methods. We make sure two |
@@ -50,27 +45,22 @@ class Namer { |
Namer(this.compiler) |
: globals = new Map<Element, String>(), |
+ usedGlobals = new Map<String, int>(), |
shortPrivateNameOwners = new Map<String, LibraryElement>(), |
bailoutNames = new Map<Element, String>(), |
usedBailoutInstanceNames = new Set<String>(), |
- usedGlobalNames = new Set<String>(), |
- usedInstanceNames = new Set<String>(), |
- instanceNameMap = new Map<String, String>(), |
- globalNameMap = new Map<String, String>(), |
- constantNames = new Map<Constant, String>(), |
- popularNameCounters = new Map<String, int>(); |
- |
- String get ISOLATE => 'Isolate'; |
- String get ISOLATE_PROPERTIES => r'$isolateProperties'; |
+ constantNames = new Map<Constant, String>(); |
+ |
+ final String CURRENT_ISOLATE = r'$'; |
+ final String ISOLATE = 'Isolate'; |
+ final String ISOLATE_PROPERTIES = r"$isolateProperties"; |
/** |
* Some closures must contain their name. The name is stored in |
* [STATIC_CLOSURE_NAME_NAME]. |
*/ |
- String get STATIC_CLOSURE_NAME_NAME => r'$name'; |
- SourceString get CLOSURE_INVOCATION_NAME => Compiler.CALL_OPERATOR_NAME; |
- bool get shouldMinify => false; |
- |
- bool isReserved(String name) => name == ISOLATE; |
+ final String STATIC_CLOSURE_NAME_NAME = r'$name'; |
+ static const SourceString CLOSURE_INVOCATION_NAME = |
+ Compiler.CALL_OPERATOR_NAME; |
String constantName(Constant constant) { |
// In the current implementation it doesn't make sense to give names to |
@@ -79,30 +69,16 @@ class Namer { |
assert(!constant.isFunction()); |
String result = constantNames[constant]; |
if (result == null) { |
- String longName; |
- if (shouldMinify) { |
- if (constant.isString()) { |
- StringConstant stringConstant = constant; |
- // The minifier never returns the same string as we suggested so we |
- // can suggest any name and it will use it as input to the hashing |
- // algorithm. This means that constants will tend to have the same |
- // name from version to version of the program being minfied. |
- longName = stringConstant.value.slowToString(); |
- } else { |
- longName = "C"; |
- } |
- } else { |
- longName = "CTC"; |
- } |
- result = getFreshName(longName, usedGlobalNames); |
+ result = getFreshGlobalName("CTC"); |
constantNames[constant] = result; |
} |
return result; |
} |
String closureInvocationName(Selector selector) { |
- return |
- instanceMethodInvocationName(null, CLOSURE_INVOCATION_NAME, selector); |
+ // TODO(floitsch): mangle, while not conflicting with instance names. |
+ return instanceMethodInvocationName(null, CLOSURE_INVOCATION_NAME, |
+ selector); |
} |
String breakLabelName(LabelElement label) { |
@@ -128,7 +104,6 @@ class Namer { |
* mangles the [name] so that each library has a unique name. |
*/ |
String privateName(LibraryElement lib, SourceString name) { |
- String result; |
if (name.isPrivate()) { |
String nameString = name.slowToString(); |
// The first library asking for a short private name wins. |
@@ -137,22 +112,17 @@ class Namer { |
// If a private name could clash with a mangled private name we don't |
// use the short name. For example a private name "_lib3_foo" would |
// clash with "_foo" from "lib3". |
- if (owner == lib && |
- !nameString.startsWith('_$LIBRARY_PREFIX') && |
- !shouldMinify) { |
- result = nameString; |
- } else { |
- String libName = getName(lib); |
- // If a library name does not start with the [LIBRARY_PREFIX] then our |
- // assumptions about clashing with mangled private members do not hold. |
- assert(shouldMinify || libName.startsWith(LIBRARY_PREFIX)); |
- // TODO(erikcorry): Fix this with other manglings to avoid clashes. |
- result = '_lib$libName\$$nameString'; |
+ if (identical(owner, lib) && !nameString.startsWith('_$LIBRARY_PREFIX')) { |
+ return nameString; |
} |
+ String libName = getName(lib); |
+ // If a library name does not start with the [LIBRARY_PREFIX] then our |
+ // assumptions about clashing with mangled private members do not hold. |
+ assert(libName.startsWith(LIBRARY_PREFIX)); |
+ return '_$libName$nameString'; |
} else { |
- result = name.slowToString(); |
+ return name.slowToString(); |
} |
- return result; |
} |
String instanceMethodName(FunctionElement element) { |
@@ -165,27 +135,21 @@ class Namer { |
FunctionSignature signature = element.computeSignature(compiler); |
String methodName = |
'${privateName(lib, name)}\$${signature.parameterCount}'; |
- if (signature.optionalParametersAreNamed && |
- !signature.optionalParameters.isEmpty) { |
+ if (!signature.optionalParametersAreNamed) { |
+ return methodName; |
+ } else if (!signature.optionalParameters.isEmpty) { |
StringBuffer buffer = new StringBuffer(); |
signature.orderedOptionalParameters.forEach((Element element) { |
buffer.add('\$${JsNames.getValid(element.name.slowToString())}'); |
}); |
- methodName = '$methodName$buffer'; |
+ return '$methodName$buffer'; |
} |
- if (name == CLOSURE_INVOCATION_NAME) return methodName; |
- return getMappedInstanceName(methodName); |
} |
String publicInstanceMethodNameByArity(SourceString name, int arity) { |
name = Elements.operatorNameToIdentifier(name); |
assert(!name.isPrivate()); |
- var base = name.slowToString(); |
- // We don't mangle the closure invoking function name because it is |
- // generated in applyFunction. |
- var proposedName = '$base\$$arity'; |
- if (base == CLOSURE_INVOCATION_NAME) return proposedName; |
- return getMappedInstanceName(proposedName); |
+ return '${name.slowToString()}\$$arity'; |
} |
String instanceMethodInvocationName(LibraryElement lib, SourceString name, |
@@ -198,16 +162,12 @@ class Namer { |
buffer.add(r'$'); |
argumentName.printOn(buffer); |
} |
- if (name == CLOSURE_INVOCATION_NAME) { |
- return '$CLOSURE_INVOCATION_NAME\$${selector.argumentCount}$buffer'; |
- } |
- return getMappedInstanceName( |
- '${privateName(lib, name)}\$${selector.argumentCount}$buffer'); |
+ return '${privateName(lib, name)}\$${selector.argumentCount}$buffer'; |
} |
String instanceFieldName(LibraryElement libraryElement, SourceString name) { |
String proposedName = privateName(libraryElement, name); |
- return getMappedInstanceName(proposedName); |
+ return safeName(proposedName); |
} |
String shadowedFieldName(Element fieldElement) { |
@@ -216,71 +176,45 @@ class Namer { |
String libName = getName(libraryElement); |
String clsName = getName(cls); |
String instanceName = instanceFieldName(libraryElement, fieldElement.name); |
- return getMappedInstanceName('$libName\$$clsName\$$instanceName'); |
+ return safeName('$libName\$$clsName\$$instanceName'); |
} |
String setterName(LibraryElement lib, SourceString name) { |
// We dynamically create setters from the field-name. The setter name must |
// therefore be derived from the instance field-name. |
- String fieldName = getMappedInstanceName(privateName(lib, name)); |
+ String fieldName = safeName(privateName(lib, name)); |
return 'set\$$fieldName'; |
} |
String publicGetterName(SourceString name) { |
// We dynamically create getters from the field-name. The getter name must |
// therefore be derived from the instance field-name. |
- String fieldName = getMappedInstanceName(name.slowToString()); |
+ String fieldName = safeName(name.slowToString()); |
return 'get\$$fieldName'; |
} |
String getterName(LibraryElement lib, SourceString name) { |
// We dynamically create getters from the field-name. The getter name must |
// therefore be derived from the instance field-name. |
- String fieldName = getMappedInstanceName(privateName(lib, name)); |
+ String fieldName = safeName(privateName(lib, name)); |
return 'get\$$fieldName'; |
} |
- String publicSetterName(SourceString name) { |
- // We dynamically create setter from the field-name. The setter name must |
- // therefore be derived from the instance field-name. |
- String fieldName = name.slowToString(); |
- return 'set\$$fieldName'; |
- } |
- |
- String getMappedGlobalName(String proposedName) { |
- var newName = globalNameMap[proposedName]; |
- if (newName == null) { |
- newName = getFreshName(proposedName, usedGlobalNames); |
- globalNameMap[proposedName] = newName; |
- } |
- return newName; |
- } |
- |
- String getMappedInstanceName(String proposedName) { |
- var newName = instanceNameMap[proposedName]; |
- if (newName == null) { |
- newName = getFreshName(proposedName, usedInstanceNames); |
- instanceNameMap[proposedName] = newName; |
- } |
- return newName; |
- } |
- |
- String getFreshName(String proposedName, Set<String> usedNames) { |
- var candidate; |
- proposedName = safeName(proposedName); |
- if (!usedNames.contains(proposedName)) { |
- candidate = proposedName; |
- } else { |
- var counter = popularNameCounters[proposedName]; |
- var i = counter == null ? 0 : counter; |
- while (usedNames.contains("$proposedName$i")) { |
- i++; |
- } |
- popularNameCounters[proposedName] = i + 1; |
- candidate = "$proposedName$i"; |
+ String getFreshGlobalName(String proposedName) { |
+ String name = proposedName; |
+ int count = usedGlobals[name]; |
+ if (count != null) { |
+ // Not the first time we see this name. Append a number to make it unique. |
+ do { |
+ name = '$proposedName${count++}'; |
+ } while (usedGlobals[name] != null); |
+ // Record the count in case we see this name later. We |
+ // frequently see names multiple times, as all our closures use |
+ // the same name for their class. |
+ usedGlobals[proposedName] = count; |
} |
- usedNames.add(candidate); |
- return candidate; |
+ usedGlobals[name] = 0; |
+ return name; |
} |
static const String LIBRARY_PREFIX = "lib"; |
@@ -313,7 +247,7 @@ class Namer { |
} else { |
name = element.name.slowToString(); |
} |
- return name; |
+ return safeName(name); |
} |
String getBailoutName(Element element) { |
@@ -321,15 +255,12 @@ class Namer { |
if (name != null) return name; |
bool global = !element.isInstanceMember(); |
String unminifiedName = '${getName(element)}\$bailout'; |
- if (global) { |
- name = getMappedGlobalName(unminifiedName); |
- } else { |
- name = unminifiedName; |
+ name = unminifiedName; |
+ if (!global) { |
int i = 0; |
while (usedBailoutInstanceNames.contains(name)) { |
name = '$unminifiedName${i++}'; |
} |
- name = getMappedInstanceName(name); |
usedBailoutInstanceNames.add(name); |
} |
bailoutNames[element] = name; |
@@ -371,26 +302,18 @@ class Namer { |
if (identical(kind, ElementKind.VARIABLE) || |
identical(kind, ElementKind.PARAMETER)) { |
// The name is not guaranteed to be unique. |
- return safeName(guess); |
+ return guess; |
} |
- if (kind == ElementKind.GENERATIVE_CONSTRUCTOR || |
- kind == ElementKind.FUNCTION || |
- kind == ElementKind.CLASS || |
- kind == ElementKind.FIELD || |
- kind == ElementKind.GETTER || |
- kind == ElementKind.SETTER || |
- kind == ElementKind.TYPEDEF || |
- kind == ElementKind.LIBRARY || |
- kind == ElementKind.MALFORMED_TYPE) { |
- bool isNative = false; |
- if (identical(kind, ElementKind.CLASS)) { |
- ClassElement class_elt = element; |
- isNative = class_elt.isNative(); |
- } |
- if (Elements.isInstanceField(element)) { |
- isNative = element.isNative(); |
- } |
- String result = isNative ? guess : getFreshName(guess, usedGlobalNames); |
+ if (identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR) || |
+ identical(kind, ElementKind.FUNCTION) || |
+ identical(kind, ElementKind.CLASS) || |
+ identical(kind, ElementKind.FIELD) || |
+ identical(kind, ElementKind.GETTER) || |
+ identical(kind, ElementKind.SETTER) || |
+ identical(kind, ElementKind.TYPEDEF) || |
+ identical(kind, ElementKind.LIBRARY) || |
+ identical(kind, ElementKind.MALFORMED_TYPE)) { |
+ String result = getFreshGlobalName(guess); |
globals[element] = result; |
return result; |
} |
@@ -400,8 +323,9 @@ class Namer { |
} |
String getLazyInitializerName(Element element) { |
+ // TODO(floitsch): mangle while not conflicting with other statics. |
assert(Elements.isStaticOrTopLevelField(element)); |
- return getMappedGlobalName("get\$${getName(element)}"); |
+ return "get\$${getName(element)}"; |
} |
String isolatePropertiesAccess(Element element) { |
@@ -417,8 +341,7 @@ class Namer { |
} |
String isolateBailoutAccess(Element element) { |
- String newName = getMappedGlobalName('${getName(element)}\$bailout'); |
- return '$CURRENT_ISOLATE.$newName'; |
+ return '${isolateAccess(element)}\$bailout'; |
} |
String isolateLazyInitializerAccess(Element element) { |
@@ -426,7 +349,6 @@ class Namer { |
} |
String operatorIs(Element element) { |
- // TODO(erikcorry): Reduce from is$x to ix when we are minifying. |
return 'is\$${getName(element)}'; |
} |