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