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 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
342 */ | 342 */ |
343 void addParameterStub(FunctionElement member, | 343 void addParameterStub(FunctionElement member, |
344 Selector selector, | 344 Selector selector, |
345 DefineMemberFunction defineInstanceMember) { | 345 DefineMemberFunction defineInstanceMember) { |
346 FunctionSignature parameters = member.computeSignature(compiler); | 346 FunctionSignature parameters = member.computeSignature(compiler); |
347 int positionalArgumentCount = selector.positionalArgumentCount; | 347 int positionalArgumentCount = selector.positionalArgumentCount; |
348 if (positionalArgumentCount == parameters.parameterCount) { | 348 if (positionalArgumentCount == parameters.parameterCount) { |
349 assert(selector.namedArgumentCount == 0); | 349 assert(selector.namedArgumentCount == 0); |
350 return; | 350 return; |
351 } | 351 } |
352 if (parameters.optionalParametersAreNamed | |
353 && selector.namedArgumentCount == parameters.optionalParameterCount) { | |
354 // If the selector has the same number of named arguments than | |
ahe
2012/09/13 14:29:10
than -> as
ngeoffray
2012/09/17 12:21:01
Done.
| |
355 // the element, we don't need to add a stub. The call site will | |
356 // hit the method directly. | |
357 return; | |
358 } | |
352 ConstantHandler handler = compiler.constantHandler; | 359 ConstantHandler handler = compiler.constantHandler; |
353 List<SourceString> names = selector.getOrderedNamedArguments(); | 360 List<SourceString> names = selector.getOrderedNamedArguments(); |
354 | 361 |
355 String invocationName = | 362 String invocationName = |
356 namer.instanceMethodInvocationName(member.getLibrary(), member.name, | 363 namer.instanceMethodInvocationName(member.getLibrary(), member.name, |
357 selector); | 364 selector); |
358 CodeBuffer buffer = new CodeBuffer(); | 365 CodeBuffer buffer = new CodeBuffer(); |
359 buffer.add('function('); | 366 buffer.add('function('); |
360 | 367 |
361 // The parameters that this stub takes. | 368 // The parameters that this stub takes. |
362 List<String> parametersBuffer = new List<String>(selector.argumentCount); | 369 List<String> parametersBuffer = new List<String>(selector.argumentCount); |
363 // The arguments that will be passed to the real method. | 370 // The arguments that will be passed to the real method. |
364 List<String> argumentsBuffer = new List<String>(parameters.parameterCount); | 371 List<String> argumentsBuffer = new List<String>(parameters.parameterCount); |
365 | 372 |
373 // TODO(5074): Update this comment once we remove support for | |
374 // the deprecated parameter specification. | |
ahe
2012/09/13 14:29:10
Actually, I think this comment should be moved to
ngeoffray
2012/09/17 12:21:01
Done.
| |
366 // We fill the lists depending on the selector. For example, | 375 // We fill the lists depending on the selector. For example, |
367 // take method foo: | 376 // take method foo: |
368 // foo(a, b, [c, d]); | 377 // foo(a, b, [c, d]); |
369 // | 378 // |
370 // We may have multiple ways of calling foo: | 379 // We may have multiple ways of calling foo: |
371 // (1) foo(1, 2, 3, 4) | 380 // (1) foo(1, 2, 3, 4) |
372 // (2) foo(1, 2); | 381 // (2) foo(1, 2); |
373 // (3) foo(1, 2, 3); | 382 // (3) foo(1, 2, 3); |
374 // (4) foo(1, 2, c: 3); | 383 // (4) foo(1, 2, c: 3); |
375 // (5) foo(1, 2, d: 4); | 384 // (5) foo(1, 2, d: 4); |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
803 Set<FunctionElement> functionsNeedingGetter = | 812 Set<FunctionElement> functionsNeedingGetter = |
804 compiler.codegenWorld.staticFunctionsNeedingGetter; | 813 compiler.codegenWorld.staticFunctionsNeedingGetter; |
805 for (FunctionElement element in functionsNeedingGetter) { | 814 for (FunctionElement element in functionsNeedingGetter) { |
806 // The static function does not have the correct name. Since | 815 // The static function does not have the correct name. Since |
807 // [addParameterStubs] use the name to create its stubs we simply | 816 // [addParameterStubs] use the name to create its stubs we simply |
808 // create a fake element with the correct name. | 817 // create a fake element with the correct name. |
809 // Note: the callElement will not have any enclosingElement. | 818 // Note: the callElement will not have any enclosingElement. |
810 FunctionElement callElement = | 819 FunctionElement callElement = |
811 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, element); | 820 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, element); |
812 String staticName = namer.getName(element); | 821 String staticName = namer.getName(element); |
813 int parameterCount = element.parameterCount(compiler); | 822 String invocationName = namer.instanceMethodName(callElement); |
814 String invocationName = | |
815 namer.instanceMethodName(element.getLibrary(), callElement.name, | |
816 parameterCount); | |
817 String fieldAccess = '$isolateProperties.$staticName'; | 823 String fieldAccess = '$isolateProperties.$staticName'; |
818 buffer.add("$fieldAccess.$invocationName = $fieldAccess;\n"); | 824 buffer.add("$fieldAccess.$invocationName = $fieldAccess;\n"); |
819 addParameterStubs(callElement, (String name, CodeBuffer value) { | 825 addParameterStubs(callElement, (String name, CodeBuffer value) { |
820 buffer.add('$fieldAccess.$name = $value;\n'); | 826 buffer.add('$fieldAccess.$name = $value;\n'); |
821 }); | 827 }); |
822 // If a static function is used as a closure we need to add its name | 828 // If a static function is used as a closure we need to add its name |
823 // in case it is used in spawnFunction. | 829 // in case it is used in spawnFunction. |
824 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; | 830 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; |
825 buffer.add('$fieldAccess.$fieldName = "$staticName";\n'); | 831 buffer.add('$fieldAccess.$fieldName = "$staticName";\n'); |
826 } | 832 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
871 ['self', 'target'], | 877 ['self', 'target'], |
872 'super': '$superName', | 878 'super': '$superName', |
873 """); | 879 """); |
874 // Now add the methods on the closure class. The instance method does not | 880 // Now add the methods on the closure class. The instance method does not |
875 // have the correct name. Since [addParameterStubs] use the name to create | 881 // have the correct name. Since [addParameterStubs] use the name to create |
876 // its stubs we simply create a fake element with the correct name. | 882 // its stubs we simply create a fake element with the correct name. |
877 // Note: the callElement will not have any enclosingElement. | 883 // Note: the callElement will not have any enclosingElement. |
878 FunctionElement callElement = | 884 FunctionElement callElement = |
879 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member); | 885 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member); |
880 | 886 |
881 String invocationName = | 887 String invocationName = namer.instanceMethodName(callElement); |
882 namer.instanceMethodName(member.getLibrary(), | |
883 callElement.name, parameterCount); | |
884 List<String> arguments = new List<String>(parameterCount); | 888 List<String> arguments = new List<String>(parameterCount); |
885 for (int i = 0; i < parameterCount; i++) { | 889 for (int i = 0; i < parameterCount; i++) { |
886 arguments[i] = "p$i"; | 890 arguments[i] = "p$i"; |
887 } | 891 } |
888 String joinedArgs = Strings.join(arguments, ", "); | 892 String joinedArgs = Strings.join(arguments, ", "); |
889 boundClosureBuffer.add( | 893 boundClosureBuffer.add( |
890 "$invocationName: function($joinedArgs) {"); | 894 "$invocationName: function($joinedArgs) {"); |
891 boundClosureBuffer.add(" return this.self[this.target]($joinedArgs);"); | 895 boundClosureBuffer.add(" return this.self[this.target]($joinedArgs);"); |
892 boundClosureBuffer.add(" }"); | 896 boundClosureBuffer.add(" }"); |
893 addParameterStubs(callElement, (String stubName, CodeBuffer memberValue) { | 897 addParameterStubs(callElement, (String stubName, CodeBuffer memberValue) { |
894 boundClosureBuffer.add(',\n $stubName: $memberValue'); | 898 boundClosureBuffer.add(',\n $stubName: $memberValue'); |
895 }); | 899 }); |
896 boundClosureBuffer.add("\n};\n"); | 900 boundClosureBuffer.add("\n};\n"); |
897 | 901 |
898 closureClass = namer.isolateAccess(closureClassElement); | 902 closureClass = namer.isolateAccess(closureClassElement); |
899 | 903 |
900 // Cache it. | 904 // Cache it. |
901 if (!hasOptionalParameters) { | 905 if (!hasOptionalParameters) { |
902 boundClosureCache[parameterCount] = closureClass; | 906 boundClosureCache[parameterCount] = closureClass; |
903 } | 907 } |
904 } | 908 } |
905 | 909 |
906 // And finally the getter. | 910 // And finally the getter. |
907 String getterName = namer.getterName(member.getLibrary(), member.name); | 911 String getterName = namer.getterName(member.getLibrary(), member.name); |
908 String targetName = namer.instanceMethodName(member.getLibrary(), | 912 String targetName = namer.instanceMethodName(member); |
909 member.name, parameterCount); | |
910 CodeBuffer getterBuffer = new CodeBuffer(); | 913 CodeBuffer getterBuffer = new CodeBuffer(); |
911 getterBuffer.add( | 914 getterBuffer.add( |
912 "function() { return new $closureClass(this, '$targetName'); }"); | 915 "function() { return new $closureClass(this, '$targetName'); }"); |
913 defineInstanceMember(getterName, getterBuffer); | 916 defineInstanceMember(getterName, getterBuffer); |
914 } | 917 } |
915 | 918 |
916 void emitCallStubForGetter(Element member, | 919 void emitCallStubForGetter(Element member, |
917 Set<Selector> selectors, | 920 Set<Selector> selectors, |
918 DefineMemberFunction defineInstanceMember) { | 921 DefineMemberFunction defineInstanceMember) { |
919 String getter; | 922 String getter; |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1034 emitDynamicFunctionGetter(member, defineInstanceMember); | 1037 emitDynamicFunctionGetter(member, defineInstanceMember); |
1035 } | 1038 } |
1036 } | 1039 } |
1037 } | 1040 } |
1038 | 1041 |
1039 void emitNoSuchMethodHandlers(DefineMemberFunction defineInstanceMember) { | 1042 void emitNoSuchMethodHandlers(DefineMemberFunction defineInstanceMember) { |
1040 // Do not generate no such method handlers if there is no class. | 1043 // Do not generate no such method handlers if there is no class. |
1041 if (compiler.codegenWorld.instantiatedClasses.isEmpty()) return; | 1044 if (compiler.codegenWorld.instantiatedClasses.isEmpty()) return; |
1042 | 1045 |
1043 String noSuchMethodName = | 1046 String noSuchMethodName = |
1044 namer.instanceMethodName(null, Compiler.NO_SUCH_METHOD, 2); | 1047 namer.instanceMethodNameByArity(Compiler.NO_SUCH_METHOD, 2); |
1045 | 1048 |
1046 // Keep track of the JavaScript names we've already added so we | 1049 // Keep track of the JavaScript names we've already added so we |
1047 // do not introduce duplicates (bad for code size). | 1050 // do not introduce duplicates (bad for code size). |
1048 Set<String> addedJsNames = new Set<String>(); | 1051 Set<String> addedJsNames = new Set<String>(); |
1049 | 1052 |
1050 // Keep track of the noSuchMethod holders for each possible | 1053 // Keep track of the noSuchMethod holders for each possible |
1051 // receiver type. | 1054 // receiver type. |
1052 Map<ClassElement, Set<ClassElement>> noSuchMethodHolders = | 1055 Map<ClassElement, Set<ClassElement>> noSuchMethodHolders = |
1053 new Map<ClassElement, Set<ClassElement>>(); | 1056 new Map<ClassElement, Set<ClassElement>>(); |
1054 Set<ClassElement> noSuchMethodHoldersFor(DartType type) { | 1057 Set<ClassElement> noSuchMethodHoldersFor(DartType type) { |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1347 const String HOOKS_API_USAGE = """ | 1350 const String HOOKS_API_USAGE = """ |
1348 // Generated by dart2js, the Dart to JavaScript compiler. | 1351 // Generated by dart2js, the Dart to JavaScript compiler. |
1349 // The code supports the following hooks: | 1352 // The code supports the following hooks: |
1350 // dartPrint(message) - if this function is defined it is called | 1353 // dartPrint(message) - if this function is defined it is called |
1351 // instead of the Dart [print] method. | 1354 // instead of the Dart [print] method. |
1352 // dartMainRunner(main) - if this function is defined, the Dart [main] | 1355 // dartMainRunner(main) - if this function is defined, the Dart [main] |
1353 // method will not be invoked directly. | 1356 // method will not be invoked directly. |
1354 // Instead, a closure that will invoke [main] is | 1357 // Instead, a closure that will invoke [main] is |
1355 // passed to [dartMainRunner]. | 1358 // passed to [dartMainRunner]. |
1356 """; | 1359 """; |
OLD | NEW |