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

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: Created 5 years, 5 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> specialSelectors = 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> specialShorts =
137 specialSelectors.map(namer.invocationMirrorInternalName);
sigurdm 2015/06/25 09:15:00 Indent
herhut 2015/06/25 09:21:24 Done.
138 Iterable<jsAst.Name> ordinaryShorts =
139 ordinarySelectors.map(namer.invocationMirrorInternalName);
140
141 jsAst.Expression sortedShorts;
142 Iterable<String> sortedLongs;
143 if (useDiffEncoding) {
144 sortedShorts = new _DiffEncodedListOfNames(
145 [specialShorts, ordinaryShorts]);
146 } else {
147 Iterable<Selector> sorted =
148 [specialSelectors, ordinarySelectors].expand((e) => (e));
sigurdm 2015/06/25 09:15:00 Maybe call the special selectors intercepted selec
herhut 2015/06/25 09:21:24 Done.
149 sortedShorts = js.concatenateStrings(
150 js.joinLiterals(
151 sorted.map(namer.invocationMirrorInternalName),
152 js.stringPart(",")),
153 addQuotes: true);
154
155 sortedLongs = sorted.map((selector) =>
156 selector.invocationMirrorMemberName);
157 }
148 // Startup code that loops over the method names and puts handlers on the 158 // Startup code that loops over the method names and puts handlers on the
149 // Object class to catch noSuchMethod invocations. 159 // Object class to catch noSuchMethod invocations.
150 ClassElement objectClass = compiler.objectClass; 160 ClassElement objectClass = compiler.objectClass;
151 jsAst.Expression createInvocationMirror = backend.emitter 161 jsAst.Expression createInvocationMirror = backend.emitter
152 .staticFunctionAccess(backend.getCreateInvocationMirror()); 162 .staticFunctionAccess(backend.getCreateInvocationMirror());
153 if (useDiffEncoding) { 163 if (useDiffEncoding) {
154 statements.add(js.statement('''{ 164 statements.add(js.statement('''{
155 var objectClassObject = processedClasses.collected[#objectClass], 165 var objectClassObject = processedClasses.collected[#objectClass],
156 nameSequences = #diffEncoding.split("."), 166 nameSequences = #diffEncoding.split("."),
157 shortNames = []; 167 shortNames = [];
(...skipping 27 matching lines...) Expand all
185 codes.unshift(${$HASH} + remaining % 88); 195 codes.unshift(${$HASH} + remaining % 88);
186 } 196 }
187 shortNames.push( 197 shortNames.push(
188 String.fromCharCode.apply(String, codes)); 198 String.fromCharCode.apply(String, codes));
189 } 199 }
190 if (sequence.length > 1) { 200 if (sequence.length > 1) {
191 Array.prototype.push.apply(shortNames, sequence.shift()); 201 Array.prototype.push.apply(shortNames, sequence.shift());
192 } 202 }
193 } 203 }
194 }''', {'objectClass': js.quoteName(namer.className(objectClass)), 204 }''', {'objectClass': js.quoteName(namer.className(objectClass)),
195 'diffEncoding': diffEncoding})); 205 'diffEncoding': sortedShorts}));
196 } else { 206 } else {
197 // No useDiffEncoding version. 207 // No useDiffEncoding version.
198 Iterable<String> longs = trivialNsmHandlers.map((selector) =>
199 selector.invocationMirrorMemberName);
200 statements.add(js.statement( 208 statements.add(js.statement(
201 'var objectClassObject = processedClasses.collected[#objectClass],' 209 'var objectClassObject = processedClasses.collected[#objectClass],'
202 ' shortNames = #diffEncoding.split(",")', 210 ' shortNames = #diffEncoding.split(",")',
203 {'objectClass': js.quoteName(namer.className(objectClass)), 211 {'objectClass': js.quoteName(namer.className(objectClass)),
204 'diffEncoding': diffEncoding})); 212 'diffEncoding': sortedShorts}));
205 if (!minify) { 213 if (!minify) {
206 statements.add(js.statement('var longNames = #longs.split(",")', 214 statements.add(js.statement('var longNames = #longs.split(",")',
207 {'longs': js.string(longs.join(','))})); 215 {'longs': js.string(sortedLongs.join(','))}));
208 } 216 }
209 statements.add(js.statement( 217 statements.add(js.statement(
210 'if (objectClassObject instanceof Array)' 218 'if (objectClassObject instanceof Array)'
211 ' objectClassObject = objectClassObject[1];')); 219 ' objectClassObject = objectClassObject[1];'));
212 } 220 }
213 221
214 dynamic isIntercepted = // jsAst.Expression or bool. 222 dynamic isIntercepted = // jsAst.Expression or bool.
215 specialSelectors.isEmpty 223 specialSelectors.isEmpty
216 ? false 224 ? false
217 : ordinarySelectors.isEmpty 225 : ordinarySelectors.isEmpty
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 } 284 }
277 285
278 /// When pretty printed, this node computes a diff-encoded string for the list 286 /// When pretty printed, this node computes a diff-encoded string for the list
279 /// of given names. 287 /// of given names.
280 /// 288 ///
281 /// See [buildTrivialNsmHandlers]. 289 /// See [buildTrivialNsmHandlers].
282 class _DiffEncodedListOfNames extends jsAst.DeferredString 290 class _DiffEncodedListOfNames extends jsAst.DeferredString
283 implements AstContainer { 291 implements AstContainer {
284 String _cachedValue; 292 String _cachedValue;
285 jsAst.ArrayInitializer ast; 293 jsAst.ArrayInitializer ast;
286 bool useDiffEncoding;
287 294
288 _DiffEncodedListOfNames(Iterable<Iterable<jsAst.Name>> names, 295 _DiffEncodedListOfNames(Iterable<Iterable<jsAst.Name>> names) {
289 this.useDiffEncoding) {
290 // Store the names in ArrayInitializer nodes to make them discoverable 296 // Store the names in ArrayInitializer nodes to make them discoverable
291 // by traversals of the ast. 297 // by traversals of the ast.
292 ast = new jsAst.ArrayInitializer( 298 ast = new jsAst.ArrayInitializer(
293 names.map((Iterable i) => new jsAst.ArrayInitializer(i.toList())) 299 names.map((Iterable i) => new jsAst.ArrayInitializer(i.toList()))
294 .toList()); 300 .toList());
295 } 301 }
296 302
297 void _computeDiffEncodingForList(Iterable<jsAst.Name> names, 303 void _computeDiffEncodingForList(Iterable<jsAst.Name> names,
298 StringBuffer diffEncoding) { 304 StringBuffer diffEncoding) {
299 // Treat string as a number in base 88 with digits in ASCII order from # to 305 // 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); 340 return a.compareTo(b);
335 } 341 }
336 342
337 List<String> shorts = 343 List<String> shorts =
338 names.map((jsAst.Name name) => name.name) 344 names.map((jsAst.Name name) => name.name)
339 .toList() 345 .toList()
340 ..sort(compare); 346 ..sort(compare);
341 347
342 int previous = 0; 348 int previous = 0;
343 for (String short in shorts) { 349 for (String short in shorts) {
344 if (useDiffEncoding && 350 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); 351 int base63 = fromBase88(short);
347 int diff = base63 - previous; 352 int diff = base63 - previous;
348 previous = base63; 353 previous = base63;
349 String base26Diff = toBase26(diff); 354 String base26Diff = toBase26(diff);
350 diffEncoding.write(base26Diff); 355 diffEncoding.write(base26Diff);
351 } else { 356 } else {
352 if (useDiffEncoding || diffEncoding.length != 0) { 357 if (diffEncoding.length != 0) {
353 diffEncoding.write(','); 358 diffEncoding.write(',');
354 } 359 }
355 diffEncoding.write(short); 360 diffEncoding.write(short);
356 } 361 }
357 } 362 }
358 } 363 }
359 364
360 String _computeDiffEncoding() { 365 String _computeDiffEncoding() {
361 StringBuffer buffer = new StringBuffer(); 366 StringBuffer buffer = new StringBuffer();
362 for (jsAst.ArrayInitializer list in ast.elements) { 367 for (jsAst.ArrayInitializer list in ast.elements) {
363 if (buffer.isNotEmpty) { 368 if (buffer.isNotEmpty) {
364 if (useDiffEncoding) { 369 // 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 370 // normal calling convention (this avoids the need to code negative
366 // normal calling convention (this avoids the need to code negative 371 // diffs).
367 // diffs). 372 buffer.write(".");
368 buffer.write(".");
369 } else {
370 // Write a separator for the next sequence.
371 buffer.write(",");
372 }
373 } 373 }
374 List<jsAst.Name> names = list.elements; 374 List<jsAst.Name> names = list.elements;
375 _computeDiffEncodingForList(names, buffer); 375 _computeDiffEncodingForList(names, buffer);
376 } 376 }
377 return '"${buffer.toString()}"'; 377 return '"${buffer.toString()}"';
378 } 378 }
379 379
380 String get value { 380 String get value {
381 if (_cachedValue == null) { 381 if (_cachedValue == null) {
382 _cachedValue = _computeDiffEncoding(); 382 _cachedValue = _computeDiffEncoding();
383 } 383 }
384 384
385 return _cachedValue; 385 return _cachedValue;
386 } 386 }
387 } 387 }
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