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

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

Issue 917083003: Revert "dart2js: Refactoring, documentation, and a few bugfixes in Namer class." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 10 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 | Annotate | Revision Log
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 { 10 class MinifyNamer extends Namer {
11 MinifyNamer(Compiler compiler) : super(compiler) { 11 MinifyNamer(Compiler compiler) : super(compiler) {
12 reserveBackendNames(); 12 reserveBackendNames();
13 fieldRegistry = new _FieldNamingRegistry(this); 13 fieldRegistry = new _FieldNamingRegistry(this);
14 } 14 }
15 15
16 String get isolateName => 'I'; 16 String get isolateName => 'I';
17 String get isolatePropertiesName => 'p'; 17 String get isolatePropertiesName => 'p';
18 bool get shouldMinify => true; 18 bool get shouldMinify => true;
19 19
20 final String getterPrefix = 'g'; 20 final String getterPrefix = 'g';
21 final String setterPrefix = 's'; 21 final String setterPrefix = 's';
22 final String callPrefix = ''; // this will create function names $<n> 22 final String callPrefix = ''; // this will create function names $<n>
23 23
24 final ALPHABET_CHARACTERS = 52; // a-zA-Z. 24 final ALPHABET_CHARACTERS = 52; // a-zA-Z.
25 final ALPHANUMERIC_CHARACTERS = 62; // a-zA-Z0-9. 25 final ALPHANUMERIC_CHARACTERS = 62; // a-zA-Z0-9.
26 26
27 _FieldNamingRegistry fieldRegistry; 27 _FieldNamingRegistry fieldRegistry;
28 28
29 /// You can pass an invalid identifier to this and unlike its non-minifying 29 // You can pass an invalid identifier to this and unlike its non-minifying
30 /// counterpart it will never return the proposedName as the new fresh name. 30 // counterpart it will never return the proposedName as the new fresh name.
31 ///
32 /// [sanitizeForNatives] and [sanitizeForAnnotations] are ignored because the
33 /// minified names will always avoid clashing with annotated names or natives.
34 String getFreshName(String proposedName, 31 String getFreshName(String proposedName,
35 Set<String> usedNames, 32 Set<String> usedNames,
36 Map<String, String> suggestedNames, 33 Map<String, String> suggestedNames,
37 {bool sanitizeForNatives, bool sanitizeForAnnotations}) { 34 {bool ensureSafe: true}) {
38 String freshName; 35 var freshName;
39 String suggestion = suggestedNames[proposedName]; 36 var suggestion = suggestedNames[proposedName];
40 if (suggestion != null && !usedNames.contains(suggestion)) { 37 if (suggestion != null && !usedNames.contains(suggestion)) {
41 freshName = suggestion; 38 freshName = suggestion;
42 } else { 39 } else {
43 freshName = _getUnusedName(proposedName, usedNames, 40 freshName = _getUnusedName(proposedName, usedNames,
44 suggestedNames.values); 41 suggestedNames.values);
45 } 42 }
46 usedNames.add(freshName); 43 usedNames.add(freshName);
47 return freshName; 44 return freshName;
48 } 45 }
49 46
50 String getClosureVariableName(String _, int id) { 47 String getClosureVariableName(String name, int id) {
51 if (id < ALPHABET_CHARACTERS) { 48 if (id < ALPHABET_CHARACTERS) {
52 return new String.fromCharCodes([_letterNumber(id)]); 49 return new String.fromCharCodes([_letterNumber(id)]);
53 } 50 }
54 // Fall back to a slightly longer name. 51 return "${getMappedInstanceName('closure')}_$id";
55 String basename = _disambiguateMember(null, 'closure');
56 return '${basename}_$id';
57 } 52 }
58 53
59 // From issue 7554. These should not be used on objects (as instance 54 // From issue 7554. These should not be used on objects (as instance
60 // variables) because they clash with names from the DOM. However, it is 55 // variables) because they clash with names from the DOM. However, it is
61 // OK to use them as fields, as we only access fields directly if we know 56 // OK to use them as fields, as we only access fields directly if we know
62 // the receiver type. 57 // the receiver type.
63 static const List<String> _reservedNativeProperties = const <String>[ 58 static const _reservedNativeProperties = const <String>[
64 'Q', 'a', 'b', 'c', 'd', 'e', 'f', 'r', 'x', 'y', 'z', 59 'Q', 'a', 'b', 'c', 'd', 'e', 'f', 'r', 'x', 'y', 'z',
65 // 2-letter: 60 // 2-letter:
66 'ch', 'cx', 'cy', 'db', 'dx', 'dy', 'fr', 'fx', 'fy', 'go', 'id', 'k1', 61 'ch', 'cx', 'cy', 'db', 'dx', 'dy', 'fr', 'fx', 'fy', 'go', 'id', 'k1',
67 'k2', 'k3', 'k4', 'r1', 'r2', 'rx', 'ry', 'x1', 'x2', 'y1', 'y2', 62 'k2', 'k3', 'k4', 'r1', 'r2', 'rx', 'ry', 'x1', 'x2', 'y1', 'y2',
68 // 3-letter: 63 // 3-letter:
69 'add', 'all', 'alt', 'arc', 'CCW', 'cmp', 'dir', 'end', 'get', 'in1', 64 'add', 'all', 'alt', 'arc', 'CCW', 'cmp', 'dir', 'end', 'get', 'in1',
70 'in2', 'INT', 'key', 'log', 'low', 'm11', 'm12', 'm13', 'm14', 'm21', 65 'in2', 'INT', 'key', 'log', 'low', 'm11', 'm12', 'm13', 'm14', 'm21',
71 'm22', 'm23', 'm24', 'm31', 'm32', 'm33', 'm34', 'm41', 'm42', 'm43', 66 'm22', 'm23', 'm24', 'm31', 'm32', 'm33', 'm34', 'm41', 'm42', 'm43',
72 'm44', 'max', 'min', 'now', 'ONE', 'put', 'red', 'rel', 'rev', 'RGB', 67 'm44', 'max', 'min', 'now', 'ONE', 'put', 'red', 'rel', 'rev', 'RGB',
73 'sdp', 'set', 'src', 'tag', 'top', 'uid', 'uri', 'url', 'URL', 68 'sdp', 'set', 'src', 'tag', 'top', 'uid', 'uri', 'url', 'URL',
74 // 4-letter: 69 // 4-letter:
75 'abbr', 'atob', 'Attr', 'axes', 'axis', 'back', 'BACK', 'beta', 'bias', 70 'abbr', 'atob', 'Attr', 'axes', 'axis', 'back', 'BACK', 'beta', 'bias',
76 'Blob', 'blue', 'blur', 'BLUR', 'body', 'BOOL', 'BOTH', 'btoa', 'BYTE', 71 'Blob', 'blue', 'blur', 'BLUR', 'body', 'BOOL', 'BOTH', 'btoa', 'BYTE',
77 'cite', 'clip', 'code', 'cols', 'cues', 'data', 'DECR', 'DONE', 'face', 72 'cite', 'clip', 'code', 'cols', 'cues', 'data', 'DECR', 'DONE', 'face',
78 'file', 'File', 'fill', 'find', 'font', 'form', 'gain', 'hash', 'head', 73 'file', 'File', 'fill', 'find', 'font', 'form', 'gain', 'hash', 'head',
79 'high', 'hint', 'host', 'href', 'HRTF', 'IDLE', 'INCR', 'info', 'INIT', 74 'high', 'hint', 'host', 'href', 'HRTF', 'IDLE', 'INCR', 'info', 'INIT',
80 'isId', 'item', 'KEEP', 'kind', 'knee', 'lang', 'left', 'LESS', 'line', 75 'isId', 'item', 'KEEP', 'kind', 'knee', 'lang', 'left', 'LESS', 'line',
81 'link', 'list', 'load', 'loop', 'mode', 'name', 'Node', 'None', 'NONE', 76 'link', 'list', 'load', 'loop', 'mode', 'name', 'Node', 'None', 'NONE',
82 'only', 'open', 'OPEN', 'ping', 'play', 'port', 'rect', 'Rect', 'refX', 77 'only', 'open', 'OPEN', 'ping', 'play', 'port', 'rect', 'Rect', 'refX',
83 'refY', 'RGBA', 'root', 'rows', 'save', 'seed', 'seek', 'self', 'send', 78 'refY', 'RGBA', 'root', 'rows', 'save', 'seed', 'seek', 'self', 'send',
84 'show', 'SINE', 'size', 'span', 'stat', 'step', 'stop', 'tags', 'text', 79 'show', 'SINE', 'size', 'span', 'stat', 'step', 'stop', 'tags', 'text',
85 'Text', 'time', 'type', 'view', 'warn', 'wrap', 'ZERO']; 80 'Text', 'time', 'type', 'view', 'warn', 'wrap', 'ZERO'];
86 81
87 void reserveBackendNames() { 82 void reserveBackendNames() {
88 for (String name in _reservedNativeProperties) { 83 for (var name in _reservedNativeProperties) {
89 if (name.length < 2) { 84 if (name.length < 2) {
90 // Ensure the 1-letter names are disambiguated to the same name. 85 instanceNameMap[name] = name;
91 String disambiguatedName = name;
92 reservePublicMemberName(name, disambiguatedName);
93 } 86 }
94 usedInstanceNames.add(name); 87 usedInstanceNames.add(name);
95 // Getter and setter names are autogenerated by prepending 'g' and 's' to 88 // Getter and setter names are autogenerated by prepending 'g' and 's' to
96 // field names. Therefore there are some field names we don't want to 89 // field names. Therefore there are some field names we don't want to
97 // use. It is implicit in the next line that the banned prefix is 90 // use. It is implicit in the next line that the banned prefix is
98 // only one character. 91 // only one character.
99 if (_hasBannedPrefix(name)) usedInstanceNames.add(name.substring(1)); 92 if (_hasBannedPrefix(name)) usedInstanceNames.add(name.substring(1));
100 } 93 }
101 94
102 // These popular names are present in most programs and deserve 95 // These popular names are present in most programs and deserve
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 Iterable<String> suggestions) { 159 Iterable<String> suggestions) {
167 int hash = _calculateHash(proposedName); 160 int hash = _calculateHash(proposedName);
168 // Avoid very small hashes that won't try many names. 161 // Avoid very small hashes that won't try many names.
169 hash = hash < 1000 ? hash * 314159 : hash; // Yes, it's prime. 162 hash = hash < 1000 ? hash * 314159 : hash; // Yes, it's prime.
170 163
171 // Try other n-character names based on the hash. We try one to three 164 // Try other n-character names based on the hash. We try one to three
172 // character identifiers. For each length we try around 10 different names 165 // character identifiers. For each length we try around 10 different names
173 // in a predictable order determined by the proposed name. This is in order 166 // in a predictable order determined by the proposed name. This is in order
174 // to make the renamer stable: small changes in the input should nornally 167 // to make the renamer stable: small changes in the input should nornally
175 // result in relatively small changes in the output. 168 // result in relatively small changes in the output.
176 for (int n = 1; n <= 3; n++) { 169 for (var n = 1; n <= 3; n++) {
177 int h = hash; 170 int h = hash;
178 while (h > 10) { 171 while (h > 10) {
179 List<int> codes = <int>[_letterNumber(h)]; 172 var codes = <int>[_letterNumber(h)];
180 int h2 = h ~/ ALPHABET_CHARACTERS; 173 int h2 = h ~/ ALPHABET_CHARACTERS;
181 for (int i = 1; i < n; i++) { 174 for (var i = 1; i < n; i++) {
182 codes.add(_alphaNumericNumber(h2)); 175 codes.add(_alphaNumericNumber(h2));
183 h2 ~/= ALPHANUMERIC_CHARACTERS; 176 h2 ~/= ALPHANUMERIC_CHARACTERS;
184 } 177 }
185 final candidate = new String.fromCharCodes(codes); 178 final candidate = new String.fromCharCodes(codes);
186 if (!usedNames.contains(candidate) && 179 if (!usedNames.contains(candidate) &&
187 !jsReserved.contains(candidate) && 180 !jsReserved.contains(candidate) &&
188 !_hasBannedPrefix(candidate) && 181 !_hasBannedPrefix(candidate) &&
189 (n != 1 || !suggestions.contains(candidate))) { 182 (n != 1 || !suggestions.contains(candidate))) {
190 return candidate; 183 return candidate;
191 } 184 }
(...skipping 21 matching lines...) Expand all
213 h &= 0xffffffff; 206 h &= 0xffffffff;
214 h ^= h >> 6; 207 h ^= h >> 6;
215 h &= 0xffffffff; 208 h &= 0xffffffff;
216 } 209 }
217 return h; 210 return h;
218 } 211 }
219 212
220 /// If we can't find a hash based name in the three-letter space, then base 213 /// If we can't find a hash based name in the three-letter space, then base
221 /// the name on a letter and a counter. 214 /// the name on a letter and a counter.
222 String _badName(int hash, Set<String> usedNames) { 215 String _badName(int hash, Set<String> usedNames) {
223 String startLetter = new String.fromCharCodes([_letterNumber(hash)]); 216 var startLetter = new String.fromCharCodes([_letterNumber(hash)]);
224 String name; 217 var name;
225 int i = 0; 218 var i = 0;
226 do { 219 do {
227 name = "$startLetter${i++}"; 220 name = "$startLetter${i++}";
228 } while (usedNames.contains(name)); 221 } while (usedNames.contains(name));
229 // We don't need to check for banned prefix because the name is in the form 222 // We don't need to check for banned prefix because the name is in the form
230 // xnnn, where nnn is a number. There can be no getter or setter called 223 // xnnn, where nnn is a number. There can be no getter or setter called
231 // gnnn since that would imply a numeric field name. 224 // gnnn since that would imply a numeric field name.
232 return name; 225 return name;
233 } 226 }
234 227
235 int _letterNumber(int x) { 228 int _letterNumber(int x) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 if (count >= nameStore.length) { 284 if (count >= nameStore.length) {
292 // The namer usually does not use certain names as they clash with 285 // The namer usually does not use certain names as they clash with
293 // existing properties on JS objects (see [_reservedNativeProperties]). 286 // existing properties on JS objects (see [_reservedNativeProperties]).
294 // However, some of them are really short and safe to use for fields. 287 // However, some of them are really short and safe to use for fields.
295 // Thus, we shortcut the namer to use those first. 288 // Thus, we shortcut the namer to use those first.
296 if (count < MinifyNamer._reservedNativeProperties.length && 289 if (count < MinifyNamer._reservedNativeProperties.length &&
297 MinifyNamer._reservedNativeProperties[count].length <= 2) { 290 MinifyNamer._reservedNativeProperties[count].length <= 2) {
298 nameStore.add(MinifyNamer._reservedNativeProperties[count]); 291 nameStore.add(MinifyNamer._reservedNativeProperties[count]);
299 } else { 292 } else {
300 nameStore.add(namer.getFreshName("field$count", 293 nameStore.add(namer.getFreshName("field$count",
301 namer.usedInstanceNames, namer.suggestedInstanceNames)); 294 namer.usedInstanceNames, namer.suggestedInstanceNames,
295 ensureSafe: true));
302 } 296 }
303 } 297 }
304 298
305 return nameStore[count]; 299 return nameStore[count];
306 } 300 }
307 } 301 }
308 302
309 /** 303 /**
310 * A [_FieldNamingScope] encodes a node in the inheritance tree of the current 304 * A [_FieldNamingScope] encodes a node in the inheritance tree of the current
311 * class hierarchy. The root node typically is the node corresponding to the 305 * class hierarchy. The root node typically is the node corresponding to the
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 Map<Entity, String> get names => registry.globalNames; 415 Map<Entity, String> get names => registry.globalNames;
422 416
423 _MixinFieldNamingScope.mixin(ClassElement cls, _FieldNamingRegistry registry) 417 _MixinFieldNamingScope.mixin(ClassElement cls, _FieldNamingRegistry registry)
424 : super.rootScope(cls, registry); 418 : super.rootScope(cls, registry);
425 419
426 _MixinFieldNamingScope.mixedIn(MixinApplicationElement container, 420 _MixinFieldNamingScope.mixedIn(MixinApplicationElement container,
427 _FieldNamingScope superScope, _FieldNamingRegistry registry) 421 _FieldNamingScope superScope, _FieldNamingRegistry registry)
428 : super.inherit(container, superScope, registry); 422 : super.inherit(container, superScope, registry);
429 423
430 String _nextName() { 424 String _nextName() {
431 String proposed = super._nextName(); 425 var proposed = super._nextName();
432 return proposed + r'$'; 426 return proposed + r'$';
433 } 427 }
434 } 428 }
435 429
436 /** 430 /**
437 * [BoxFieldElement] fields work differently in that they do not belong to an 431 * [BoxFieldElement] fields work differently in that they do not belong to an
438 * actual class but an anonymous box associated to a [Local]. As there is no 432 * actual class but an anonymous box associated to a [Local]. As there is no
439 * inheritance chain, we do not need to compute fields a priori but can assign 433 * inheritance chain, we do not need to compute fields a priori but can assign
440 * names on the fly. 434 * names on the fly.
441 */ 435 */
442 class _BoxFieldNamingScope extends _FieldNamingScope { 436 class _BoxFieldNamingScope extends _FieldNamingScope {
443 _BoxFieldNamingScope(Local box, _FieldNamingRegistry registry) : 437 _BoxFieldNamingScope(Local box, _FieldNamingRegistry registry) :
444 super.rootScope(box, registry); 438 super.rootScope(box, registry);
445 439
446 bool containsField(_) => true; 440 bool containsField(_) => true;
447 441
448 String operator[](Element field) { 442 String operator[](Element field) {
449 if (!names.containsKey(field)) add(field); 443 if (!names.containsKey(field)) add(field);
450 return names[field]; 444 return names[field];
451 } 445 }
452 } 446 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/constant_emitter.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