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

Side by Side Diff: pkg/compiler/lib/src/js_emitter/old_emitter/nsm_emitter.dart

Issue 1211503003: dart2js: Fix nsm emitter in non-minified mode. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Comments Created 5 years, 6 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 dart2js.js_emitter; 5 part of dart2js.js_emitter;
6 6
7 class NsmEmitter extends CodeEmitterHelper { 7 class NsmEmitter extends CodeEmitterHelper {
8 final List<Selector> trivialNsmHandlers = <Selector>[]; 8 final List<Selector> trivialNsmHandlers = <Selector>[];
9 9
10 /// If this is true then we can generate the noSuchMethod handlers at startup 10 /// If this is true then we can generate the noSuchMethod handlers at startup
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 * decoding the base 88 numbers would overflow JavaScript's puny integers. 115 * decoding the base 88 numbers would overflow JavaScript's puny integers.
116 * 116 *
117 * There are some selectors that have a special calling convention (because 117 * There are some selectors that have a special calling convention (because
118 * they are called with the receiver as the first argument). They need a 118 * they are called with the receiver as the first argument). They need a
119 * slightly different noSuchMethod handler, so we handle these first. 119 * slightly different noSuchMethod handler, so we handle these first.
120 */ 120 */
121 List<jsAst.Statement> buildTrivialNsmHandlers() { 121 List<jsAst.Statement> buildTrivialNsmHandlers() {
122 List<jsAst.Statement> statements = <jsAst.Statement>[]; 122 List<jsAst.Statement> statements = <jsAst.Statement>[];
123 if (trivialNsmHandlers.length == 0) return statements; 123 if (trivialNsmHandlers.length == 0) return statements;
124 124
125 // Find out how many selectors there are with the special calling
126 // convention.
127 bool hasSpecialCallingConvention(Selector selector) {
128 return backend.isInterceptedName(selector.name);
129 }
130 Iterable<Selector> specialSelectors = trivialNsmHandlers.where(
131 (Selector s) => backend.isInterceptedName(s.name));
132 Iterable<Selector> ordinarySelectors = trivialNsmHandlers.where(
133 (Selector s) => !backend.isInterceptedName(s.name));
134
135 // Get the short names (JS names, perhaps minified).
136 Iterable<jsAst.Name> specialShorts =
137 specialSelectors.map(namer.invocationMirrorInternalName);
138 Iterable<jsAst.Name> ordinaryShorts =
139 ordinarySelectors.map(namer.invocationMirrorInternalName);
140
141 bool minify = compiler.enableMinification; 125 bool minify = compiler.enableMinification;
142 bool useDiffEncoding = minify && trivialNsmHandlers.length > 30; 126 bool useDiffEncoding = minify && trivialNsmHandlers.length > 30;
143 127
144 jsAst.Expression diffEncoding = new _DiffEncodedListOfNames( 128 // Find out how many selectors there are with the special calling
145 [specialShorts, ordinaryShorts], 129 // convention.
146 useDiffEncoding); 130 Iterable<Selector> interceptedSelectors = trivialNsmHandlers.where(
131 (Selector s) => backend.isInterceptedName(s.name));
132 Iterable<Selector> ordinarySelectors = trivialNsmHandlers.where(
133 (Selector s) => !backend.isInterceptedName(s.name));
147 134
135 // Get the short names (JS names, perhaps minified).
136 Iterable<jsAst.Name> interceptedShorts =
137 interceptedSelectors.map(namer.invocationMirrorInternalName);
138 Iterable<jsAst.Name> ordinaryShorts =
139 ordinarySelectors.map(namer.invocationMirrorInternalName);
140
141 jsAst.Expression sortedShorts;
142 Iterable<String> sortedLongs;
143 if (useDiffEncoding) {
144 assert(minify);
145 sortedShorts = new _DiffEncodedListOfNames(
146 [interceptedShorts, ordinaryShorts]);
147 } else {
148 Iterable<Selector> sorted =
149 [interceptedSelectors, ordinarySelectors].expand((e) => (e));
150 sortedShorts = js.concatenateStrings(
151 js.joinLiterals(
152 sorted.map(namer.invocationMirrorInternalName),
153 js.stringPart(",")),
154 addQuotes: true);
155
156 if (!minify) {
157 sortedLongs = sorted.map((selector) =>
158 selector.invocationMirrorMemberName);
159 }
160 }
148 // Startup code that loops over the method names and puts handlers on the 161 // Startup code that loops over the method names and puts handlers on the
149 // Object class to catch noSuchMethod invocations. 162 // Object class to catch noSuchMethod invocations.
150 ClassElement objectClass = compiler.objectClass; 163 ClassElement objectClass = compiler.objectClass;
151 jsAst.Expression createInvocationMirror = backend.emitter 164 jsAst.Expression createInvocationMirror = backend.emitter
152 .staticFunctionAccess(backend.getCreateInvocationMirror()); 165 .staticFunctionAccess(backend.getCreateInvocationMirror());
153 if (useDiffEncoding) { 166 if (useDiffEncoding) {
154 statements.add(js.statement('''{ 167 statements.add(js.statement('''{
155 var objectClassObject = processedClasses.collected[#objectClass], 168 var objectClassObject = processedClasses.collected[#objectClass],
156 nameSequences = #diffEncoding.split("."), 169 nameSequences = #diffEncoding.split("."),
157 shortNames = []; 170 shortNames = [];
(...skipping 27 matching lines...) Expand all
185 codes.unshift(${$HASH} + remaining % 88); 198 codes.unshift(${$HASH} + remaining % 88);
186 } 199 }
187 shortNames.push( 200 shortNames.push(
188 String.fromCharCode.apply(String, codes)); 201 String.fromCharCode.apply(String, codes));
189 } 202 }
190 if (sequence.length > 1) { 203 if (sequence.length > 1) {
191 Array.prototype.push.apply(shortNames, sequence.shift()); 204 Array.prototype.push.apply(shortNames, sequence.shift());
192 } 205 }
193 } 206 }
194 }''', {'objectClass': js.quoteName(namer.className(objectClass)), 207 }''', {'objectClass': js.quoteName(namer.className(objectClass)),
195 'diffEncoding': diffEncoding})); 208 'diffEncoding': sortedShorts}));
196 } else { 209 } else {
197 // No useDiffEncoding version. 210 // No useDiffEncoding version.
198 Iterable<String> longs = trivialNsmHandlers.map((selector) =>
199 selector.invocationMirrorMemberName);
200 statements.add(js.statement( 211 statements.add(js.statement(
201 'var objectClassObject = processedClasses.collected[#objectClass],' 212 'var objectClassObject = processedClasses.collected[#objectClass],'
202 ' shortNames = #diffEncoding.split(",")', 213 ' shortNames = #diffEncoding.split(",")',
203 {'objectClass': js.quoteName(namer.className(objectClass)), 214 {'objectClass': js.quoteName(namer.className(objectClass)),
204 'diffEncoding': diffEncoding})); 215 'diffEncoding': sortedShorts}));
205 if (!minify) { 216 if (!minify) {
206 statements.add(js.statement('var longNames = #longs.split(",")', 217 statements.add(js.statement('var longNames = #longs.split(",")',
207 {'longs': js.string(longs.join(','))})); 218 {'longs': js.string(sortedLongs.join(','))}));
208 } 219 }
209 statements.add(js.statement( 220 statements.add(js.statement(
210 'if (objectClassObject instanceof Array)' 221 'if (objectClassObject instanceof Array)'
211 ' objectClassObject = objectClassObject[1];')); 222 ' objectClassObject = objectClassObject[1];'));
212 } 223 }
213 224
214 dynamic isIntercepted = // jsAst.Expression or bool. 225 dynamic isIntercepted = // jsAst.Expression or bool.
215 specialSelectors.isEmpty 226 interceptedSelectors.isEmpty
216 ? false 227 ? false
217 : ordinarySelectors.isEmpty 228 : ordinarySelectors.isEmpty
218 ? true 229 ? true
219 : js('j < #', js.number(specialSelectors.length)); 230 : js('j < #', js.number(interceptedSelectors.length));
220 231
221 statements.add(js.statement(''' 232 statements.add(js.statement('''
222 // If we are loading a deferred library the object class will not be in 233 // If we are loading a deferred library the object class will not be in
223 // the collectedClasses so objectClassObject is undefined, and we skip 234 // the collectedClasses so objectClassObject is undefined, and we skip
224 // setting up the names. 235 // setting up the names.
225 if (objectClassObject) { 236 if (objectClassObject) {
226 for (var j = 0; j < shortNames.length; j++) { 237 for (var j = 0; j < shortNames.length; j++) {
227 var type = 0; 238 var type = 0;
228 var shortName = shortNames[j]; 239 var shortName = shortNames[j];
229 if (shortName[0] == "${namer.getterPrefix[0]}") type = 1; 240 if (shortName[0] == "${namer.getterPrefix[0]}") type = 1;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 } 287 }
277 288
278 /// When pretty printed, this node computes a diff-encoded string for the list 289 /// When pretty printed, this node computes a diff-encoded string for the list
279 /// of given names. 290 /// of given names.
280 /// 291 ///
281 /// See [buildTrivialNsmHandlers]. 292 /// See [buildTrivialNsmHandlers].
282 class _DiffEncodedListOfNames extends jsAst.DeferredString 293 class _DiffEncodedListOfNames extends jsAst.DeferredString
283 implements AstContainer { 294 implements AstContainer {
284 String _cachedValue; 295 String _cachedValue;
285 jsAst.ArrayInitializer ast; 296 jsAst.ArrayInitializer ast;
286 bool useDiffEncoding;
287 297
288 _DiffEncodedListOfNames(Iterable<Iterable<jsAst.Name>> names, 298 _DiffEncodedListOfNames(Iterable<Iterable<jsAst.Name>> names) {
289 this.useDiffEncoding) {
290 // Store the names in ArrayInitializer nodes to make them discoverable 299 // Store the names in ArrayInitializer nodes to make them discoverable
291 // by traversals of the ast. 300 // by traversals of the ast.
292 ast = new jsAst.ArrayInitializer( 301 ast = new jsAst.ArrayInitializer(
293 names.map((Iterable i) => new jsAst.ArrayInitializer(i.toList())) 302 names.map((Iterable i) => new jsAst.ArrayInitializer(i.toList()))
294 .toList()); 303 .toList());
295 } 304 }
296 305
297 void _computeDiffEncodingForList(Iterable<jsAst.Name> names, 306 void _computeDiffEncodingForList(Iterable<jsAst.Name> names,
298 StringBuffer diffEncoding) { 307 StringBuffer diffEncoding) {
299 // Treat string as a number in base 88 with digits in ASCII order from # to 308 // Treat string as a number in base 88 with digits in ASCII order from # to
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 return a.compareTo(b); 343 return a.compareTo(b);
335 } 344 }
336 345
337 List<String> shorts = 346 List<String> shorts =
338 names.map((jsAst.Name name) => name.name) 347 names.map((jsAst.Name name) => name.name)
339 .toList() 348 .toList()
340 ..sort(compare); 349 ..sort(compare);
341 350
342 int previous = 0; 351 int previous = 0;
343 for (String short in shorts) { 352 for (String short in shorts) {
344 if (useDiffEncoding && 353 if (short.length <= NsmEmitter.MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING) {
345 short.length <= NsmEmitter.MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING) {
346 int base63 = fromBase88(short); 354 int base63 = fromBase88(short);
347 int diff = base63 - previous; 355 int diff = base63 - previous;
348 previous = base63; 356 previous = base63;
349 String base26Diff = toBase26(diff); 357 String base26Diff = toBase26(diff);
350 diffEncoding.write(base26Diff); 358 diffEncoding.write(base26Diff);
351 } else { 359 } else {
352 if (useDiffEncoding || diffEncoding.length != 0) { 360 if (diffEncoding.length != 0) {
353 diffEncoding.write(','); 361 diffEncoding.write(',');
354 } 362 }
355 diffEncoding.write(short); 363 diffEncoding.write(short);
356 } 364 }
357 } 365 }
358 } 366 }
359 367
360 String _computeDiffEncoding() { 368 String _computeDiffEncoding() {
361 StringBuffer buffer = new StringBuffer(); 369 StringBuffer buffer = new StringBuffer();
362 for (jsAst.ArrayInitializer list in ast.elements) { 370 for (jsAst.ArrayInitializer list in ast.elements) {
363 if (buffer.isNotEmpty) { 371 if (buffer.isNotEmpty) {
364 if (useDiffEncoding) { 372 // Emit period that resets the diff base to zero when we switch to
365 // Emit period that resets the diff base to zero when we switch to 373 // normal calling convention (this avoids the need to code negative
366 // normal calling convention (this avoids the need to code negative 374 // diffs).
367 // diffs). 375 buffer.write(".");
368 buffer.write(".");
369 } else {
370 // Write a separator for the next sequence.
371 buffer.write(",");
372 }
373 } 376 }
374 List<jsAst.Name> names = list.elements; 377 List<jsAst.Name> names = list.elements;
375 _computeDiffEncodingForList(names, buffer); 378 _computeDiffEncodingForList(names, buffer);
376 } 379 }
377 return '"${buffer.toString()}"'; 380 return '"${buffer.toString()}"';
378 } 381 }
379 382
380 String get value { 383 String get value {
381 if (_cachedValue == null) { 384 if (_cachedValue == null) {
382 _cachedValue = _computeDiffEncoding(); 385 _cachedValue = _computeDiffEncoding();
383 } 386 }
384 387
385 return _cachedValue; 388 return _cachedValue;
386 } 389 }
387 } 390 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698