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 ISOLATE => 'Isolate'; |
| 55 final String ISOLATE = 'Isolate'; | 64 String get ISOLATE_PROPERTIES => 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 CLOSURE_INVOCATION_NAME => Compiler.CALL_OPERATOR_NAME; |
| 63 Compiler.CALL_OPERATOR_NAME; | 71 bool get shouldMinify => false; |
| 72 | |
| 73 bool isReserved(String name) => name == ISOLATE; | |
| 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 never returns the same string as we suggested so we | |
|
floitsch
2012/12/07 12:01:01
The minifier always constructs a new name, using t
erikcorry
2012/12/10 08:36:01
Done.
| |
| 87 // can suggest any name and it will use it as input to the hashing | |
| 88 // algorithm. This means that constants will tend to have the same | |
| 89 // name from version to version of the program being minfied. | |
| 90 longName = stringConstant.value.slowToString(); | |
| 91 } else { | |
| 92 longName = "C"; | |
| 93 } | |
| 94 } else { | |
| 95 longName = "CTC"; | |
|
floitsch
2012/12/07 12:01:01
We could maybe switch to "CONSTANT" now? (but no s
erikcorry
2012/12/10 08:36:01
Done.
| |
| 96 } | |
| 97 result = getFreshName(longName, usedGlobalNames); | |
| 73 constantNames[constant] = result; | 98 constantNames[constant] = result; |
| 74 } | 99 } |
| 75 return result; | 100 return result; |
| 76 } | 101 } |
| 77 | 102 |
| 78 String closureInvocationName(Selector selector) { | 103 String closureInvocationName(Selector selector) { |
| 79 // TODO(floitsch): mangle, while not conflicting with instance names. | 104 return |
| 80 return instanceMethodInvocationName(null, CLOSURE_INVOCATION_NAME, | 105 instanceMethodInvocationName(null, CLOSURE_INVOCATION_NAME, selector); |
| 81 selector); | |
| 82 } | 106 } |
| 83 | 107 |
| 84 String breakLabelName(LabelElement label) { | 108 String breakLabelName(LabelElement label) { |
| 85 return '\$${label.labelName}\$${label.target.nestingLevel}'; | 109 return '\$${label.labelName}\$${label.target.nestingLevel}'; |
| 86 } | 110 } |
| 87 | 111 |
| 88 String implicitBreakLabelName(TargetElement target) { | 112 String implicitBreakLabelName(TargetElement target) { |
| 89 return '\$${target.nestingLevel}'; | 113 return '\$${target.nestingLevel}'; |
| 90 } | 114 } |
| 91 | 115 |
| 92 // We sometimes handle continue targets differently from break targets, | 116 // We sometimes handle continue targets differently from break targets, |
| 93 // so we have special continue-only labels. | 117 // so we have special continue-only labels. |
| 94 String continueLabelName(LabelElement label) { | 118 String continueLabelName(LabelElement label) { |
| 95 return 'c\$${label.labelName}\$${label.target.nestingLevel}'; | 119 return 'c\$${label.labelName}\$${label.target.nestingLevel}'; |
| 96 } | 120 } |
| 97 | 121 |
| 98 String implicitContinueLabelName(TargetElement target) { | 122 String implicitContinueLabelName(TargetElement target) { |
| 99 return 'c\$${target.nestingLevel}'; | 123 return 'c\$${target.nestingLevel}'; |
| 100 } | 124 } |
| 101 | 125 |
| 102 /** | 126 /** |
| 103 * If the [name] is not private returns [:name.slowToString():]. Otherwise | 127 * If the [name] is not private returns [:name.slowToString():]. Otherwise |
| 104 * mangles the [name] so that each library has a unique name. | 128 * mangles the [name] so that each library has a unique name. |
| 105 */ | 129 */ |
| 106 String privateName(LibraryElement lib, SourceString name) { | 130 String privateName(LibraryElement lib, SourceString name) { |
| 131 String result; | |
| 107 if (name.isPrivate()) { | 132 if (name.isPrivate()) { |
| 108 String nameString = name.slowToString(); | 133 String nameString = name.slowToString(); |
| 109 // The first library asking for a short private name wins. | 134 // The first library asking for a short private name wins. |
| 110 LibraryElement owner = | 135 LibraryElement owner = |
|
floitsch
2012/12/07 12:01:01
I don't think you need to fill the shortPrivateNam
erikcorry
2012/12/10 08:36:01
Done.
| |
| 111 shortPrivateNameOwners.putIfAbsent(nameString, () => lib); | 136 shortPrivateNameOwners.putIfAbsent(nameString, () => 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 == CLOSURE_INVOCATION_NAME) 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 == CLOSURE_INVOCATION_NAME) 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 == CLOSURE_INVOCATION_NAME) { |
|
floitsch
2012/12/07 12:01:01
Copy comment from above. (saying that closure invo
erikcorry
2012/12/10 08:36:01
Done.
| |
| 202 return '$CLOSURE_INVOCATION_NAME\$${selector.argumentCount}$buffer'; | |
| 203 } | |
| 204 return getMappedInstanceName( | |
| 205 '${privateName(lib, name)}\$${selector.argumentCount}$buffer'); | |
| 166 } | 206 } |
| 167 | 207 |
| 168 String instanceFieldName(LibraryElement libraryElement, SourceString name) { | 208 String instanceFieldName(LibraryElement libraryElement, SourceString name) { |
| 169 String proposedName = privateName(libraryElement, name); | 209 String proposedName = privateName(libraryElement, name); |
| 170 return safeName(proposedName); | 210 return getMappedInstanceName(proposedName); |
| 171 } | 211 } |
| 172 | 212 |
| 213 // Construct a new name for the element based on the library and class it is | |
| 214 // in. The name here is not important, we just need to make sure it is | |
| 215 // unique. If we are minifying, we actually construct the name from the | |
| 216 // minfiied versions of the class and instance names, but the result is | |
|
sra1
2012/12/07 06:03:18
minfiied -> minified
erikcorry
2012/12/10 08:36:01
Done.
| |
| 217 // minified once again, so that is not visible in the end result. | |
| 173 String shadowedFieldName(Element fieldElement) { | 218 String shadowedFieldName(Element fieldElement) { |
| 219 // Check for following situation: Native field ${fieldElement.name} has | |
| 220 // fixed JSName ${fieldElement.nativeName()}, but a subclass shadows this | |
| 221 // name. We normally handle that by renaming the superclass field, but we | |
| 222 // can't do that because native fields have fixed JSNames. In practice | |
| 223 // this can't happen because we can't inherit from native classes. | |
| 224 assert (!fieldElement.isNative()); | |
| 225 | |
| 174 ClassElement cls = fieldElement.getEnclosingClass(); | 226 ClassElement cls = fieldElement.getEnclosingClass(); |
| 175 LibraryElement libraryElement = fieldElement.getLibrary(); | 227 LibraryElement libraryElement = fieldElement.getLibrary(); |
| 176 String libName = getName(libraryElement); | 228 String libName = getName(libraryElement); |
| 177 String clsName = getName(cls); | 229 String clsName = getName(cls); |
| 178 String instanceName = instanceFieldName(libraryElement, fieldElement.name); | 230 String instanceName = instanceFieldName(libraryElement, fieldElement.name); |
| 179 return safeName('$libName\$$clsName\$$instanceName'); | 231 return getMappedInstanceName('$libName\$$clsName\$$instanceName'); |
| 180 } | 232 } |
| 181 | 233 |
| 182 String setterName(LibraryElement lib, SourceString name) { | 234 String setterName(LibraryElement lib, SourceString name) { |
| 183 // We dynamically create setters from the field-name. The setter name must | 235 // We dynamically create setters from the field-name. The setter name must |
| 184 // therefore be derived from the instance field-name. | 236 // therefore be derived from the instance field-name. |
| 185 String fieldName = safeName(privateName(lib, name)); | 237 String fieldName = getMappedInstanceName(privateName(lib, name)); |
| 186 return 'set\$$fieldName'; | 238 return 'set\$$fieldName'; |
| 187 } | 239 } |
| 188 | 240 |
| 241 String setterNameFromAccessorName(String name) { | |
| 242 // We dynamically create setters from the field-name. The setter name must | |
| 243 // therefore be derived from the instance field-name. | |
| 244 return 'set\$$name'; | |
| 245 } | |
| 246 | |
| 189 String publicGetterName(SourceString name) { | 247 String publicGetterName(SourceString name) { |
| 190 // We dynamically create getters from the field-name. The getter name must | 248 // We dynamically create getters from the field-name. The getter name must |
| 191 // therefore be derived from the instance field-name. | 249 // therefore be derived from the instance field-name. |
| 192 String fieldName = safeName(name.slowToString()); | 250 String fieldName = getMappedInstanceName(name.slowToString()); |
| 193 return 'get\$$fieldName'; | 251 return 'get\$$fieldName'; |
| 194 } | 252 } |
| 195 | 253 |
| 254 String getterNameFromAccessorName(String name) { | |
| 255 // We dynamically create getters from the field-name. The getter name must | |
| 256 // therefore be derived from the instance field-name. | |
| 257 return 'get\$$name'; | |
| 258 } | |
| 259 | |
| 196 String getterName(LibraryElement lib, SourceString name) { | 260 String getterName(LibraryElement lib, SourceString name) { |
| 197 // We dynamically create getters from the field-name. The getter name must | 261 // We dynamically create getters from the field-name. The getter name must |
| 198 // therefore be derived from the instance field-name. | 262 // therefore be derived from the instance field-name. |
| 199 String fieldName = safeName(privateName(lib, name)); | 263 String fieldName = getMappedInstanceName(privateName(lib, name)); |
| 200 return 'get\$$fieldName'; | 264 return 'get\$$fieldName'; |
| 201 } | 265 } |
| 202 | 266 |
| 203 String getFreshGlobalName(String proposedName) { | 267 String getMappedGlobalName(String proposedName) { |
| 204 String name = proposedName; | 268 var newName = globalNameMap[proposedName]; |
| 205 int count = usedGlobals[name]; | 269 if (newName == null) { |
| 206 if (count != null) { | 270 newName = getFreshName(proposedName, usedGlobalNames); |
| 207 // Not the first time we see this name. Append a number to make it unique. | 271 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 } | 272 } |
| 216 usedGlobals[name] = 0; | 273 return newName; |
| 217 return name; | 274 } |
| 275 | |
| 276 String getMappedInstanceName(String proposedName) { | |
| 277 var newName = instanceNameMap[proposedName]; | |
| 278 if (newName == null) { | |
| 279 newName = getFreshName(proposedName, usedInstanceNames); | |
| 280 instanceNameMap[proposedName] = newName; | |
| 281 } | |
| 282 return newName; | |
| 283 } | |
| 284 | |
| 285 String getFreshName(String proposedName, Set<String> usedNames) { | |
| 286 var candidate; | |
| 287 proposedName = safeName(proposedName); | |
| 288 if (!usedNames.contains(proposedName)) { | |
| 289 candidate = proposedName; | |
| 290 } else { | |
| 291 var counter = popularNameCounters[proposedName]; | |
| 292 var i = counter == null ? 0 : counter; | |
| 293 while (usedNames.contains("$proposedName$i")) { | |
| 294 i++; | |
| 295 } | |
| 296 popularNameCounters[proposedName] = i + 1; | |
| 297 candidate = "$proposedName$i"; | |
| 298 } | |
| 299 usedNames.add(candidate); | |
| 300 return candidate; | |
| 218 } | 301 } |
| 219 | 302 |
| 220 static const String LIBRARY_PREFIX = "lib"; | 303 static const String LIBRARY_PREFIX = "lib"; |
| 221 | 304 |
| 222 /** | 305 /** |
| 223 * Returns a preferred JS-id for the given top-level or static element. | 306 * 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. | 307 * The returned id is guaranteed to be a valid JS-id. |
| 225 */ | 308 */ |
| 226 String _computeGuess(Element element) { | 309 String _computeGuess(Element element) { |
| 227 assert(!element.isInstanceMember()); | 310 assert(!element.isInstanceMember()); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 240 name = "${enclosingClass.name.slowToString()}_" | 323 name = "${enclosingClass.name.slowToString()}_" |
| 241 "${element.name.slowToString()}"; | 324 "${element.name.slowToString()}"; |
| 242 } else { | 325 } else { |
| 243 name = element.name.slowToString(); | 326 name = element.name.slowToString(); |
| 244 } | 327 } |
| 245 } else if (element.isLibrary()) { | 328 } else if (element.isLibrary()) { |
| 246 name = LIBRARY_PREFIX; | 329 name = LIBRARY_PREFIX; |
| 247 } else { | 330 } else { |
| 248 name = element.name.slowToString(); | 331 name = element.name.slowToString(); |
| 249 } | 332 } |
| 250 return safeName(name); | 333 return name; |
| 251 } | 334 } |
| 252 | 335 |
| 253 String getSpecializedName(Element element, Collection<ClassElement> classes) { | 336 String getSpecializedName(Element element, Collection<ClassElement> classes) { |
| 337 // This gets the minified name, but it doesn't really make much difference. | |
| 338 // the important thing is that it is a unique name. | |
| 254 StringBuffer buffer = new StringBuffer('${getName(element)}\$'); | 339 StringBuffer buffer = new StringBuffer('${getName(element)}\$'); |
| 255 for (ClassElement cls in classes) { | 340 for (ClassElement cls in classes) { |
| 256 buffer.add(getName(cls)); | 341 buffer.add(getName(cls)); |
| 257 } | 342 } |
| 258 return safeName(buffer.toString()); | 343 return getMappedGlobalName(buffer.toString()); |
| 259 } | 344 } |
| 260 | 345 |
| 261 String getBailoutName(Element element) { | 346 String getBailoutName(Element element) { |
| 262 String name = bailoutNames[element]; | 347 String name = bailoutNames[element]; |
| 263 if (name != null) return name; | 348 if (name != null) return name; |
| 264 bool global = !element.isInstanceMember(); | 349 bool global = !element.isInstanceMember(); |
| 350 // Despite the name of the variable, this gets the minified name when we | |
| 351 // are minifying, but it doesn't really make much difference. The | |
| 352 // important thing is that it is a unique name. We add $bailout and, if we | |
| 353 // are minifying, we minify the minified name and '$bailout'. | |
| 265 String unminifiedName = '${getName(element)}\$bailout'; | 354 String unminifiedName = '${getName(element)}\$bailout'; |
| 266 name = unminifiedName; | 355 if (global) { |
| 267 if (!global) { | 356 name = getMappedGlobalName(unminifiedName); |
| 357 } else { | |
| 358 name = unminifiedName; | |
| 268 int i = 0; | 359 int i = 0; |
| 269 while (usedBailoutInstanceNames.contains(name)) { | 360 while (usedBailoutInstanceNames.contains(name)) { |
| 270 name = '$unminifiedName${i++}'; | 361 name = '$unminifiedName${i++}'; |
| 271 } | 362 } |
| 272 usedBailoutInstanceNames.add(name); | 363 usedBailoutInstanceNames.add(name); |
| 364 name = getMappedInstanceName(name); | |
| 273 } | 365 } |
| 274 bailoutNames[element] = name; | 366 bailoutNames[element] = name; |
| 275 return name; | 367 return name; |
| 276 } | 368 } |
| 277 | 369 |
| 278 /** | 370 /** |
| 279 * Returns a preferred JS-id for the given element. The returned id is | 371 * 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 | 372 * guaranteed to be a valid JS-id. Globals and static fields are furthermore |
| 281 * guaranteed to be unique. | 373 * guaranteed to be unique. |
| 282 * | 374 * |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 303 element = element.declaration; | 395 element = element.declaration; |
| 304 // Dealing with a top-level or static element. | 396 // Dealing with a top-level or static element. |
| 305 String cached = globals[element]; | 397 String cached = globals[element]; |
| 306 if (cached != null) return cached; | 398 if (cached != null) return cached; |
| 307 | 399 |
| 308 String guess = _computeGuess(element); | 400 String guess = _computeGuess(element); |
| 309 ElementKind kind = element.kind; | 401 ElementKind kind = element.kind; |
| 310 if (identical(kind, ElementKind.VARIABLE) || | 402 if (identical(kind, ElementKind.VARIABLE) || |
| 311 identical(kind, ElementKind.PARAMETER)) { | 403 identical(kind, ElementKind.PARAMETER)) { |
| 312 // The name is not guaranteed to be unique. | 404 // The name is not guaranteed to be unique. |
| 313 return guess; | 405 return safeName(guess); |
| 314 } | 406 } |
| 315 if (identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR) || | 407 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR || |
| 316 identical(kind, ElementKind.FUNCTION) || | 408 kind == ElementKind.FUNCTION || |
| 317 identical(kind, ElementKind.CLASS) || | 409 kind == ElementKind.CLASS || |
| 318 identical(kind, ElementKind.FIELD) || | 410 kind == ElementKind.FIELD || |
| 319 identical(kind, ElementKind.GETTER) || | 411 kind == ElementKind.GETTER || |
| 320 identical(kind, ElementKind.SETTER) || | 412 kind == ElementKind.SETTER || |
| 321 identical(kind, ElementKind.TYPEDEF) || | 413 kind == ElementKind.TYPEDEF || |
| 322 identical(kind, ElementKind.LIBRARY) || | 414 kind == ElementKind.LIBRARY || |
| 323 identical(kind, ElementKind.MALFORMED_TYPE)) { | 415 kind == ElementKind.MALFORMED_TYPE) { |
| 324 String result = getFreshGlobalName(guess); | 416 bool isNative = false; |
| 417 if (identical(kind, ElementKind.CLASS)) { | |
|
floitsch
2012/12/07 12:01:01
use "=="
erikcorry
2012/12/10 08:36:01
Done.
| |
| 418 ClassElement class_elt = element; | |
| 419 isNative = class_elt.isNative(); | |
| 420 } | |
| 421 if (Elements.isInstanceField(element)) { | |
| 422 isNative = element.isNative(); | |
| 423 } | |
| 424 String result = isNative ? guess : getFreshName(guess, usedGlobalNames); | |
| 325 globals[element] = result; | 425 globals[element] = result; |
| 326 return result; | 426 return result; |
| 327 } | 427 } |
| 328 compiler.internalError('getName for unknown kind: ${element.kind}', | 428 compiler.internalError('getName for unknown kind: ${element.kind}', |
| 329 node: element.parseNode(compiler)); | 429 node: element.parseNode(compiler)); |
| 330 } | 430 } |
| 331 } | 431 } |
| 332 | 432 |
| 333 String getLazyInitializerName(Element element) { | 433 String getLazyInitializerName(Element element) { |
| 334 // TODO(floitsch): mangle while not conflicting with other statics. | |
| 335 assert(Elements.isStaticOrTopLevelField(element)); | 434 assert(Elements.isStaticOrTopLevelField(element)); |
| 336 return "get\$${getName(element)}"; | 435 return getMappedGlobalName("get\$${getName(element)}"); |
| 337 } | 436 } |
| 338 | 437 |
| 339 String isolatePropertiesAccess(Element element) { | 438 String isolatePropertiesAccess(Element element) { |
| 340 return "$ISOLATE.$ISOLATE_PROPERTIES.${getName(element)}"; | 439 return "$ISOLATE.$ISOLATE_PROPERTIES.${getName(element)}"; |
| 341 } | 440 } |
| 342 | 441 |
| 343 String isolateAccess(Element element) { | 442 String isolateAccess(Element element) { |
| 344 return "$CURRENT_ISOLATE.${getName(element)}"; | 443 return "$CURRENT_ISOLATE.${getName(element)}"; |
| 345 } | 444 } |
| 346 | 445 |
| 347 String isolateBailoutAccess(Element element) { | 446 String isolateBailoutAccess(Element element) { |
| 348 return '${isolateAccess(element)}\$bailout'; | 447 String newName = getMappedGlobalName('${getName(element)}\$bailout'); |
| 448 return '$CURRENT_ISOLATE.$newName'; | |
| 349 } | 449 } |
| 350 | 450 |
| 351 String isolateLazyInitializerAccess(Element element) { | 451 String isolateLazyInitializerAccess(Element element) { |
| 352 return "$CURRENT_ISOLATE.${getLazyInitializerName(element)}"; | 452 return "$CURRENT_ISOLATE.${getLazyInitializerName(element)}"; |
| 353 } | 453 } |
| 354 | 454 |
| 355 String operatorIs(Element element) { | 455 String operatorIs(Element element) { |
| 456 // TODO(erikcorry): Reduce from is$x to ix when we are minifying. | |
| 356 return 'is\$${getName(element)}'; | 457 return 'is\$${getName(element)}'; |
| 357 } | 458 } |
| 358 | 459 |
| 359 String safeName(String name) { | 460 String safeName(String name) { |
| 360 if (jsReserved.contains(name) || name.startsWith('\$')) { | 461 if (jsReserved.contains(name) || name.startsWith('\$')) { |
| 361 name = "\$$name"; | 462 name = "\$$name"; |
| 362 assert(!jsReserved.contains(name)); | 463 assert(!jsReserved.contains(name)); |
| 363 } | 464 } |
| 364 return name; | 465 return name; |
| 365 } | 466 } |
| 366 } | 467 } |
| OLD | NEW |