Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Assigns JavaScript identifiers to Dart variables, class-names and members. | 8 * Assigns JavaScript identifiers to Dart variables, class-names and members. |
| 9 */ | 9 */ |
| 10 class Namer { | 10 class Namer { |
| 11 final Compiler compiler; | |
| 12 | |
| 13 static Set<String> _jsReserved = null; | 11 static Set<String> _jsReserved = null; |
| 14 Set<String> get jsReserved { | 12 Set<String> get jsReserved { |
| 15 if (_jsReserved == null) { | 13 if (_jsReserved == null) { |
| 16 _jsReserved = new Set<String>(); | 14 _jsReserved = new Set<String>(); |
| 17 _jsReserved.addAll(JsNames.javaScriptKeywords); | 15 _jsReserved.addAll(JsNames.javaScriptKeywords); |
| 18 _jsReserved.addAll(JsNames.reservedPropertySymbols); | 16 _jsReserved.addAll(JsNames.reservedPropertySymbols); |
| 19 } | 17 } |
| 20 return _jsReserved; | 18 return _jsReserved; |
| 21 } | 19 } |
| 22 | 20 |
| 21 final String CURRENT_ISOLATE = r'$'; | |
| 22 | |
| 23 /** | 23 /** |
| 24 * Map from top-level or static elements to their unique identifiers provided | 24 * Map from top-level or static elements to their unique identifiers provided |
| 25 * by [getName]. | 25 * by [getName]. |
| 26 * | 26 * |
| 27 * Invariant: Keys must be declaration elements. | 27 * Invariant: Keys must be declaration elements. |
| 28 */ | 28 */ |
| 29 final Compiler compiler; | |
| 29 final Map<Element, String> globals; | 30 final Map<Element, String> globals; |
| 30 final Map<String, int> usedGlobals; | |
| 31 final Map<String, LibraryElement> shortPrivateNameOwners; | 31 final Map<String, LibraryElement> shortPrivateNameOwners; |
| 32 final Set<String> usedGlobalNames; | |
| 33 final Set<String> usedInstanceNames; | |
| 34 final Map<String, String> instanceNameMap; | |
| 35 final Map<String, String> globalNameMap; | |
| 36 final Map<String, int> popularNameCounters; | |
| 32 | 37 |
| 33 /** | 38 /** |
| 34 * A cache of names used for bailout methods. We make sure two | 39 * A cache of names used for bailout methods. We make sure two |
| 35 * bailout methods cannot have the same name because if the two | 40 * bailout methods cannot have the same name because if the two |
| 36 * bailout methods are in a class and a subclass, we would | 41 * bailout methods are in a class and a subclass, we would |
| 37 * call the wrong bailout method at runtime. To make it | 42 * call the wrong bailout method at runtime. To make it |
| 38 * simple, we don't keep track of inheritance and always avoid | 43 * simple, we don't keep track of inheritance and always avoid |
| 39 * similar names. | 44 * similar names. |
| 40 */ | 45 */ |
| 41 final Set<String> usedBailoutInstanceNames; | 46 final Set<String> usedBailoutInstanceNames; |
| 42 final Map<Element, String> bailoutNames; | 47 final Map<Element, String> bailoutNames; |
| 43 | 48 |
| 44 final Map<Constant, String> constantNames; | 49 final Map<Constant, String> constantNames; |
| 45 | 50 |
| 46 Namer(this.compiler) | 51 Namer(this.compiler) |
| 47 : globals = new Map<Element, String>(), | 52 : globals = new Map<Element, String>(), |
| 48 usedGlobals = new Map<String, int>(), | |
| 49 shortPrivateNameOwners = new Map<String, LibraryElement>(), | 53 shortPrivateNameOwners = new Map<String, LibraryElement>(), |
| 50 bailoutNames = new Map<Element, String>(), | 54 bailoutNames = new Map<Element, String>(), |
| 51 usedBailoutInstanceNames = new Set<String>(), | 55 usedBailoutInstanceNames = new Set<String>(), |
| 52 constantNames = new Map<Constant, String>(); | 56 usedGlobalNames = new Set<String>(), |
| 57 usedInstanceNames = new Set<String>(), | |
| 58 instanceNameMap = new Map<String, String>(), | |
| 59 globalNameMap = new Map<String, String>(), | |
| 60 constantNames = new Map<Constant, String>(), | |
| 61 popularNameCounters = new Map<String, int>(); | |
| 53 | 62 |
| 54 final String CURRENT_ISOLATE = r'$'; | 63 String get isolateName => 'Isolate'; |
| 55 final String ISOLATE = 'Isolate'; | 64 String get isolatePropertiesName => r'$isolateProperties'; |
| 56 final String ISOLATE_PROPERTIES = r"$isolateProperties"; | |
| 57 /** | 65 /** |
| 58 * Some closures must contain their name. The name is stored in | 66 * Some closures must contain their name. The name is stored in |
| 59 * [STATIC_CLOSURE_NAME_NAME]. | 67 * [STATIC_CLOSURE_NAME_NAME]. |
| 60 */ | 68 */ |
| 61 final String STATIC_CLOSURE_NAME_NAME = r'$name'; | 69 String get STATIC_CLOSURE_NAME_NAME => r'$name'; |
| 62 static const SourceString CLOSURE_INVOCATION_NAME = | 70 SourceString get closureInvocationSelector => Compiler.CALL_OPERATOR_NAME; |
|
ngeoffray
2012/12/10 08:55:42
We have the Selector class in the compiler, so I'd
erikcorry
2012/12/10 12:37:40
We already have something else called closureInvoc
| |
| 63 Compiler.CALL_OPERATOR_NAME; | 71 bool get shouldMinify => false; |
| 72 | |
| 73 bool isReserved(String name) => name == isolateName; | |
| 64 | 74 |
| 65 String constantName(Constant constant) { | 75 String constantName(Constant constant) { |
| 66 // In the current implementation it doesn't make sense to give names to | 76 // In the current implementation it doesn't make sense to give names to |
| 67 // function constants since the function-implementation itself serves as | 77 // function constants since the function-implementation itself serves as |
| 68 // constant and can be accessed directly. | 78 // constant and can be accessed directly. |
| 69 assert(!constant.isFunction()); | 79 assert(!constant.isFunction()); |
| 70 String result = constantNames[constant]; | 80 String result = constantNames[constant]; |
| 71 if (result == null) { | 81 if (result == null) { |
| 72 result = getFreshGlobalName("CTC"); | 82 String longName; |
| 83 if (shouldMinify) { | |
| 84 if (constant.isString()) { | |
| 85 StringConstant stringConstant = constant; | |
| 86 // The minifier always constructs a new name, using the argument as | |
| 87 // input to its hashing algorithm. The given name does not need to be | |
| 88 // valid. | |
| 89 longName = stringConstant.value.slowToString(); | |
| 90 } else { | |
| 91 longName = "C"; | |
| 92 } | |
| 93 } else { | |
| 94 longName = "CONSTANT"; | |
| 95 } | |
| 96 result = getFreshName(longName, usedGlobalNames); | |
| 73 constantNames[constant] = result; | 97 constantNames[constant] = result; |
| 74 } | 98 } |
| 75 return result; | 99 return result; |
| 76 } | 100 } |
| 77 | 101 |
| 78 String closureInvocationName(Selector selector) { | 102 String closureInvocationName(Selector selector) { |
| 79 // TODO(floitsch): mangle, while not conflicting with instance names. | 103 return |
| 80 return instanceMethodInvocationName(null, CLOSURE_INVOCATION_NAME, | 104 instanceMethodInvocationName(null, closureInvocationSelector, selector); |
|
ngeoffray
2012/12/10 08:55:42
The style we usually use is arguments on the new l
erikcorry
2012/12/10 12:37:40
Done.
| |
| 81 selector); | |
| 82 } | 105 } |
| 83 | 106 |
| 84 String breakLabelName(LabelElement label) { | 107 String breakLabelName(LabelElement label) { |
| 85 return '\$${label.labelName}\$${label.target.nestingLevel}'; | 108 return '\$${label.labelName}\$${label.target.nestingLevel}'; |
| 86 } | 109 } |
| 87 | 110 |
| 88 String implicitBreakLabelName(TargetElement target) { | 111 String implicitBreakLabelName(TargetElement target) { |
| 89 return '\$${target.nestingLevel}'; | 112 return '\$${target.nestingLevel}'; |
| 90 } | 113 } |
| 91 | 114 |
| 92 // We sometimes handle continue targets differently from break targets, | 115 // We sometimes handle continue targets differently from break targets, |
| 93 // so we have special continue-only labels. | 116 // so we have special continue-only labels. |
| 94 String continueLabelName(LabelElement label) { | 117 String continueLabelName(LabelElement label) { |
| 95 return 'c\$${label.labelName}\$${label.target.nestingLevel}'; | 118 return 'c\$${label.labelName}\$${label.target.nestingLevel}'; |
| 96 } | 119 } |
| 97 | 120 |
| 98 String implicitContinueLabelName(TargetElement target) { | 121 String implicitContinueLabelName(TargetElement target) { |
| 99 return 'c\$${target.nestingLevel}'; | 122 return 'c\$${target.nestingLevel}'; |
| 100 } | 123 } |
| 101 | 124 |
| 102 /** | 125 /** |
| 103 * If the [name] is not private returns [:name.slowToString():]. Otherwise | 126 * If the [name] is not private returns [:name.slowToString():]. Otherwise |
| 104 * mangles the [name] so that each library has a unique name. | 127 * mangles the [name] so that each library has a unique name. |
| 105 */ | 128 */ |
| 106 String privateName(LibraryElement lib, SourceString name) { | 129 String privateName(LibraryElement lib, SourceString name) { |
| 130 String result; | |
| 107 if (name.isPrivate()) { | 131 if (name.isPrivate()) { |
| 108 String nameString = name.slowToString(); | 132 String nameString = name.slowToString(); |
| 109 // The first library asking for a short private name wins. | 133 // The first library asking for a short private name wins. |
| 110 LibraryElement owner = | 134 LibraryElement owner = shouldMinify ? |
| 111 shortPrivateNameOwners.putIfAbsent(nameString, () => lib); | 135 shortPrivateNameOwners.putIfAbsent(nameString, () => lib) : |
| 136 lib; | |
| 112 // If a private name could clash with a mangled private name we don't | 137 // If a private name could clash with a mangled private name we don't |
| 113 // use the short name. For example a private name "_lib3_foo" would | 138 // use the short name. For example a private name "_lib3_foo" would |
| 114 // clash with "_foo" from "lib3". | 139 // clash with "_foo" from "lib3". |
| 115 if (identical(owner, lib) && !nameString.startsWith('_$LIBRARY_PREFIX')) { | 140 if (owner == lib && |
| 116 return nameString; | 141 !nameString.startsWith('_$LIBRARY_PREFIX') && |
| 142 !shouldMinify) { | |
| 143 result = nameString; | |
| 144 } else { | |
| 145 String libName = getName(lib); | |
| 146 // If a library name does not start with the [LIBRARY_PREFIX] then our | |
| 147 // assumptions about clashing with mangled private members do not hold. | |
| 148 assert(shouldMinify || libName.startsWith(LIBRARY_PREFIX)); | |
| 149 // TODO(erikcorry): Fix this with other manglings to avoid clashes. | |
| 150 result = '_lib$libName\$$nameString'; | |
| 117 } | 151 } |
| 118 String libName = getName(lib); | |
| 119 // If a library name does not start with the [LIBRARY_PREFIX] then our | |
| 120 // assumptions about clashing with mangled private members do not hold. | |
| 121 assert(libName.startsWith(LIBRARY_PREFIX)); | |
| 122 return '_$libName$nameString'; | |
| 123 } else { | 152 } else { |
| 124 return name.slowToString(); | 153 result = name.slowToString(); |
| 125 } | 154 } |
| 155 return result; | |
| 126 } | 156 } |
| 127 | 157 |
| 128 String instanceMethodName(FunctionElement element) { | 158 String instanceMethodName(FunctionElement element) { |
| 129 SourceString name = Elements.operatorNameToIdentifier(element.name); | 159 SourceString name = Elements.operatorNameToIdentifier(element.name); |
| 130 LibraryElement lib = element.getLibrary(); | 160 LibraryElement lib = element.getLibrary(); |
| 131 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY) { | 161 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY) { |
| 132 ConstructorBodyElement bodyElement = element; | 162 ConstructorBodyElement bodyElement = element; |
| 133 name = bodyElement.constructor.name; | 163 name = bodyElement.constructor.name; |
| 134 } | 164 } |
| 135 FunctionSignature signature = element.computeSignature(compiler); | 165 FunctionSignature signature = element.computeSignature(compiler); |
| 136 String methodName = | 166 String methodName = |
| 137 '${privateName(lib, name)}\$${signature.parameterCount}'; | 167 '${privateName(lib, name)}\$${signature.parameterCount}'; |
| 138 if (!signature.optionalParametersAreNamed) { | 168 if (signature.optionalParametersAreNamed && |
| 139 return methodName; | 169 !signature.optionalParameters.isEmpty) { |
| 140 } else if (!signature.optionalParameters.isEmpty) { | |
| 141 StringBuffer buffer = new StringBuffer(); | 170 StringBuffer buffer = new StringBuffer(); |
| 142 signature.orderedOptionalParameters.forEach((Element element) { | 171 signature.orderedOptionalParameters.forEach((Element element) { |
| 143 buffer.add('\$${JsNames.getValid(element.name.slowToString())}'); | 172 buffer.add('\$${JsNames.getValid(element.name.slowToString())}'); |
| 144 }); | 173 }); |
| 145 return '$methodName$buffer'; | 174 methodName = '$methodName$buffer'; |
| 146 } | 175 } |
| 176 if (name == closureInvocationSelector) return methodName; | |
| 177 return getMappedInstanceName(methodName); | |
| 147 } | 178 } |
| 148 | 179 |
| 149 String publicInstanceMethodNameByArity(SourceString name, int arity) { | 180 String publicInstanceMethodNameByArity(SourceString name, int arity) { |
| 150 name = Elements.operatorNameToIdentifier(name); | 181 name = Elements.operatorNameToIdentifier(name); |
| 151 assert(!name.isPrivate()); | 182 assert(!name.isPrivate()); |
| 152 return '${name.slowToString()}\$$arity'; | 183 var base = name.slowToString(); |
| 184 // We don't mangle the closure invoking function name because it is | |
| 185 // generated in applyFunction. | |
| 186 var proposedName = '$base\$$arity'; | |
| 187 if (base == closureInvocationSelector) return proposedName; | |
| 188 return getMappedInstanceName(proposedName); | |
| 153 } | 189 } |
| 154 | 190 |
| 155 String instanceMethodInvocationName(LibraryElement lib, SourceString name, | 191 String instanceMethodInvocationName(LibraryElement lib, SourceString name, |
| 156 Selector selector) { | 192 Selector selector) { |
| 157 name = Elements.operatorNameToIdentifier(name); | 193 name = Elements.operatorNameToIdentifier(name); |
| 158 // TODO(floitsch): mangle, while preserving uniqueness. | 194 // TODO(floitsch): mangle, while preserving uniqueness. |
| 159 StringBuffer buffer = new StringBuffer(); | 195 StringBuffer buffer = new StringBuffer(); |
| 160 List<SourceString> names = selector.getOrderedNamedArguments(); | 196 List<SourceString> names = selector.getOrderedNamedArguments(); |
| 161 for (SourceString argumentName in names) { | 197 for (SourceString argumentName in names) { |
| 162 buffer.add(r'$'); | 198 buffer.add(r'$'); |
| 163 argumentName.printOn(buffer); | 199 argumentName.printOn(buffer); |
| 164 } | 200 } |
| 165 return '${privateName(lib, name)}\$${selector.argumentCount}$buffer'; | 201 if (name == closureInvocationSelector) { |
| 202 // We don't mangle the closure invoking function name because it is | |
| 203 // generated in applyFunction. | |
|
ngeoffray
2012/12/10 08:55:42
generated or used? What is applyFunction? Dart's F
erikcorry
2012/12/10 12:37:40
The name is generated (wiith string addition), the
| |
| 204 return '$closureInvocationSelector\$${selector.argumentCount}$buffer'; | |
| 205 } | |
| 206 return getMappedInstanceName( | |
| 207 '${privateName(lib, name)}\$${selector.argumentCount}$buffer'); | |
| 166 } | 208 } |
| 167 | 209 |
| 168 String instanceFieldName(LibraryElement libraryElement, SourceString name) { | 210 String instanceFieldName(LibraryElement libraryElement, SourceString name) { |
| 169 String proposedName = privateName(libraryElement, name); | 211 String proposedName = privateName(libraryElement, name); |
| 170 return safeName(proposedName); | 212 return getMappedInstanceName(proposedName); |
| 171 } | 213 } |
| 172 | 214 |
| 215 // Construct a new name for the element based on the library and class it is | |
| 216 // in. The name here is not important, we just need to make sure it is | |
| 217 // unique. If we are minifying, we actually construct the name from the | |
| 218 // minified versions of the class and instance names, but the result is | |
| 219 // minified once again, so that is not visible in the end result. | |
| 173 String shadowedFieldName(Element fieldElement) { | 220 String shadowedFieldName(Element fieldElement) { |
| 221 // Check for following situation: Native field ${fieldElement.name} has | |
| 222 // fixed JSName ${fieldElement.nativeName()}, but a subclass shadows this | |
| 223 // name. We normally handle that by renaming the superclass field, but we | |
| 224 // can't do that because native fields have fixed JSNames. In practice | |
| 225 // this can't happen because we can't inherit from native classes. | |
| 226 assert (!fieldElement.isNative()); | |
| 227 | |
| 174 ClassElement cls = fieldElement.getEnclosingClass(); | 228 ClassElement cls = fieldElement.getEnclosingClass(); |
| 175 LibraryElement libraryElement = fieldElement.getLibrary(); | 229 LibraryElement libraryElement = fieldElement.getLibrary(); |
| 176 String libName = getName(libraryElement); | 230 String libName = getName(libraryElement); |
| 177 String clsName = getName(cls); | 231 String clsName = getName(cls); |
| 178 String instanceName = instanceFieldName(libraryElement, fieldElement.name); | 232 String instanceName = instanceFieldName(libraryElement, fieldElement.name); |
| 179 return safeName('$libName\$$clsName\$$instanceName'); | 233 return getMappedInstanceName('$libName\$$clsName\$$instanceName'); |
| 180 } | 234 } |
| 181 | 235 |
| 182 String setterName(LibraryElement lib, SourceString name) { | 236 String setterName(LibraryElement lib, SourceString name) { |
| 183 // We dynamically create setters from the field-name. The setter name must | 237 // We dynamically create setters from the field-name. The setter name must |
| 184 // therefore be derived from the instance field-name. | 238 // therefore be derived from the instance field-name. |
| 185 String fieldName = safeName(privateName(lib, name)); | 239 String fieldName = getMappedInstanceName(privateName(lib, name)); |
| 186 return 'set\$$fieldName'; | 240 return 'set\$$fieldName'; |
| 187 } | 241 } |
| 188 | 242 |
| 243 String setterNameFromAccessorName(String name) { | |
| 244 // We dynamically create setters from the field-name. The setter name must | |
| 245 // therefore be derived from the instance field-name. | |
| 246 return 'set\$$name'; | |
| 247 } | |
| 248 | |
| 189 String publicGetterName(SourceString name) { | 249 String publicGetterName(SourceString name) { |
| 190 // We dynamically create getters from the field-name. The getter name must | 250 // We dynamically create getters from the field-name. The getter name must |
| 191 // therefore be derived from the instance field-name. | 251 // therefore be derived from the instance field-name. |
| 192 String fieldName = safeName(name.slowToString()); | 252 String fieldName = getMappedInstanceName(name.slowToString()); |
| 193 return 'get\$$fieldName'; | 253 return 'get\$$fieldName'; |
| 194 } | 254 } |
| 195 | 255 |
| 256 String getterNameFromAccessorName(String name) { | |
| 257 // We dynamically create getters from the field-name. The getter name must | |
| 258 // therefore be derived from the instance field-name. | |
| 259 return 'get\$$name'; | |
| 260 } | |
| 261 | |
| 196 String getterName(LibraryElement lib, SourceString name) { | 262 String getterName(LibraryElement lib, SourceString name) { |
| 197 // We dynamically create getters from the field-name. The getter name must | 263 // We dynamically create getters from the field-name. The getter name must |
| 198 // therefore be derived from the instance field-name. | 264 // therefore be derived from the instance field-name. |
| 199 String fieldName = safeName(privateName(lib, name)); | 265 String fieldName = getMappedInstanceName(privateName(lib, name)); |
| 200 return 'get\$$fieldName'; | 266 return 'get\$$fieldName'; |
| 201 } | 267 } |
| 202 | 268 |
| 203 String getFreshGlobalName(String proposedName) { | 269 String getMappedGlobalName(String proposedName) { |
| 204 String name = proposedName; | 270 var newName = globalNameMap[proposedName]; |
| 205 int count = usedGlobals[name]; | 271 if (newName == null) { |
| 206 if (count != null) { | 272 newName = getFreshName(proposedName, usedGlobalNames); |
| 207 // Not the first time we see this name. Append a number to make it unique. | 273 globalNameMap[proposedName] = newName; |
| 208 do { | |
| 209 name = '$proposedName${count++}'; | |
| 210 } while (usedGlobals[name] != null); | |
| 211 // Record the count in case we see this name later. We | |
| 212 // frequently see names multiple times, as all our closures use | |
| 213 // the same name for their class. | |
| 214 usedGlobals[proposedName] = count; | |
| 215 } | 274 } |
| 216 usedGlobals[name] = 0; | 275 return newName; |
| 217 return name; | 276 } |
| 277 | |
| 278 String getMappedInstanceName(String proposedName) { | |
| 279 var newName = instanceNameMap[proposedName]; | |
| 280 if (newName == null) { | |
| 281 newName = getFreshName(proposedName, usedInstanceNames); | |
| 282 instanceNameMap[proposedName] = newName; | |
| 283 } | |
| 284 return newName; | |
| 285 } | |
| 286 | |
| 287 String getFreshName(String proposedName, Set<String> usedNames) { | |
| 288 var candidate; | |
| 289 proposedName = safeName(proposedName); | |
| 290 if (!usedNames.contains(proposedName)) { | |
| 291 candidate = proposedName; | |
| 292 } else { | |
| 293 var counter = popularNameCounters[proposedName]; | |
| 294 var i = counter == null ? 0 : counter; | |
| 295 while (usedNames.contains("$proposedName$i")) { | |
| 296 i++; | |
| 297 } | |
| 298 popularNameCounters[proposedName] = i + 1; | |
| 299 candidate = "$proposedName$i"; | |
| 300 } | |
| 301 usedNames.add(candidate); | |
| 302 return candidate; | |
| 218 } | 303 } |
| 219 | 304 |
| 220 static const String LIBRARY_PREFIX = "lib"; | 305 static const String LIBRARY_PREFIX = "lib"; |
| 221 | 306 |
| 222 /** | 307 /** |
| 223 * Returns a preferred JS-id for the given top-level or static element. | 308 * Returns a preferred JS-id for the given top-level or static element. |
| 224 * The returned id is guaranteed to be a valid JS-id. | 309 * The returned id is guaranteed to be a valid JS-id. |
| 225 */ | 310 */ |
| 226 String _computeGuess(Element element) { | 311 String _computeGuess(Element element) { |
| 227 assert(!element.isInstanceMember()); | 312 assert(!element.isInstanceMember()); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 240 name = "${enclosingClass.name.slowToString()}_" | 325 name = "${enclosingClass.name.slowToString()}_" |
| 241 "${element.name.slowToString()}"; | 326 "${element.name.slowToString()}"; |
| 242 } else { | 327 } else { |
| 243 name = element.name.slowToString(); | 328 name = element.name.slowToString(); |
| 244 } | 329 } |
| 245 } else if (element.isLibrary()) { | 330 } else if (element.isLibrary()) { |
| 246 name = LIBRARY_PREFIX; | 331 name = LIBRARY_PREFIX; |
| 247 } else { | 332 } else { |
| 248 name = element.name.slowToString(); | 333 name = element.name.slowToString(); |
| 249 } | 334 } |
| 250 return safeName(name); | 335 return name; |
| 251 } | 336 } |
| 252 | 337 |
| 253 String getSpecializedName(Element element, Collection<ClassElement> classes) { | 338 String getSpecializedName(Element element, Collection<ClassElement> classes) { |
| 339 // This gets the minified name, but it doesn't really make much difference. | |
| 340 // the important thing is that it is a unique name. | |
|
ngeoffray
2012/12/10 08:55:42
the -> The
erikcorry
2012/12/10 12:37:40
Done.
| |
| 254 StringBuffer buffer = new StringBuffer('${getName(element)}\$'); | 341 StringBuffer buffer = new StringBuffer('${getName(element)}\$'); |
| 255 for (ClassElement cls in classes) { | 342 for (ClassElement cls in classes) { |
| 256 buffer.add(getName(cls)); | 343 buffer.add(getName(cls)); |
| 257 } | 344 } |
| 258 return safeName(buffer.toString()); | 345 return getMappedGlobalName(buffer.toString()); |
| 259 } | 346 } |
| 260 | 347 |
| 261 String getBailoutName(Element element) { | 348 String getBailoutName(Element element) { |
| 262 String name = bailoutNames[element]; | 349 String name = bailoutNames[element]; |
| 263 if (name != null) return name; | 350 if (name != null) return name; |
| 264 bool global = !element.isInstanceMember(); | 351 bool global = !element.isInstanceMember(); |
| 352 // Despite the name of the variable, this gets the minified name when we | |
| 353 // are minifying, but it doesn't really make much difference. The | |
| 354 // important thing is that it is a unique name. We add $bailout and, if we | |
| 355 // are minifying, we minify the minified name and '$bailout'. | |
| 265 String unminifiedName = '${getName(element)}\$bailout'; | 356 String unminifiedName = '${getName(element)}\$bailout'; |
| 266 name = unminifiedName; | 357 if (global) { |
| 267 if (!global) { | 358 name = getMappedGlobalName(unminifiedName); |
| 359 } else { | |
| 360 name = unminifiedName; | |
| 268 int i = 0; | 361 int i = 0; |
| 269 while (usedBailoutInstanceNames.contains(name)) { | 362 while (usedBailoutInstanceNames.contains(name)) { |
| 270 name = '$unminifiedName${i++}'; | 363 name = '$unminifiedName${i++}'; |
| 271 } | 364 } |
| 272 usedBailoutInstanceNames.add(name); | 365 usedBailoutInstanceNames.add(name); |
| 366 name = getMappedInstanceName(name); | |
| 273 } | 367 } |
| 274 bailoutNames[element] = name; | 368 bailoutNames[element] = name; |
| 275 return name; | 369 return name; |
| 276 } | 370 } |
| 277 | 371 |
| 278 /** | 372 /** |
| 279 * Returns a preferred JS-id for the given element. The returned id is | 373 * Returns a preferred JS-id for the given element. The returned id is |
| 280 * guaranteed to be a valid JS-id. Globals and static fields are furthermore | 374 * guaranteed to be a valid JS-id. Globals and static fields are furthermore |
| 281 * guaranteed to be unique. | 375 * guaranteed to be unique. |
| 282 * | 376 * |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 300 } | 394 } |
| 301 } else { | 395 } else { |
| 302 // Use declaration element to ensure invariant on [globals]. | 396 // Use declaration element to ensure invariant on [globals]. |
| 303 element = element.declaration; | 397 element = element.declaration; |
| 304 // Dealing with a top-level or static element. | 398 // Dealing with a top-level or static element. |
| 305 String cached = globals[element]; | 399 String cached = globals[element]; |
| 306 if (cached != null) return cached; | 400 if (cached != null) return cached; |
| 307 | 401 |
| 308 String guess = _computeGuess(element); | 402 String guess = _computeGuess(element); |
| 309 ElementKind kind = element.kind; | 403 ElementKind kind = element.kind; |
| 310 if (identical(kind, ElementKind.VARIABLE) || | 404 if (kind == ElementKind.VARIABLE || |
| 311 identical(kind, ElementKind.PARAMETER)) { | 405 kind == ElementKind.PARAMETER) { |
| 312 // The name is not guaranteed to be unique. | 406 // The name is not guaranteed to be unique. |
| 313 return guess; | 407 return safeName(guess); |
| 314 } | 408 } |
| 315 if (identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR) || | 409 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR || |
| 316 identical(kind, ElementKind.FUNCTION) || | 410 kind == ElementKind.FUNCTION || |
| 317 identical(kind, ElementKind.CLASS) || | 411 kind == ElementKind.CLASS || |
| 318 identical(kind, ElementKind.FIELD) || | 412 kind == ElementKind.FIELD || |
| 319 identical(kind, ElementKind.GETTER) || | 413 kind == ElementKind.GETTER || |
| 320 identical(kind, ElementKind.SETTER) || | 414 kind == ElementKind.SETTER || |
| 321 identical(kind, ElementKind.TYPEDEF) || | 415 kind == ElementKind.TYPEDEF || |
| 322 identical(kind, ElementKind.LIBRARY) || | 416 kind == ElementKind.LIBRARY || |
| 323 identical(kind, ElementKind.MALFORMED_TYPE)) { | 417 kind == ElementKind.MALFORMED_TYPE) { |
| 324 String result = getFreshGlobalName(guess); | 418 bool isNative = false; |
| 419 if (kind == ElementKind.CLASS) { | |
| 420 ClassElement class_elt = element; | |
|
ngeoffray
2012/12/10 08:55:42
class_elt -> classElement
erikcorry
2012/12/10 12:37:40
Done.
| |
| 421 isNative = class_elt.isNative(); | |
| 422 } | |
| 423 if (Elements.isInstanceField(element)) { | |
| 424 isNative = element.isNative(); | |
| 425 } | |
| 426 String result = isNative ? guess : getFreshName(guess, usedGlobalNames); | |
| 325 globals[element] = result; | 427 globals[element] = result; |
| 326 return result; | 428 return result; |
| 327 } | 429 } |
| 328 compiler.internalError('getName for unknown kind: ${element.kind}', | 430 compiler.internalError('getName for unknown kind: ${element.kind}', |
| 329 node: element.parseNode(compiler)); | 431 node: element.parseNode(compiler)); |
| 330 } | 432 } |
| 331 } | 433 } |
| 332 | 434 |
| 333 String getLazyInitializerName(Element element) { | 435 String getLazyInitializerName(Element element) { |
| 334 // TODO(floitsch): mangle while not conflicting with other statics. | |
| 335 assert(Elements.isStaticOrTopLevelField(element)); | 436 assert(Elements.isStaticOrTopLevelField(element)); |
| 336 return "get\$${getName(element)}"; | 437 return getMappedGlobalName("get\$${getName(element)}"); |
| 337 } | 438 } |
| 338 | 439 |
| 339 String isolatePropertiesAccess(Element element) { | 440 String isolatePropertiesAccess(Element element) { |
| 340 return "$ISOLATE.$ISOLATE_PROPERTIES.${getName(element)}"; | 441 return "$isolateName.$isolatePropertiesName.${getName(element)}"; |
| 341 } | 442 } |
| 342 | 443 |
| 343 String isolateAccess(Element element) { | 444 String isolateAccess(Element element) { |
| 344 return "$CURRENT_ISOLATE.${getName(element)}"; | 445 return "$CURRENT_ISOLATE.${getName(element)}"; |
| 345 } | 446 } |
| 346 | 447 |
| 347 String isolateBailoutAccess(Element element) { | 448 String isolateBailoutAccess(Element element) { |
| 348 return '${isolateAccess(element)}\$bailout'; | 449 String newName = getMappedGlobalName('${getName(element)}\$bailout'); |
| 450 return '$CURRENT_ISOLATE.$newName'; | |
| 349 } | 451 } |
| 350 | 452 |
| 351 String isolateLazyInitializerAccess(Element element) { | 453 String isolateLazyInitializerAccess(Element element) { |
| 352 return "$CURRENT_ISOLATE.${getLazyInitializerName(element)}"; | 454 return "$CURRENT_ISOLATE.${getLazyInitializerName(element)}"; |
| 353 } | 455 } |
| 354 | 456 |
| 355 String operatorIs(Element element) { | 457 String operatorIs(Element element) { |
| 458 // TODO(erikcorry): Reduce from is$x to ix when we are minifying. | |
| 356 return 'is\$${getName(element)}'; | 459 return 'is\$${getName(element)}'; |
| 357 } | 460 } |
| 358 | 461 |
| 359 String safeName(String name) { | 462 String safeName(String name) { |
| 360 if (jsReserved.contains(name) || name.startsWith('\$')) { | 463 if (jsReserved.contains(name) || name.startsWith('\$')) { |
| 361 name = "\$$name"; | 464 name = "\$$name"; |
| 362 assert(!jsReserved.contains(name)); | 465 assert(!jsReserved.contains(name)); |
| 363 } | 466 } |
| 364 return name; | 467 return name; |
| 365 } | 468 } |
| 366 } | 469 } |
| OLD | NEW |