| 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 typedef void Recompile(Element element); | 7 typedef void Recompile(Element element); |
| 8 | 8 |
| 9 class ReturnInfo { | 9 class ReturnInfo { |
| 10 HType returnType; | 10 HType returnType; |
| (...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 692 */ | 692 */ |
| 693 final Set<Selector> usedInterceptors; | 693 final Set<Selector> usedInterceptors; |
| 694 | 694 |
| 695 /** | 695 /** |
| 696 * A collection of selectors that must have a one shot interceptor | 696 * A collection of selectors that must have a one shot interceptor |
| 697 * generated. | 697 * generated. |
| 698 */ | 698 */ |
| 699 final Map<String, Selector> oneShotInterceptors; | 699 final Map<String, Selector> oneShotInterceptors; |
| 700 | 700 |
| 701 /** | 701 /** |
| 702 * The members of instantiated interceptor classes: maps a member | 702 * The members of instantiated interceptor classes: maps a member name to the |
| 703 * name to the list of members that have that name. This map is used | 703 * list of members that have that name. This map is used by the codegen to |
| 704 * by the codegen to know whether a send must be intercepted or not. | 704 * know whether a send must be intercepted or not. |
| 705 */ | 705 */ |
| 706 final Map<SourceString, Set<Element>> interceptedElements; | 706 final Map<SourceString, Set<Element>> interceptedElements; |
| 707 // TODO(sra): Not all methods in the Set always require an interceptor. A |
| 708 // method may be mixed into a true interceptor *and* a plain class. For the |
| 709 // method to work on the interceptor class it needs to use the explicit |
| 710 // receiver. This constrains the call on a known plain receiver to pass the |
| 711 // explicit receiver. https://code.google.com/p/dart/issues/detail?id=8942 |
| 707 | 712 |
| 708 /** | 713 /** |
| 709 * A map of specialized versions of the [getInterceptorMethod]. | 714 * A map of specialized versions of the [getInterceptorMethod]. |
| 710 * Since [getInterceptorMethod] is a hot method at runtime, we're | 715 * Since [getInterceptorMethod] is a hot method at runtime, we're |
| 711 * always specializing it based on the incoming type. The keys in | 716 * always specializing it based on the incoming type. The keys in |
| 712 * the map are the names of these specialized versions. Note that | 717 * the map are the names of these specialized versions. Note that |
| 713 * the generic version that contains all possible type checks is | 718 * the generic version that contains all possible type checks is |
| 714 * also stored in this map. | 719 * also stored in this map. |
| 715 */ | 720 */ |
| 716 final Map<String, Collection<ClassElement>> specializedGetInterceptors; | 721 final Map<String, Collection<ClassElement>> specializedGetInterceptors; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 argumentTypes = new ArgumentTypesRegistry(this); | 765 argumentTypes = new ArgumentTypesRegistry(this); |
| 761 fieldTypes = new FieldTypesRegistry(this); | 766 fieldTypes = new FieldTypesRegistry(this); |
| 762 } | 767 } |
| 763 | 768 |
| 764 static Namer determineNamer(Compiler compiler) { | 769 static Namer determineNamer(Compiler compiler) { |
| 765 return compiler.enableMinification ? | 770 return compiler.enableMinification ? |
| 766 new MinifyNamer(compiler) : | 771 new MinifyNamer(compiler) : |
| 767 new Namer(compiler); | 772 new Namer(compiler); |
| 768 } | 773 } |
| 769 | 774 |
| 770 bool isInterceptorClass(Element element) { | 775 bool isInterceptorClass(ClassElement element) { |
| 771 if (element == null) return false; | 776 if (element == null) return false; |
| 777 if (element.isNative()) return true; |
| 772 return interceptedClasses.contains(element); | 778 return interceptedClasses.contains(element); |
| 773 } | 779 } |
| 774 | 780 |
| 775 void addInterceptedSelector(Selector selector) { | 781 void addInterceptedSelector(Selector selector) { |
| 776 usedInterceptors.add(selector); | 782 usedInterceptors.add(selector); |
| 777 } | 783 } |
| 778 | 784 |
| 779 String registerOneShotInterceptor(Selector selector) { | 785 String registerOneShotInterceptor(Selector selector) { |
| 780 Set<ClassElement> classes = getInterceptedClassesOn(selector.name); | 786 Set<ClassElement> classes = getInterceptedClassesOn(selector.name); |
| 781 String name = namer.getOneShotInterceptorName(selector, classes); | 787 String name = namer.getOneShotInterceptorName(selector, classes); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 813 * [name]. Returns [:null:] if there is no class. | 819 * [name]. Returns [:null:] if there is no class. |
| 814 */ | 820 */ |
| 815 Set<ClassElement> getInterceptedClassesOn(SourceString name) { | 821 Set<ClassElement> getInterceptedClassesOn(SourceString name) { |
| 816 Set<Element> intercepted = interceptedElements[name]; | 822 Set<Element> intercepted = interceptedElements[name]; |
| 817 if (intercepted == null) return null; | 823 if (intercepted == null) return null; |
| 818 return interceptedClassesCache.putIfAbsent(name, () { | 824 return interceptedClassesCache.putIfAbsent(name, () { |
| 819 // Populate the cache by running through all the elements and | 825 // Populate the cache by running through all the elements and |
| 820 // determine if the given selector applies to them. | 826 // determine if the given selector applies to them. |
| 821 Set<ClassElement> result = new Set<ClassElement>(); | 827 Set<ClassElement> result = new Set<ClassElement>(); |
| 822 for (Element element in intercepted) { | 828 for (Element element in intercepted) { |
| 823 result.add(element.getEnclosingClass()); | 829 ClassElement classElement = element.getEnclosingClass(); |
| 830 result.add(classElement); |
| 824 } | 831 } |
| 825 return result; | 832 return result; |
| 826 }); | 833 }); |
| 827 } | 834 } |
| 828 | 835 |
| 829 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) { | 836 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) { |
| 830 return specialOperatorEqClasses.contains( | 837 return specialOperatorEqClasses.contains( |
| 831 operatorEqfunction.getEnclosingClass()); | 838 operatorEqfunction.getEnclosingClass()); |
| 832 } | 839 } |
| 833 | 840 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 895 mapLiteralClass = | 902 mapLiteralClass = |
| 896 compiler.coreLibrary.find(const SourceString('LinkedHashMap')); | 903 compiler.coreLibrary.find(const SourceString('LinkedHashMap')); |
| 897 constMapLiteralClass = | 904 constMapLiteralClass = |
| 898 compiler.findHelper(const SourceString('ConstantMap')); | 905 compiler.findHelper(const SourceString('ConstantMap')); |
| 899 | 906 |
| 900 specialOperatorEqClasses | 907 specialOperatorEqClasses |
| 901 ..add(jsNullClass) | 908 ..add(jsNullClass) |
| 902 ..add(jsNumberClass); | 909 ..add(jsNumberClass); |
| 903 } | 910 } |
| 904 | 911 |
| 912 void addInterceptorsForNativeClassMembers( |
| 913 ClassElement cls, Enqueuer enqueuer) { |
| 914 if (enqueuer.isResolutionQueue) { |
| 915 cls.ensureResolved(compiler); |
| 916 cls.forEachMember((ClassElement classElement, Element member) { |
| 917 Set<Element> set = interceptedElements.putIfAbsent( |
| 918 member.name, () => new Set<Element>()); |
| 919 set.add(member); |
| 920 }, |
| 921 includeSuperMembers: true); |
| 922 } |
| 923 } |
| 924 |
| 905 void addInterceptors(ClassElement cls, | 925 void addInterceptors(ClassElement cls, |
| 906 Enqueuer enqueuer, | 926 Enqueuer enqueuer, |
| 907 TreeElements elements) { | 927 TreeElements elements) { |
| 908 if (enqueuer.isResolutionQueue) { | 928 if (enqueuer.isResolutionQueue) { |
| 909 cls.ensureResolved(compiler); | 929 cls.ensureResolved(compiler); |
| 910 cls.forEachMember((ClassElement classElement, Element member) { | 930 cls.forEachMember((ClassElement classElement, Element member) { |
| 911 Set<Element> set = interceptedElements.putIfAbsent( | 931 Set<Element> set = interceptedElements.putIfAbsent( |
| 912 member.name, () => new Set<Element>()); | 932 member.name, () => new Set<Element>()); |
| 913 set.add(member); | 933 set.add(member); |
| 914 }, | 934 }, |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 991 addInterceptors(jsFunctionClass, enqueuer, elements); | 1011 addInterceptors(jsFunctionClass, enqueuer, elements); |
| 992 } else if (cls == compiler.boolClass) { | 1012 } else if (cls == compiler.boolClass) { |
| 993 addInterceptors(jsBoolClass, enqueuer, elements); | 1013 addInterceptors(jsBoolClass, enqueuer, elements); |
| 994 } else if (cls == compiler.nullClass) { | 1014 } else if (cls == compiler.nullClass) { |
| 995 addInterceptors(jsNullClass, enqueuer, elements); | 1015 addInterceptors(jsNullClass, enqueuer, elements); |
| 996 } else if (cls == compiler.numClass) { | 1016 } else if (cls == compiler.numClass) { |
| 997 addInterceptors(jsIntClass, enqueuer, elements); | 1017 addInterceptors(jsIntClass, enqueuer, elements); |
| 998 addInterceptors(jsDoubleClass, enqueuer, elements); | 1018 addInterceptors(jsDoubleClass, enqueuer, elements); |
| 999 addInterceptors(jsNumberClass, enqueuer, elements); | 1019 addInterceptors(jsNumberClass, enqueuer, elements); |
| 1000 } else if (cls == compiler.mapClass) { | 1020 } else if (cls == compiler.mapClass) { |
| 1021 } else if (cls.isNative()) { |
| 1022 addInterceptorsForNativeClassMembers(cls, enqueuer); |
| 1001 } | 1023 } |
| 1002 | 1024 |
| 1003 if (compiler.enableTypeAssertions) { | 1025 if (compiler.enableTypeAssertions) { |
| 1004 // We need to register is checks for assignments to fields. | 1026 // We need to register is checks for assignments to fields. |
| 1005 cls.forEachLocalMember((Element member) { | 1027 cls.forEachLocalMember((Element member) { |
| 1006 if (!member.isInstanceMember() || !member.isField()) return; | 1028 if (!member.isInstanceMember() || !member.isField()) return; |
| 1007 DartType type = member.computeType(compiler); | 1029 DartType type = member.computeType(compiler); |
| 1008 enqueuer.registerIsCheck(type, elements); | 1030 enqueuer.registerIsCheck(type, elements); |
| 1009 }); | 1031 }); |
| 1010 } | 1032 } |
| (...skipping 637 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1648 ClassElement get constListImplementation => jsArrayClass; | 1670 ClassElement get constListImplementation => jsArrayClass; |
| 1649 ClassElement get fixedListImplementation => jsFixedArrayClass; | 1671 ClassElement get fixedListImplementation => jsFixedArrayClass; |
| 1650 ClassElement get growableListImplementation => jsExtendableArrayClass; | 1672 ClassElement get growableListImplementation => jsExtendableArrayClass; |
| 1651 ClassElement get mapImplementation => mapLiteralClass; | 1673 ClassElement get mapImplementation => mapLiteralClass; |
| 1652 ClassElement get constMapImplementation => constMapLiteralClass; | 1674 ClassElement get constMapImplementation => constMapLiteralClass; |
| 1653 ClassElement get functionImplementation => jsFunctionClass; | 1675 ClassElement get functionImplementation => jsFunctionClass; |
| 1654 ClassElement get typeImplementation => typeLiteralClass; | 1676 ClassElement get typeImplementation => typeLiteralClass; |
| 1655 ClassElement get boolImplementation => jsBoolClass; | 1677 ClassElement get boolImplementation => jsBoolClass; |
| 1656 ClassElement get nullImplementation => jsNullClass; | 1678 ClassElement get nullImplementation => jsNullClass; |
| 1657 } | 1679 } |
| OLD | NEW |