Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(204)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js_backend/backend.dart

Issue 11413184: Create specialized versions of getInterceptor. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 617 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 ClassElement jsNumberClass; 628 ClassElement jsNumberClass;
629 ClassElement jsIntClass; 629 ClassElement jsIntClass;
630 ClassElement jsDoubleClass; 630 ClassElement jsDoubleClass;
631 ClassElement jsFunctionClass; 631 ClassElement jsFunctionClass;
632 ClassElement jsNullClass; 632 ClassElement jsNullClass;
633 ClassElement jsBoolClass; 633 ClassElement jsBoolClass;
634 ClassElement objectInterceptorClass; 634 ClassElement objectInterceptorClass;
635 Element jsArrayLength; 635 Element jsArrayLength;
636 Element jsStringLength; 636 Element jsStringLength;
637 Element getInterceptorMethod; 637 Element getInterceptorMethod;
638 Element arrayInterceptor;
639 Element boolInterceptor;
640 Element doubleInterceptor;
641 Element functionInterceptor;
642 Element intInterceptor;
643 Element nullInterceptor;
644 Element numberInterceptor;
645 Element stringInterceptor;
646 bool _interceptorsAreInitialized = false; 638 bool _interceptorsAreInitialized = false;
647 639
648 final Namer namer; 640 final Namer namer;
649 641
650 /** 642 /**
651 * Interface used to determine if an object has the JavaScript 643 * Interface used to determine if an object has the JavaScript
652 * indexing behavior. The interface is only visible to specific 644 * indexing behavior. The interface is only visible to specific
653 * libraries. 645 * libraries.
654 */ 646 */
655 ClassElement jsIndexingBehaviorInterface; 647 ClassElement jsIndexingBehaviorInterface;
(...skipping 16 matching lines...) Expand all
672 * emitter uses this set to generate the [:ObjectInterceptor:] class 664 * emitter uses this set to generate the [:ObjectInterceptor:] class
673 * whose members just forward the call to the intercepted receiver. 665 * whose members just forward the call to the intercepted receiver.
674 */ 666 */
675 final Set<Selector> usedInterceptors; 667 final Set<Selector> usedInterceptors;
676 668
677 /** 669 /**
678 * The members of instantiated interceptor classes: maps a member 670 * The members of instantiated interceptor classes: maps a member
679 * name to the list of members that have that name. This map is used 671 * name to the list of members that have that name. This map is used
680 * by the codegen to know whether a send must be intercepted or not. 672 * by the codegen to know whether a send must be intercepted or not.
681 */ 673 */
682 final Map<SourceString, Set<Element>> interceptedElements; 674 final Map<SourceString, Set<Element>> interceptedElements;
675
676 /**
677 * A map of specialized versions of the [getInterceptorMethod].
678 * Since [getInterceptorMethod] is a hot method at runtime, we're
679 * always specializing it based on the incoming type. The keys in
680 * the map are the names of these specialized versions. Note that
681 * the generic version that contains all possible type checks is
682 * also stored in this map.
683 */
684 final Map<String, Collection<ClassElement>> specializedGetInterceptors;
ahe 2012/11/27 14:29:45 What is the key?
ngeoffray 2012/11/27 15:50:54 It's in the comment above: the name of the special
685
686 /**
687 * Set of classes whose instances are intercepted.
688 */
689 final Set<ClassElement> interceptedClasses;
683 690
684 List<CompilerTask> get tasks { 691 List<CompilerTask> get tasks {
685 return <CompilerTask>[builder, optimizer, generator, emitter]; 692 return <CompilerTask>[builder, optimizer, generator, emitter];
686 } 693 }
687 694
688 final RuntimeTypeInformation rti; 695 final RuntimeTypeInformation rti;
689 696
690 JavaScriptBackend(Compiler compiler, bool generateSourceMap, bool disableEval) 697 JavaScriptBackend(Compiler compiler, bool generateSourceMap, bool disableEval)
691 : namer = determineNamer(compiler), 698 : namer = determineNamer(compiler),
692 returnInfo = new Map<Element, ReturnInfo>(), 699 returnInfo = new Map<Element, ReturnInfo>(),
693 invalidateAfterCodegen = new List<Element>(), 700 invalidateAfterCodegen = new List<Element>(),
694 interceptors = new Interceptors(compiler), 701 interceptors = new Interceptors(compiler),
695 usedInterceptors = new Set<Selector>(), 702 usedInterceptors = new Set<Selector>(),
696 interceptedElements = new Map<SourceString, Set<Element>>(), 703 interceptedElements = new Map<SourceString, Set<Element>>(),
697 rti = new RuntimeTypeInformation(compiler), 704 rti = new RuntimeTypeInformation(compiler),
705 specializedGetInterceptors =
706 new Map<String, Collection<ClassElement>>(),
707 interceptedClasses = new Set<ClassElement>(),
698 super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) { 708 super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) {
699 emitter = disableEval 709 emitter = disableEval
700 ? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap) 710 ? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap)
701 : new CodeEmitterTask(compiler, namer, generateSourceMap); 711 : new CodeEmitterTask(compiler, namer, generateSourceMap);
702 builder = new SsaBuilderTask(this); 712 builder = new SsaBuilderTask(this);
703 optimizer = new SsaOptimizerTask(this); 713 optimizer = new SsaOptimizerTask(this);
704 generator = new SsaCodeGeneratorTask(this); 714 generator = new SsaCodeGeneratorTask(this);
705 argumentTypes = new ArgumentTypesRegistry(this); 715 argumentTypes = new ArgumentTypesRegistry(this);
706 fieldTypes = new FieldTypesRegistry(this); 716 fieldTypes = new FieldTypesRegistry(this);
707 } 717 }
708 718
709 static Namer determineNamer(Compiler compiler) { 719 static Namer determineNamer(Compiler compiler) {
710 return compiler.enableMinification ? 720 return compiler.enableMinification ?
711 new MinifyNamer(compiler) : 721 new MinifyNamer(compiler) :
712 new Namer(compiler); 722 new Namer(compiler);
713 } 723 }
714 724
715 bool isInterceptorClass(Element element) { 725 bool isInterceptorClass(Element element) {
716 if (element == null) return false; 726 if (element == null) return false;
717 return element == jsStringClass 727 return interceptedClasses.contains(element);
718 || element == jsArrayClass
719 || element == jsIntClass
720 || element == jsDoubleClass
721 || element == jsNullClass
722 || element == jsFunctionClass
723 || element == jsBoolClass
724 || element == jsNumberClass;
725 } 728 }
726 729
727 void addInterceptedSelector(Selector selector) { 730 void addInterceptedSelector(Selector selector) {
728 usedInterceptors.add(selector); 731 usedInterceptors.add(selector);
729 } 732 }
730 733
731 /** 734 /**
732 * Returns a set of interceptor classes that contain a member whose 735 * Returns a set of interceptor classes that contain a member whose
733 * signature matches the given [selector]. Returns [:null:] if there 736 * signature matches the given [selector]. Returns [:null:] if there
734 * is no class. 737 * is no class.
735 */ 738 */
736 Set<ClassElement> getInterceptedClassesOn(Selector selector) { 739 Set<ClassElement> getInterceptedClassesOn(Selector selector) {
737 Set<Element> intercepted = interceptedElements[selector.name]; 740 Set<Element> intercepted = interceptedElements[selector.name];
738 if (intercepted == null) return null; 741 if (intercepted == null) return null;
739 Set<ClassElement> result = new Set<ClassElement>(); 742 Set<ClassElement> result = new Set<ClassElement>();
740 for (Element element in intercepted) { 743 for (Element element in intercepted) {
741 if (selector.applies(element, compiler)) { 744 if (selector.applies(element, compiler)) {
742 result.add(element.getEnclosingClass()); 745 result.add(element.getEnclosingClass());
743 } 746 }
744 } 747 }
745 if (result.isEmpty) return null; 748 if (result.isEmpty) return null;
746 return result; 749 return result;
747 } 750 }
748 751
752 List<ClassElement> getListOfInterceptedClasses() {
753 return <ClassElement>[jsStringClass, jsArrayClass, jsIntClass,
ahe 2012/11/27 14:29:45 I suggest you create this list in initializeInterc
ngeoffray 2012/11/27 15:50:54 Done.
754 jsDoubleClass, jsNumberClass, jsNullClass,
755 jsFunctionClass, jsBoolClass];
756 }
757
749 void initializeInterceptorElements() { 758 void initializeInterceptorElements() {
750 objectInterceptorClass = 759 objectInterceptorClass =
751 compiler.findInterceptor(const SourceString('ObjectInterceptor')); 760 compiler.findInterceptor(const SourceString('ObjectInterceptor'));
752 getInterceptorMethod = 761 getInterceptorMethod =
753 compiler.findInterceptor(const SourceString('getInterceptor')); 762 compiler.findInterceptor(const SourceString('getInterceptor'));
754 jsStringClass = 763 jsStringClass =
755 compiler.findInterceptor(const SourceString('JSString')); 764 compiler.findInterceptor(const SourceString('JSString'));
756 jsArrayClass = 765 jsArrayClass =
757 compiler.findInterceptor(const SourceString('JSArray')); 766 compiler.findInterceptor(const SourceString('JSArray'));
758 jsNumberClass = 767 jsNumberClass =
759 compiler.findInterceptor(const SourceString('JSNumber')); 768 compiler.findInterceptor(const SourceString('JSNumber'));
760 jsIntClass = 769 jsIntClass =
761 compiler.findInterceptor(const SourceString('JSInt')); 770 compiler.findInterceptor(const SourceString('JSInt'));
762 jsDoubleClass = 771 jsDoubleClass =
763 compiler.findInterceptor(const SourceString('JSDouble')); 772 compiler.findInterceptor(const SourceString('JSDouble'));
764 jsNullClass = 773 jsNullClass =
765 compiler.findInterceptor(const SourceString('JSNull')); 774 compiler.findInterceptor(const SourceString('JSNull'));
766 jsFunctionClass = 775 jsFunctionClass =
767 compiler.findInterceptor(const SourceString('JSFunction')); 776 compiler.findInterceptor(const SourceString('JSFunction'));
768 jsBoolClass = 777 jsBoolClass =
769 compiler.findInterceptor(const SourceString('JSBool')); 778 compiler.findInterceptor(const SourceString('JSBool'));
770 jsArrayClass.ensureResolved(compiler); 779 jsArrayClass.ensureResolved(compiler);
771 jsArrayLength = 780 jsArrayLength =
772 jsArrayClass.lookupLocalMember(const SourceString('length')); 781 jsArrayClass.lookupLocalMember(const SourceString('length'));
773 jsStringClass.ensureResolved(compiler); 782 jsStringClass.ensureResolved(compiler);
774 jsStringLength = 783 jsStringLength =
775 jsStringClass.lookupLocalMember(const SourceString('length')); 784 jsStringClass.lookupLocalMember(const SourceString('length'));
776 785
777 arrayInterceptor = 786 interceptedClasses.addAll(getListOfInterceptedClasses());
778 compiler.findInterceptor(const SourceString('arrayInterceptor'));
779 boolInterceptor =
780 compiler.findInterceptor(const SourceString('boolInterceptor'));
781 doubleInterceptor =
782 compiler.findInterceptor(const SourceString('doubleInterceptor'));
783 functionInterceptor =
784 compiler.findInterceptor(const SourceString('functionInterceptor'));
785 intInterceptor =
786 compiler.findInterceptor(const SourceString('intInterceptor'));
787 nullInterceptor =
788 compiler.findInterceptor(const SourceString('nullInterceptor'));
789 stringInterceptor =
790 compiler.findInterceptor(const SourceString('stringInterceptor'));
791 numberInterceptor =
792 compiler.findInterceptor(const SourceString('numberInterceptor'));
793 } 787 }
794 788
795 void addInterceptors(ClassElement cls) { 789 void addInterceptors(ClassElement cls) {
796 cls.ensureResolved(compiler); 790 cls.ensureResolved(compiler);
797 cls.forEachMember((ClassElement classElement, Element member) { 791 cls.forEachMember((ClassElement classElement, Element member) {
798 Set<Element> set = interceptedElements.putIfAbsent( 792 Set<Element> set = interceptedElements.putIfAbsent(
799 member.name, () => new Set<Element>()); 793 member.name, () => new Set<Element>());
800 set.add(member); 794 set.add(member);
801 }, 795 },
802 includeSuperMembers: true); 796 includeSuperMembers: true);
803 } 797 }
804 798
799 String registerSpecializedGetInterceptor(
800 Set<ClassElement> interceptedClasses) {
801 compiler.enqueuer.codegen.registerInstantiatedClass(objectInterceptorClass);
802 if (interceptedClasses.contains(compiler.objectClass)) {
803 // We can't use a specialized [getInterceptorMethod], so we make
804 // sure we emit the one with all checks.
805 String name = namer.getName(getInterceptorMethod);
806 specializedGetInterceptors.putIfAbsent(name, () {
ahe 2012/11/27 14:29:45 I don't understand why you do this. Why shouldn't
ngeoffray 2012/11/27 15:50:54 Because I did not want to call getListOfIntercepte
807 // It is important to take the order provided by this list,
808 // because we want the int type check to happen before the
809 // double type check: the double type check covers the int
810 // type check.
811 return getListOfInterceptedClasses();
812 });
813 return namer.isolateAccess(getInterceptorMethod);
814 } else {
815 String name = namer.getSpecializedName(getInterceptorMethod,
816 interceptedClasses);
817 specializedGetInterceptors[name] = interceptedClasses;
818 return '${namer.CURRENT_ISOLATE}.$name';
819 }
820 }
821
805 void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) { 822 void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) {
806 ClassElement result = null; 823 ClassElement result = null;
807 if (!_interceptorsAreInitialized) { 824 if (!_interceptorsAreInitialized) {
808 initializeInterceptorElements(); 825 initializeInterceptorElements();
809 _interceptorsAreInitialized = true; 826 _interceptorsAreInitialized = true;
810 // The null interceptor and the function interceptor are
811 // currently always instantiated if a new class is instantiated.
812 // TODO(ngeoffray): do this elsewhere for the function
813 // interceptor?
814 if (jsNullClass != null) {
815 addInterceptors(jsNullClass);
816 enqueuer.registerInstantiatedClass(jsNullClass);
817 }
818 if (jsFunctionClass != null) {
819 addInterceptors(jsFunctionClass);
820 enqueuer.registerInstantiatedClass(jsFunctionClass);
821 }
822 enqueuer.addToWorkList(getInterceptorMethod);
823 } 827 }
824 if (cls == compiler.stringClass) { 828 if (cls == compiler.stringClass) {
825 result = jsStringClass; 829 result = jsStringClass;
826 } else if (cls == compiler.listClass) { 830 } else if (cls == compiler.listClass) {
827 result = jsArrayClass; 831 result = jsArrayClass;
828 } else if (cls == compiler.intClass) { 832 } else if (cls == compiler.intClass) {
829 result = jsIntClass; 833 result = jsIntClass;
834 enqueuer.registerInstantiatedClass(jsNumberClass);
830 } else if (cls == compiler.doubleClass) { 835 } else if (cls == compiler.doubleClass) {
831 result = jsDoubleClass; 836 result = jsDoubleClass;
837 enqueuer.registerInstantiatedClass(jsNumberClass);
832 } else if (cls == compiler.functionClass) { 838 } else if (cls == compiler.functionClass) {
833 result = jsFunctionClass; 839 result = jsFunctionClass;
834 } else if (cls == compiler.boolClass) { 840 } else if (cls == compiler.boolClass) {
835 result = jsBoolClass; 841 result = jsBoolClass;
842 } else if (cls == compiler.nullClass) {
843 result = jsNullClass;
836 } 844 }
837 845
838 if (result == null) return; 846 if (result == null) return;
839 if (enqueuer.isResolutionQueue) addInterceptors(result); 847 if (enqueuer.isResolutionQueue) addInterceptors(result);
840 enqueuer.registerInstantiatedClass(result); 848 enqueuer.registerInstantiatedClass(result);
841 } 849 }
842 850
843 Element get cyclicThrowHelper { 851 Element get cyclicThrowHelper {
844 return compiler.findHelper(const SourceString("throwCyclicInit")); 852 return compiler.findHelper(const SourceString("throwCyclicInit"));
845 } 853 }
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
1102 print("Inferred return types:"); 1110 print("Inferred return types:");
1103 print("----------------------"); 1111 print("----------------------");
1104 dumpReturnTypes(); 1112 dumpReturnTypes();
1105 print(""); 1113 print("");
1106 print("Inferred field types:"); 1114 print("Inferred field types:");
1107 print("------------------------"); 1115 print("------------------------");
1108 fieldTypes.dump(); 1116 fieldTypes.dump();
1109 print(""); 1117 print("");
1110 } 1118 }
1111 } 1119 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698