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

Side by Side Diff: pkg/compiler/lib/src/universe/function_set.dart

Issue 2804293002: Add MemberEntity.isAbstract and use MemberEntity in function_set.dart (Closed)
Patch Set: Inference doesn't like MemberEntity Created 3 years, 8 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 universe.function_set; 5 library universe.function_set;
6 6
7 import '../common/names.dart' show Identifiers, Selectors; 7 import '../common/names.dart' show Identifiers, Selectors;
8 import '../elements/elements.dart' show MemberElement;
9 import '../elements/entities.dart'; 8 import '../elements/entities.dart';
10 import '../types/types.dart'; 9 import '../types/types.dart';
11 import '../util/util.dart' show Hashing, Setlet; 10 import '../util/util.dart' show Hashing, Setlet;
12 import '../world.dart' show ClosedWorld; 11 import '../world.dart' show ClosedWorld;
13 import 'selector.dart' show Selector; 12 import 'selector.dart' show Selector;
14 import 'world_builder.dart' show ReceiverConstraint; 13 import 'world_builder.dart' show ReceiverConstraint;
15 14
16 class FunctionSetBuilder { 15 class FunctionSetBuilder {
17 final Map<String, FunctionSetNode> nodes = new Map<String, FunctionSetNode>(); 16 final Map<String, FunctionSetNode> nodes = new Map<String, FunctionSetNode>();
18 17
19 FunctionSetNode newNode(String name) => new FunctionSetNode(name); 18 FunctionSetNode newNode(String name) => new FunctionSetNode(name);
20 19
21 void add(MemberElement element) { 20 void add(MemberEntity element) {
22 assert(element.isInstanceMember); 21 assert(element.isInstanceMember);
23 assert(!element.isAbstract); 22 assert(!element.isAbstract);
24 String name = element.name; 23 String name = element.name;
25 FunctionSetNode node = nodes.putIfAbsent(name, () => newNode(name)); 24 FunctionSetNode node = nodes.putIfAbsent(name, () => newNode(name));
26 node.add(element); 25 node.add(element);
27 } 26 }
28 27
29 void remove(MemberElement element) { 28 void remove(MemberEntity element) {
30 assert(element.isInstanceMember); 29 assert(element.isInstanceMember);
31 assert(!element.isAbstract); 30 assert(!element.isAbstract);
32 String name = element.name; 31 String name = element.name;
33 FunctionSetNode node = nodes[name]; 32 FunctionSetNode node = nodes[name];
34 if (node != null) { 33 if (node != null) {
35 node.remove(element); 34 node.remove(element);
36 } 35 }
37 } 36 }
38 37
39 FunctionSet close(ClosedWorld closedWorld) { 38 FunctionSet close(ClosedWorld closedWorld) {
40 return new FunctionSet(closedWorld, nodes); 39 return new FunctionSet(closedWorld, nodes);
41 } 40 }
42 } 41 }
43 42
44 // TODO(kasperl): This actually holds getters and setters just fine 43 // TODO(kasperl): This actually holds getters and setters just fine
45 // too and stricly they aren't functions. Maybe this needs a better 44 // too and stricly they aren't functions. Maybe this needs a better
46 // name -- something like ElementSet seems a bit too generic. 45 // name -- something like ElementSet seems a bit too generic.
47 class FunctionSet { 46 class FunctionSet {
48 final ClosedWorld closedWorld; 47 final ClosedWorld closedWorld;
49 final Map<String, FunctionSetNode> nodes; 48 final Map<String, FunctionSetNode> nodes;
50 49
51 FunctionSet(this.closedWorld, this.nodes); 50 FunctionSet(this.closedWorld, this.nodes);
52 51
53 bool contains(MemberElement element) { 52 bool contains(MemberEntity element) {
54 assert(element.isInstanceMember); 53 assert(element.isInstanceMember);
55 assert(!element.isAbstract); 54 assert(!element.isAbstract);
56 String name = element.name; 55 String name = element.name;
57 FunctionSetNode node = nodes[name]; 56 FunctionSetNode node = nodes[name];
58 return (node != null) ? node.contains(element) : false; 57 return (node != null) ? node.contains(element) : false;
59 } 58 }
60 59
61 /// Returns all the functions that may be invoked with the [selector] on a 60 /// Returns all the functions that may be invoked with the [selector] on a
62 /// receiver with the given [constraint]. The returned elements may include 61 /// receiver with the given [constraint]. The returned elements may include
63 /// noSuchMethod handlers that are potential targets indirectly through the 62 /// noSuchMethod handlers that are potential targets indirectly through the
64 /// noSuchMethod mechanism. 63 /// noSuchMethod mechanism.
65 Iterable<MemberElement> filter( 64 Iterable<MemberEntity> filter(
66 Selector selector, ReceiverConstraint constraint) { 65 Selector selector, ReceiverConstraint constraint) {
67 return query(selector, constraint).functions; 66 return query(selector, constraint).functions;
68 } 67 }
69 68
70 /// Returns the mask for the potential receivers of a dynamic call to 69 /// Returns the mask for the potential receivers of a dynamic call to
71 /// [selector] on [constraint]. 70 /// [selector] on [constraint].
72 /// 71 ///
73 /// This will narrow the constraints of [constraint] to a [TypeMask] of the 72 /// This will narrow the constraints of [constraint] to a [TypeMask] of the
74 /// set of classes that actually implement the selected member or implement 73 /// set of classes that actually implement the selected member or implement
75 /// the handling 'noSuchMethod' where the selected member is unimplemented. 74 /// the handling 'noSuchMethod' where the selected member is unimplemented.
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 /// selectors with the same [name]. 154 /// selectors with the same [name].
156 class FunctionSetNode { 155 class FunctionSetNode {
157 final String name; 156 final String name;
158 final Map<SelectorMask, FunctionSetQuery> cache = 157 final Map<SelectorMask, FunctionSetQuery> cache =
159 <SelectorMask, FunctionSetQuery>{}; 158 <SelectorMask, FunctionSetQuery>{};
160 159
161 // Initially, we keep the elements in a list because it is more 160 // Initially, we keep the elements in a list because it is more
162 // compact than a hash set. Once we get enough elements, we change 161 // compact than a hash set. Once we get enough elements, we change
163 // the representation to be a set to get faster contains checks. 162 // the representation to be a set to get faster contains checks.
164 static const int MAX_ELEMENTS_IN_LIST = 8; 163 static const int MAX_ELEMENTS_IN_LIST = 8;
165 var elements = <MemberElement>[]; 164 var elements = <MemberEntity>[];
166 bool isList = true; 165 bool isList = true;
167 166
168 FunctionSetNode(this.name); 167 FunctionSetNode(this.name);
169 168
170 void add(MemberElement element) { 169 void add(MemberEntity element) {
171 assert(element.name == name); 170 assert(element.name == name);
172 // We try to avoid clearing the cache unless we have to. For that 171 // We try to avoid clearing the cache unless we have to. For that
173 // reason we keep the explicit contains check even though the add 172 // reason we keep the explicit contains check even though the add
174 // method ends up doing the work again (for sets). 173 // method ends up doing the work again (for sets).
175 if (!elements.contains(element)) { 174 if (!elements.contains(element)) {
176 if (isList && elements.length >= MAX_ELEMENTS_IN_LIST) { 175 if (isList && elements.length >= MAX_ELEMENTS_IN_LIST) {
177 elements = elements.toSet(); 176 elements = elements.toSet();
178 isList = false; 177 isList = false;
179 } 178 }
180 elements.add(element); 179 elements.add(element);
181 if (!cache.isEmpty) cache.clear(); 180 if (!cache.isEmpty) cache.clear();
182 } 181 }
183 } 182 }
184 183
185 void remove(MemberElement element) { 184 void remove(MemberEntity element) {
186 assert(element.name == name); 185 assert(element.name == name);
187 if (isList) { 186 if (isList) {
188 List list = elements; 187 List list = elements;
189 int index = list.indexOf(element); 188 int index = list.indexOf(element);
190 if (index < 0) return; 189 if (index < 0) return;
191 MemberElement last = list.removeLast(); 190 MemberEntity last = list.removeLast();
192 if (index != list.length) { 191 if (index != list.length) {
193 list[index] = last; 192 list[index] = last;
194 } 193 }
195 if (!cache.isEmpty) cache.clear(); 194 if (!cache.isEmpty) cache.clear();
196 } else { 195 } else {
197 Set set = elements; 196 Set set = elements;
198 if (set.remove(element)) { 197 if (set.remove(element)) {
199 // To avoid wobbling between the two representations, we do 198 // To avoid wobbling between the two representations, we do
200 // not transition back to the list representation even if we 199 // not transition back to the list representation even if we
201 // end up with few enough elements at this point. 200 // end up with few enough elements at this point.
202 if (!cache.isEmpty) cache.clear(); 201 if (!cache.isEmpty) cache.clear();
203 } 202 }
204 } 203 }
205 } 204 }
206 205
207 bool contains(MemberElement element) { 206 bool contains(MemberEntity element) {
208 assert(element.name == name); 207 assert(element.name == name);
209 return elements.contains(element); 208 return elements.contains(element);
210 } 209 }
211 210
212 void forEach(Function action) { 211 void forEach(Function action) {
213 elements.forEach(action); 212 elements.forEach(action);
214 } 213 }
215 214
216 /// Returns the set of functions that can be the target of [selectorMask] 215 /// Returns the set of functions that can be the target of [selectorMask]
217 /// including no such method handling where applicable. 216 /// including no such method handling where applicable.
218 FunctionSetQuery query(SelectorMask selectorMask, ClosedWorld closedWorld, 217 FunctionSetQuery query(SelectorMask selectorMask, ClosedWorld closedWorld,
219 [FunctionSetNode noSuchMethods, SelectorMask noSuchMethodMask]) { 218 [FunctionSetNode noSuchMethods, SelectorMask noSuchMethodMask]) {
220 assert(selectorMask.name == name); 219 assert(selectorMask.name == name);
221 FunctionSetQuery result = cache[selectorMask]; 220 FunctionSetQuery result = cache[selectorMask];
222 if (result != null) return result; 221 if (result != null) return result;
223 222
224 Setlet<MemberElement> functions; 223 Setlet<MemberEntity> functions;
225 for (MemberElement element in elements) { 224 for (MemberEntity element in elements) {
226 if (selectorMask.applies(element, closedWorld)) { 225 if (selectorMask.applies(element, closedWorld)) {
227 if (functions == null) { 226 if (functions == null) {
228 // Defer the allocation of the functions set until we are 227 // Defer the allocation of the functions set until we are
229 // sure we need it. This allows us to return immutable empty 228 // sure we need it. This allows us to return immutable empty
230 // lists when the filtering produced no results. 229 // lists when the filtering produced no results.
231 functions = new Setlet<MemberElement>(); 230 functions = new Setlet<MemberEntity>();
232 } 231 }
233 functions.add(element); 232 functions.add(element);
234 } 233 }
235 } 234 }
236 235
237 // If we cannot ensure a method will be found at runtime, we also 236 // If we cannot ensure a method will be found at runtime, we also
238 // add [noSuchMethod] implementations that apply to [mask] as 237 // add [noSuchMethod] implementations that apply to [mask] as
239 // potential targets. 238 // potential targets.
240 if (noSuchMethods != null && 239 if (noSuchMethods != null &&
241 selectorMask.needsNoSuchMethodHandling(closedWorld)) { 240 selectorMask.needsNoSuchMethodHandling(closedWorld)) {
242 FunctionSetQuery noSuchMethodQuery = 241 FunctionSetQuery noSuchMethodQuery =
243 noSuchMethods.query(noSuchMethodMask, closedWorld); 242 noSuchMethods.query(noSuchMethodMask, closedWorld);
244 if (!noSuchMethodQuery.functions.isEmpty) { 243 if (!noSuchMethodQuery.functions.isEmpty) {
245 if (functions == null) { 244 if (functions == null) {
246 functions = 245 functions =
247 new Setlet<MemberElement>.from(noSuchMethodQuery.functions); 246 new Setlet<MemberEntity>.from(noSuchMethodQuery.functions);
248 } else { 247 } else {
249 functions.addAll(noSuchMethodQuery.functions); 248 functions.addAll(noSuchMethodQuery.functions);
250 } 249 }
251 } 250 }
252 } 251 }
253 cache[selectorMask] = result = (functions != null) 252 cache[selectorMask] = result = (functions != null)
254 ? new FullFunctionSetQuery(functions) 253 ? new FullFunctionSetQuery(functions)
255 : const EmptyFunctionSetQuery(); 254 : const EmptyFunctionSetQuery();
256 return result; 255 return result;
257 } 256 }
258 } 257 }
259 258
260 /// A set of functions that are the potential targets of all call sites sharing 259 /// A set of functions that are the potential targets of all call sites sharing
261 /// the same receiver mask and selector. 260 /// the same receiver mask and selector.
262 abstract class FunctionSetQuery { 261 abstract class FunctionSetQuery {
263 const FunctionSetQuery(); 262 const FunctionSetQuery();
264 263
265 /// Compute the type of all potential receivers of this function set. 264 /// Compute the type of all potential receivers of this function set.
266 TypeMask computeMask(ClosedWorld closedWorld); 265 TypeMask computeMask(ClosedWorld closedWorld);
267 266
268 /// Returns all potential targets of this function set. 267 /// Returns all potential targets of this function set.
269 Iterable<MemberElement> get functions; 268 Iterable<MemberEntity> get functions;
270 } 269 }
271 270
272 class EmptyFunctionSetQuery implements FunctionSetQuery { 271 class EmptyFunctionSetQuery implements FunctionSetQuery {
273 const EmptyFunctionSetQuery(); 272 const EmptyFunctionSetQuery();
274 273
275 @override 274 @override
276 TypeMask computeMask(ClosedWorld closedWorld) => 275 TypeMask computeMask(ClosedWorld closedWorld) =>
277 const TypeMask.nonNullEmpty(); 276 const TypeMask.nonNullEmpty();
278 277
279 @override 278 @override
280 Iterable<MemberElement> get functions => const <MemberElement>[]; 279 Iterable<MemberEntity> get functions => const <MemberEntity>[];
281 } 280 }
282 281
283 class FullFunctionSetQuery implements FunctionSetQuery { 282 class FullFunctionSetQuery implements FunctionSetQuery {
284 @override 283 @override
285 final Iterable<MemberElement> functions; 284 final Iterable<MemberEntity> functions;
286 285
287 TypeMask _mask; 286 TypeMask _mask;
288 287
289 FullFunctionSetQuery(this.functions); 288 FullFunctionSetQuery(this.functions);
290 289
291 @override 290 @override
292 TypeMask computeMask(ClosedWorld closedWorld) { 291 TypeMask computeMask(ClosedWorld closedWorld) {
293 assert(closedWorld 292 assert(closedWorld
294 .hasAnyStrictSubclass(closedWorld.commonElements.objectClass)); 293 .hasAnyStrictSubclass(closedWorld.commonElements.objectClass));
295 if (_mask != null) return _mask; 294 if (_mask != null) return _mask;
296 return _mask = new TypeMask.unionOf( 295 return _mask = new TypeMask.unionOf(
297 functions.expand((MemberElement element) { 296 functions.expand((MemberEntity element) {
298 ClassEntity cls = element.enclosingClass; 297 ClassEntity cls = element.enclosingClass;
299 return [cls]..addAll(closedWorld.mixinUsesOf(cls)); 298 return [cls]..addAll(closedWorld.mixinUsesOf(cls));
300 }).map((cls) { 299 }).map((cls) {
301 if (closedWorld.backendClasses.nullClass == cls) { 300 if (closedWorld.backendClasses.nullClass == cls) {
302 return const TypeMask.empty(); 301 return const TypeMask.empty();
303 } else if (closedWorld.isInstantiated(cls)) { 302 } else if (closedWorld.isInstantiated(cls)) {
304 return new TypeMask.nonNullSubclass(cls, closedWorld); 303 return new TypeMask.nonNullSubclass(cls, closedWorld);
305 } else { 304 } else {
306 // TODO(johnniwinther): Avoid the need for this case. 305 // TODO(johnniwinther): Avoid the need for this case.
307 return const TypeMask.empty(); 306 return const TypeMask.empty();
308 } 307 }
309 }), 308 }),
310 closedWorld); 309 closedWorld);
311 } 310 }
312 } 311 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/universe/element_world_builder.dart ('k') | pkg/compiler/lib/src/universe/resolution_world_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698