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

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

Issue 12330135: Make instance methods whose names collide with intercepted methods have the interceptor calling con… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 months 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 624 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 new Map<Element, jsAst.Expression>(); 635 new Map<Element, jsAst.Expression>();
636 636
637 ClassElement jsStringClass; 637 ClassElement jsStringClass;
638 ClassElement jsArrayClass; 638 ClassElement jsArrayClass;
639 ClassElement jsNumberClass; 639 ClassElement jsNumberClass;
640 ClassElement jsIntClass; 640 ClassElement jsIntClass;
641 ClassElement jsDoubleClass; 641 ClassElement jsDoubleClass;
642 ClassElement jsFunctionClass; 642 ClassElement jsFunctionClass;
643 ClassElement jsNullClass; 643 ClassElement jsNullClass;
644 ClassElement jsBoolClass; 644 ClassElement jsBoolClass;
645 ClassElement objectInterceptorClass;
646 Element jsArrayLength; 645 Element jsArrayLength;
647 Element jsStringLength; 646 Element jsStringLength;
648 Element jsArrayRemoveLast; 647 Element jsArrayRemoveLast;
649 Element jsArrayAdd; 648 Element jsArrayAdd;
650 Element jsStringSplit; 649 Element jsStringSplit;
651 Element jsStringConcat; 650 Element jsStringConcat;
652 Element jsStringToString; 651 Element jsStringToString;
653 Element getInterceptorMethod; 652 Element getInterceptorMethod;
653 Element interceptedNames;
654 Element fixedLengthListConstructor; 654 Element fixedLengthListConstructor;
655 bool seenAnyClass = false; 655 bool seenAnyClass = false;
656 656
657 final Namer namer; 657 final Namer namer;
658 658
659 /** 659 /**
660 * Interface used to determine if an object has the JavaScript 660 * Interface used to determine if an object has the JavaScript
661 * indexing behavior. The interface is only visible to specific 661 * indexing behavior. The interface is only visible to specific
662 * libraries. 662 * libraries.
663 */ 663 */
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 * A map of specialized versions of the [getInterceptorMethod]. 698 * A map of specialized versions of the [getInterceptorMethod].
699 * Since [getInterceptorMethod] is a hot method at runtime, we're 699 * Since [getInterceptorMethod] is a hot method at runtime, we're
700 * always specializing it based on the incoming type. The keys in 700 * always specializing it based on the incoming type. The keys in
701 * the map are the names of these specialized versions. Note that 701 * the map are the names of these specialized versions. Note that
702 * the generic version that contains all possible type checks is 702 * the generic version that contains all possible type checks is
703 * also stored in this map. 703 * also stored in this map.
704 */ 704 */
705 final Map<String, Collection<ClassElement>> specializedGetInterceptors; 705 final Map<String, Collection<ClassElement>> specializedGetInterceptors;
706 706
707 /** 707 /**
708 * Set of classes whose instances are intercepted. Implemented as a 708 * Set of classes whose methods are intercepted.
709 * [LinkedHashMap] to preserve the insertion order.
710 * TODO(ngeoffray): No need to preserve order anymore.
711 */ 709 */
712 final Map<ClassElement, ClassElement> interceptedClasses; 710 final Set<ClassElement> interceptedClasses;
713 711
714 /** 712 /**
715 * Set of selectors that are used from within loops. Used by the 713 * Set of selectors that are used from within loops. Used by the
716 * builder to allow speculative optimizations for functions without 714 * builder to allow speculative optimizations for functions without
717 * loops themselves. 715 * loops themselves.
718 */ 716 */
719 final Map<SourceString, Set<Selector>> selectorsCalledInLoop = 717 final Map<SourceString, Set<Selector>> selectorsCalledInLoop =
720 new Map<SourceString, Set<Selector>>(); 718 new Map<SourceString, Set<Selector>>();
721 719
722 List<CompilerTask> get tasks { 720 List<CompilerTask> get tasks {
723 return <CompilerTask>[builder, optimizer, generator, emitter]; 721 return <CompilerTask>[builder, optimizer, generator, emitter];
724 } 722 }
725 723
726 final RuntimeTypeInformation rti; 724 final RuntimeTypeInformation rti;
727 725
728 JavaScriptBackend(Compiler compiler, bool generateSourceMap, bool disableEval) 726 JavaScriptBackend(Compiler compiler, bool generateSourceMap, bool disableEval)
729 : namer = determineNamer(compiler), 727 : namer = determineNamer(compiler),
730 returnInfo = new Map<Element, ReturnInfo>(), 728 returnInfo = new Map<Element, ReturnInfo>(),
731 invalidateAfterCodegen = new List<Element>(), 729 invalidateAfterCodegen = new List<Element>(),
732 usedInterceptors = new Set<Selector>(), 730 usedInterceptors = new Set<Selector>(),
733 oneShotInterceptors = new Map<String, Selector>(), 731 oneShotInterceptors = new Map<String, Selector>(),
734 interceptedElements = new Map<SourceString, Set<Element>>(), 732 interceptedElements = new Map<SourceString, Set<Element>>(),
735 rti = new RuntimeTypeInformation(compiler), 733 rti = new RuntimeTypeInformation(compiler),
736 specializedGetInterceptors = 734 specializedGetInterceptors =
737 new Map<String, Collection<ClassElement>>(), 735 new Map<String, Collection<ClassElement>>(),
738 interceptedClasses = new LinkedHashMap<ClassElement, ClassElement>(), 736 interceptedClasses = new Set<ClassElement>(),
739 super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) { 737 super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) {
740 emitter = disableEval 738 emitter = disableEval
741 // TODO(8522): Restore --disallow-unsafe-eval. 739 // TODO(8522): Restore --disallow-unsafe-eval.
742 ? null // new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap) 740 ? null // new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap)
743 : new CodeEmitterTask(compiler, namer, generateSourceMap); 741 : new CodeEmitterTask(compiler, namer, generateSourceMap);
744 builder = new SsaBuilderTask(this); 742 builder = new SsaBuilderTask(this);
745 optimizer = new SsaOptimizerTask(this); 743 optimizer = new SsaOptimizerTask(this);
746 generator = new SsaCodeGeneratorTask(this); 744 generator = new SsaCodeGeneratorTask(this);
747 argumentTypes = new ArgumentTypesRegistry(this); 745 argumentTypes = new ArgumentTypesRegistry(this);
748 fieldTypes = new FieldTypesRegistry(this); 746 fieldTypes = new FieldTypesRegistry(this);
749 } 747 }
750 748
751 static Namer determineNamer(Compiler compiler) { 749 static Namer determineNamer(Compiler compiler) {
752 return compiler.enableMinification ? 750 return compiler.enableMinification ?
753 new MinifyNamer(compiler) : 751 new MinifyNamer(compiler) :
754 new Namer(compiler); 752 new Namer(compiler);
755 } 753 }
756 754
757 bool isInterceptorClass(Element element) { 755 bool isInterceptorClass(Element element) {
758 if (element == null) return false; 756 if (element == null) return false;
759 return interceptedClasses.containsKey(element); 757 return interceptedClasses.contains(element);
760 } 758 }
761 759
762 void addInterceptedSelector(Selector selector) { 760 void addInterceptedSelector(Selector selector) {
763 usedInterceptors.add(selector); 761 usedInterceptors.add(selector);
764 } 762 }
765 763
766 String registerOneShotInterceptor(Selector selector) { 764 String registerOneShotInterceptor(Selector selector) {
767 Set<ClassElement> classes = getInterceptedClassesOn(selector); 765 Set<ClassElement> classes = getInterceptedClassesOn(selector.name);
768 String name = namer.getOneShotInterceptorName(selector, classes); 766 String name = namer.getOneShotInterceptorName(selector, classes);
769 if (!oneShotInterceptors.containsKey(name)) { 767 if (!oneShotInterceptors.containsKey(name)) {
770 registerSpecializedGetInterceptor(classes); 768 registerSpecializedGetInterceptor(classes);
771 oneShotInterceptors[name] = selector; 769 oneShotInterceptors[name] = selector;
772 } 770 }
773 return name; 771 return name;
774 } 772 }
775 773
776 final Map<Selector, Set<ClassElement>> interceptedClassesCache = 774 bool isInterceptedMethod(Element element) {
777 new Map<Selector, Set<ClassElement>>(); 775 return element.isInstanceMember()
778 final Map<Selector, Set<ClassElement>> interceptedClassesNonNullCache = 776 && interceptedElements[element.name] != null;
779 new Map<Selector, Set<ClassElement>>(); 777 }
778
779 bool isInterceptedName(SourceString name) {
780 return interceptedElements[name] != null;
781 }
782
783 final Map<SourceString, Set<ClassElement>> interceptedClassesCache =
784 new Map<SourceString, Set<ClassElement>>();
780 785
781 /** 786 /**
782 * Returns a set of interceptor classes that contain a member whose 787 * Returns a set of interceptor classes that contain a member named
783 * signature matches the given [selector]. Returns [:null:] if there 788 * [name[. Returns [:null:] if there is no class.
sra1 2013/02/27 05:13:28 [name]
ngeoffray 2013/02/28 10:39:42 Done.
784 * is no class.
785 */ 789 */
786 Set<ClassElement> getInterceptedClassesOn(Selector selector, 790 Set<ClassElement> getInterceptedClassesOn(SourceString name) {
787 {bool canBeNull: true}) { 791 Set<Element> intercepted = interceptedElements[name];
788 Set<Element> intercepted = interceptedElements[selector.name];
789 if (intercepted == null) return null; 792 if (intercepted == null) return null;
790 // Pick the right cache and query it. 793 if (interceptedClassesCache.containsKey(name)) {
791 Map<Selector, Set<ClassElement>> cache = canBeNull 794 return interceptedClassesCache[name];
792 ? interceptedClassesCache 795 }
793 : interceptedClassesNonNullCache;
794 if (cache.containsKey(selector)) return cache[selector];
795 // Populate the cache by running through all the elements and 796 // Populate the cache by running through all the elements and
796 // determine if the given selector applies to them. 797 // determine if the given selector applies to them.
797 Set<ClassElement> result = new Set<ClassElement>(); 798 Set<ClassElement> result = new Set<ClassElement>();
798 for (Element element in intercepted) { 799 for (Element element in intercepted) {
799 ClassElement enclosing = element.getEnclosingClass(); 800 result.add(element.getEnclosingClass());
800 // We have to treat null as a bottom type, so we use the untyped
801 // applies method for those elements that are implemented on the
802 // null class.
803 bool applies = (enclosing == jsNullClass)
804 ? canBeNull && selector.appliesUntyped(element, compiler)
805 : selector.applies(element, compiler);
806 if (applies) result.add(enclosing);
807 } 801 }
808 if (result.isEmpty) result = null; 802 interceptedClassesCache[name] = result;
809 cache[selector] = result;
810 assert(cache.containsKey(selector));
811 return result; 803 return result;
812 } 804 }
813 805
814 void initializeInterceptorElements() { 806 void initializeInterceptorElements() {
815 objectInterceptorClass =
816 compiler.findInterceptor(const SourceString('ObjectInterceptor'));
817 getInterceptorMethod = 807 getInterceptorMethod =
818 compiler.findInterceptor(const SourceString('getInterceptor')); 808 compiler.findInterceptor(const SourceString('getInterceptor'));
809 interceptedNames =
810 compiler.findInterceptor(const SourceString('interceptedNames'));
819 List<ClassElement> classes = [ 811 List<ClassElement> classes = [
812 compiler.objectClass,
820 jsStringClass = compiler.findInterceptor(const SourceString('JSString')), 813 jsStringClass = compiler.findInterceptor(const SourceString('JSString')),
821 jsArrayClass = compiler.findInterceptor(const SourceString('JSArray')), 814 jsArrayClass = compiler.findInterceptor(const SourceString('JSArray')),
822 // The int class must be before the double class, because the 815 // The int class must be before the double class, because the
823 // emitter relies on this list for the order of type checks. 816 // emitter relies on this list for the order of type checks.
824 jsIntClass = compiler.findInterceptor(const SourceString('JSInt')), 817 jsIntClass = compiler.findInterceptor(const SourceString('JSInt')),
825 jsDoubleClass = compiler.findInterceptor(const SourceString('JSDouble')), 818 jsDoubleClass = compiler.findInterceptor(const SourceString('JSDouble')),
826 jsNumberClass = compiler.findInterceptor(const SourceString('JSNumber')), 819 jsNumberClass = compiler.findInterceptor(const SourceString('JSNumber')),
827 jsNullClass = compiler.findInterceptor(const SourceString('JSNull')), 820 jsNullClass = compiler.findInterceptor(const SourceString('JSNull')),
828 jsFunctionClass = 821 jsFunctionClass =
829 compiler.findInterceptor(const SourceString('JSFunction')), 822 compiler.findInterceptor(const SourceString('JSFunction')),
(...skipping 11 matching lines...) Expand all
841 jsStringLength = compiler.lookupElementIn( 834 jsStringLength = compiler.lookupElementIn(
842 jsStringClass, const SourceString('length')); 835 jsStringClass, const SourceString('length'));
843 jsStringSplit = compiler.lookupElementIn( 836 jsStringSplit = compiler.lookupElementIn(
844 jsStringClass, const SourceString('split')); 837 jsStringClass, const SourceString('split'));
845 jsStringConcat = compiler.lookupElementIn( 838 jsStringConcat = compiler.lookupElementIn(
846 jsStringClass, const SourceString('concat')); 839 jsStringClass, const SourceString('concat'));
847 jsStringToString = compiler.lookupElementIn( 840 jsStringToString = compiler.lookupElementIn(
848 jsStringClass, const SourceString('toString')); 841 jsStringClass, const SourceString('toString'));
849 842
850 for (ClassElement cls in classes) { 843 for (ClassElement cls in classes) {
851 if (cls != null) interceptedClasses[cls] = null; 844 if (cls != null) interceptedClasses.add(cls);
852 } 845 }
853 } 846 }
854 847
855 void addInterceptors(ClassElement cls, Enqueuer enqueuer) { 848 void addInterceptors(ClassElement cls, Enqueuer enqueuer) {
856 if (enqueuer.isResolutionQueue) { 849 if (enqueuer.isResolutionQueue) {
857 cls.ensureResolved(compiler); 850 cls.ensureResolved(compiler);
858 cls.forEachMember((ClassElement classElement, Element member) { 851 cls.forEachMember((ClassElement classElement, Element member) {
859 Set<Element> set = interceptedElements.putIfAbsent( 852 Set<Element> set = interceptedElements.putIfAbsent(
860 member.name, () => new Set<Element>()); 853 member.name, () => new Set<Element>());
861 set.add(member); 854 set.add(member);
862 }, 855 },
863 includeSuperMembers: true); 856 includeSuperMembers: true);
864 } 857 }
865 enqueuer.registerInstantiatedClass(cls); 858 enqueuer.registerInstantiatedClass(cls);
866 } 859 }
867 860
868 void registerSpecializedGetInterceptor(Set<ClassElement> classes) { 861 void registerSpecializedGetInterceptor(Set<ClassElement> classes) {
869 compiler.enqueuer.codegen.registerInstantiatedClass(objectInterceptorClass);
870 String name = namer.getInterceptorName(getInterceptorMethod, classes); 862 String name = namer.getInterceptorName(getInterceptorMethod, classes);
871 if (classes.contains(compiler.objectClass)) { 863 if (classes.contains(compiler.objectClass)) {
872 // We can't use a specialized [getInterceptorMethod], so we make 864 // We can't use a specialized [getInterceptorMethod], so we make
873 // sure we emit the one with all checks. 865 // sure we emit the one with all checks.
874 specializedGetInterceptors.putIfAbsent(name, () { 866 specializedGetInterceptors[name] = interceptedClasses;
875 // It is important to take the order provided by the map,
876 // because we want the int type check to happen before the
877 // double type check: the double type check covers the int
878 // type check. Also we don't need to do a number type check
879 // because that is covered by the double type check.
880 List<ClassElement> keys = <ClassElement>[];
881 interceptedClasses.forEach((ClassElement cls, _) {
882 if (cls != jsNumberClass) keys.add(cls);
883 });
884 return keys;
885 });
886 } else { 867 } else {
887 specializedGetInterceptors[name] = classes; 868 specializedGetInterceptors[name] = classes;
888 } 869 }
889 } 870 }
890 871
891 void initializeNoSuchMethod() { 872 void initializeNoSuchMethod() {
892 // In case the emitter generates noSuchMethod calls, we need to 873 // In case the emitter generates noSuchMethod calls, we need to
893 // make sure all [noSuchMethod] methods know they might take a 874 // make sure all [noSuchMethod] methods know they might take a
894 // [JsInvocationMirror] as parameter. 875 // [JsInvocationMirror] as parameter.
895 HTypeList types = new HTypeList(1); 876 HTypeList types = new HTypeList(1);
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after
1499 * 1480 *
1500 * Invariant: [element] must be a declaration element. 1481 * Invariant: [element] must be a declaration element.
1501 */ 1482 */
1502 void eagerRecompile(Element element) { 1483 void eagerRecompile(Element element) {
1503 assert(invariant(element, element.isDeclaration)); 1484 assert(invariant(element, element.isDeclaration));
1504 generatedCode.remove(element); 1485 generatedCode.remove(element);
1505 generatedBailoutCode.remove(element); 1486 generatedBailoutCode.remove(element);
1506 compiler.enqueuer.codegen.addToWorkList(element); 1487 compiler.enqueuer.codegen.addToWorkList(element);
1507 } 1488 }
1508 } 1489 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698