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

Side by Side Diff: pkg/compiler/lib/src/js_backend/no_such_method_registry.dart

Issue 1020853007: Don't bailout of type inference for simple NSM implementations (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 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) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 /** 7 /**
8 * Categorizes `noSuchMethod` implementations. 8 * Categorizes `noSuchMethod` implementations.
9 * 9 *
10 * If user code includes `noSuchMethod` implementations, type inference is 10 * If user code includes `noSuchMethod` implementations, type inference is
(...skipping 27 matching lines...) Expand all
38 */ 38 */
39 class NoSuchMethodRegistry { 39 class NoSuchMethodRegistry {
40 /// The implementations that fall into category A, described above. 40 /// The implementations that fall into category A, described above.
41 final Set<FunctionElement> defaultImpls = new Set<FunctionElement>(); 41 final Set<FunctionElement> defaultImpls = new Set<FunctionElement>();
42 /// The implementations that fall into category B, described above. 42 /// The implementations that fall into category B, described above.
43 final Set<FunctionElement> throwingImpls = new Set<FunctionElement>(); 43 final Set<FunctionElement> throwingImpls = new Set<FunctionElement>();
44 /// The implementations that fall into category C, described above. 44 /// The implementations that fall into category C, described above.
45 final Set<Element> otherImpls = new Set<Element>(); 45 final Set<Element> otherImpls = new Set<Element>();
46 46
47 /// The implementations that have not yet been categorized. 47 /// The implementations that have not yet been categorized.
48 final Set<Element> uncategorizedImpls = new Set<Element>(); 48 final Set<Element> _uncategorizedImpls = new Set<Element>();
49 49
50 final JavaScriptBackend backend; 50 final JavaScriptBackend _backend;
51 final Compiler compiler; 51 final Compiler _compiler;
52 52
53 NoSuchMethodRegistry(JavaScriptBackend backend) 53 NoSuchMethodRegistry(JavaScriptBackend backend)
54 : this.backend = backend, 54 : this._backend = backend,
55 this.compiler = backend.compiler; 55 this._compiler = backend.compiler;
56 56
57 bool get hasThrowingNoSuchMethod => throwingImpls.isNotEmpty; 57 bool get hasThrowingNoSuchMethod => throwingImpls.isNotEmpty;
58 bool get hasComplexNoSuchMethod => otherImpls.isNotEmpty; 58 bool get hasComplexNoSuchMethod => otherImpls.isNotEmpty;
59 59
60 void registerNoSuchMethod(Element noSuchMethodElement) { 60 void registerNoSuchMethod(Element noSuchMethodElement) {
61 uncategorizedImpls.add(noSuchMethodElement); 61 _uncategorizedImpls.add(noSuchMethodElement);
62 } 62 }
63 63
64 void onQueueEmpty() { 64 void onQueueEmpty() {
65 uncategorizedImpls.forEach(_categorizeImpl); 65 _uncategorizedImpls.forEach(_categorizeImpl);
66 uncategorizedImpls.clear(); 66 _uncategorizedImpls.clear();
67 }
68
69 /// Returns [true] if the given element is a complex [noSuchMethod]
70 /// implementation. An implementation is complex if it falls into
71 /// category C, as described above.
72 bool isComplex(FunctionElement element) {
73 assert(element.name == Compiler.NO_SUCH_METHOD);
74 return otherImpls.contains(element);
67 } 75 }
68 76
69 NsmCategory _categorizeImpl(Element noSuchMethodElement) { 77 NsmCategory _categorizeImpl(Element noSuchMethodElement) {
70 assert(noSuchMethodElement.name == Compiler.NO_SUCH_METHOD); 78 assert(noSuchMethodElement.name == Compiler.NO_SUCH_METHOD);
71 if (defaultImpls.contains(noSuchMethodElement)) { 79 if (defaultImpls.contains(noSuchMethodElement)) {
72 return NsmCategory.DEFAULT; 80 return NsmCategory.DEFAULT;
73 } 81 }
74 if (throwingImpls.contains(noSuchMethodElement)) { 82 if (throwingImpls.contains(noSuchMethodElement)) {
75 return NsmCategory.THROWING; 83 return NsmCategory.THROWING;
76 } 84 }
77 if (otherImpls.contains(noSuchMethodElement)) { 85 if (otherImpls.contains(noSuchMethodElement)) {
78 return NsmCategory.OTHER; 86 return NsmCategory.OTHER;
79 } 87 }
80 if (noSuchMethodElement is! FunctionElement || 88 if (noSuchMethodElement is! FunctionElement ||
81 !compiler.noSuchMethodSelector.signatureApplies(noSuchMethodElement)) { 89 !_compiler.noSuchMethodSelector.signatureApplies(noSuchMethodElement)) {
82 otherImpls.add(noSuchMethodElement); 90 otherImpls.add(noSuchMethodElement);
83 return NsmCategory.OTHER; 91 return NsmCategory.OTHER;
84 } 92 }
85 FunctionElement noSuchMethodFunc = noSuchMethodElement as FunctionElement; 93 FunctionElement noSuchMethodFunc = noSuchMethodElement as FunctionElement;
86 if (backend.isDefaultNoSuchMethodImplementation(noSuchMethodFunc)) { 94 if (_isDefaultNoSuchMethodImplementation(noSuchMethodFunc)) {
87 defaultImpls.add(noSuchMethodFunc); 95 defaultImpls.add(noSuchMethodFunc);
88 return NsmCategory.DEFAULT; 96 return NsmCategory.DEFAULT;
89 } else if (hasForwardingSyntax(noSuchMethodFunc)) { 97 } else if (_hasForwardingSyntax(noSuchMethodFunc)) {
90 // If the implementation is 'noSuchMethod(x) => super.noSuchMethod(x);' 98 // If the implementation is 'noSuchMethod(x) => super.noSuchMethod(x);'
91 // then it is in the same category as the super call. 99 // then it is in the same category as the super call.
92 Element superCall = noSuchMethodFunc.enclosingClass 100 Element superCall = noSuchMethodFunc.enclosingClass
93 .lookupSuperSelector(compiler.noSuchMethodSelector); 101 .lookupSuperSelector(_compiler.noSuchMethodSelector);
94 NsmCategory category = _categorizeImpl(superCall); 102 NsmCategory category = _categorizeImpl(superCall);
95 switch(category) { 103 switch(category) {
96 case NsmCategory.DEFAULT: 104 case NsmCategory.DEFAULT:
97 defaultImpls.add(noSuchMethodFunc); 105 defaultImpls.add(noSuchMethodFunc);
98 break; 106 break;
99 case NsmCategory.THROWING: 107 case NsmCategory.THROWING:
100 throwingImpls.add(noSuchMethodFunc); 108 throwingImpls.add(noSuchMethodFunc);
101 break; 109 break;
102 case NsmCategory.OTHER: 110 case NsmCategory.OTHER:
103 otherImpls.add(noSuchMethodFunc); 111 otherImpls.add(noSuchMethodFunc);
104 break; 112 break;
105 } 113 }
106 return category; 114 return category;
107 } else if (isThrowing(noSuchMethodFunc)) { 115 } else if (_hasThrowingSyntax(noSuchMethodFunc)) {
108 throwingImpls.add(noSuchMethodFunc); 116 throwingImpls.add(noSuchMethodFunc);
109 return NsmCategory.THROWING; 117 return NsmCategory.THROWING;
110 } else { 118 } else {
111 otherImpls.add(noSuchMethodFunc); 119 otherImpls.add(noSuchMethodFunc);
112 return NsmCategory.OTHER; 120 return NsmCategory.OTHER;
113 } 121 }
114 } 122 }
115 123
116 bool hasForwardingSyntax(FunctionElement element) { 124 bool _isDefaultNoSuchMethodImplementation(Element element) {
125 ClassElement classElement = element.enclosingClass;
126 return classElement == _compiler.objectClass
127 || classElement == _backend.jsInterceptorClass
128 || classElement == _backend.jsNullClass;
129 }
130
131 bool _hasForwardingSyntax(FunctionElement element) {
117 // At this point we know that this is signature-compatible with 132 // At this point we know that this is signature-compatible with
118 // Object.noSuchMethod, but it may have more than one argument as long as 133 // Object.noSuchMethod, but it may have more than one argument as long as
119 // it only has one required argument. 134 // it only has one required argument.
120 String param = element.parameters.first.name; 135 String param = element.parameters.first.name;
121 Statement body = element.node.body; 136 Statement body = element.node.body;
122 Expression expr; 137 Expression expr;
123 if (body is Return && body.isArrowBody) { 138 if (body is Return && body.isArrowBody) {
124 expr = body.expression; 139 expr = body.expression;
125 } else if (body is Block && 140 } else if (body is Block &&
126 !body.statements.isEmpty && 141 !body.statements.isEmpty &&
(...skipping 13 matching lines...) Expand all
140 arg.argumentsNode == null && 155 arg.argumentsNode == null &&
141 arg.receiver == null && 156 arg.receiver == null &&
142 arg.selector is Identifier && 157 arg.selector is Identifier &&
143 arg.selector.source == param) { 158 arg.selector.source == param) {
144 return true; 159 return true;
145 } 160 }
146 } 161 }
147 return false; 162 return false;
148 } 163 }
149 164
150 bool isThrowing(FunctionElement element) { 165 bool _hasThrowingSyntax(FunctionElement element) {
151 Statement body = element.node.body; 166 Statement body = element.node.body;
152 if (body is Return && body.isArrowBody) { 167 if (body is Return && body.isArrowBody) {
153 if (body.expression is Throw) { 168 if (body.expression is Throw) {
154 return true; 169 return true;
155 } 170 }
156 } else if (body is Block && 171 } else if (body is Block &&
157 !body.statements.isEmpty && 172 !body.statements.isEmpty &&
158 body.statements.nodes.tail.isEmpty) { 173 body.statements.nodes.tail.isEmpty) {
159 if (body.statements.nodes.head is Throw) { 174 if (body.statements.nodes.head is Throw) {
160 return true; 175 return true;
161 } 176 }
162 } 177 }
163 return false; 178 return false;
164 } 179 }
165 } 180 }
166 181
167 enum NsmCategory { DEFAULT, THROWING, OTHER } 182 enum NsmCategory { DEFAULT, THROWING, OTHER }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/backend.dart ('k') | pkg/compiler/lib/src/types/flat_type_mask.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698