Chromium Code Reviews| Index: pkg/compiler/lib/src/js_backend/frequency_namer.dart |
| diff --git a/pkg/compiler/lib/src/js_backend/frequency_namer.dart b/pkg/compiler/lib/src/js_backend/frequency_namer.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..79c9874ab9b44604fdfea683765287faeb6725b1 |
| --- /dev/null |
| +++ b/pkg/compiler/lib/src/js_backend/frequency_namer.dart |
| @@ -0,0 +1,132 @@ |
| +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +part of js_backend; |
| + |
| +class FrequencyBasedNamer extends Namer with _MinifiedFieldNamer, |
| + _MinifiedOneShotInterceptorNamer implements jsAst.TokenFinalizer { |
| + _FieldNamingRegistry fieldRegistry; |
| + List<TokenName> tokens = new List<TokenName>(); |
| + |
| + Map<NamingScope, TokenScope> _tokenScopes = |
| + new Maplet<NamingScope, TokenScope>(); |
| + |
| + // Some basic settings for smaller names |
| + String get isolateName => 'I'; |
| + String get isolatePropertiesName => 'p'; |
| + bool get shouldMinify => true; |
| + |
| + final String getterPrefix = 'g'; |
| + final String setterPrefix = 's'; |
| + final String callPrefix = ''; // this will create function names $<n> |
| + |
| + FrequencyBasedNamer(Compiler compiler) : super(compiler) { |
| + fieldRegistry = new _FieldNamingRegistry(this); |
| + } |
| + |
| + TokenScope newScopeFor(NamingScope scope) { |
| + if (scope == NamingScope.instance) { |
| + Set<String> illegalNames = new Set<String>(); |
| + for (String illegal in MinifyNamer._reservedNativeProperties) { |
| + illegalNames.add(illegal); |
| + if (MinifyNamer._hasBannedPrefix(illegal)) { |
| + illegalNames.add(illegal.substring(1)); |
| + } |
| + } |
| + return new TokenScope(illegalNames); |
| + } else { |
| + return new TokenScope(); |
| + } |
| + } |
| + |
| + @override |
| + jsAst.Name getFreshName(NamingScope scope, String proposedName, |
| + {bool sanitizeForNatives: false, |
| + bool sanitizeForAnnotations: false}) { |
| + // Grab the scope for this token |
| + TokenScope tokenScope = _tokenScopes.putIfAbsent(scope, |
| + () => newScopeFor(scope)); |
| + |
| + // Get the name the normal namer would use as a key. |
| + String proposed = _generateFreshStringForName(proposedName, |
| + getUsedNames(scope), |
| + getSuggestedNames(scope), |
| + sanitizeForNatives: |
| + sanitizeForNatives, |
| + sanitizeForAnnotations: |
| + sanitizeForAnnotations); |
| + |
| + TokenName name = new TokenName(tokenScope, proposed); |
| + tokens.add(name); |
| + return name; |
| + } |
| + |
| + @override |
| + jsAst.Name instanceFieldPropertyName(Element element) { |
| + jsAst.Name proposed = _minifiedInstanceFieldPropertyName(element); |
| + if (proposed != null) { |
| + return proposed; |
| + } |
| + return super.instanceFieldPropertyName(element); |
| + } |
| + |
| + @override |
| + void finalizeTokens() { |
| + int compareReferenceCount(TokenName a, TokenName b) { |
| + int result = b._rc - a._rc; |
| + if (result == 0) result = a._proposed.compareTo(b._proposed); |
| + return result; |
| + } |
| + |
| + List<TokenName> usedNames = |
| + tokens.where((TokenName a) => a._rc > 0).toList(); |
| + usedNames.sort(compareReferenceCount); |
| + usedNames.forEach((TokenName token) => token.finalize()); |
| + } |
| +} |
| + |
| +class TokenScope { |
| + List<int> _nextName = [$a]; |
| + final Set<String> illegalNames; |
| + |
| + TokenScope([this.illegalNames = const ImmutableEmptySet()]); |
| + |
| + bool _incrementPosition(int pos) { |
|
sra1
2015/07/01 04:11:09
Add a comment to say what sequence this generates.
herhut
2015/07/02 08:54:51
Done.
|
| + bool overflow = false; |
| + if (pos < 0) return true; |
| + int value = _nextName[pos]; |
| + if (value == $_) { |
| + value = $0; |
| + } else if (value == $9) { |
| + value = $a; |
| + } else if (value == $z) { |
| + value = $A; |
| + } else if (value == $Z) { |
| + overflow = _incrementPosition(pos - 1); |
| + value = (pos > 0) ? $_ : $a; |
| + } else { |
| + value++; |
| + } |
| + _nextName[pos] = value; |
| + return overflow; |
| + } |
| + |
| + _incrementName() { |
| + if (_incrementPosition(_nextName.length - 1)) { |
| + _nextName.add($a); |
| + } |
| + } |
| + |
| + String getNextName() { |
| + String proposal; |
| + do { |
| + proposal = new String.fromCharCodes(_nextName); |
| + _incrementName(); |
| + } while (MinifyNamer._hasBannedPrefix(proposal) || |
| + illegalNames.contains(proposal)); |
| + |
| + return proposal; |
| + } |
| +} |
| + |