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

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

Issue 1303363006: Cleanup of function_set.dart (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 universe; 5 part of universe;
6 6
7 // TODO(kasperl): This actually holds getters and setters just fine 7 // TODO(kasperl): This actually holds getters and setters just fine
8 // too and stricly they aren't functions. Maybe this needs a better 8 // too and stricly they aren't functions. Maybe this needs a better
9 // name -- something like ElementSet seems a bit too generic. 9 // name -- something like ElementSet seems a bit too generic.
10 class FunctionSet { 10 class FunctionSet {
11 final Compiler compiler; 11 final Compiler compiler;
12 final Map<String, FunctionSetNode> nodes = 12 final Map<String, FunctionSetNode> nodes =
13 new Map<String, FunctionSetNode>(); 13 new Map<String, FunctionSetNode>();
14 FunctionSet(this.compiler); 14 FunctionSet(this.compiler);
15 15
16 ClassWorld get classWorld => compiler.world;
17
16 FunctionSetNode newNode(String name) 18 FunctionSetNode newNode(String name)
17 => new FunctionSetNode(name); 19 => new FunctionSetNode(name);
18 20
19 void add(Element element) { 21 void add(Element element) {
20 assert(element.isInstanceMember); 22 assert(element.isInstanceMember);
21 assert(!element.isAbstract); 23 assert(!element.isAbstract);
22 String name = element.name; 24 String name = element.name;
23 FunctionSetNode node = nodes.putIfAbsent(name, () => newNode(name)); 25 FunctionSetNode node = nodes.putIfAbsent(name, () => newNode(name));
24 node.add(element); 26 node.add(element);
25 } 27 }
(...skipping 11 matching lines...) Expand all
37 bool contains(Element element) { 39 bool contains(Element element) {
38 assert(element.isInstanceMember); 40 assert(element.isInstanceMember);
39 assert(!element.isAbstract); 41 assert(!element.isAbstract);
40 String name = element.name; 42 String name = element.name;
41 FunctionSetNode node = nodes[name]; 43 FunctionSetNode node = nodes[name];
42 return (node != null) 44 return (node != null)
43 ? node.contains(element) 45 ? node.contains(element)
44 : false; 46 : false;
45 } 47 }
46 48
47 /** 49 /// Returns an object that allows iterating over all the functions
48 * Returns an object that allows iterating over all the functions 50 /// that may be invoked with the given [selector].
49 * that may be invoked with the given [selector].
50 */
51 Iterable<Element> filter(Selector selector, TypeMask mask) { 51 Iterable<Element> filter(Selector selector, TypeMask mask) {
52 return query(selector, mask).functions; 52 return query(selector, mask).functions;
53 } 53 }
54 54
55 /// Returns the mask for the potential receivers of a dynamic call to
56 /// [selector] on [mask].
57 ///
58 /// This will reduces the set of classes in [mask] to a [TypeMask] of the set
karlklose 2015/09/01 07:47:03 'reduces' -> 'reduce'.
Johnni Winther 2015/09/01 11:54:47 Done.
59 /// of classes that actually implement the selected member or implement the
60 /// handling 'noSuchMethod' where the selected member is unimplemented.
55 TypeMask receiverType(Selector selector, TypeMask mask) { 61 TypeMask receiverType(Selector selector, TypeMask mask) {
56 return query(selector, mask).computeMask(compiler.world); 62 return query(selector, mask).computeMask(classWorld);
57 } 63 }
58 64
65 SelectorMask _createSelectorMask(
66 Selector selector, TypeMask mask, ClassWorld classWorld) {
67 return mask != null
68 ? new SelectorMask(selector, mask)
69 : new SelectorMask(selector,
70 new TypeMask.subclass(classWorld.objectClass, classWorld));
71 }
72
73 /// Returns the set of functions that can be the target of a call to
74 /// [selector] on a receiver of type [mask] including 'noSuchMethod' methods
75 /// where applicable.
59 FunctionSetQuery query(Selector selector, TypeMask mask) { 76 FunctionSetQuery query(Selector selector, TypeMask mask) {
60 String name = selector.name; 77 String name = selector.name;
78 SelectorMask selectorMask = _createSelectorMask(selector, mask, classWorld);
79 SelectorMask noSuchMethodMask =
80 new SelectorMask(Selectors.noSuchMethod_, selectorMask.mask);
61 FunctionSetNode node = nodes[name]; 81 FunctionSetNode node = nodes[name];
62 FunctionSetNode noSuchMethods = nodes[Identifiers.noSuchMethod_]; 82 FunctionSetNode noSuchMethods = nodes[Identifiers.noSuchMethod_];
63 if (node != null) { 83 if (node != null) {
64 return node.query(selector, mask, compiler, noSuchMethods); 84 return node.query(
85 selectorMask, classWorld, noSuchMethods, noSuchMethodMask);
65 } 86 }
66 // If there is no method that matches [selector] we know we can 87 // If there is no method that matches [selector] we know we can
67 // only hit [:noSuchMethod:]. 88 // only hit [:noSuchMethod:].
68 if (noSuchMethods == null) return const FunctionSetQuery(const <Element>[]); 89 if (noSuchMethods == null) {
69 return noSuchMethods.query( 90 return const FunctionSetQuery();
70 Selectors.noSuchMethod_, mask, compiler, null); 91 }
92 return noSuchMethods.query(noSuchMethodMask, classWorld);
71 } 93 }
72 94
73 void forEach(Function action) { 95 void forEach(Function action) {
74 nodes.forEach((String name, FunctionSetNode node) { 96 nodes.forEach((String name, FunctionSetNode node) {
75 node.forEach(action); 97 node.forEach(action);
76 }); 98 });
77 } 99 }
78 } 100 }
79 101
102 /// A selector/mask pair representing the dynamic invocation of [selector] on
103 /// a receiver of type [mask].
80 class SelectorMask { 104 class SelectorMask {
81 final Selector selector; 105 final Selector selector;
82 final TypeMask mask; 106 final TypeMask mask;
83 final int hashCode; 107 final int hashCode;
84 108
85 SelectorMask(Selector selector, TypeMask mask) 109 SelectorMask(Selector selector, TypeMask mask)
86 : this.selector = selector, 110 : this.selector = selector,
87 this.mask = mask, 111 this.mask = mask,
88 this.hashCode = 112 this.hashCode =
89 Hashing.mixHashCodeBits(selector.hashCode, mask.hashCode); 113 Hashing.mixHashCodeBits(selector.hashCode, mask.hashCode) {
114 assert(mask != null);
karlklose 2015/09/01 07:47:03 The initializer for hashCode uses mask as receiver
Johnni Winther 2015/09/01 11:54:47 Null implements hashCode so it will not fail.
115 }
90 116
91 String get name => selector.name; 117 String get name => selector.name;
92 118
93 bool applies(Element element, ClassWorld classWorld) { 119 bool applies(Element element, ClassWorld classWorld) {
94 if (!selector.appliesUnnamed(element, classWorld)) return false; 120 if (!selector.appliesUnnamed(element, classWorld)) return false;
95 if (mask == null) return true;
96 return mask.canHit(element, selector, classWorld); 121 return mask.canHit(element, selector, classWorld);
97 } 122 }
98 123
124 bool needsNoSuchMethodHandling(ClassWorld classWorld) {
125 return mask.needsNoSuchMethodHandling(selector, classWorld);
126 }
127
99 bool operator ==(other) { 128 bool operator ==(other) {
100 if (identical(this, other)) return true; 129 if (identical(this, other)) return true;
101 return selector == other.selector && mask == other.mask; 130 return selector == other.selector && mask == other.mask;
102 } 131 }
103 132
104 String toString() => '($selector,$mask)'; 133 String toString() => '($selector,$mask)';
105 } 134 }
106 135
136 /// A node in the [FunctionSet] caching all [FunctionSetQuery] object for
137 /// selectors with the same [name].
107 class FunctionSetNode { 138 class FunctionSetNode {
108 final String name; 139 final String name;
109 final Map<SelectorMask, FunctionSetQuery> cache = 140 final Map<SelectorMask, FunctionSetQuery> cache =
110 <SelectorMask, FunctionSetQuery>{}; 141 <SelectorMask, FunctionSetQuery>{};
111 142
112 // Initially, we keep the elements in a list because it is more 143 // Initially, we keep the elements in a list because it is more
113 // compact than a hash set. Once we get enough elements, we change 144 // compact than a hash set. Once we get enough elements, we change
114 // the representation to be a set to get faster contains checks. 145 // the representation to be a set to get faster contains checks.
115 static const int MAX_ELEMENTS_IN_LIST = 8; 146 static const int MAX_ELEMENTS_IN_LIST = 8;
116 var elements = <Element>[]; 147 var elements = <Element>[];
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 188
158 bool contains(Element element) { 189 bool contains(Element element) {
159 assert(element.name == name); 190 assert(element.name == name);
160 return elements.contains(element); 191 return elements.contains(element);
161 } 192 }
162 193
163 void forEach(Function action) { 194 void forEach(Function action) {
164 elements.forEach(action); 195 elements.forEach(action);
165 } 196 }
166 197
167 TypeMask getNonNullTypeMaskOfSelector(TypeMask mask, ClassWorld classWorld) { 198 /// Returns the set of functions that can be the target of [selectorMask]
168 // TODO(ngeoffray): We should probably change untyped selector 199 /// including no such method handling where applicable.
169 // to always be a subclass of Object. 200 FunctionSetQuery query(SelectorMask selectorMask,
170 return mask != null 201 ClassWorld classWorld,
171 ? mask 202 [FunctionSetNode noSuchMethods,
172 : new TypeMask.subclass(classWorld.objectClass, classWorld); 203 SelectorMask noSuchMethodMask]) {
173 } 204 assert(selectorMask.name == name);
174
175 // TODO(johnniwinther): Use [SelectorMask] instead of [Selector] and
176 // [TypeMask].
177 FunctionSetQuery query(Selector selector,
178 TypeMask mask,
179 Compiler compiler,
180 FunctionSetNode noSuchMethods) {
181 mask = getNonNullTypeMaskOfSelector(mask, compiler.world);
182 SelectorMask selectorMask = new SelectorMask(selector, mask);
183 ClassWorld classWorld = compiler.world;
184 assert(selector.name == name);
185 FunctionSetQuery result = cache[selectorMask]; 205 FunctionSetQuery result = cache[selectorMask];
186 if (result != null) return result; 206 if (result != null) return result;
187 207
188 Setlet<Element> functions; 208 Setlet<Element> functions;
189 for (Element element in elements) { 209 for (Element element in elements) {
190 if (selectorMask.applies(element, classWorld)) { 210 if (selectorMask.applies(element, classWorld)) {
191 if (functions == null) { 211 if (functions == null) {
192 // Defer the allocation of the functions set until we are 212 // Defer the allocation of the functions set until we are
193 // sure we need it. This allows us to return immutable empty 213 // sure we need it. This allows us to return immutable empty
194 // lists when the filtering produced no results. 214 // lists when the filtering produced no results.
195 functions = new Setlet<Element>(); 215 functions = new Setlet<Element>();
196 } 216 }
197 functions.add(element); 217 functions.add(element);
198 } 218 }
199 } 219 }
200 220
201 // If we cannot ensure a method will be found at runtime, we also 221 // If we cannot ensure a method will be found at runtime, we also
202 // add [noSuchMethod] implementations that apply to [mask] as 222 // add [noSuchMethod] implementations that apply to [mask] as
203 // potential targets. 223 // potential targets.
204 if (noSuchMethods != null 224 if (noSuchMethods != null &&
205 && mask.needsNoSuchMethodHandling(selector, classWorld)) { 225 selectorMask.needsNoSuchMethodHandling(classWorld)) {
206 FunctionSetQuery noSuchMethodQuery = noSuchMethods.query( 226 FunctionSetQuery noSuchMethodQuery =
207 Selectors.noSuchMethod_, 227 noSuchMethods.query(noSuchMethodMask, classWorld);
208 mask,
209 compiler,
210 null);
211 if (!noSuchMethodQuery.functions.isEmpty) { 228 if (!noSuchMethodQuery.functions.isEmpty) {
212 if (functions == null) { 229 if (functions == null) {
213 functions = new Setlet<Element>.from(noSuchMethodQuery.functions); 230 functions = new Setlet<Element>.from(noSuchMethodQuery.functions);
214 } else { 231 } else {
215 functions.addAll(noSuchMethodQuery.functions); 232 functions.addAll(noSuchMethodQuery.functions);
216 } 233 }
217 } 234 }
218 } 235 }
219 cache[selectorMask] = result = (functions != null) 236 cache[selectorMask] = result = (functions != null)
220 ? newQuery(functions, selector, mask, compiler) 237 ? new FullFunctionSetQuery(functions)
221 : const FunctionSetQuery(const <Element>[]); 238 : const FunctionSetQuery();
222 return result; 239 return result;
223 } 240 }
224
225 FunctionSetQuery newQuery(Iterable<Element> functions,
226 Selector selector,
227 TypeMask mask,
228 Compiler compiler) {
229 return new FullFunctionSetQuery(functions);
230 }
231 } 241 }
232 242
243 /// A set of function that are the potential targets of all call sites sharing
karlklose 2015/09/01 07:47:03 'function' -> 'functions'.
Johnni Winther 2015/09/01 11:54:47 Done.
244 /// the same receiver mask and selector.
233 class FunctionSetQuery { 245 class FunctionSetQuery {
234 final Iterable<Element> functions; 246 const FunctionSetQuery();
247
248 /// Compute the type of all potential receivers of this function set.
235 TypeMask computeMask(ClassWorld classWorld) => const TypeMask.nonNullEmpty(); 249 TypeMask computeMask(ClassWorld classWorld) => const TypeMask.nonNullEmpty();
236 const FunctionSetQuery(this.functions); 250
251 /// Returns all potential targets of this function set.
252 Iterable<Element> get functions => const <Element>[];
237 } 253 }
238 254
239 class FullFunctionSetQuery extends FunctionSetQuery { 255 class FullFunctionSetQuery extends FunctionSetQuery {
256 final Iterable<Element> _functions;
240 TypeMask _mask; 257 TypeMask _mask;
241 258
242 /** 259 FullFunctionSetQuery(this._functions);
243 * Compute the type of all potential receivers of this function set. 260
244 */
245 TypeMask computeMask(ClassWorld classWorld) { 261 TypeMask computeMask(ClassWorld classWorld) {
246 assert(classWorld.hasAnyStrictSubclass(classWorld.objectClass)); 262 assert(classWorld.hasAnyStrictSubclass(classWorld.objectClass));
247 if (_mask != null) return _mask; 263 if (_mask != null) return _mask;
248 return _mask = new TypeMask.unionOf(functions 264 return _mask = new TypeMask.unionOf(functions
249 .expand((element) { 265 .expand((element) {
250 ClassElement cls = element.enclosingClass; 266 ClassElement cls = element.enclosingClass;
251 return [cls]..addAll(classWorld.mixinUsesOf(cls)); 267 return [cls]..addAll(classWorld.mixinUsesOf(cls));
252 }) 268 })
253 .map((cls) { 269 .map((cls) {
254 if (classWorld.backend.isNullImplementation(cls)) { 270 if (classWorld.backend.isNullImplementation(cls)) {
255 return const TypeMask.empty(); 271 return const TypeMask.empty();
256 } else { 272 } else {
257 return new TypeMask.nonNullSubclass(cls.declaration, classWorld); 273 return new TypeMask.nonNullSubclass(cls.declaration, classWorld);
258 } 274 }
259 }), 275 }),
260 classWorld); 276 classWorld);
261 } 277 }
262
263 FullFunctionSetQuery(functions) : super(functions);
264 } 278 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698