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 MinifyNamer extends Namer { | 10 class MinifyNamer extends Namer { |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 202 h += name.codeUnitAt(i); | 202 h += name.codeUnitAt(i); |
| 203 h &= 0xffffffff; | 203 h &= 0xffffffff; |
| 204 h += h << 10; | 204 h += h << 10; |
| 205 h &= 0xffffffff; | 205 h &= 0xffffffff; |
| 206 h ^= h >> 6; | 206 h ^= h >> 6; |
| 207 h &= 0xffffffff; | 207 h &= 0xffffffff; |
| 208 } | 208 } |
| 209 return h; | 209 return h; |
| 210 } | 210 } |
| 211 | 211 |
| 212 int _letterNumber(int x) { | 212 static int _letterNumber(int x) { |
| 213 if (x >= ALPHABET_CHARACTERS) x %= ALPHABET_CHARACTERS; | 213 if (x >= ALPHABET_CHARACTERS) x %= ALPHABET_CHARACTERS; |
| 214 if (x < 26) return $a + x; | 214 if (x < 26) return $a + x; |
| 215 return $A + x - 26; | 215 return $A + x - 26; |
| 216 } | 216 } |
| 217 | 217 |
| 218 int _alphaNumericNumber(int x) { | 218 static int _alphaNumericNumber(int x) { |
| 219 if (x >= ALPHANUMERIC_CHARACTERS) x %= ALPHANUMERIC_CHARACTERS; | 219 if (x >= ALPHANUMERIC_CHARACTERS) x %= ALPHANUMERIC_CHARACTERS; |
| 220 if (x < 26) return $a + x; | 220 if (x < 26) return $a + x; |
| 221 if (x < 52) return $A + x - 26; | 221 if (x < 52) return $A + x - 26; |
| 222 return $0 + x - 52; | 222 return $0 + x - 52; |
| 223 } | 223 } |
| 224 | 224 |
| 225 String instanceFieldPropertyName(Element element) { | |
| 226 _FieldNamingScope names; | |
| 227 | |
| 228 if (element is BoxFieldElement) { | |
| 229 names = new _FieldNamingScope.forBox(element.box); | |
| 230 } else { | |
| 231 ClassElement cls = element is ClosureFieldElement | |
| 232 ? element.closureClass : element.enclosingClass; | |
| 233 names = new _FieldNamingScope.forClass(cls, compiler.world); | |
| 234 } | |
| 235 | |
| 236 if (!names.containsField(element)) { | |
| 237 return super.instanceFieldPropertyName(element); | |
|
floitsch
2014/11/06 14:05:41
When can this happen? (add comment).
How do you en
herhut
2014/11/14 10:40:05
I have reworked this and included support for nami
| |
| 238 } | |
| 239 | |
| 240 return names[element]; | |
| 241 } | |
| 225 } | 242 } |
| 243 | |
| 244 /** | |
| 245 * A [_FieldNamingScope] encodes a node in the inheritance tree of the current | |
| 246 * class hierarchy. The root node typically is the node corresponding to the | |
| 247 * `Object` class. It is used to assign a unique name to each field of a class. | |
| 248 * Unique here means unique wrt. all fields along the path back to the root. | |
| 249 * This is achieved at construction time via the [_count] field that counts the | |
| 250 * number of fields on the path to the root node that have been encountered so | |
| 251 * far. | |
| 252 * Obviously, this only works if no fields are added to a parent node after its | |
|
floitsch
2014/11/06 14:05:41
New line before.
herhut
2014/11/14 10:40:05
Done.
| |
| 253 * children have added their first field. | |
| 254 */ | |
| 255 class _FieldNamingScope { | |
| 256 final _FieldNamingScope superScope; | |
| 257 final Entity container; | |
| 258 final Map<Element, String> names = new Maplet<Element, String>(); | |
| 259 int _count; | |
| 260 | |
| 261 static Map<Entity, _FieldNamingScope> _scopes = | |
|
floitsch
2014/11/06 14:05:41
When is this map cleared?
This looks like somethi
herhut
2014/11/14 10:40:05
I have factored the state out into a field of the
| |
| 262 new Map<Entity, _FieldNamingScope>(); | |
| 263 | |
| 264 factory _FieldNamingScope.forClass(ClassElement cls, ClassWorld world) { | |
| 265 _FieldNamingScope computeFieldNames() { | |
| 266 _FieldNamingScope result; | |
| 267 ClassElement superClass = cls.superclass; | |
| 268 if (superClass != null) { | |
| 269 result = new _FieldNamingScope.inherit(cls, | |
| 270 new _FieldNamingScope.forClass(superClass, world)); | |
| 271 } else { | |
| 272 result = new _FieldNamingScope.rootScope(cls); | |
| 273 } | |
| 274 | |
| 275 // If this class is used as a mixin, we cannot rename its fields as | |
| 276 // there is no single place in the hierarchy where it belongs. Also, | |
| 277 // if this class is the result of a mixin application, we cannot remane | |
| 278 // its fields as they have to stay in sync with the fields of the mixed | |
| 279 // in class. | |
| 280 // However, we still produce an empty scope, as subclasses of this mixin | |
| 281 // application might still have their fields renamed. | |
| 282 if (cls.isMixinApplication || world.isUsedAsMixin(cls)) return result; | |
| 283 | |
| 284 cls.forEachInstanceField((cls, field) => result.add(field)); | |
| 285 return result; | |
| 286 } | |
| 287 | |
| 288 return _scopes.putIfAbsent(cls, computeFieldNames); | |
| 289 } | |
| 290 | |
| 291 factory _FieldNamingScope.forBox(Local box) { | |
| 292 return _scopes.putIfAbsent(box, () => new _BoxFieldNamingScope(box)); | |
| 293 } | |
| 294 | |
| 295 _FieldNamingScope.rootScope(this.container) : | |
|
floitsch
2014/11/06 14:05:41
: in next line.
herhut
2014/11/14 10:40:05
Done.
| |
| 296 superScope = null, | |
|
floitsch
2014/11/06 14:05:41
indent by 4.
herhut
2014/11/14 10:40:05
Done.
| |
| 297 _count = 0; | |
| 298 | |
| 299 _FieldNamingScope.inherit(this.container, this.superScope) { | |
| 300 _count = superScope._count; | |
| 301 } | |
| 302 | |
| 303 _valueIsUnused(String name) { | |
|
floitsch
2014/11/06 14:05:41
_isValueUnused
herhut
2014/11/14 10:40:05
Done.
| |
| 304 return !names.values.contains(name) && | |
| 305 ((superScope == null) || superScope._valueIsUnused(name)); | |
| 306 } | |
| 307 | |
| 308 String _nextName() { | |
| 309 List<int> codes = <int>[]; | |
| 310 var cnt = _count++; | |
| 311 codes.add(MinifyNamer._letterNumber(cnt)); | |
| 312 cnt ~/= MinifyNamer.ALPHABET_CHARACTERS; | |
| 313 while (cnt > 0) { | |
| 314 codes.add(MinifyNamer._alphaNumericNumber(cnt)); | |
| 315 cnt ~/= MinifyNamer.ALPHANUMERIC_CHARACTERS; | |
| 316 } | |
| 317 return new String.fromCharCodes(codes); | |
| 318 } | |
| 319 | |
| 320 String operator[](Element field) { | |
| 321 String name = names[field]; | |
| 322 if (name == null && superScope != null) return superScope[field]; | |
| 323 return name; | |
| 324 } | |
| 325 | |
| 326 void add(Element field) { | |
| 327 String value = _nextName(); | |
| 328 assert(invariant(field, _valueIsUnused(value))); | |
| 329 names[field] = value; | |
| 330 } | |
| 331 | |
| 332 bool containsField(Element field) => names.containsKey(field); | |
| 333 } | |
| 334 | |
| 335 /** | |
| 336 * [BoxFieldElement] fields work differently in that they do not belong to an | |
| 337 * actual class but an anonymous box associated to a [Local]. As there is no | |
| 338 * inheritance chain, we do not need to compute fields a priori but can assign | |
| 339 * names on the fly. | |
| 340 */ | |
| 341 class _BoxFieldNamingScope extends _FieldNamingScope { | |
| 342 _BoxFieldNamingScope(Local box) : super.rootScope(box); | |
| 343 | |
| 344 bool containsField(_) => true; | |
| 345 | |
| 346 String operator[](Element field) { | |
| 347 if (!names.containsKey(field)) add(field); | |
| 348 return names[field]; | |
| 349 } | |
| 350 } | |
| OLD | NEW |