| 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 |