 Chromium Code Reviews
 Chromium Code Reviews Issue 11348177:
  Cleanup after the interceptor refactoring work, and add a new SSA instruction for an interceptor, s…  (Closed) 
  Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
    
  
    Issue 11348177:
  Cleanup after the interceptor refactoring work, and add a new SSA instruction for an interceptor, s…  (Closed) 
  Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/| 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 |