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 2f0b37cac60070b4876a3399e3717047d6a2817b..4b3095110ad79721793e358a894248424eec0bce 100644 |
| --- a/pkg/compiler/lib/src/js_backend/minify_namer.dart |
| +++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart |
| @@ -7,12 +7,14 @@ part of js_backend; |
| /** |
| * Assigns JavaScript identifiers to Dart variables, class-names and members. |
| */ |
| -class MinifyNamer extends Namer { |
| +class MinifyNamer extends Namer with _MinifiedFieldNamer { |
| MinifyNamer(Compiler compiler) : super(compiler) { |
| reserveBackendNames(); |
| fieldRegistry = new _FieldNamingRegistry(this); |
| } |
| + _FieldNamingRegistry fieldRegistry; |
| + |
| String get isolateName => 'I'; |
| String get isolatePropertiesName => 'p'; |
| bool get shouldMinify => true; |
| @@ -24,13 +26,12 @@ class MinifyNamer extends Namer { |
| final ALPHABET_CHARACTERS = 52; // a-zA-Z. |
| final ALPHANUMERIC_CHARACTERS = 62; // a-zA-Z0-9. |
| - _FieldNamingRegistry fieldRegistry; |
| - |
| /// You can pass an invalid identifier to this and unlike its non-minifying |
| /// counterpart it will never return the proposedName as the new fresh name. |
| /// |
| /// [sanitizeForNatives] and [sanitizeForAnnotations] are ignored because the |
| /// minified names will always avoid clashing with annotated names or natives. |
| + @override |
| jsAst.Name getFreshName(String proposedName, |
| Set<String> usedNames, |
|
Johnni Winther
2015/06/26 10:03:35
Identation is off.
herhut
2015/06/29 12:19:31
Done.
|
| Map<String, String> suggestedNames, |
| @@ -244,209 +245,13 @@ class MinifyNamer extends Namer { |
| return $0 + x - 52; |
| } |
| + @override |
| jsAst.Name instanceFieldPropertyName(Element element) { |
| - if (element.hasFixedBackendName) { |
| - return new StringBackedName(element.fixedBackendName); |
| - } |
| - |
| - _FieldNamingScope names; |
| - if (element is BoxFieldElement) { |
| - names = new _FieldNamingScope.forBox(element.box, fieldRegistry); |
| - } else { |
| - ClassElement cls = element is ClosureFieldElement |
| - ? element.closureClass : element.enclosingClass; |
| - names = new _FieldNamingScope.forClass(cls, compiler.world, |
| - fieldRegistry); |
| - } |
| - |
| - // The inheritance scope based naming did not yield a name. For instance, |
| - // this could be because the field belongs to a mixin. |
| - if (!names.containsField(element)) { |
| - return super.instanceFieldPropertyName(element); |
| - } |
| - |
| - return names[element]; |
| - } |
| -} |
| - |
| -/** |
| - * Encapsulates the global state of field naming. |
| - */ |
| -class _FieldNamingRegistry { |
| - final MinifyNamer namer; |
| - |
| - final Map<Entity, _FieldNamingScope> scopes = |
| - new Map<Entity, _FieldNamingScope>(); |
| - |
| - final Map<Entity, jsAst.Name> globalNames = new Map<Entity, jsAst.Name>(); |
| - |
| - int globalCount = 0; |
| - |
| - final List<jsAst.Name> nameStore = new List<jsAst.Name>(); |
| - |
| - _FieldNamingRegistry(this.namer); |
| - |
| - jsAst.Name getName(int count) { |
| - if (count >= nameStore.length) { |
| - // The namer usually does not use certain names as they clash with |
| - // existing properties on JS objects (see [_reservedNativeProperties]). |
| - // However, some of them are really short and safe to use for fields. |
| - // Thus, we shortcut the namer to use those first. |
| - if (count < MinifyNamer._reservedNativeProperties.length && |
| - MinifyNamer._reservedNativeProperties[count].length <= 2) { |
| - nameStore.add(new StringBackedName( |
| - MinifyNamer._reservedNativeProperties[count])); |
| - } else { |
| - nameStore.add(namer.getFreshName("field$count", |
| - namer.usedInstanceNames, namer.suggestedInstanceNames)); |
| - } |
| - } |
| - |
| - return nameStore[count]; |
| - } |
| -} |
| - |
| -/** |
| - * 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 [_fieldNameCounter] 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 |
| - * children have added their first field. |
| - */ |
| -class _FieldNamingScope { |
| - final _FieldNamingScope superScope; |
| - final Entity container; |
| - final Map<Element, jsAst.Name> names = new Maplet<Element, jsAst.Name>(); |
| - final _FieldNamingRegistry registry; |
| - |
| - /// Naming counter used for fields of ordinary classes. |
| - int _fieldNameCounter; |
| - |
| - /// The number of fields along the superclass chain that use inheritance |
| - /// based naming, including the ones allocated for this scope. |
| - int get inheritanceBasedFieldNameCounter => _fieldNameCounter; |
| - |
| - /// The number of locally used fields. Depending on the naming source |
| - /// (e.g. inheritance based or globally unique for mixixns) this |
| - /// might be different from [inheritanceBasedFieldNameCounter]. |
| - int get _localFieldNameCounter => _fieldNameCounter; |
| - void set _localFieldNameCounter(int val) { _fieldNameCounter = val; } |
| - |
| - factory _FieldNamingScope.forClass(ClassElement cls, ClassWorld world, |
| - _FieldNamingRegistry registry) { |
| - _FieldNamingScope result = registry.scopes[cls]; |
| - if (result != null) return result; |
| - |
| - if (world.isUsedAsMixin(cls)) { |
| - result = new _MixinFieldNamingScope.mixin(cls, registry); |
| - } else { |
| - if (cls.superclass == null) { |
| - result = new _FieldNamingScope.rootScope(cls, registry); |
| - } else { |
| - _FieldNamingScope superScope = new _FieldNamingScope.forClass( |
| - cls.superclass, world, registry); |
| - if (cls.isMixinApplication) { |
| - result = new _MixinFieldNamingScope.mixedIn(cls, superScope, |
| - registry); |
| - } else { |
| - result = new _FieldNamingScope.inherit(cls, superScope, registry); |
| - } |
| - } |
| + jsAst.Name proposed = _minifiedInstanceFieldPropertyName(element); |
| + if (proposed != null) { |
| + return proposed; |
| } |
| - |
| - cls.forEachInstanceField((cls, field) => result.add(field)); |
| - |
| - registry.scopes[cls] = result; |
| - return result; |
| - } |
| - |
| - factory _FieldNamingScope.forBox(Local box, _FieldNamingRegistry registry) { |
| - return registry.scopes.putIfAbsent(box, |
| - () => new _BoxFieldNamingScope(box, registry)); |
| - } |
| - |
| - _FieldNamingScope.rootScope(this.container, this.registry) |
| - : superScope = null, |
| - _fieldNameCounter = 0; |
| - |
| - _FieldNamingScope.inherit(this.container, this.superScope, this.registry) { |
| - _fieldNameCounter = superScope.inheritanceBasedFieldNameCounter; |
| - } |
| - |
| - /** |
| - * Checks whether [name] is already used in the current scope chain. |
| - */ |
| - _isNameUnused(jsAst.Name name) { |
| - return !names.values.contains(name) && |
| - ((superScope == null) || superScope._isNameUnused(name)); |
| + return super.instanceFieldPropertyName(element); |
| } |
| - |
| - jsAst.Name _nextName() => registry.getName(_localFieldNameCounter++); |
| - |
| - jsAst.Name operator[](Element field) { |
| - jsAst.Name name = names[field]; |
| - if (name == null && superScope != null) return superScope[field]; |
| - return name; |
| - } |
| - |
| - void add(Element field) { |
| - if (names.containsKey(field)) return; |
| - |
| - jsAst.Name value = _nextName(); |
| - assert(invariant(field, _isNameUnused(value))); |
| - names[field] = value; |
| - } |
| - |
| - bool containsField(Element field) => names.containsKey(field); |
| } |
| -/** |
| - * Field names for mixins have two constraints: They need to be unique in the |
| - * hierarchy of each application of a mixin and they need to be the same for |
| - * all applications of a mixin. To achieve this, we use global naming for |
| - * mixins from the same name pool as fields and add a `$` at the end to ensure |
| - * they do not collide with normal field names. The `$` sign is typically used |
| - * as a separator between method names and argument counts and does not appear |
| - * in generated names themselves. |
| - */ |
| -class _MixinFieldNamingScope extends _FieldNamingScope { |
| - int get _localFieldNameCounter => registry.globalCount; |
| - void set _localFieldNameCounter(int val) { registry.globalCount = val; } |
| - |
| - Map<Entity, jsAst.Name> get names => registry.globalNames; |
| - |
| - _MixinFieldNamingScope.mixin(ClassElement cls, _FieldNamingRegistry registry) |
| - : super.rootScope(cls, registry); |
| - |
| - _MixinFieldNamingScope.mixedIn(MixinApplicationElement container, |
| - _FieldNamingScope superScope, _FieldNamingRegistry registry) |
| - : super.inherit(container, superScope, registry); |
| - |
| - jsAst.Name _nextName() { |
| - jsAst.Name proposed = super._nextName(); |
| - return new CompoundName([proposed, Namer._literalDollar]); |
| - } |
| -} |
| - |
| -/** |
| - * [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, _FieldNamingRegistry registry) : |
| - super.rootScope(box, registry); |
| - |
| - bool containsField(_) => true; |
| - |
| - jsAst.Name operator[](Element field) { |
| - if (!names.containsKey(field)) add(field); |
| - return names[field]; |
| - } |
| -} |