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 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
688 * emitter uses this set to generate the [:ObjectInterceptor:] class | 688 * emitter uses this set to generate the [:ObjectInterceptor:] class |
689 * whose members just forward the call to the intercepted receiver. | 689 * whose members just forward the call to the intercepted receiver. |
690 */ | 690 */ |
691 final Set<Selector> usedInterceptors; | 691 final Set<Selector> usedInterceptors; |
692 | 692 |
693 /** | 693 /** |
694 * The members of instantiated interceptor classes: maps a member | 694 * The members of instantiated interceptor classes: maps a member |
695 * name to the list of members that have that name. This map is used | 695 * name to the list of members that have that name. This map is used |
696 * by the codegen to know whether a send must be intercepted or not. | 696 * by the codegen to know whether a send must be intercepted or not. |
697 */ | 697 */ |
698 final Map<SourceString, List<Element>> interceptedElements; | 698 final Map<SourceString, Set<Element>> interceptedElements; |
699 | 699 |
700 List<CompilerTask> get tasks { | 700 List<CompilerTask> get tasks { |
701 return <CompilerTask>[builder, optimizer, generator, emitter]; | 701 return <CompilerTask>[builder, optimizer, generator, emitter]; |
702 } | 702 } |
703 | 703 |
704 final RuntimeTypeInformation rti; | 704 final RuntimeTypeInformation rti; |
705 | 705 |
706 JavaScriptBackend(Compiler compiler, bool generateSourceMap, bool disableEval) | 706 JavaScriptBackend(Compiler compiler, bool generateSourceMap, bool disableEval) |
707 : namer = determineNamer(compiler), | 707 : namer = determineNamer(compiler), |
708 returnInfo = new Map<Element, ReturnInfo>(), | 708 returnInfo = new Map<Element, ReturnInfo>(), |
709 invalidateAfterCodegen = new List<Element>(), | 709 invalidateAfterCodegen = new List<Element>(), |
710 interceptors = new Interceptors(compiler), | 710 interceptors = new Interceptors(compiler), |
711 usedInterceptors = new Set<Selector>(), | 711 usedInterceptors = new Set<Selector>(), |
712 interceptedElements = new Map<SourceString, List<Element>>(), | 712 interceptedElements = new Map<SourceString, Set<Element>>(), |
713 rti = new RuntimeTypeInformation(compiler), | 713 rti = new RuntimeTypeInformation(compiler), |
714 super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) { | 714 super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) { |
715 emitter = disableEval | 715 emitter = disableEval |
716 ? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap) | 716 ? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap) |
717 : new CodeEmitterTask(compiler, namer, generateSourceMap); | 717 : new CodeEmitterTask(compiler, namer, generateSourceMap); |
718 builder = new SsaBuilderTask(this); | 718 builder = new SsaBuilderTask(this); |
719 optimizer = new SsaOptimizerTask(this); | 719 optimizer = new SsaOptimizerTask(this); |
720 generator = new SsaCodeGeneratorTask(this); | 720 generator = new SsaCodeGeneratorTask(this); |
721 argumentTypes = new ArgumentTypesRegistry(this); | 721 argumentTypes = new ArgumentTypesRegistry(this); |
722 fieldTypes = new FieldTypesRegistry(this); | 722 fieldTypes = new FieldTypesRegistry(this); |
(...skipping 14 matching lines...) Expand all Loading... | |
737 || element == jsNullClass | 737 || element == jsNullClass |
738 || element == jsFunctionClass | 738 || element == jsFunctionClass |
739 || element == jsBoolClass | 739 || element == jsBoolClass |
740 || element == jsNumberClass; | 740 || element == jsNumberClass; |
741 } | 741 } |
742 | 742 |
743 void addInterceptedSelector(Selector selector) { | 743 void addInterceptedSelector(Selector selector) { |
744 usedInterceptors.add(selector); | 744 usedInterceptors.add(selector); |
745 } | 745 } |
746 | 746 |
747 bool shouldInterceptSelector(Selector selector) { | 747 /** |
748 List<Element> intercepted = interceptedElements[selector.name]; | 748 * Returns a set of interceptor classes that contain a member whose |
749 if (intercepted == null) return false; | 749 * signature matches the given [selector]. Returns [:null:] if there |
750 * is no class. | |
751 */ | |
752 Set<ClassElement> getInterceptedClassesOn(Selector selector) { | |
ahe
2012/11/22 13:26:11
How about computing the reverse mapping? This see
ngeoffray
2012/11/22 13:37:59
As discussed, we already have the reverse mapping,
| |
753 Set<Element> intercepted = interceptedElements[selector.name]; | |
754 if (intercepted == null) return null; | |
755 Set<ClassElement> result = new Set<ClassElement>(); | |
750 for (Element element in intercepted) { | 756 for (Element element in intercepted) { |
751 if (selector.applies(element, compiler)) return true; | 757 if (selector.applies(element, compiler)) { |
758 result.add(element.getEnclosingClass()); | |
759 } | |
752 } | 760 } |
753 return false; | 761 if (result.isEmpty) return null; |
762 return result; | |
754 } | 763 } |
755 | 764 |
756 void initializeInterceptorElements() { | 765 void initializeInterceptorElements() { |
757 objectInterceptorClass = | 766 objectInterceptorClass = |
758 compiler.findInterceptor(const SourceString('ObjectInterceptor')); | 767 compiler.findInterceptor(const SourceString('ObjectInterceptor')); |
759 getInterceptorMethod = | 768 getInterceptorMethod = |
760 compiler.findInterceptor(const SourceString('getInterceptor')); | 769 compiler.findInterceptor(const SourceString('getInterceptor')); |
761 jsStringClass = | 770 jsStringClass = |
762 compiler.findInterceptor(const SourceString('JSString')); | 771 compiler.findInterceptor(const SourceString('JSString')); |
763 jsArrayClass = | 772 jsArrayClass = |
(...skipping 16 matching lines...) Expand all Loading... | |
780 jsStringClass.ensureResolved(compiler); | 789 jsStringClass.ensureResolved(compiler); |
781 jsStringLength = | 790 jsStringLength = |
782 jsStringClass.lookupLocalMember(const SourceString('length')); | 791 jsStringClass.lookupLocalMember(const SourceString('length')); |
783 listImplementation = | 792 listImplementation = |
784 compiler.coreLibrary.find(const SourceString('ListImplementation')); | 793 compiler.coreLibrary.find(const SourceString('ListImplementation')); |
785 } | 794 } |
786 | 795 |
787 void addInterceptors(ClassElement cls) { | 796 void addInterceptors(ClassElement cls) { |
788 cls.ensureResolved(compiler); | 797 cls.ensureResolved(compiler); |
789 cls.forEachMember((ClassElement classElement, Element member) { | 798 cls.forEachMember((ClassElement classElement, Element member) { |
790 // TODO(ngeoffray): Support interceptors on Object methods. | 799 Set<Element> set = interceptedElements.putIfAbsent( |
791 if (classElement == compiler.objectClass) return; | 800 member.name, () => new Set<Element>()); |
792 List<Element> list = interceptedElements.putIfAbsent( | 801 set.add(member); |
793 member.name, () => new List<Element>()); | 802 }, |
794 list.add(member); | 803 includeSuperMembers: true); |
795 }, includeSuperMembers: true); | |
796 } | 804 } |
797 | 805 |
798 void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) { | 806 void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) { |
799 ClassElement result = null; | 807 ClassElement result = null; |
800 if (!_interceptorsAreInitialized) { | 808 if (!_interceptorsAreInitialized) { |
801 initializeInterceptorElements(); | 809 initializeInterceptorElements(); |
802 _interceptorsAreInitialized = true; | 810 _interceptorsAreInitialized = true; |
803 // The null interceptor and the function interceptor are | 811 // The null interceptor and the function interceptor are |
804 // currently always instantiated if a new class is instantiated. | 812 // currently always instantiated if a new class is instantiated. |
805 // TODO(ngeoffray): do this elsewhere for the function | 813 // TODO(ngeoffray): do this elsewhere for the function |
806 // interceptor? | 814 // interceptor? |
807 if (jsNullClass != null) { | 815 if (jsNullClass != null) { |
808 addInterceptors(jsNullClass); | 816 addInterceptors(jsNullClass); |
809 enqueuer.registerInstantiatedClass(jsNullClass); | 817 enqueuer.registerInstantiatedClass(jsNullClass); |
810 } | 818 } |
811 if (jsFunctionClass != null) { | 819 if (jsFunctionClass != null) { |
812 addInterceptors(jsFunctionClass); | 820 addInterceptors(jsFunctionClass); |
813 enqueuer.registerInstantiatedClass(jsFunctionClass); | 821 enqueuer.registerInstantiatedClass(jsFunctionClass); |
814 } | 822 } |
823 enqueuer.addToWorkList(getInterceptorMethod); | |
815 } | 824 } |
816 if (cls == compiler.stringClass) { | 825 if (cls == compiler.stringClass) { |
817 result = jsStringClass; | 826 result = jsStringClass; |
818 } else if (cls == compiler.listClass || cls == listImplementation) { | 827 } else if (cls == compiler.listClass || cls == listImplementation) { |
819 result = jsArrayClass; | 828 result = jsArrayClass; |
820 } else if (cls == compiler.intClass) { | 829 } else if (cls == compiler.intClass) { |
821 result = jsIntClass; | 830 result = jsIntClass; |
822 } else if (cls == compiler.doubleClass) { | 831 } else if (cls == compiler.doubleClass) { |
823 result = jsDoubleClass; | 832 result = jsDoubleClass; |
824 } else if (cls == compiler.functionClass) { | 833 } else if (cls == compiler.functionClass) { |
825 result = jsFunctionClass; | 834 result = jsFunctionClass; |
826 } else if (cls == compiler.boolClass) { | 835 } else if (cls == compiler.boolClass) { |
827 result = jsBoolClass; | 836 result = jsBoolClass; |
828 } | 837 } |
829 | 838 |
830 if (result == null) return; | 839 if (result == null) return; |
831 if (enqueuer.isResolutionQueue) addInterceptors(result); | 840 if (enqueuer.isResolutionQueue) addInterceptors(result); |
832 enqueuer.registerInstantiatedClass(result); | 841 enqueuer.registerInstantiatedClass(result); |
833 } | 842 } |
834 | 843 |
835 Element get cyclicThrowHelper { | 844 Element get cyclicThrowHelper { |
836 return compiler.findHelper(const SourceString("throwCyclicInit")); | 845 return compiler.findHelper(const SourceString("throwCyclicInit")); |
837 } | 846 } |
838 | 847 |
839 JavaScriptItemCompilationContext createItemCompilationContext() { | 848 JavaScriptItemCompilationContext createItemCompilationContext() { |
840 return new JavaScriptItemCompilationContext(); | 849 return new JavaScriptItemCompilationContext(); |
841 } | 850 } |
842 | 851 |
843 Element getInterceptor(Selector selector) { | |
844 return interceptors.getStaticInterceptor(selector); | |
845 } | |
846 | |
847 void enqueueHelpers(Enqueuer world) { | 852 void enqueueHelpers(Enqueuer world) { |
848 enqueueAllTopLevelFunctions(compiler.jsHelperLibrary, world); | 853 enqueueAllTopLevelFunctions(compiler.jsHelperLibrary, world); |
849 | 854 |
850 jsIndexingBehaviorInterface = | 855 jsIndexingBehaviorInterface = |
851 compiler.findHelper(const SourceString('JavaScriptIndexingBehavior')); | 856 compiler.findHelper(const SourceString('JavaScriptIndexingBehavior')); |
852 if (jsIndexingBehaviorInterface != null) { | 857 if (jsIndexingBehaviorInterface != null) { |
853 world.registerIsCheck(jsIndexingBehaviorInterface.computeType(compiler)); | 858 world.registerIsCheck(jsIndexingBehaviorInterface.computeType(compiler)); |
854 } | 859 } |
855 | 860 |
856 for (var helper in [const SourceString('Closure'), | 861 for (var helper in [const SourceString('Closure'), |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1098 print("Inferred return types:"); | 1103 print("Inferred return types:"); |
1099 print("----------------------"); | 1104 print("----------------------"); |
1100 dumpReturnTypes(); | 1105 dumpReturnTypes(); |
1101 print(""); | 1106 print(""); |
1102 print("Inferred field types:"); | 1107 print("Inferred field types:"); |
1103 print("------------------------"); | 1108 print("------------------------"); |
1104 fieldTypes.dump(); | 1109 fieldTypes.dump(); |
1105 print(""); | 1110 print(""); |
1106 } | 1111 } |
1107 } | 1112 } |
OLD | NEW |