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

Side by Side Diff: lib/compiler/implementation/js_backend/emitter.dart

Issue 10967013: Avoid generating duplicate stubs. Fixes issue 3184. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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
« no previous file with comments | « no previous file | tests/compiler/dart2js/no_duplicate_stub_test.dart » ('j') | 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 /** 5 /**
6 * A function element that represents a closure call. The signature is copied 6 * A function element that represents a closure call. The signature is copied
7 * from the given element. 7 * from the given element.
8 */ 8 */
9 class ClosureInvocationElement extends FunctionElement { 9 class ClosureInvocationElement extends FunctionElement {
10 ClosureInvocationElement(SourceString name, 10 ClosureInvocationElement(SourceString name,
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 /** 344 /**
345 * Generate stubs to handle invocation of methods with optional 345 * Generate stubs to handle invocation of methods with optional
346 * arguments. 346 * arguments.
347 * 347 *
348 * A method like [: foo([x]) :] may be invoked by the following 348 * A method like [: foo([x]) :] may be invoked by the following
349 * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this 349 * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this
350 * function for detailed examples. 350 * function for detailed examples.
351 */ 351 */
352 void addParameterStub(FunctionElement member, 352 void addParameterStub(FunctionElement member,
353 Selector selector, 353 Selector selector,
354 DefineMemberFunction defineInstanceMember) { 354 DefineMemberFunction defineInstanceMember,
355 Set<String> alreadyGenerated) {
355 FunctionSignature parameters = member.computeSignature(compiler); 356 FunctionSignature parameters = member.computeSignature(compiler);
356 int positionalArgumentCount = selector.positionalArgumentCount; 357 int positionalArgumentCount = selector.positionalArgumentCount;
357 if (positionalArgumentCount == parameters.parameterCount) { 358 if (positionalArgumentCount == parameters.parameterCount) {
358 assert(selector.namedArgumentCount == 0); 359 assert(selector.namedArgumentCount == 0);
359 return; 360 return;
360 } 361 }
361 if (parameters.optionalParametersAreNamed 362 if (parameters.optionalParametersAreNamed
362 && selector.namedArgumentCount == parameters.optionalParameterCount) { 363 && selector.namedArgumentCount == parameters.optionalParameterCount) {
363 // If the selector has the same number of named arguments as 364 // If the selector has the same number of named arguments as
364 // the element, we don't need to add a stub. The call site will 365 // the element, we don't need to add a stub. The call site will
365 // hit the method directly. 366 // hit the method directly.
366 return; 367 return;
367 } 368 }
368 ConstantHandler handler = compiler.constantHandler; 369 ConstantHandler handler = compiler.constantHandler;
369 List<SourceString> names = selector.getOrderedNamedArguments(); 370 List<SourceString> names = selector.getOrderedNamedArguments();
370 371
371 String invocationName = 372 String invocationName =
372 namer.instanceMethodInvocationName(member.getLibrary(), member.name, 373 namer.instanceMethodInvocationName(member.getLibrary(), member.name,
373 selector); 374 selector);
375 if (alreadyGenerated.contains(invocationName)) return;
376 alreadyGenerated.add(invocationName);
374 CodeBuffer buffer = new CodeBuffer(); 377 CodeBuffer buffer = new CodeBuffer();
375 buffer.add('function('); 378 buffer.add('function(');
376 379
377 // The parameters that this stub takes. 380 // The parameters that this stub takes.
378 List<String> parametersBuffer = new List<String>(selector.argumentCount); 381 List<String> parametersBuffer = new List<String>(selector.argumentCount);
379 // The arguments that will be passed to the real method. 382 // The arguments that will be passed to the real method.
380 List<String> argumentsBuffer = new List<String>(parameters.parameterCount); 383 List<String> argumentsBuffer = new List<String>(parameters.parameterCount);
381 384
382 int count = 0; 385 int count = 0;
383 int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1; 386 int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 // (3) foo$3(a, b, c) => foo$4(a, b, c, null) 470 // (3) foo$3(a, b, c) => foo$4(a, b, c, null)
468 // (4) foo$3$c(a, b, c) => foo$4(a, b, c, null); 471 // (4) foo$3$c(a, b, c) => foo$4(a, b, c, null);
469 // (5) foo$3$d(a, b, d) => foo$4(a, b, null, d); 472 // (5) foo$3$d(a, b, d) => foo$4(a, b, null, d);
470 // (6) foo$4$c$d(a, b, c, d) => foo$4(a, b, c, d); 473 // (6) foo$4$c$d(a, b, c, d) => foo$4(a, b, c, d);
471 // (7) Same as (5). 474 // (7) Same as (5).
472 // 475 //
473 // We need to generate a stub for (5) because the order of the 476 // We need to generate a stub for (5) because the order of the
474 // stub arguments and the real method may be different. 477 // stub arguments and the real method may be different.
475 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; 478 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name];
476 if (selectors == null) return; 479 if (selectors == null) return;
480 // Keep a cache of which stubs have already been generated, to
481 // avoid duplicates. Note that even if selectors are
482 // canonicalized, we would still need this cache: a typed selector
483 // on A and a typed selector on B could yield the same stub.
484 Set<String> generatedStubNames = new Set<String>();
477 for (Selector selector in selectors) { 485 for (Selector selector in selectors) {
478 if (!selector.applies(member, compiler)) continue; 486 if (!selector.applies(member, compiler)) continue;
479 addParameterStub(member, selector, defineInstanceMember); 487 addParameterStub(
488 member, selector, defineInstanceMember, generatedStubNames);
480 } 489 }
481 } 490 }
482 491
483 bool instanceFieldNeedsGetter(Element member) { 492 bool instanceFieldNeedsGetter(Element member) {
484 assert(member.isField()); 493 assert(member.isField());
485 return compiler.codegenWorld.hasInvokedGetter(member, compiler); 494 return compiler.codegenWorld.hasInvokedGetter(member, compiler);
486 } 495 }
487 496
488 bool instanceFieldNeedsSetter(Element member) { 497 bool instanceFieldNeedsSetter(Element member) {
489 assert(member.isField()); 498 assert(member.isField());
(...skipping 887 matching lines...) Expand 10 before | Expand all | Expand 10 after
1377 const String HOOKS_API_USAGE = """ 1386 const String HOOKS_API_USAGE = """
1378 // Generated by dart2js, the Dart to JavaScript compiler. 1387 // Generated by dart2js, the Dart to JavaScript compiler.
1379 // The code supports the following hooks: 1388 // The code supports the following hooks:
1380 // dartPrint(message) - if this function is defined it is called 1389 // dartPrint(message) - if this function is defined it is called
1381 // instead of the Dart [print] method. 1390 // instead of the Dart [print] method.
1382 // dartMainRunner(main) - if this function is defined, the Dart [main] 1391 // dartMainRunner(main) - if this function is defined, the Dart [main]
1383 // method will not be invoked directly. 1392 // method will not be invoked directly.
1384 // Instead, a closure that will invoke [main] is 1393 // Instead, a closure that will invoke [main] is
1385 // passed to [dartMainRunner]. 1394 // passed to [dartMainRunner].
1386 """; 1395 """;
OLDNEW
« no previous file with comments | « no previous file | tests/compiler/dart2js/no_duplicate_stub_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698