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

Side by Side Diff: pkg/compiler/lib/src/world.dart

Issue 2428543002: Optimize needNoSuchMethodHandling computation (Closed)
Patch Set: Created 4 years, 2 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
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 library dart2js.world; 5 library dart2js.world;
6 6
7 import 'closure.dart' show SynthesizedCallMethodElementX; 7 import 'closure.dart' show SynthesizedCallMethodElementX;
8 import 'common/backend_api.dart' show BackendClasses; 8 import 'common/backend_api.dart' show BackendClasses;
9 import 'common.dart'; 9 import 'common.dart';
10 import 'compiler.dart' show Compiler; 10 import 'compiler.dart' show Compiler;
(...skipping 710 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 @override 721 @override
722 bool hasElementIn(ClassElement cls, Selector selector, Element element) { 722 bool hasElementIn(ClassElement cls, Selector selector, Element element) {
723 // Use [:implementation:] of [element] 723 // Use [:implementation:] of [element]
724 // because our function set only stores declarations. 724 // because our function set only stores declarations.
725 Element result = findMatchIn(cls, selector); 725 Element result = findMatchIn(cls, selector);
726 return result == null 726 return result == null
727 ? false 727 ? false
728 : result.implementation == element.implementation; 728 : result.implementation == element.implementation;
729 } 729 }
730 730
731 Element findMatchIn(ClassElement cls, Selector selector) { 731 Element findMatchIn(ClassElement cls, Selector selector,
732 {ClassElement stopAtSuperclass}) {
732 // Use the [:implementation] of [cls] in case the found [element] 733 // Use the [:implementation] of [cls] in case the found [element]
733 // is in the patch class. 734 // is in the patch class.
734 var result = cls.implementation.lookupByName(selector.memberName); 735 var result = cls.implementation
736 .lookupByName(selector.memberName, stopAtSuperclass: stopAtSuperclass);
735 return result; 737 return result;
736 } 738 }
737 739
738 /// Returns whether a [selector] call on an instance of [cls] 740 /// Returns whether a [selector] call on an instance of [cls]
739 /// will hit a method at runtime, and not go through [noSuchMethod]. 741 /// will hit a method at runtime, and not go through [noSuchMethod].
740 bool hasConcreteMatch(ClassElement cls, Selector selector) { 742 bool hasConcreteMatch(ClassElement cls, Selector selector,
743 {ClassElement stopAtSuperclass}) {
741 assert(invariant(cls, isInstantiated(cls), 744 assert(invariant(cls, isInstantiated(cls),
742 message: '$cls has not been instantiated.')); 745 message: '$cls has not been instantiated.'));
743 Element element = findMatchIn(cls, selector); 746 Element element = findMatchIn(cls, selector);
744 if (element == null) return false; 747 if (element == null) return false;
745 748
746 if (element.isAbstract) { 749 if (element.isAbstract) {
747 ClassElement enclosingClass = element.enclosingClass; 750 ClassElement enclosingClass = element.enclosingClass;
748 return hasConcreteMatch(enclosingClass.superclass, selector); 751 return hasConcreteMatch(enclosingClass.superclass, selector);
749 } 752 }
750 return selector.appliesUntyped(element); 753 return selector.appliesUntyped(element);
751 } 754 }
752 755
753 @override 756 @override
754 bool needsNoSuchMethod( 757 bool needsNoSuchMethod(
755 ClassElement base, Selector selector, ClassQuery query) { 758 ClassElement base, Selector selector, ClassQuery query) {
756 /// Returns `true` if [cls] is an instantiated class that does not have 759 /// Returns `true` if subclasses in the [rootNode] tree needs noSuchMethod
757 /// a concrete method matching [selector]. 760 /// handling.
758 bool needsNoSuchMethod(ClassElement cls) { 761 bool subclassesNeedNoSuchMethod(ClassHierarchyNode rootNode) {
759 // We can skip uninstantiated subclasses. 762 if (!rootNode.isInstantiated) {
760 if (!isInstantiated(cls)) { 763 // No subclass needs noSuchMethod handling since they are all
764 // uninstantiated.
761 return false; 765 return false;
762 } 766 }
763 // We can just skip abstract classes because we know no 767 ClassElement rootClass = rootNode.cls;
764 // instance of them will be created at runtime, and 768 if (hasConcreteMatch(rootClass, selector)) {
765 // therefore there is no instance that will require 769 // The root subclass has a concrete implementation so no subclass needs
766 // [noSuchMethod] handling. 770 // noSuchMethod handling.
767 return !cls.isAbstract && !hasConcreteMatch(cls, selector); 771 return false;
772 } else if (rootNode.isDirectlyInstantiated && !rootClass.isAbstract) {
773 // The root class need noSuchMethod handling.
774 return true;
775 }
776 IterationStep result = rootNode.forEachSubclass((ClassElement subclass) {
777 if (hasConcreteMatch(subclass, selector, stopAtSuperclass: rootClass)) {
778 // Found a match - skip all subclasses.
779 return IterationStep.SKIP_SUBCLASSES;
780 } else {
781 // Stop fast - we found a need for noSuchMethod handling.
782 return IterationStep.STOP;
Siggi Cherem (dart-lang) 2016/10/17 19:30:34 should we also check that subclass is not abstract
Johnni Winther 2016/10/18 08:13:51 Wasn't needed above either (now that type inferenc
783 }
784 }, ClassHierarchyNode.DIRECTLY_INSTANTIATED, strict: true);
785 // We stopped fast so we need noSuchMethod handling.
786 return result == IterationStep.STOP;
768 } 787 }
769 788
770 bool baseNeedsNoSuchMethod = needsNoSuchMethod(base); 789 ClassSet classSet = getClassSet(base);
771 if (query == ClassQuery.EXACT || baseNeedsNoSuchMethod) { 790 ClassHierarchyNode node = classSet.node;
772 return baseNeedsNoSuchMethod; 791 if (query == ClassQuery.EXACT) {
792 return node.isDirectlyInstantiated && !hasConcreteMatch(base, selector);
793 } else if (query == ClassQuery.SUBCLASS) {
794 return subclassesNeedNoSuchMethod(node);
795 } else {
796 if (subclassesNeedNoSuchMethod(node)) return true;
797 for (ClassHierarchyNode subtypeNode in classSet.subtypeNodes) {
Siggi Cherem (dart-lang) 2016/10/17 19:30:34 remind me - do subtype nodes include just the imme
Johnni Winther 2016/10/18 08:13:51 It contains the roots for subclass trees that impl
798 if (subclassesNeedNoSuchMethod(subtypeNode)) return true;
Siggi Cherem (dart-lang) 2016/10/17 19:30:34 Q: are we guaranteed that subtypes here can't be s
Johnni Winther 2016/10/18 08:13:51 Yes. The are not subclasses of [base] (then they w
799 }
800 return false;
773 } 801 }
774
775 Iterable<ClassElement> subclassesToCheck;
776 if (query == ClassQuery.SUBTYPE) {
777 subclassesToCheck = strictSubtypesOf(base);
778 } else {
779 assert(query == ClassQuery.SUBCLASS);
780 subclassesToCheck = strictSubclassesOf(base);
781 }
782
783 return subclassesToCheck != null &&
784 subclassesToCheck.any(needsNoSuchMethod);
785 } 802 }
786 803
787 final Compiler _compiler; 804 final Compiler _compiler;
788 BackendClasses get backendClasses => _backend.backendClasses; 805 BackendClasses get backendClasses => _backend.backendClasses;
789 JavaScriptBackend get _backend => _compiler.backend; 806 JavaScriptBackend get _backend => _compiler.backend;
790 CommonMasks get commonMasks => _compiler.commonMasks; 807 CommonMasks get commonMasks => _compiler.commonMasks;
791 final FunctionSet allFunctions; 808 final FunctionSet allFunctions;
792 final Set<Element> functionsCalledInLoop = new Set<Element>(); 809 final Set<Element> functionsCalledInLoop = new Set<Element>();
793 final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>(); 810 final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>();
794 811
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
1143 /// Only the class itself is included. 1160 /// Only the class itself is included.
1144 EXACT, 1161 EXACT,
1145 1162
1146 /// The class and all subclasses (transitively) are included. 1163 /// The class and all subclasses (transitively) are included.
1147 SUBCLASS, 1164 SUBCLASS,
1148 1165
1149 /// The class and all classes that implement or subclass it (transitively) 1166 /// The class and all classes that implement or subclass it (transitively)
1150 /// are included. 1167 /// are included.
1151 SUBTYPE, 1168 SUBTYPE,
1152 } 1169 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698