Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Side by Side Diff: pkg/compiler/lib/src/js_backend/minify_namer.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 with _MinifiedFieldNamer, 10 class MinifyNamer extends Namer
11 _MinifyConstructorBodyNamer, _MinifiedOneShotInterceptorNamer { 11 with
12 _MinifiedFieldNamer,
13 _MinifyConstructorBodyNamer,
14 _MinifiedOneShotInterceptorNamer {
12 MinifyNamer(Compiler compiler) : super(compiler) { 15 MinifyNamer(Compiler compiler) : super(compiler) {
13 reserveBackendNames(); 16 reserveBackendNames();
14 fieldRegistry = new _FieldNamingRegistry(this); 17 fieldRegistry = new _FieldNamingRegistry(this);
15 } 18 }
16 19
17 _FieldNamingRegistry fieldRegistry; 20 _FieldNamingRegistry fieldRegistry;
18 21
19 String get isolateName => 'I'; 22 String get isolateName => 'I';
20 String get isolatePropertiesName => 'p'; 23 String get isolatePropertiesName => 'p';
21 bool get shouldMinify => true; 24 bool get shouldMinify => true;
22 25
23 final String getterPrefix = 'g'; 26 final String getterPrefix = 'g';
24 final String setterPrefix = 's'; 27 final String setterPrefix = 's';
25 final String callPrefix = ''; // this will create function names $<n> 28 final String callPrefix = ''; // this will create function names $<n>
26 29
27 final ALPHABET_CHARACTERS = 52; // a-zA-Z. 30 final ALPHABET_CHARACTERS = 52; // a-zA-Z.
28 final ALPHANUMERIC_CHARACTERS = 62; // a-zA-Z0-9. 31 final ALPHANUMERIC_CHARACTERS = 62; // a-zA-Z0-9.
29 32
30 /// You can pass an invalid identifier to this and unlike its non-minifying 33 /// You can pass an invalid identifier to this and unlike its non-minifying
31 /// counterpart it will never return the proposedName as the new fresh name. 34 /// counterpart it will never return the proposedName as the new fresh name.
32 /// 35 ///
33 /// [sanitizeForNatives] and [sanitizeForAnnotations] are ignored because the 36 /// [sanitizeForNatives] and [sanitizeForAnnotations] are ignored because the
34 /// minified names will always avoid clashing with annotated names or natives. 37 /// minified names will always avoid clashing with annotated names or natives.
35 @override 38 @override
36 String _generateFreshStringForName(String proposedName, 39 String _generateFreshStringForName(String proposedName, NamingScope scope,
37 NamingScope scope, 40 {bool sanitizeForNatives: false, bool sanitizeForAnnotations: false}) {
38 {bool sanitizeForNatives: false,
39 bool sanitizeForAnnotations: false}) {
40 String freshName; 41 String freshName;
41 String suggestion = scope.suggestName(proposedName); 42 String suggestion = scope.suggestName(proposedName);
42 if (suggestion != null && scope.isUnused(suggestion)) { 43 if (suggestion != null && scope.isUnused(suggestion)) {
43 freshName = suggestion; 44 freshName = suggestion;
44 } else { 45 } else {
45 freshName = _getUnusedName(proposedName, scope); 46 freshName = _getUnusedName(proposedName, scope);
46 } 47 }
47 scope.registerUse(freshName); 48 scope.registerUse(freshName);
48 return freshName; 49 return freshName;
49 } 50 }
50 51
51 // From issue 7554. These should not be used on objects (as instance 52 // From issue 7554. These should not be used on objects (as instance
52 // variables) because they clash with names from the DOM. However, it is 53 // variables) because they clash with names from the DOM. However, it is
53 // OK to use them as fields, as we only access fields directly if we know 54 // OK to use them as fields, as we only access fields directly if we know
54 // the receiver type. 55 // the receiver type.
55 static const List<String> _reservedNativeProperties = const <String>[ 56 static const List<String> _reservedNativeProperties = const <String>[
56 'a', 'b', 'c', 'd', 'e', 'f', 'r', 'x', 'y', 'z', 'Q', 57 'a', 'b', 'c', 'd', 'e', 'f', 'r', 'x', 'y', 'z', 'Q',
57 // 2-letter: 58 // 2-letter:
58 'ch', 'cx', 'cy', 'db', 'dx', 'dy', 'fr', 'fx', 'fy', 'go', 'id', 'k1', 59 'ch', 'cx', 'cy', 'db', 'dx', 'dy', 'fr', 'fx', 'fy', 'go', 'id', 'k1',
59 'k2', 'k3', 'k4', 'r1', 'r2', 'rx', 'ry', 'x1', 'x2', 'y1', 'y2', 60 'k2', 'k3', 'k4', 'r1', 'r2', 'rx', 'ry', 'x1', 'x2', 'y1', 'y2',
60 // 3-letter: 61 // 3-letter:
61 'add', 'all', 'alt', 'arc', 'CCW', 'cmp', 'dir', 'end', 'get', 'in1', 62 'add', 'all', 'alt', 'arc', 'CCW', 'cmp', 'dir', 'end', 'get', 'in1',
62 'in2', 'INT', 'key', 'log', 'low', 'm11', 'm12', 'm13', 'm14', 'm21', 63 'in2', 'INT', 'key', 'log', 'low', 'm11', 'm12', 'm13', 'm14', 'm21',
63 'm22', 'm23', 'm24', 'm31', 'm32', 'm33', 'm34', 'm41', 'm42', 'm43', 64 'm22', 'm23', 'm24', 'm31', 'm32', 'm33', 'm34', 'm41', 'm42', 'm43',
64 'm44', 'max', 'min', 'now', 'ONE', 'put', 'red', 'rel', 'rev', 'RGB', 65 'm44', 'max', 'min', 'now', 'ONE', 'put', 'red', 'rel', 'rev', 'RGB',
65 'sdp', 'set', 'src', 'tag', 'top', 'uid', 'uri', 'url', 'URL', 66 'sdp', 'set', 'src', 'tag', 'top', 'uid', 'uri', 'url', 'URL',
66 // 4-letter: 67 // 4-letter:
67 'abbr', 'atob', 'Attr', 'axes', 'axis', 'back', 'BACK', 'beta', 'bias', 68 'abbr', 'atob', 'Attr', 'axes', 'axis', 'back', 'BACK', 'beta', 'bias',
68 'Blob', 'blue', 'blur', 'BLUR', 'body', 'BOOL', 'BOTH', 'btoa', 'BYTE', 69 'Blob', 'blue', 'blur', 'BLUR', 'body', 'BOOL', 'BOTH', 'btoa', 'BYTE',
69 'cite', 'clip', 'code', 'cols', 'cues', 'data', 'DECR', 'DONE', 'face', 70 'cite', 'clip', 'code', 'cols', 'cues', 'data', 'DECR', 'DONE', 'face',
70 'file', 'File', 'fill', 'find', 'font', 'form', 'gain', 'hash', 'head', 71 'file', 'File', 'fill', 'find', 'font', 'form', 'gain', 'hash', 'head',
71 'high', 'hint', 'host', 'href', 'HRTF', 'IDLE', 'INCR', 'info', 'INIT', 72 'high', 'hint', 'host', 'href', 'HRTF', 'IDLE', 'INCR', 'info', 'INIT',
72 'isId', 'item', 'KEEP', 'kind', 'knee', 'lang', 'left', 'LESS', 'line', 73 'isId', 'item', 'KEEP', 'kind', 'knee', 'lang', 'left', 'LESS', 'line',
73 'link', 'list', 'load', 'loop', 'mode', 'name', 'Node', 'None', 'NONE', 74 'link', 'list', 'load', 'loop', 'mode', 'name', 'Node', 'None', 'NONE',
74 'only', 'open', 'OPEN', 'ping', 'play', 'port', 'rect', 'Rect', 'refX', 75 'only', 'open', 'OPEN', 'ping', 'play', 'port', 'rect', 'Rect', 'refX',
75 'refY', 'RGBA', 'root', 'rows', 'save', 'seed', 'seek', 'self', 'send', 76 'refY', 'RGBA', 'root', 'rows', 'save', 'seed', 'seek', 'self', 'send',
76 'show', 'SINE', 'size', 'span', 'stat', 'step', 'stop', 'tags', 'text', 77 'show', 'SINE', 'size', 'span', 'stat', 'step', 'stop', 'tags', 'text',
77 'Text', 'time', 'type', 'view', 'warn', 'wrap', 'ZERO']; 78 'Text', 'time', 'type', 'view', 'warn', 'wrap', 'ZERO'
79 ];
78 80
79 void reserveBackendNames() { 81 void reserveBackendNames() {
80 for (String name in _reservedNativeProperties) { 82 for (String name in _reservedNativeProperties) {
81 if (name.length < 2) { 83 if (name.length < 2) {
82 // Ensure the 1-letter names are disambiguated to the same name. 84 // Ensure the 1-letter names are disambiguated to the same name.
83 String disambiguatedName = name; 85 String disambiguatedName = name;
84 reservePublicMemberName(name, disambiguatedName); 86 reservePublicMemberName(name, disambiguatedName);
85 } 87 }
86 instanceScope.registerUse(name); 88 instanceScope.registerUse(name);
87 // Getter and setter names are autogenerated by prepending 'g' and 's' to 89 // Getter and setter names are autogenerated by prepending 'g' and 's' to
88 // field names. Therefore there are some field names we don't want to 90 // field names. Therefore there are some field names we don't want to
89 // use. It is implicit in the next line that the banned prefix is 91 // use. It is implicit in the next line that the banned prefix is
90 // only one character. 92 // only one character.
91 if (_hasBannedPrefix(name)) { 93 if (_hasBannedPrefix(name)) {
92 instanceScope.registerUse(name.substring(1)); 94 instanceScope.registerUse(name.substring(1));
93 } 95 }
94 } 96 }
95 97
96 // These popular names are present in most programs and deserve 98 // These popular names are present in most programs and deserve
97 // single character minified names. We could determine the popular names 99 // single character minified names. We could determine the popular names
98 // individually per program, but that would mean that the output of the 100 // individually per program, but that would mean that the output of the
99 // minifier was less stable from version to version of the program being 101 // minifier was less stable from version to version of the program being
100 // minified. 102 // minified.
101 _populateSuggestedNames( 103 _populateSuggestedNames(instanceScope, const <String>[
102 instanceScope, 104 r'$add',
103 const <String>[ 105 r'add$1',
104 r'$add', r'add$1', r'$and', 106 r'$and',
105 r'$or', 107 r'$or',
106 r'current', r'$shr', r'$eq', r'$ne', 108 r'current',
107 r'$index', r'$indexSet', 109 r'$shr',
108 r'$xor', r'clone$0', 110 r'$eq',
109 r'iterator', r'length', 111 r'$ne',
110 r'$lt', r'$gt', r'$le', r'$ge', 112 r'$index',
111 r'moveNext$0', r'node', r'on', r'$negate', r'push', r'self', 113 r'$indexSet',
112 r'start', r'target', r'$shl', r'value', r'width', r'style', 114 r'$xor',
113 r'noSuchMethod$1', r'$mul', r'$div', r'$sub', r'$not', r'$mod', 115 r'clone$0',
114 r'$tdiv', r'toString$0']); 116 r'iterator',
117 r'length',
118 r'$lt',
119 r'$gt',
120 r'$le',
121 r'$ge',
122 r'moveNext$0',
123 r'node',
124 r'on',
125 r'$negate',
126 r'push',
127 r'self',
128 r'start',
129 r'target',
130 r'$shl',
131 r'value',
132 r'width',
133 r'style',
134 r'noSuchMethod$1',
135 r'$mul',
136 r'$div',
137 r'$sub',
138 r'$not',
139 r'$mod',
140 r'$tdiv',
141 r'toString$0'
142 ]);
115 143
116 _populateSuggestedNames( 144 _populateSuggestedNames(globalScope, const <String>[
117 globalScope, 145 r'Object',
118 const <String>[ 146 'wrapException',
119 r'Object', 'wrapException', r'$eq', r'S', r'ioore', 147 r'$eq',
120 r'UnsupportedError$', r'length', r'$sub', 148 r'S',
121 r'$add', r'$gt', r'$ge', r'$lt', r'$le', r'add', 149 r'ioore',
122 r'iae', 150 r'UnsupportedError$',
123 r'ArgumentError$', r'BoundClosure', r'Closure', r'StateError$', 151 r'length',
124 r'getInterceptor', r'max', r'$mul', 152 r'$sub',
125 r'Map', r'Key_Key', r'$div', 153 r'$add',
126 r'List_List$from', 154 r'$gt',
127 r'LinkedHashMap_LinkedHashMap$_empty', 155 r'$ge',
128 r'LinkedHashMap_LinkedHashMap$_literal', 156 r'$lt',
129 r'min', 157 r'$le',
130 r'RangeError$value', r'JSString', r'JSNumber', 158 r'add',
131 r'JSArray', r'createInvocationMirror', r'String', 159 r'iae',
132 r'setRuntimeTypeInfo', r'createRuntimeType' 160 r'ArgumentError$',
133 ]); 161 r'BoundClosure',
162 r'Closure',
163 r'StateError$',
164 r'getInterceptor',
165 r'max',
166 r'$mul',
167 r'Map',
168 r'Key_Key',
169 r'$div',
170 r'List_List$from',
171 r'LinkedHashMap_LinkedHashMap$_empty',
172 r'LinkedHashMap_LinkedHashMap$_literal',
173 r'min',
174 r'RangeError$value',
175 r'JSString',
176 r'JSNumber',
177 r'JSArray',
178 r'createInvocationMirror',
179 r'String',
180 r'setRuntimeTypeInfo',
181 r'createRuntimeType'
182 ]);
134 } 183 }
135 184
136 void _populateSuggestedNames(NamingScope scope, 185 void _populateSuggestedNames(NamingScope scope, List<String> suggestions) {
137 List<String> suggestions) {
138 int c = $a - 1; 186 int c = $a - 1;
139 String letter; 187 String letter;
140 for (String name in suggestions) { 188 for (String name in suggestions) {
141 do { 189 do {
142 assert(c != $Z); 190 assert(c != $Z);
143 c = (c == $z) ? $A : c + 1; 191 c = (c == $z) ? $A : c + 1;
144 letter = new String.fromCharCodes([c]); 192 letter = new String.fromCharCodes([c]);
145 } while (_hasBannedPrefix(letter) || scope.isUsed(letter)); 193 } while (_hasBannedPrefix(letter) || scope.isUsed(letter));
146 assert(!scope.hasSuggestion(name)); 194 assert(!scope.hasSuggestion(name));
147 scope.addSuggestion(name, letter); 195 scope.addSuggestion(name, letter);
148 } 196 }
149 } 197 }
150 198
151
152 // This gets a minified name based on a hash of the proposed name. This 199 // This gets a minified name based on a hash of the proposed name. This
153 // is slightly less efficient than just getting the next name in a series, 200 // is slightly less efficient than just getting the next name in a series,
154 // but it means that small changes in the input program will give smallish 201 // but it means that small changes in the input program will give smallish
155 // changes in the output, which can be useful for diffing etc. 202 // changes in the output, which can be useful for diffing etc.
156 String _getUnusedName(String proposedName, NamingScope scope) { 203 String _getUnusedName(String proposedName, NamingScope scope) {
157 int hash = _calculateHash(proposedName); 204 int hash = _calculateHash(proposedName);
158 // Avoid very small hashes that won't try many names. 205 // Avoid very small hashes that won't try many names.
159 hash = hash < 1000 ? hash * 314159 : hash; // Yes, it's prime. 206 hash = hash < 1000 ? hash * 314159 : hash; // Yes, it's prime.
160 207
161 // Try other n-character names based on the hash. We try one to three 208 // Try other n-character names based on the hash. We try one to three
162 // character identifiers. For each length we try around 10 different names 209 // character identifiers. For each length we try around 10 different names
163 // in a predictable order determined by the proposed name. This is in order 210 // in a predictable order determined by the proposed name. This is in order
164 // to make the renamer stable: small changes in the input should nornally 211 // to make the renamer stable: small changes in the input should nornally
165 // result in relatively small changes in the output. 212 // result in relatively small changes in the output.
166 for (int n = 1; n <= 3; n++) { 213 for (int n = 1; n <= 3; n++) {
167 int h = hash; 214 int h = hash;
168 while (h > 10) { 215 while (h > 10) {
169 List<int> codes = <int>[_letterNumber(h)]; 216 List<int> codes = <int>[_letterNumber(h)];
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 315
269 int get numberOfConstructors => _constructors.length; 316 int get numberOfConstructors => _constructors.length;
270 317
271 _ConstructorBodyNamingScope _superScope; 318 _ConstructorBodyNamingScope _superScope;
272 319
273 _ConstructorBodyNamingScope.rootScope(ClassElement cls) 320 _ConstructorBodyNamingScope.rootScope(ClassElement cls)
274 : _superScope = null, 321 : _superScope = null,
275 _startIndex = 0, 322 _startIndex = 0,
276 _constructors = cls.constructors.toList(growable: false); 323 _constructors = cls.constructors.toList(growable: false);
277 324
278 _ConstructorBodyNamingScope.forClass(ClassElement cls, 325 _ConstructorBodyNamingScope.forClass(
279 _ConstructorBodyNamingScope superScope) 326 ClassElement cls, _ConstructorBodyNamingScope superScope)
280 : _superScope = superScope, 327 : _superScope = superScope,
281 _startIndex = superScope._startIndex + superScope.numberOfConstructors, 328 _startIndex = superScope._startIndex + superScope.numberOfConstructors,
282 _constructors = cls.constructors.toList(growable: false); 329 _constructors = cls.constructors.toList(growable: false);
283 330
284 // Mixin Applications have constructors but we never generate code for them, 331 // Mixin Applications have constructors but we never generate code for them,
285 // so they do not count in the inheritance chain. 332 // so they do not count in the inheritance chain.
286 _ConstructorBodyNamingScope.forMixinApplication(ClassElement cls, 333 _ConstructorBodyNamingScope.forMixinApplication(
287 _ConstructorBodyNamingScope superScope) 334 ClassElement cls, _ConstructorBodyNamingScope superScope)
288 : _superScope = superScope, 335 : _superScope = superScope,
289 _startIndex = superScope._startIndex + superScope.numberOfConstructors, 336 _startIndex = superScope._startIndex + superScope.numberOfConstructors,
290 _constructors = const []; 337 _constructors = const [];
291 338
292 factory _ConstructorBodyNamingScope(ClassElement cls, 339 factory _ConstructorBodyNamingScope(ClassElement cls,
293 Map<ClassElement, _ConstructorBodyNamingScope> registry) { 340 Map<ClassElement, _ConstructorBodyNamingScope> registry) {
294 return registry.putIfAbsent(cls, () { 341 return registry.putIfAbsent(cls, () {
295 if (cls.superclass == null) { 342 if (cls.superclass == null) {
296 return new _ConstructorBodyNamingScope.rootScope(cls); 343 return new _ConstructorBodyNamingScope.rootScope(cls);
297 } else if (cls.isMixinApplication) { 344 } else if (cls.isMixinApplication) {
298 return new _ConstructorBodyNamingScope.forMixinApplication(cls, 345 return new _ConstructorBodyNamingScope.forMixinApplication(
299 new _ConstructorBodyNamingScope(cls.superclass, registry)); 346 cls, new _ConstructorBodyNamingScope(cls.superclass, registry));
300 } else { 347 } else {
301 return new _ConstructorBodyNamingScope.forClass(cls, 348 return new _ConstructorBodyNamingScope.forClass(
302 new _ConstructorBodyNamingScope(cls.superclass, registry)); 349 cls, new _ConstructorBodyNamingScope(cls.superclass, registry));
303 } 350 }
304 }); 351 });
305 } 352 }
306 353
307 String constructorBodyKeyFor(ConstructorBodyElement body) { 354 String constructorBodyKeyFor(ConstructorBodyElement body) {
308 int position = _constructors.indexOf(body.constructor); 355 int position = _constructors.indexOf(body.constructor);
309 assert(invariant(body, position >= 0, message: "constructor body missing")); 356 assert(invariant(body, position >= 0, message: "constructor body missing"));
310 return "@constructorBody@${_startIndex + position}"; 357 return "@constructorBody@${_startIndex + position}";
311 } 358 }
312 } 359 }
313 360
314 abstract class _MinifyConstructorBodyNamer implements Namer { 361 abstract class _MinifyConstructorBodyNamer implements Namer {
315 Map<ClassElement, _ConstructorBodyNamingScope> _constructorBodyScopes = 362 Map<ClassElement, _ConstructorBodyNamingScope> _constructorBodyScopes =
316 new Map<ClassElement, _ConstructorBodyNamingScope>(); 363 new Map<ClassElement, _ConstructorBodyNamingScope>();
317 364
318 @override 365 @override
319 jsAst.Name constructorBodyName(FunctionElement method) { 366 jsAst.Name constructorBodyName(FunctionElement method) {
320 _ConstructorBodyNamingScope scope = 367 _ConstructorBodyNamingScope scope = new _ConstructorBodyNamingScope(
321 new _ConstructorBodyNamingScope(method.enclosingClass, 368 method.enclosingClass, _constructorBodyScopes);
322 _constructorBodyScopes);
323 String key = scope.constructorBodyKeyFor(method); 369 String key = scope.constructorBodyKeyFor(method);
324 return _disambiguateMemberByKey(key, 370 return _disambiguateMemberByKey(
325 () => _proposeNameForConstructorBody(method)); 371 key, () => _proposeNameForConstructorBody(method));
326 } 372 }
327 } 373 }
328 374
329 abstract class _MinifiedOneShotInterceptorNamer implements Namer { 375 abstract class _MinifiedOneShotInterceptorNamer implements Namer {
330 /// Property name used for the one-shot interceptor method for the given 376 /// Property name used for the one-shot interceptor method for the given
331 /// [selector] and return-type specialization. 377 /// [selector] and return-type specialization.
332 @override 378 @override
333 jsAst.Name nameForGetOneShotInterceptor(Selector selector, 379 jsAst.Name nameForGetOneShotInterceptor(
334 Iterable<ClassElement> classes) { 380 Selector selector, Iterable<ClassElement> classes) {
335 String root = selector.isOperator 381 String root = selector.isOperator
336 ? operatorNameToIdentifier(selector.name) 382 ? operatorNameToIdentifier(selector.name)
337 : privateName(selector.memberName); 383 : privateName(selector.memberName);
338 String prefix = selector.isGetter 384 String prefix =
339 ? r"$get" 385 selector.isGetter ? r"$get" : selector.isSetter ? r"$set" : "";
340 : selector.isSetter ? r"$set" : ""; 386 String callSuffix = selector.isCall
341 String callSuffix = 387 ? callSuffixForStructure(selector.callStructure).join()
342 selector.isCall ? callSuffixForStructure(selector.callStructure).join() 388 : "";
343 : "";
344 String suffix = suffixForGetInterceptor(classes); 389 String suffix = suffixForGetInterceptor(classes);
345 String fullName = "\$intercepted$prefix\$$root$callSuffix\$$suffix"; 390 String fullName = "\$intercepted$prefix\$$root$callSuffix\$$suffix";
346 return _disambiguateInternalGlobal(fullName); 391 return _disambiguateInternalGlobal(fullName);
347 } 392 }
348 } 393 }
349
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart ('k') | pkg/compiler/lib/src/js_backend/namer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698