Chromium Code Reviews| Index: pkg/compiler/lib/src/js_backend/minify_namer.dart |
| diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart |
| index a3182791dc285c6182fea6b83224b135a3336050..bdb4953b6344621df37c71bf0a81527e9e5fcae6 100644 |
| --- a/pkg/compiler/lib/src/js_backend/minify_namer.dart |
| +++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart |
| @@ -209,17 +209,142 @@ class MinifyNamer extends Namer { |
| return h; |
| } |
| - int _letterNumber(int x) { |
| + static int _letterNumber(int x) { |
| if (x >= ALPHABET_CHARACTERS) x %= ALPHABET_CHARACTERS; |
| if (x < 26) return $a + x; |
| return $A + x - 26; |
| } |
| - int _alphaNumericNumber(int x) { |
| + static int _alphaNumericNumber(int x) { |
| if (x >= ALPHANUMERIC_CHARACTERS) x %= ALPHANUMERIC_CHARACTERS; |
| if (x < 26) return $a + x; |
| if (x < 52) return $A + x - 26; |
| return $0 + x - 52; |
| } |
| + String instanceFieldPropertyName(Element element) { |
| + _FieldNamingScope names; |
| + |
| + if (element is BoxFieldElement) { |
| + names = new _FieldNamingScope.forBox(element.box); |
| + } else { |
| + ClassElement cls = element is ClosureFieldElement |
| + ? element.closureClass : element.enclosingClass; |
| + names = new _FieldNamingScope.forClass(cls, compiler.world); |
| + } |
| + |
| + if (!names.containsField(element)) { |
| + 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
|
| + } |
| + |
| + return names[element]; |
| + } |
| +} |
| + |
| +/** |
| + * A [_FieldNamingScope] encodes a node in the inheritance tree of the current |
| + * class hierarchy. The root node typically is the node corresponding to the |
| + * `Object` class. It is used to assign a unique name to each field of a class. |
| + * Unique here means unique wrt. all fields along the path back to the root. |
| + * This is achieved at construction time via the [_count] field that counts the |
| + * number of fields on the path to the root node that have been encountered so |
| + * far. |
| + * 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.
|
| + * children have added their first field. |
| + */ |
| +class _FieldNamingScope { |
| + final _FieldNamingScope superScope; |
| + final Entity container; |
| + final Map<Element, String> names = new Maplet<Element, String>(); |
| + int _count; |
| + |
| + 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
|
| + new Map<Entity, _FieldNamingScope>(); |
| + |
| + factory _FieldNamingScope.forClass(ClassElement cls, ClassWorld world) { |
| + _FieldNamingScope computeFieldNames() { |
| + _FieldNamingScope result; |
| + ClassElement superClass = cls.superclass; |
| + if (superClass != null) { |
| + result = new _FieldNamingScope.inherit(cls, |
| + new _FieldNamingScope.forClass(superClass, world)); |
| + } else { |
| + result = new _FieldNamingScope.rootScope(cls); |
| + } |
| + |
| + // If this class is used as a mixin, we cannot rename its fields as |
| + // there is no single place in the hierarchy where it belongs. Also, |
| + // if this class is the result of a mixin application, we cannot remane |
| + // its fields as they have to stay in sync with the fields of the mixed |
| + // in class. |
| + // However, we still produce an empty scope, as subclasses of this mixin |
| + // application might still have their fields renamed. |
| + if (cls.isMixinApplication || world.isUsedAsMixin(cls)) return result; |
| + |
| + cls.forEachInstanceField((cls, field) => result.add(field)); |
| + return result; |
| + } |
| + |
| + return _scopes.putIfAbsent(cls, computeFieldNames); |
| + } |
| + |
| + factory _FieldNamingScope.forBox(Local box) { |
| + return _scopes.putIfAbsent(box, () => new _BoxFieldNamingScope(box)); |
| + } |
| + |
| + _FieldNamingScope.rootScope(this.container) : |
|
floitsch
2014/11/06 14:05:41
: in next line.
herhut
2014/11/14 10:40:05
Done.
|
| + superScope = null, |
|
floitsch
2014/11/06 14:05:41
indent by 4.
herhut
2014/11/14 10:40:05
Done.
|
| + _count = 0; |
| + |
| + _FieldNamingScope.inherit(this.container, this.superScope) { |
| + _count = superScope._count; |
| + } |
| + |
| + _valueIsUnused(String name) { |
|
floitsch
2014/11/06 14:05:41
_isValueUnused
herhut
2014/11/14 10:40:05
Done.
|
| + return !names.values.contains(name) && |
| + ((superScope == null) || superScope._valueIsUnused(name)); |
| + } |
| + |
| + String _nextName() { |
| + List<int> codes = <int>[]; |
| + var cnt = _count++; |
| + codes.add(MinifyNamer._letterNumber(cnt)); |
| + cnt ~/= MinifyNamer.ALPHABET_CHARACTERS; |
| + while (cnt > 0) { |
| + codes.add(MinifyNamer._alphaNumericNumber(cnt)); |
| + cnt ~/= MinifyNamer.ALPHANUMERIC_CHARACTERS; |
| + } |
| + return new String.fromCharCodes(codes); |
| + } |
| + |
| + String operator[](Element field) { |
| + String name = names[field]; |
| + if (name == null && superScope != null) return superScope[field]; |
| + return name; |
| + } |
| + |
| + void add(Element field) { |
| + String value = _nextName(); |
| + assert(invariant(field, _valueIsUnused(value))); |
| + names[field] = value; |
| + } |
| + |
| + bool containsField(Element field) => names.containsKey(field); |
| } |
| + |
| +/** |
| + * [BoxFieldElement] fields work differently in that they do not belong to an |
| + * actual class but an anonymous box associated to a [Local]. As there is no |
| + * inheritance chain, we do not need to compute fields a priori but can assign |
| + * names on the fly. |
| + */ |
| +class _BoxFieldNamingScope extends _FieldNamingScope { |
| + _BoxFieldNamingScope(Local box) : super.rootScope(box); |
| + |
| + bool containsField(_) => true; |
| + |
| + String operator[](Element field) { |
| + if (!names.containsKey(field)) add(field); |
| + return names[field]; |
| + } |
| +} |