| 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)}';
|
| }
|
|
|
|
|