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 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 Selector selector, | 353 Selector selector, |
354 DefineMemberFunction defineInstanceMember) { | 354 DefineMemberFunction defineInstanceMember) { |
355 FunctionSignature parameters = member.computeSignature(compiler); | 355 FunctionSignature parameters = member.computeSignature(compiler); |
356 int positionalArgumentCount = selector.positionalArgumentCount; | 356 int positionalArgumentCount = selector.positionalArgumentCount; |
357 if (positionalArgumentCount == parameters.parameterCount) { | 357 if (positionalArgumentCount == parameters.parameterCount) { |
358 assert(selector.namedArgumentCount == 0); | 358 assert(selector.namedArgumentCount == 0); |
359 return; | 359 return; |
360 } | 360 } |
361 if (parameters.optionalParametersAreNamed | 361 if (parameters.optionalParametersAreNamed |
362 && selector.namedArgumentCount == parameters.optionalParameterCount) { | 362 && selector.namedArgumentCount == parameters.optionalParameterCount) { |
363 // If the selector has the same number of named arguments than | 363 // 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 | 364 // the element, we don't need to add a stub. The call site will |
365 // hit the method directly. | 365 // hit the method directly. |
366 return; | 366 return; |
367 } | 367 } |
368 ConstantHandler handler = compiler.constantHandler; | 368 ConstantHandler handler = compiler.constantHandler; |
369 List<SourceString> names = selector.getOrderedNamedArguments(); | 369 List<SourceString> names = selector.getOrderedNamedArguments(); |
370 | 370 |
371 String invocationName = | 371 String invocationName = |
372 namer.instanceMethodInvocationName(member.getLibrary(), member.name, | 372 namer.instanceMethodInvocationName(member.getLibrary(), member.name, |
373 selector); | 373 selector); |
374 CodeBuffer buffer = new CodeBuffer(); | 374 CodeBuffer buffer = new CodeBuffer(); |
375 buffer.add('function('); | 375 buffer.add('function('); |
376 | 376 |
377 // The parameters that this stub takes. | 377 // The parameters that this stub takes. |
378 List<String> parametersBuffer = new List<String>(selector.argumentCount); | 378 List<String> parametersBuffer = new List<String>(selector.argumentCount); |
379 // The arguments that will be passed to the real method. | 379 // The arguments that will be passed to the real method. |
380 List<String> argumentsBuffer = new List<String>(parameters.parameterCount); | 380 List<String> argumentsBuffer = new List<String>(parameters.parameterCount); |
381 | 381 |
382 // TODO(5074): Update this comment once we remove support for | |
383 // the deprecated parameter specification. | |
384 // We fill the lists depending on the selector. For example, | |
385 // take method foo: | |
386 // foo(a, b, [c, d]); | |
387 // | |
388 // We may have multiple ways of calling foo: | |
389 // (1) foo(1, 2, 3, 4) | |
390 // (2) foo(1, 2); | |
391 // (3) foo(1, 2, 3); | |
392 // (4) foo(1, 2, c: 3); | |
393 // (5) foo(1, 2, d: 4); | |
394 // (6) foo(1, 2, c: 3, d: 4); | |
395 // (7) foo(1, 2, d: 4, c: 3); | |
396 // | |
397 // What we generate at the call sites are: | |
398 // (1) foo$4(1, 2, 3, 4) | |
399 // (2) foo$2(1, 2); | |
400 // (3) foo$3(1, 2, 3); | |
401 // (4) foo$3$c(1, 2, 3); | |
402 // (5) foo$3$d(1, 2, 4); | |
403 // (6) foo$4$c$d(1, 2, 3, 4); | |
404 // (7) foo$4$c$d(1, 2, 3, 4); | |
405 // | |
406 // The stubs we generate are (expressed in Dart): | |
407 // (1) No stub generated, call is direct. | |
408 // (2) foo$2(a, b) => foo$4(a, b, null, null) | |
409 // (3) foo$3(a, b, c) => foo$4(a, b, c, null) | |
410 // (4) foo$3$c(a, b, c) => foo$4(a, b, c, null); | |
411 // (5) foo$3$d(a, b, d) => foo$4(a, b, null, d); | |
412 // (6) foo$4$c$d(a, b, c, d) => foo$4(a, b, c, d); | |
413 // (7) Same as (5). | |
414 // | |
415 // We need to generate a stub for (5) because the order of the | |
416 // stub arguments and the real method may be different. | |
417 | |
418 int count = 0; | 382 int count = 0; |
419 int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1; | 383 int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1; |
420 TreeElements elements = | 384 TreeElements elements = |
421 compiler.enqueuer.resolution.getCachedElements(member); | 385 compiler.enqueuer.resolution.getCachedElements(member); |
422 | 386 |
423 parameters.forEachParameter((Element element) { | 387 parameters.forEachParameter((Element element) { |
424 String jsName = JsNames.getValid(element.name.slowToString()); | 388 String jsName = JsNames.getValid(element.name.slowToString()); |
425 if (count < positionalArgumentCount) { | 389 if (count < positionalArgumentCount) { |
426 parametersBuffer[count] = jsName; | 390 parametersBuffer[count] = jsName; |
427 argumentsBuffer[count] = jsName; | 391 argumentsBuffer[count] = jsName; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 } else { | 430 } else { |
467 String arguments = Strings.join(argumentsBuffer, ","); | 431 String arguments = Strings.join(argumentsBuffer, ","); |
468 buffer.add(' return this.${namer.getName(member)}($arguments)'); | 432 buffer.add(' return this.${namer.getName(member)}($arguments)'); |
469 } | 433 } |
470 buffer.add('\n}'); | 434 buffer.add('\n}'); |
471 defineInstanceMember(invocationName, buffer); | 435 defineInstanceMember(invocationName, buffer); |
472 } | 436 } |
473 | 437 |
474 void addParameterStubs(FunctionElement member, | 438 void addParameterStubs(FunctionElement member, |
475 DefineMemberFunction defineInstanceMember) { | 439 DefineMemberFunction defineInstanceMember) { |
| 440 // TODO(5074): Update this comment once we remove support for |
| 441 // the deprecated parameter specification. |
| 442 // We fill the lists depending on the selector. For example, |
| 443 // take method foo: |
| 444 // foo(a, b, [c, d]); |
| 445 // |
| 446 // We may have multiple ways of calling foo: |
| 447 // (1) foo(1, 2, 3, 4) |
| 448 // (2) foo(1, 2); |
| 449 // (3) foo(1, 2, 3); |
| 450 // (4) foo(1, 2, c: 3); |
| 451 // (5) foo(1, 2, d: 4); |
| 452 // (6) foo(1, 2, c: 3, d: 4); |
| 453 // (7) foo(1, 2, d: 4, c: 3); |
| 454 // |
| 455 // What we generate at the call sites are: |
| 456 // (1) foo$4(1, 2, 3, 4) |
| 457 // (2) foo$2(1, 2); |
| 458 // (3) foo$3(1, 2, 3); |
| 459 // (4) foo$3$c(1, 2, 3); |
| 460 // (5) foo$3$d(1, 2, 4); |
| 461 // (6) foo$4$c$d(1, 2, 3, 4); |
| 462 // (7) foo$4$c$d(1, 2, 3, 4); |
| 463 // |
| 464 // The stubs we generate are (expressed in Dart): |
| 465 // (1) No stub generated, call is direct. |
| 466 // (2) foo$2(a, b) => foo$4(a, b, null, null) |
| 467 // (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); |
| 469 // (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); |
| 471 // (7) Same as (5). |
| 472 // |
| 473 // We need to generate a stub for (5) because the order of the |
| 474 // stub arguments and the real method may be different. |
476 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; | 475 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; |
477 if (selectors == null) return; | 476 if (selectors == null) return; |
478 for (Selector selector in selectors) { | 477 for (Selector selector in selectors) { |
479 if (!selector.applies(member, compiler)) continue; | 478 if (!selector.applies(member, compiler)) continue; |
480 addParameterStub(member, selector, defineInstanceMember); | 479 addParameterStub(member, selector, defineInstanceMember); |
481 } | 480 } |
482 } | 481 } |
483 | 482 |
484 bool instanceFieldNeedsGetter(Element member) { | 483 bool instanceFieldNeedsGetter(Element member) { |
485 assert(member.isField()); | 484 assert(member.isField()); |
(...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1049 emitDynamicFunctionGetter(member, defineInstanceMember); | 1048 emitDynamicFunctionGetter(member, defineInstanceMember); |
1050 } | 1049 } |
1051 } | 1050 } |
1052 } | 1051 } |
1053 | 1052 |
1054 void emitNoSuchMethodHandlers(DefineMemberFunction defineInstanceMember) { | 1053 void emitNoSuchMethodHandlers(DefineMemberFunction defineInstanceMember) { |
1055 // Do not generate no such method handlers if there is no class. | 1054 // Do not generate no such method handlers if there is no class. |
1056 if (compiler.codegenWorld.instantiatedClasses.isEmpty()) return; | 1055 if (compiler.codegenWorld.instantiatedClasses.isEmpty()) return; |
1057 | 1056 |
1058 String noSuchMethodName = | 1057 String noSuchMethodName = |
1059 namer.instanceMethodNameByArity(Compiler.NO_SUCH_METHOD, 2); | 1058 namer.publicInstanceMethodNameByArity(Compiler.NO_SUCH_METHOD, 2); |
1060 | 1059 |
1061 // Keep track of the JavaScript names we've already added so we | 1060 // Keep track of the JavaScript names we've already added so we |
1062 // do not introduce duplicates (bad for code size). | 1061 // do not introduce duplicates (bad for code size). |
1063 Set<String> addedJsNames = new Set<String>(); | 1062 Set<String> addedJsNames = new Set<String>(); |
1064 | 1063 |
1065 // Keep track of the noSuchMethod holders for each possible | 1064 // Keep track of the noSuchMethod holders for each possible |
1066 // receiver type. | 1065 // receiver type. |
1067 Map<ClassElement, Set<ClassElement>> noSuchMethodHolders = | 1066 Map<ClassElement, Set<ClassElement>> noSuchMethodHolders = |
1068 new Map<ClassElement, Set<ClassElement>>(); | 1067 new Map<ClassElement, Set<ClassElement>>(); |
1069 Set<ClassElement> noSuchMethodHoldersFor(DartType type) { | 1068 Set<ClassElement> noSuchMethodHoldersFor(DartType type) { |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1365 const String HOOKS_API_USAGE = """ | 1364 const String HOOKS_API_USAGE = """ |
1366 // Generated by dart2js, the Dart to JavaScript compiler. | 1365 // Generated by dart2js, the Dart to JavaScript compiler. |
1367 // The code supports the following hooks: | 1366 // The code supports the following hooks: |
1368 // dartPrint(message) - if this function is defined it is called | 1367 // dartPrint(message) - if this function is defined it is called |
1369 // instead of the Dart [print] method. | 1368 // instead of the Dart [print] method. |
1370 // dartMainRunner(main) - if this function is defined, the Dart [main] | 1369 // dartMainRunner(main) - if this function is defined, the Dart [main] |
1371 // method will not be invoked directly. | 1370 // method will not be invoked directly. |
1372 // Instead, a closure that will invoke [main] is | 1371 // Instead, a closure that will invoke [main] is |
1373 // passed to [dartMainRunner]. | 1372 // passed to [dartMainRunner]. |
1374 """; | 1373 """; |
OLD | NEW |