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

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;
685
686 /**
687 * Set of classes whose instances are intercepted. Implemented as a
688 * [LinkedHashMap] to preserve the insertion order.
689 * TODO(ngeoffray): Use a BitSet instead.
690 */
691 final Map<ClassElement, ClassElement> interceptedClasses;
683 692
684 List<CompilerTask> get tasks { 693 List<CompilerTask> get tasks {
685 return <CompilerTask>[builder, optimizer, generator, emitter]; 694 return <CompilerTask>[builder, optimizer, generator, emitter];
686 } 695 }
687 696
688 final RuntimeTypeInformation rti; 697 final RuntimeTypeInformation rti;
689 698
690 JavaScriptBackend(Compiler compiler, bool generateSourceMap, bool disableEval) 699 JavaScriptBackend(Compiler compiler, bool generateSourceMap, bool disableEval)
691 : namer = determineNamer(compiler), 700 : namer = determineNamer(compiler),
692 returnInfo = new Map<Element, ReturnInfo>(), 701 returnInfo = new Map<Element, ReturnInfo>(),
693 invalidateAfterCodegen = new List<Element>(), 702 invalidateAfterCodegen = new List<Element>(),
694 interceptors = new Interceptors(compiler), 703 interceptors = new Interceptors(compiler),
695 usedInterceptors = new Set<Selector>(), 704 usedInterceptors = new Set<Selector>(),
696 interceptedElements = new Map<SourceString, Set<Element>>(), 705 interceptedElements = new Map<SourceString, Set<Element>>(),
697 rti = new RuntimeTypeInformation(compiler), 706 rti = new RuntimeTypeInformation(compiler),
707 specializedGetInterceptors =
708 new Map<String, Collection<ClassElement>>(),
709 interceptedClasses = new LinkedHashMap<ClassElement, ClassElement>(),
698 super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) { 710 super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) {
699 emitter = disableEval 711 emitter = disableEval
700 ? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap) 712 ? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap)
701 : new CodeEmitterTask(compiler, namer, generateSourceMap); 713 : new CodeEmitterTask(compiler, namer, generateSourceMap);
702 builder = new SsaBuilderTask(this); 714 builder = new SsaBuilderTask(this);
703 optimizer = new SsaOptimizerTask(this); 715 optimizer = new SsaOptimizerTask(this);
704 generator = new SsaCodeGeneratorTask(this); 716 generator = new SsaCodeGeneratorTask(this);
705 argumentTypes = new ArgumentTypesRegistry(this); 717 argumentTypes = new ArgumentTypesRegistry(this);
706 fieldTypes = new FieldTypesRegistry(this); 718 fieldTypes = new FieldTypesRegistry(this);
707 } 719 }
708 720
709 static Namer determineNamer(Compiler compiler) { 721 static Namer determineNamer(Compiler compiler) {
710 return compiler.enableMinification ? 722 return compiler.enableMinification ?
711 new MinifyNamer(compiler) : 723 new MinifyNamer(compiler) :
712 new Namer(compiler); 724 new Namer(compiler);
713 } 725 }
714 726
715 bool isInterceptorClass(Element element) { 727 bool isInterceptorClass(Element element) {
716 if (element == null) return false; 728 if (element == null) return false;
717 return element == jsStringClass 729 return interceptedClasses.containsKey(element);
718 || element == jsArrayClass
719 || element == jsIntClass
720 || element == jsDoubleClass
721 || element == jsNullClass
722 || element == jsFunctionClass
723 || element == jsBoolClass
724 || element == jsNumberClass;
725 } 730 }
726 731
727 void addInterceptedSelector(Selector selector) { 732 void addInterceptedSelector(Selector selector) {
728 usedInterceptors.add(selector); 733 usedInterceptors.add(selector);
729 } 734 }
730 735
731 /** 736 /**
732 * Returns a set of interceptor classes that contain a member whose 737 * Returns a set of interceptor classes that contain a member whose
733 * signature matches the given [selector]. Returns [:null:] if there 738 * signature matches the given [selector]. Returns [:null:] if there
734 * is no class. 739 * is no class.
735 */ 740 */
736 Set<ClassElement> getInterceptedClassesOn(Selector selector) { 741 Set<ClassElement> getInterceptedClassesOn(Selector selector) {
737 Set<Element> intercepted = interceptedElements[selector.name]; 742 Set<Element> intercepted = interceptedElements[selector.name];
738 if (intercepted == null) return null; 743 if (intercepted == null) return null;
739 Set<ClassElement> result = new Set<ClassElement>(); 744 Set<ClassElement> result = new Set<ClassElement>();
740 for (Element element in intercepted) { 745 for (Element element in intercepted) {
741 if (selector.applies(element, compiler)) { 746 if (selector.applies(element, compiler)) {
742 result.add(element.getEnclosingClass()); 747 result.add(element.getEnclosingClass());
743 } 748 }
744 } 749 }
745 if (result.isEmpty) return null; 750 if (result.isEmpty) return null;
746 return result; 751 return result;
747 } 752 }
748 753
754 List<ClassElement> getListOfInterceptedClasses() {
755 return <ClassElement>[jsStringClass, jsArrayClass, jsIntClass,
756 jsDoubleClass, jsNumberClass, jsNullClass,
757 jsFunctionClass, jsBoolClass];
758 }
759
749 void initializeInterceptorElements() { 760 void initializeInterceptorElements() {
750 objectInterceptorClass = 761 objectInterceptorClass =
751 compiler.findInterceptor(const SourceString('ObjectInterceptor')); 762 compiler.findInterceptor(const SourceString('ObjectInterceptor'));
752 getInterceptorMethod = 763 getInterceptorMethod =
753 compiler.findInterceptor(const SourceString('getInterceptor')); 764 compiler.findInterceptor(const SourceString('getInterceptor'));
754 jsStringClass = 765 List<ClassElement> classes = [
755 compiler.findInterceptor(const SourceString('JSString')); 766 jsStringClass = compiler.findInterceptor(const SourceString('JSString')),
756 jsArrayClass = 767 jsArrayClass = compiler.findInterceptor(const SourceString('JSArray')),
757 compiler.findInterceptor(const SourceString('JSArray')); 768 jsNumberClass = compiler.findInterceptor(const SourceString('JSNumber')),
758 jsNumberClass = 769 jsIntClass = compiler.findInterceptor(const SourceString('JSInt')),
759 compiler.findInterceptor(const SourceString('JSNumber')); 770 jsDoubleClass = compiler.findInterceptor(const SourceString('JSDouble')),
760 jsIntClass = 771 jsNullClass = compiler.findInterceptor(const SourceString('JSNull')),
761 compiler.findInterceptor(const SourceString('JSInt')); 772 jsFunctionClass =
762 jsDoubleClass = 773 compiler.findInterceptor(const SourceString('JSFunction')),
763 compiler.findInterceptor(const SourceString('JSDouble')); 774 jsBoolClass = compiler.findInterceptor(const SourceString('JSBool'))];
764 jsNullClass = 775
765 compiler.findInterceptor(const SourceString('JSNull'));
766 jsFunctionClass =
767 compiler.findInterceptor(const SourceString('JSFunction'));
768 jsBoolClass =
769 compiler.findInterceptor(const SourceString('JSBool'));
770 jsArrayClass.ensureResolved(compiler); 776 jsArrayClass.ensureResolved(compiler);
771 jsArrayLength = 777 jsArrayLength =
772 jsArrayClass.lookupLocalMember(const SourceString('length')); 778 jsArrayClass.lookupLocalMember(const SourceString('length'));
779
773 jsStringClass.ensureResolved(compiler); 780 jsStringClass.ensureResolved(compiler);
774 jsStringLength = 781 jsStringLength =
775 jsStringClass.lookupLocalMember(const SourceString('length')); 782 jsStringClass.lookupLocalMember(const SourceString('length'));
776 783
777 arrayInterceptor = 784 for (ClassElement cls in classes) {
778 compiler.findInterceptor(const SourceString('arrayInterceptor')); 785 interceptedClasses[cls] = null;
779 boolInterceptor = 786 }
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(Set<ClassElement> classes) {
800 compiler.enqueuer.codegen.registerInstantiatedClass(objectInterceptorClass);
801 if (classes.contains(compiler.objectClass)) {
802 // We can't use a specialized [getInterceptorMethod], so we make
803 // sure we emit the one with all checks.
804 String name = namer.getName(getInterceptorMethod);
805 specializedGetInterceptors.putIfAbsent(name, () {
806 // It is important to take the order provided by this list,
807 // because we want the int type check to happen before the
808 // double type check: the double type check covers the int
809 // type check.
810 return interceptedClasses.keys;
811 });
812 return namer.isolateAccess(getInterceptorMethod);
813 } else {
814 String name = namer.getSpecializedName(getInterceptorMethod, classes);
815 specializedGetInterceptors[name] = classes;
816 return '${namer.CURRENT_ISOLATE}.$name';
817 }
818 }
819
805 void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) { 820 void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) {
806 ClassElement result = null; 821 ClassElement result = null;
807 if (!_interceptorsAreInitialized) { 822 if (!_interceptorsAreInitialized) {
808 initializeInterceptorElements(); 823 initializeInterceptorElements();
809 _interceptorsAreInitialized = true; 824 _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 } 825 }
824 if (cls == compiler.stringClass) { 826 if (cls == compiler.stringClass) {
825 result = jsStringClass; 827 result = jsStringClass;
826 } else if (cls == compiler.listClass) { 828 } else if (cls == compiler.listClass) {
827 result = jsArrayClass; 829 result = jsArrayClass;
828 } else if (cls == compiler.intClass) { 830 } else if (cls == compiler.intClass) {
829 result = jsIntClass; 831 result = jsIntClass;
832 enqueuer.registerInstantiatedClass(jsNumberClass);
830 } else if (cls == compiler.doubleClass) { 833 } else if (cls == compiler.doubleClass) {
831 result = jsDoubleClass; 834 result = jsDoubleClass;
835 enqueuer.registerInstantiatedClass(jsNumberClass);
832 } else if (cls == compiler.functionClass) { 836 } else if (cls == compiler.functionClass) {
833 result = jsFunctionClass; 837 result = jsFunctionClass;
834 } else if (cls == compiler.boolClass) { 838 } else if (cls == compiler.boolClass) {
835 result = jsBoolClass; 839 result = jsBoolClass;
840 } else if (cls == compiler.nullClass) {
841 result = jsNullClass;
836 } 842 }
837 843
838 if (result == null) return; 844 if (result == null) return;
839 if (enqueuer.isResolutionQueue) addInterceptors(result); 845 if (enqueuer.isResolutionQueue) addInterceptors(result);
840 enqueuer.registerInstantiatedClass(result); 846 enqueuer.registerInstantiatedClass(result);
841 } 847 }
842 848
843 Element get cyclicThrowHelper { 849 Element get cyclicThrowHelper {
844 return compiler.findHelper(const SourceString("throwCyclicInit")); 850 return compiler.findHelper(const SourceString("throwCyclicInit"));
845 } 851 }
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
1102 print("Inferred return types:"); 1108 print("Inferred return types:");
1103 print("----------------------"); 1109 print("----------------------");
1104 dumpReturnTypes(); 1110 dumpReturnTypes();
1105 print(""); 1111 print("");
1106 print("Inferred field types:"); 1112 print("Inferred field types:");
1107 print("------------------------"); 1113 print("------------------------");
1108 fieldTypes.dump(); 1114 fieldTypes.dump();
1109 print(""); 1115 print("");
1110 } 1116 }
1111 } 1117 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698