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

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

Issue 2363773005: Move closed world reasoning methods from ClassWorld to ClosedWorld. (Closed)
Patch Set: Created 4 years, 3 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 '../compiler.dart' show Compiler; 8 import '../compiler.dart' show Compiler;
9 import '../elements/elements.dart'; 9 import '../elements/elements.dart';
10 import '../types/types.dart'; 10 import '../types/types.dart';
11 import '../util/util.dart' show Hashing, Setlet; 11 import '../util/util.dart' show Hashing, Setlet;
12 import '../world.dart' show ClassWorld; 12 import '../world.dart' show ClosedWorld;
13 import 'selector.dart' show Selector; 13 import 'selector.dart' show Selector;
14 import 'universe.dart' show ReceiverConstraint; 14 import 'universe.dart' show ReceiverConstraint;
15 15
16 // TODO(kasperl): This actually holds getters and setters just fine 16 // TODO(kasperl): This actually holds getters and setters just fine
17 // too and stricly they aren't functions. Maybe this needs a better 17 // too and stricly they aren't functions. Maybe this needs a better
18 // name -- something like ElementSet seems a bit too generic. 18 // name -- something like ElementSet seems a bit too generic.
19 class FunctionSet { 19 class FunctionSet {
20 final Compiler compiler; 20 final Compiler compiler;
21 final Map<String, FunctionSetNode> nodes = new Map<String, FunctionSetNode>(); 21 final Map<String, FunctionSetNode> nodes = new Map<String, FunctionSetNode>();
22 FunctionSet(this.compiler); 22 FunctionSet(this.compiler);
23 23
24 ClassWorld get classWorld => compiler.closedWorld; 24 ClosedWorld get closedWorld => compiler.closedWorld;
25 25
26 FunctionSetNode newNode(String name) => new FunctionSetNode(name); 26 FunctionSetNode newNode(String name) => new FunctionSetNode(name);
27 27
28 void add(Element element) { 28 void add(Element element) {
29 assert(element.isInstanceMember); 29 assert(element.isInstanceMember);
30 assert(!element.isAbstract); 30 assert(!element.isAbstract);
31 String name = element.name; 31 String name = element.name;
32 FunctionSetNode node = nodes.putIfAbsent(name, () => newNode(name)); 32 FunctionSetNode node = nodes.putIfAbsent(name, () => newNode(name));
33 node.add(element); 33 node.add(element);
34 } 34 }
(...skipping 22 matching lines...) Expand all
57 return query(selector, constraint).functions; 57 return query(selector, constraint).functions;
58 } 58 }
59 59
60 /// Returns the mask for the potential receivers of a dynamic call to 60 /// Returns the mask for the potential receivers of a dynamic call to
61 /// [selector] on [constraint]. 61 /// [selector] on [constraint].
62 /// 62 ///
63 /// This will narrow the constraints of [constraint] to a [TypeMask] of the 63 /// This will narrow the constraints of [constraint] to a [TypeMask] of the
64 /// set of classes that actually implement the selected member or implement 64 /// set of classes that actually implement the selected member or implement
65 /// the handling 'noSuchMethod' where the selected member is unimplemented. 65 /// the handling 'noSuchMethod' where the selected member is unimplemented.
66 TypeMask receiverType(Selector selector, ReceiverConstraint constraint) { 66 TypeMask receiverType(Selector selector, ReceiverConstraint constraint) {
67 return query(selector, constraint).computeMask(classWorld); 67 return query(selector, constraint).computeMask(closedWorld);
68 } 68 }
69 69
70 SelectorMask _createSelectorMask( 70 SelectorMask _createSelectorMask(Selector selector,
71 Selector selector, ReceiverConstraint constraint, ClassWorld classWorld) { 71 ReceiverConstraint constraint, ClosedWorld closedWorld) {
72 return constraint != null 72 return constraint != null
73 ? new SelectorMask(selector, constraint) 73 ? new SelectorMask(selector, constraint)
74 : new SelectorMask( 74 : new SelectorMask(
75 selector, 75 selector,
76 new TypeMask.subclass( 76 new TypeMask.subclass(
77 classWorld.coreClasses.objectClass, classWorld)); 77 closedWorld.coreClasses.objectClass, closedWorld));
78 } 78 }
79 79
80 /// Returns the set of functions that can be the target of a call to 80 /// Returns the set of functions that can be the target of a call to
81 /// [selector] on a receiver constrained by [constraint] including 81 /// [selector] on a receiver constrained by [constraint] including
82 /// 'noSuchMethod' methods where applicable. 82 /// 'noSuchMethod' methods where applicable.
83 FunctionSetQuery query(Selector selector, ReceiverConstraint constraint) { 83 FunctionSetQuery query(Selector selector, ReceiverConstraint constraint) {
84 String name = selector.name; 84 String name = selector.name;
85 SelectorMask selectorMask = 85 SelectorMask selectorMask =
86 _createSelectorMask(selector, constraint, classWorld); 86 _createSelectorMask(selector, constraint, closedWorld);
87 SelectorMask noSuchMethodMask = 87 SelectorMask noSuchMethodMask =
88 new SelectorMask(Selectors.noSuchMethod_, selectorMask.constraint); 88 new SelectorMask(Selectors.noSuchMethod_, selectorMask.constraint);
89 FunctionSetNode node = nodes[name]; 89 FunctionSetNode node = nodes[name];
90 FunctionSetNode noSuchMethods = nodes[Identifiers.noSuchMethod_]; 90 FunctionSetNode noSuchMethods = nodes[Identifiers.noSuchMethod_];
91 if (node != null) { 91 if (node != null) {
92 return node.query( 92 return node.query(
93 selectorMask, classWorld, noSuchMethods, noSuchMethodMask); 93 selectorMask, closedWorld, noSuchMethods, noSuchMethodMask);
94 } 94 }
95 // If there is no method that matches [selector] we know we can 95 // If there is no method that matches [selector] we know we can
96 // only hit [:noSuchMethod:]. 96 // only hit [:noSuchMethod:].
97 if (noSuchMethods == null) { 97 if (noSuchMethods == null) {
98 return const EmptyFunctionSetQuery(); 98 return const EmptyFunctionSetQuery();
99 } 99 }
100 return noSuchMethods.query(noSuchMethodMask, classWorld); 100 return noSuchMethods.query(noSuchMethodMask, closedWorld);
101 } 101 }
102 102
103 void forEach(Function action) { 103 void forEach(Function action) {
104 nodes.forEach((String name, FunctionSetNode node) { 104 nodes.forEach((String name, FunctionSetNode node) {
105 node.forEach(action); 105 node.forEach(action);
106 }); 106 });
107 } 107 }
108 } 108 }
109 109
110 /// A selector/constraint pair representing the dynamic invocation of [selector] 110 /// A selector/constraint pair representing the dynamic invocation of [selector]
111 /// on a receiver constrained by [constraint]. 111 /// on a receiver constrained by [constraint].
112 class SelectorMask { 112 class SelectorMask {
113 final Selector selector; 113 final Selector selector;
114 final ReceiverConstraint constraint; 114 final ReceiverConstraint constraint;
115 final int hashCode; 115 final int hashCode;
116 116
117 SelectorMask(Selector selector, ReceiverConstraint constraint) 117 SelectorMask(Selector selector, ReceiverConstraint constraint)
118 : this.selector = selector, 118 : this.selector = selector,
119 this.constraint = constraint, 119 this.constraint = constraint,
120 this.hashCode = 120 this.hashCode =
121 Hashing.mixHashCodeBits(selector.hashCode, constraint.hashCode) { 121 Hashing.mixHashCodeBits(selector.hashCode, constraint.hashCode) {
122 assert(constraint != null); 122 assert(constraint != null);
123 } 123 }
124 124
125 String get name => selector.name; 125 String get name => selector.name;
126 126
127 bool applies(Element element, ClassWorld classWorld) { 127 bool applies(Element element, ClosedWorld closedWorld) {
128 if (!selector.appliesUnnamed(element, classWorld.backend)) return false; 128 if (!selector.appliesUnnamed(element, closedWorld.backend)) return false;
129 return constraint.canHit(element, selector, classWorld); 129 return constraint.canHit(element, selector, closedWorld);
130 } 130 }
131 131
132 bool needsNoSuchMethodHandling(ClassWorld classWorld) { 132 bool needsNoSuchMethodHandling(ClosedWorld closedWorld) {
133 return constraint.needsNoSuchMethodHandling(selector, classWorld); 133 return constraint.needsNoSuchMethodHandling(selector, closedWorld);
134 } 134 }
135 135
136 bool operator ==(other) { 136 bool operator ==(other) {
137 if (identical(this, other)) return true; 137 if (identical(this, other)) return true;
138 return selector == other.selector && constraint == other.constraint; 138 return selector == other.selector && constraint == other.constraint;
139 } 139 }
140 140
141 String toString() => '($selector,$constraint)'; 141 String toString() => '($selector,$constraint)';
142 } 142 }
143 143
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 assert(element.name == name); 198 assert(element.name == name);
199 return elements.contains(element); 199 return elements.contains(element);
200 } 200 }
201 201
202 void forEach(Function action) { 202 void forEach(Function action) {
203 elements.forEach(action); 203 elements.forEach(action);
204 } 204 }
205 205
206 /// Returns the set of functions that can be the target of [selectorMask] 206 /// Returns the set of functions that can be the target of [selectorMask]
207 /// including no such method handling where applicable. 207 /// including no such method handling where applicable.
208 FunctionSetQuery query(SelectorMask selectorMask, ClassWorld classWorld, 208 FunctionSetQuery query(SelectorMask selectorMask, ClosedWorld closedWorld,
209 [FunctionSetNode noSuchMethods, SelectorMask noSuchMethodMask]) { 209 [FunctionSetNode noSuchMethods, SelectorMask noSuchMethodMask]) {
210 assert(selectorMask.name == name); 210 assert(selectorMask.name == name);
211 FunctionSetQuery result = cache[selectorMask]; 211 FunctionSetQuery result = cache[selectorMask];
212 if (result != null) return result; 212 if (result != null) return result;
213 213
214 Setlet<Element> functions; 214 Setlet<Element> functions;
215 for (Element element in elements) { 215 for (Element element in elements) {
216 if (selectorMask.applies(element, classWorld)) { 216 if (selectorMask.applies(element, closedWorld)) {
217 if (functions == null) { 217 if (functions == null) {
218 // Defer the allocation of the functions set until we are 218 // Defer the allocation of the functions set until we are
219 // sure we need it. This allows us to return immutable empty 219 // sure we need it. This allows us to return immutable empty
220 // lists when the filtering produced no results. 220 // lists when the filtering produced no results.
221 functions = new Setlet<Element>(); 221 functions = new Setlet<Element>();
222 } 222 }
223 functions.add(element); 223 functions.add(element);
224 } 224 }
225 } 225 }
226 226
227 // If we cannot ensure a method will be found at runtime, we also 227 // If we cannot ensure a method will be found at runtime, we also
228 // add [noSuchMethod] implementations that apply to [mask] as 228 // add [noSuchMethod] implementations that apply to [mask] as
229 // potential targets. 229 // potential targets.
230 if (noSuchMethods != null && 230 if (noSuchMethods != null &&
231 selectorMask.needsNoSuchMethodHandling(classWorld)) { 231 selectorMask.needsNoSuchMethodHandling(closedWorld)) {
232 FunctionSetQuery noSuchMethodQuery = 232 FunctionSetQuery noSuchMethodQuery =
233 noSuchMethods.query(noSuchMethodMask, classWorld); 233 noSuchMethods.query(noSuchMethodMask, closedWorld);
234 if (!noSuchMethodQuery.functions.isEmpty) { 234 if (!noSuchMethodQuery.functions.isEmpty) {
235 if (functions == null) { 235 if (functions == null) {
236 functions = new Setlet<Element>.from(noSuchMethodQuery.functions); 236 functions = new Setlet<Element>.from(noSuchMethodQuery.functions);
237 } else { 237 } else {
238 functions.addAll(noSuchMethodQuery.functions); 238 functions.addAll(noSuchMethodQuery.functions);
239 } 239 }
240 } 240 }
241 } 241 }
242 cache[selectorMask] = result = (functions != null) 242 cache[selectorMask] = result = (functions != null)
243 ? new FullFunctionSetQuery(functions) 243 ? new FullFunctionSetQuery(functions)
244 : const EmptyFunctionSetQuery(); 244 : const EmptyFunctionSetQuery();
245 return result; 245 return result;
246 } 246 }
247 } 247 }
248 248
249 /// A set of functions that are the potential targets of all call sites sharing 249 /// A set of functions that are the potential targets of all call sites sharing
250 /// the same receiver mask and selector. 250 /// the same receiver mask and selector.
251 abstract class FunctionSetQuery { 251 abstract class FunctionSetQuery {
252 const FunctionSetQuery(); 252 const FunctionSetQuery();
253 253
254 /// Compute the type of all potential receivers of this function set. 254 /// Compute the type of all potential receivers of this function set.
255 TypeMask computeMask(ClassWorld classWorld); 255 TypeMask computeMask(ClosedWorld closedWorld);
256 256
257 /// Returns all potential targets of this function set. 257 /// Returns all potential targets of this function set.
258 Iterable<Element> get functions; 258 Iterable<Element> get functions;
259 } 259 }
260 260
261 class EmptyFunctionSetQuery implements FunctionSetQuery { 261 class EmptyFunctionSetQuery implements FunctionSetQuery {
262 const EmptyFunctionSetQuery(); 262 const EmptyFunctionSetQuery();
263 263
264 @override 264 @override
265 TypeMask computeMask(ClassWorld classWorld) => const TypeMask.nonNullEmpty(); 265 TypeMask computeMask(ClosedWorld closedWorld) =>
266 const TypeMask.nonNullEmpty();
266 267
267 @override 268 @override
268 Iterable<Element> get functions => const <Element>[]; 269 Iterable<Element> get functions => const <Element>[];
269 } 270 }
270 271
271 class FullFunctionSetQuery implements FunctionSetQuery { 272 class FullFunctionSetQuery implements FunctionSetQuery {
272 @override 273 @override
273 final Iterable<Element> functions; 274 final Iterable<Element> functions;
274 275
275 TypeMask _mask; 276 TypeMask _mask;
276 277
277 FullFunctionSetQuery(this.functions); 278 FullFunctionSetQuery(this.functions);
278 279
279 @override 280 @override
280 TypeMask computeMask(ClassWorld classWorld) { 281 TypeMask computeMask(ClosedWorld closedWorld) {
281 assert(classWorld.hasAnyStrictSubclass(classWorld.coreClasses.objectClass)); 282 assert(
283 closedWorld.hasAnyStrictSubclass(closedWorld.coreClasses.objectClass));
282 if (_mask != null) return _mask; 284 if (_mask != null) return _mask;
283 return _mask = new TypeMask.unionOf( 285 return _mask = new TypeMask.unionOf(
284 functions.expand((element) { 286 functions.expand((element) {
285 ClassElement cls = element.enclosingClass; 287 ClassElement cls = element.enclosingClass;
286 return [cls]..addAll(classWorld.mixinUsesOf(cls)); 288 return [cls]..addAll(closedWorld.mixinUsesOf(cls));
287 }).map((cls) { 289 }).map((cls) {
288 if (classWorld.backend.isNullImplementation(cls)) { 290 if (closedWorld.backend.isNullImplementation(cls)) {
289 return const TypeMask.empty(); 291 return const TypeMask.empty();
290 } else if (classWorld.isInstantiated(cls.declaration)) { 292 } else if (closedWorld.isInstantiated(cls.declaration)) {
291 return new TypeMask.nonNullSubclass(cls.declaration, classWorld); 293 return new TypeMask.nonNullSubclass(cls.declaration, closedWorld);
292 } else { 294 } else {
293 // TODO(johnniwinther): Avoid the need for this case. 295 // TODO(johnniwinther): Avoid the need for this case.
294 return const TypeMask.empty(); 296 return const TypeMask.empty();
295 } 297 }
296 }), 298 }),
297 classWorld); 299 closedWorld);
298 } 300 }
299 } 301 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698