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 721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
732 * always specializing it based on the incoming type. The keys in | 732 * always specializing it based on the incoming type. The keys in |
733 * the map are the names of these specialized versions. Note that | 733 * the map are the names of these specialized versions. Note that |
734 * the generic version that contains all possible type checks is | 734 * the generic version that contains all possible type checks is |
735 * also stored in this map. | 735 * also stored in this map. |
736 */ | 736 */ |
737 final Map<String, Collection<ClassElement>> specializedGetInterceptors; | 737 final Map<String, Collection<ClassElement>> specializedGetInterceptors; |
738 | 738 |
739 /** | 739 /** |
740 * Set of classes whose methods are intercepted. | 740 * Set of classes whose methods are intercepted. |
741 */ | 741 */ |
742 final Set<ClassElement> interceptedClasses; | 742 final Set<ClassElement> interceptedClasses = new Set<ClassElement>(); |
| 743 |
| 744 /** |
| 745 * Set of classes used as mixins on native classes. Methods on these classes |
| 746 * might also be mixed in to non-native classes. |
| 747 */ |
| 748 final Set<ClassElement> classesMixedIntoNativeClasses = |
| 749 new Set<ClassElement>(); |
743 | 750 |
744 /** | 751 /** |
745 * Set of classes whose `operator ==` methods handle `null` themselves. | 752 * Set of classes whose `operator ==` methods handle `null` themselves. |
746 */ | 753 */ |
747 final Set<ClassElement> specialOperatorEqClasses = new Set<ClassElement>(); | 754 final Set<ClassElement> specialOperatorEqClasses = new Set<ClassElement>(); |
748 | 755 |
749 List<CompilerTask> get tasks { | 756 List<CompilerTask> get tasks { |
750 return <CompilerTask>[builder, optimizer, generator, emitter]; | 757 return <CompilerTask>[builder, optimizer, generator, emitter]; |
751 } | 758 } |
752 | 759 |
753 final RuntimeTypes rti; | 760 final RuntimeTypes rti; |
754 | 761 |
755 JavaScriptBackend(Compiler compiler, bool generateSourceMap, bool disableEval) | 762 JavaScriptBackend(Compiler compiler, bool generateSourceMap, bool disableEval) |
756 : namer = determineNamer(compiler), | 763 : namer = determineNamer(compiler), |
757 returnInfo = new Map<Element, ReturnInfo>(), | 764 returnInfo = new Map<Element, ReturnInfo>(), |
758 invalidateAfterCodegen = new List<Element>(), | 765 invalidateAfterCodegen = new List<Element>(), |
759 usedInterceptors = new Set<Selector>(), | 766 usedInterceptors = new Set<Selector>(), |
760 oneShotInterceptors = new Map<String, Selector>(), | 767 oneShotInterceptors = new Map<String, Selector>(), |
761 interceptedElements = new Map<SourceString, Set<Element>>(), | 768 interceptedElements = new Map<SourceString, Set<Element>>(), |
762 rti = new RuntimeTypes(compiler), | 769 rti = new RuntimeTypes(compiler), |
763 specializedGetInterceptors = | 770 specializedGetInterceptors = |
764 new Map<String, Collection<ClassElement>>(), | 771 new Map<String, Collection<ClassElement>>(), |
765 interceptedClasses = new Set<ClassElement>(), | |
766 super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) { | 772 super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) { |
767 emitter = disableEval | 773 emitter = disableEval |
768 ? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap) | 774 ? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap) |
769 : new CodeEmitterTask(compiler, namer, generateSourceMap); | 775 : new CodeEmitterTask(compiler, namer, generateSourceMap); |
770 builder = new SsaBuilderTask(this); | 776 builder = new SsaBuilderTask(this); |
771 optimizer = new SsaOptimizerTask(this); | 777 optimizer = new SsaOptimizerTask(this); |
772 generator = new SsaCodeGeneratorTask(this); | 778 generator = new SsaCodeGeneratorTask(this); |
773 argumentTypes = new ArgumentTypesRegistry(this); | 779 argumentTypes = new ArgumentTypesRegistry(this); |
774 fieldTypes = new FieldTypesRegistry(this); | 780 fieldTypes = new FieldTypesRegistry(this); |
775 } | 781 } |
776 | 782 |
777 static Namer determineNamer(Compiler compiler) { | 783 static Namer determineNamer(Compiler compiler) { |
778 return compiler.enableMinification ? | 784 return compiler.enableMinification ? |
779 new MinifyNamer(compiler) : | 785 new MinifyNamer(compiler) : |
780 new Namer(compiler); | 786 new Namer(compiler); |
781 } | 787 } |
782 | 788 |
783 bool isInterceptorClass(ClassElement element) { | 789 bool isInterceptorClass(ClassElement element) { |
784 if (element == null) return false; | 790 if (element == null) return false; |
785 if (element.isNative()) return true; | 791 if (element.isNative()) return true; |
786 return interceptedClasses.contains(element); | 792 if (interceptedClasses.contains(element)) return true; |
| 793 if (classesMixedIntoNativeClasses.contains(element)) return true; |
| 794 return false; |
787 } | 795 } |
788 | 796 |
789 void addInterceptedSelector(Selector selector) { | 797 void addInterceptedSelector(Selector selector) { |
790 usedInterceptors.add(selector); | 798 usedInterceptors.add(selector); |
791 } | 799 } |
792 | 800 |
793 String registerOneShotInterceptor(Selector selector) { | 801 String registerOneShotInterceptor(Selector selector) { |
794 Set<ClassElement> classes = getInterceptedClassesOn(selector.name); | 802 Set<ClassElement> classes = getInterceptedClassesOn(selector.name); |
795 String name = namer.getOneShotInterceptorName(selector, classes); | 803 String name = namer.getOneShotInterceptorName(selector, classes); |
796 if (!oneShotInterceptors.containsKey(name)) { | 804 if (!oneShotInterceptors.containsKey(name)) { |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
942 // Interceptors must override all Object methods due to calling convention | 950 // Interceptors must override all Object methods due to calling convention |
943 // differences. | 951 // differences. |
944 assert(interceptorMember.getEnclosingClass() != compiler.objectClass); | 952 assert(interceptorMember.getEnclosingClass() != compiler.objectClass); |
945 }); | 953 }); |
946 } | 954 } |
947 | 955 |
948 void addInterceptorsForNativeClassMembers( | 956 void addInterceptorsForNativeClassMembers( |
949 ClassElement cls, Enqueuer enqueuer) { | 957 ClassElement cls, Enqueuer enqueuer) { |
950 if (enqueuer.isResolutionQueue) { | 958 if (enqueuer.isResolutionQueue) { |
951 cls.ensureResolved(compiler); | 959 cls.ensureResolved(compiler); |
952 addInterceptorMembers(cls); | 960 cls.forEachMember((ClassElement classElement, Element member) { |
| 961 // All methods on [Object] are shadowed by [Interceptor]. |
| 962 if (classElement == compiler.objectClass) return; |
| 963 Set<Element> set = interceptedElements.putIfAbsent( |
| 964 member.name, () => new Set<Element>()); |
| 965 set.add(member); |
| 966 if (!classElement.isNative()) { |
| 967 MixinApplicationElement mixinApplication = classElement; |
| 968 assert(member.getEnclosingClass() == mixinApplication.mixin); |
| 969 classesMixedIntoNativeClasses.add(mixinApplication.mixin); |
| 970 } |
| 971 }, |
| 972 includeSuperMembers: true); |
953 } | 973 } |
954 } | 974 } |
955 | 975 |
956 void addInterceptors(ClassElement cls, | 976 void addInterceptors(ClassElement cls, |
957 Enqueuer enqueuer, | 977 Enqueuer enqueuer, |
958 TreeElements elements) { | 978 TreeElements elements) { |
959 if (enqueuer.isResolutionQueue) { | 979 if (enqueuer.isResolutionQueue) { |
960 cls.ensureResolved(compiler); | 980 cls.ensureResolved(compiler); |
961 addInterceptorMembers(cls); | 981 cls.forEachMember((ClassElement classElement, Element member) { |
| 982 // All methods on [Object] are shadowed by [Interceptor]. |
| 983 if (classElement == compiler.objectClass) return; |
| 984 Set<Element> set = interceptedElements.putIfAbsent( |
| 985 member.name, () => new Set<Element>()); |
| 986 set.add(member); |
| 987 }, |
| 988 includeSuperMembers: true); |
962 } | 989 } |
963 enqueuer.registerInstantiatedClass(cls, elements); | 990 enqueuer.registerInstantiatedClass(cls, elements); |
964 } | 991 } |
965 | 992 |
966 void addInterceptorMembers(ClassElement cls) { | |
967 cls.forEachMember((ClassElement classElement, Element member) { | |
968 // All methods on [Object] are shadowed by [Interceptor]. | |
969 if (classElement == compiler.objectClass) return; | |
970 Set<Element> set = interceptedElements.putIfAbsent( | |
971 member.name, () => new Set<Element>()); | |
972 set.add(member); | |
973 }, | |
974 includeSuperMembers: true); | |
975 } | |
976 | |
977 void registerSpecializedGetInterceptor(Set<ClassElement> classes) { | 993 void registerSpecializedGetInterceptor(Set<ClassElement> classes) { |
978 String name = namer.getInterceptorName(getInterceptorMethod, classes); | 994 String name = namer.getInterceptorName(getInterceptorMethod, classes); |
979 if (classes.contains(jsInterceptorClass)) { | 995 if (classes.contains(jsInterceptorClass)) { |
980 // We can't use a specialized [getInterceptorMethod], so we make | 996 // We can't use a specialized [getInterceptorMethod], so we make |
981 // sure we emit the one with all checks. | 997 // sure we emit the one with all checks. |
982 specializedGetInterceptors[name] = interceptedClasses; | 998 specializedGetInterceptors[name] = interceptedClasses; |
983 } else { | 999 } else { |
984 specializedGetInterceptors[name] = classes; | 1000 specializedGetInterceptors[name] = classes; |
985 } | 1001 } |
986 } | 1002 } |
(...skipping 754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1741 ClassElement get constListImplementation => jsArrayClass; | 1757 ClassElement get constListImplementation => jsArrayClass; |
1742 ClassElement get fixedListImplementation => jsFixedArrayClass; | 1758 ClassElement get fixedListImplementation => jsFixedArrayClass; |
1743 ClassElement get growableListImplementation => jsExtendableArrayClass; | 1759 ClassElement get growableListImplementation => jsExtendableArrayClass; |
1744 ClassElement get mapImplementation => mapLiteralClass; | 1760 ClassElement get mapImplementation => mapLiteralClass; |
1745 ClassElement get constMapImplementation => constMapLiteralClass; | 1761 ClassElement get constMapImplementation => constMapLiteralClass; |
1746 ClassElement get functionImplementation => jsFunctionClass; | 1762 ClassElement get functionImplementation => jsFunctionClass; |
1747 ClassElement get typeImplementation => typeLiteralClass; | 1763 ClassElement get typeImplementation => typeLiteralClass; |
1748 ClassElement get boolImplementation => jsBoolClass; | 1764 ClassElement get boolImplementation => jsBoolClass; |
1749 ClassElement get nullImplementation => jsNullClass; | 1765 ClassElement get nullImplementation => jsNullClass; |
1750 } | 1766 } |
OLD | NEW |