| 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 part of js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A function element that represents a closure call. The signature is copied | 8 * A function element that represents a closure call. The signature is copied |
| 9 * from the given element. | 9 * from the given element. |
| 10 */ | 10 */ |
| (...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 DefineStubFunction defineStub, | 654 DefineStubFunction defineStub, |
| 655 Set<String> alreadyGenerated) { | 655 Set<String> alreadyGenerated) { |
| 656 FunctionSignature parameters = member.computeSignature(compiler); | 656 FunctionSignature parameters = member.computeSignature(compiler); |
| 657 int positionalArgumentCount = selector.positionalArgumentCount; | 657 int positionalArgumentCount = selector.positionalArgumentCount; |
| 658 if (positionalArgumentCount == parameters.parameterCount) { | 658 if (positionalArgumentCount == parameters.parameterCount) { |
| 659 assert(selector.namedArgumentCount == 0); | 659 assert(selector.namedArgumentCount == 0); |
| 660 return; | 660 return; |
| 661 } | 661 } |
| 662 if (parameters.optionalParametersAreNamed | 662 if (parameters.optionalParametersAreNamed |
| 663 && selector.namedArgumentCount == parameters.optionalParameterCount) { | 663 && selector.namedArgumentCount == parameters.optionalParameterCount) { |
| 664 // If the selector has the same number of named arguments as | 664 // If the selector has the same number of named arguments as the element, |
| 665 // the element, we don't need to add a stub. The call site will | 665 // we don't need to add a stub. The call site will hit the method |
| 666 // hit the method directly. | 666 // directly. |
| 667 return; | 667 return; |
| 668 } | 668 } |
| 669 ConstantHandler handler = compiler.constantHandler; | 669 ConstantHandler handler = compiler.constantHandler; |
| 670 List<SourceString> names = selector.getOrderedNamedArguments(); | 670 List<SourceString> names = selector.getOrderedNamedArguments(); |
| 671 | 671 |
| 672 String invocationName = namer.invocationName(selector); | 672 String invocationName = namer.invocationName(selector); |
| 673 if (alreadyGenerated.contains(invocationName)) return; | 673 if (alreadyGenerated.contains(invocationName)) return; |
| 674 alreadyGenerated.add(invocationName); | 674 alreadyGenerated.add(invocationName); |
| 675 | 675 |
| 676 bool isInterceptedMethod = backend.isInterceptedMethod(member); | 676 bool isInterceptedMethod = backend.isInterceptedMethod(member); |
| 677 | 677 |
| 678 // If the method is intercepted, we need to also pass | 678 // If the method is intercepted, we need to also pass the actual receiver. |
| 679 // the actual receiver. | |
| 680 int extraArgumentCount = isInterceptedMethod ? 1 : 0; | 679 int extraArgumentCount = isInterceptedMethod ? 1 : 0; |
| 681 // Use '$receiver' to avoid clashes with other parameter names. Using | 680 // Use '$receiver' to avoid clashes with other parameter names. Using |
| 682 // '$receiver' works because [:namer.safeName:] used for getting parameter | 681 // '$receiver' works because [:namer.safeName:] used for getting parameter |
| 683 // names never returns a name beginning with a single '$'. | 682 // names never returns a name beginning with a single '$'. |
| 684 String receiverArgumentName = r'$receiver'; | 683 String receiverArgumentName = r'$receiver'; |
| 685 | 684 |
| 686 // The parameters that this stub takes. | 685 // The parameters that this stub takes. |
| 687 List<jsAst.Parameter> parametersBuffer = | 686 List<jsAst.Parameter> parametersBuffer = |
| 688 new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount); | 687 new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount); |
| 689 // The arguments that will be passed to the real method. | 688 // The arguments that will be passed to the real method. |
| 690 List<jsAst.Expression> argumentsBuffer = | 689 List<jsAst.Expression> argumentsBuffer = |
| 691 new List<jsAst.Expression>( | 690 new List<jsAst.Expression>( |
| 692 parameters.parameterCount + extraArgumentCount); | 691 parameters.parameterCount + extraArgumentCount); |
| 693 | 692 |
| 694 int count = 0; | 693 int count = 0; |
| 695 if (isInterceptedMethod) { | 694 if (isInterceptedMethod) { |
| 696 count++; | 695 count++; |
| 697 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName); | 696 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName); |
| 698 argumentsBuffer[0] = js[receiverArgumentName]; | 697 argumentsBuffer[0] = js[receiverArgumentName]; |
| 699 } | 698 } |
| 700 | 699 |
| 701 int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1; | 700 int optionalParameterStart = positionalArgumentCount + extraArgumentCount; |
| 701 // Includes extra receiver argument when using interceptor convention |
| 702 int indexOfLastOptionalArgumentInParameters = optionalParameterStart - 1; |
| 703 |
| 702 TreeElements elements = | 704 TreeElements elements = |
| 703 compiler.enqueuer.resolution.getCachedElements(member); | 705 compiler.enqueuer.resolution.getCachedElements(member); |
| 704 | 706 |
| 705 parameters.orderedForEachParameter((Element element) { | 707 parameters.orderedForEachParameter((Element element) { |
| 706 String jsName = backend.namer.safeName(element.name.slowToString()); | 708 String jsName = backend.namer.safeName(element.name.slowToString()); |
| 707 assert(jsName != receiverArgumentName); | 709 assert(jsName != receiverArgumentName); |
| 708 int optionalParameterStart = positionalArgumentCount + extraArgumentCount; | |
| 709 if (count < optionalParameterStart) { | 710 if (count < optionalParameterStart) { |
| 710 parametersBuffer[count] = new jsAst.Parameter(jsName); | 711 parametersBuffer[count] = new jsAst.Parameter(jsName); |
| 711 argumentsBuffer[count] = js[jsName]; | 712 argumentsBuffer[count] = js[jsName]; |
| 712 } else { | 713 } else { |
| 713 int index = names.indexOf(element.name); | 714 int index = names.indexOf(element.name); |
| 714 if (index != -1) { | 715 if (index != -1) { |
| 715 indexOfLastOptionalArgumentInParameters = count; | 716 indexOfLastOptionalArgumentInParameters = count; |
| 716 // The order of the named arguments is not the same as the | 717 // The order of the named arguments is not the same as the |
| 717 // one in the real method (which is in Dart source order). | 718 // one in the real method (which is in Dart source order). |
| 718 argumentsBuffer[count] = js[jsName]; | 719 argumentsBuffer[count] = js[jsName]; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 734 argumentsBuffer[count] = constantReference(value); | 735 argumentsBuffer[count] = constantReference(value); |
| 735 } | 736 } |
| 736 } | 737 } |
| 737 } | 738 } |
| 738 count++; | 739 count++; |
| 739 }); | 740 }); |
| 740 | 741 |
| 741 List body; | 742 List body; |
| 742 if (member.hasFixedBackendName()) { | 743 if (member.hasFixedBackendName()) { |
| 743 body = nativeEmitter.generateParameterStubStatements( | 744 body = nativeEmitter.generateParameterStubStatements( |
| 744 member, invocationName, parametersBuffer, argumentsBuffer, | 745 member, isInterceptedMethod, invocationName, |
| 746 parametersBuffer, argumentsBuffer, |
| 745 indexOfLastOptionalArgumentInParameters); | 747 indexOfLastOptionalArgumentInParameters); |
| 746 } else { | 748 } else { |
| 747 body = [js.return_(js['this'][namer.getName(member)](argumentsBuffer))]; | 749 body = [js.return_(js['this'][namer.getName(member)](argumentsBuffer))]; |
| 748 } | 750 } |
| 749 | 751 |
| 750 jsAst.Fun function = js.fun(parametersBuffer, body); | 752 jsAst.Fun function = js.fun(parametersBuffer, body); |
| 751 | 753 |
| 752 defineStub(invocationName, function); | 754 defineStub(invocationName, function); |
| 753 } | 755 } |
| 754 | 756 |
| (...skipping 1484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2239 cls == backend.jsFixedArrayClass || | 2241 cls == backend.jsFixedArrayClass || |
| 2240 cls == backend.jsExtendableArrayClass) hasArray = true; | 2242 cls == backend.jsExtendableArrayClass) hasArray = true; |
| 2241 else if (cls == backend.jsBoolClass) hasBool = true; | 2243 else if (cls == backend.jsBoolClass) hasBool = true; |
| 2242 else if (cls == backend.jsDoubleClass) hasDouble = true; | 2244 else if (cls == backend.jsDoubleClass) hasDouble = true; |
| 2243 else if (cls == backend.jsFunctionClass) hasFunction = true; | 2245 else if (cls == backend.jsFunctionClass) hasFunction = true; |
| 2244 else if (cls == backend.jsIntClass) hasInt = true; | 2246 else if (cls == backend.jsIntClass) hasInt = true; |
| 2245 else if (cls == backend.jsNullClass) hasNull = true; | 2247 else if (cls == backend.jsNullClass) hasNull = true; |
| 2246 else if (cls == backend.jsNumberClass) hasNumber = true; | 2248 else if (cls == backend.jsNumberClass) hasNumber = true; |
| 2247 else if (cls == backend.jsStringClass) hasString = true; | 2249 else if (cls == backend.jsStringClass) hasString = true; |
| 2248 else { | 2250 else { |
| 2249 assert(cls == compiler.objectClass); | 2251 // TODO(sra): The set of classes includes classes mixed-in to |
| 2252 // interceptor classes. |
| 2253 // assert(cls == compiler.objectClass || cls.isNative()); |
| 2250 } | 2254 } |
| 2251 } | 2255 } |
| 2252 if (hasDouble) { | 2256 if (hasDouble) { |
| 2253 hasNumber = true; | 2257 hasNumber = true; |
| 2254 } | 2258 } |
| 2255 if (hasInt) hasNumber = true; | 2259 if (hasInt) hasNumber = true; |
| 2256 | 2260 |
| 2257 jsAst.Block block = new jsAst.Block.empty(); | 2261 jsAst.Block block = new jsAst.Block.empty(); |
| 2258 | 2262 |
| 2259 if (hasNumber) { | 2263 if (hasNumber) { |
| (...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2786 """; | 2790 """; |
| 2787 const String HOOKS_API_USAGE = """ | 2791 const String HOOKS_API_USAGE = """ |
| 2788 // The code supports the following hooks: | 2792 // The code supports the following hooks: |
| 2789 // dartPrint(message) - if this function is defined it is called | 2793 // dartPrint(message) - if this function is defined it is called |
| 2790 // instead of the Dart [print] method. | 2794 // instead of the Dart [print] method. |
| 2791 // dartMainRunner(main) - if this function is defined, the Dart [main] | 2795 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 2792 // method will not be invoked directly. | 2796 // method will not be invoked directly. |
| 2793 // Instead, a closure that will invoke [main] is | 2797 // Instead, a closure that will invoke [main] is |
| 2794 // passed to [dartMainRunner]. | 2798 // passed to [dartMainRunner]. |
| 2795 """; | 2799 """; |
| OLD | NEW |