| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 """; |
| OLD | NEW |