OLD | NEW |
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 | 7 import 'closure.dart' show SynthesizedCallMethodElementX; |
8 SynthesizedCallMethodElementX; | |
9 import 'common.dart'; | 8 import 'common.dart'; |
10 import 'common/backend_api.dart' show | 9 import 'common/backend_api.dart' show Backend; |
11 Backend; | 10 import 'compiler.dart' show Compiler; |
12 import 'compiler.dart' show | 11 import 'core_types.dart' show CoreClasses; |
13 Compiler; | |
14 import 'core_types.dart' show | |
15 CoreClasses; | |
16 import 'dart_types.dart'; | 12 import 'dart_types.dart'; |
17 import 'elements/elements.dart' show | 13 import 'elements/elements.dart' |
18 ClassElement, | 14 show |
19 Element, | 15 ClassElement, |
20 FunctionElement, | 16 Element, |
21 MixinApplicationElement, | 17 FunctionElement, |
22 TypedefElement, | 18 MixinApplicationElement, |
23 VariableElement; | 19 TypedefElement, |
| 20 VariableElement; |
24 import 'ordered_typeset.dart'; | 21 import 'ordered_typeset.dart'; |
25 import 'types/types.dart' as ti; | 22 import 'types/types.dart' as ti; |
26 import 'universe/class_set.dart'; | 23 import 'universe/class_set.dart'; |
27 import 'universe/function_set.dart' show | 24 import 'universe/function_set.dart' show FunctionSet; |
28 FunctionSet; | 25 import 'universe/selector.dart' show Selector; |
29 import 'universe/selector.dart' show | 26 import 'universe/side_effects.dart' show SideEffects; |
30 Selector; | 27 import 'util/util.dart' show Link; |
31 import 'universe/side_effects.dart' show | |
32 SideEffects; | |
33 import 'util/util.dart' show | |
34 Link; | |
35 | 28 |
36 abstract class ClassWorld { | 29 abstract class ClassWorld { |
37 // TODO(johnniwinther): Refine this into a `BackendClasses` interface. | 30 // TODO(johnniwinther): Refine this into a `BackendClasses` interface. |
38 Backend get backend; | 31 Backend get backend; |
39 | 32 |
40 // TODO(johnniwinther): Remove the need for this getter. | 33 // TODO(johnniwinther): Remove the need for this getter. |
41 @deprecated | 34 @deprecated |
42 Compiler get compiler; | 35 Compiler get compiler; |
43 | 36 |
44 /// The [ClassElement] for the [Object] class defined in 'dart:core'. | 37 /// The [ClassElement] for the [Object] class defined in 'dart:core'. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 /// Returns an iterable over the live classes that extend [cls] _not_ | 85 /// Returns an iterable over the live classes that extend [cls] _not_ |
93 /// including [cls] itself. | 86 /// including [cls] itself. |
94 Iterable<ClassElement> strictSubclassesOf(ClassElement cls); | 87 Iterable<ClassElement> strictSubclassesOf(ClassElement cls); |
95 | 88 |
96 /// Returns the number of live classes that extend [cls] _not_ | 89 /// Returns the number of live classes that extend [cls] _not_ |
97 /// including [cls] itself. | 90 /// including [cls] itself. |
98 int strictSubclassCount(ClassElement cls); | 91 int strictSubclassCount(ClassElement cls); |
99 | 92 |
100 /// Applies [f] to each live class that extend [cls] _not_ including [cls] | 93 /// Applies [f] to each live class that extend [cls] _not_ including [cls] |
101 /// itself. | 94 /// itself. |
102 void forEachStrictSubclassOf(ClassElement cls, | 95 void forEachStrictSubclassOf( |
103 IterationStep f(ClassElement cls)); | 96 ClassElement cls, IterationStep f(ClassElement cls)); |
104 | 97 |
105 /// Returns `true` if [predicate] applies to any live class that extend [cls] | 98 /// Returns `true` if [predicate] applies to any live class that extend [cls] |
106 /// _not_ including [cls] itself. | 99 /// _not_ including [cls] itself. |
107 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)); | 100 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)); |
108 | 101 |
109 /// Returns an iterable over the directly instantiated that implement [cls] | 102 /// Returns an iterable over the directly instantiated that implement [cls] |
110 /// possibly including [cls] itself, if it is live. | 103 /// possibly including [cls] itself, if it is live. |
111 Iterable<ClassElement> subtypesOf(ClassElement cls); | 104 Iterable<ClassElement> subtypesOf(ClassElement cls); |
112 | 105 |
113 /// Returns an iterable over the live classes that implement [cls] _not_ | 106 /// Returns an iterable over the live classes that implement [cls] _not_ |
114 /// including [cls] if it is live. | 107 /// including [cls] if it is live. |
115 Iterable<ClassElement> strictSubtypesOf(ClassElement cls); | 108 Iterable<ClassElement> strictSubtypesOf(ClassElement cls); |
116 | 109 |
117 /// Returns the number of live classes that implement [cls] _not_ | 110 /// Returns the number of live classes that implement [cls] _not_ |
118 /// including [cls] itself. | 111 /// including [cls] itself. |
119 int strictSubtypeCount(ClassElement cls); | 112 int strictSubtypeCount(ClassElement cls); |
120 | 113 |
121 /// Applies [f] to each live class that implements [cls] _not_ including [cls] | 114 /// Applies [f] to each live class that implements [cls] _not_ including [cls] |
122 /// itself. | 115 /// itself. |
123 void forEachStrictSubtypeOf(ClassElement cls, | 116 void forEachStrictSubtypeOf( |
124 IterationStep f(ClassElement cls)); | 117 ClassElement cls, IterationStep f(ClassElement cls)); |
125 | 118 |
126 /// Returns `true` if [predicate] applies to any live class that implements | 119 /// Returns `true` if [predicate] applies to any live class that implements |
127 /// [cls] _not_ including [cls] itself. | 120 /// [cls] _not_ including [cls] itself. |
128 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)); | 121 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)); |
129 | 122 |
130 /// Returns `true` if [a] and [b] have any known common subtypes. | 123 /// Returns `true` if [a] and [b] have any known common subtypes. |
131 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b); | 124 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b); |
132 | 125 |
133 /// Returns `true` if any live class other than [cls] extends [cls]. | 126 /// Returns `true` if any live class other than [cls] extends [cls]. |
134 bool hasAnyStrictSubclass(ClassElement cls); | 127 bool hasAnyStrictSubclass(ClassElement cls); |
(...skipping 17 matching lines...) Expand all Loading... |
152 /// Returns an iterable over the common supertypes of the [classes]. | 145 /// Returns an iterable over the common supertypes of the [classes]. |
153 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes); | 146 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes); |
154 | 147 |
155 /// Returns an iterable over the live mixin applications that mixin [cls]. | 148 /// Returns an iterable over the live mixin applications that mixin [cls]. |
156 Iterable<MixinApplicationElement> mixinUsesOf(ClassElement cls); | 149 Iterable<MixinApplicationElement> mixinUsesOf(ClassElement cls); |
157 | 150 |
158 /// Returns `true` if [cls] is mixed into a live class. | 151 /// Returns `true` if [cls] is mixed into a live class. |
159 bool isUsedAsMixin(ClassElement cls); | 152 bool isUsedAsMixin(ClassElement cls); |
160 | 153 |
161 /// Returns `true` if any live class that mixes in [cls] implements [type]. | 154 /// Returns `true` if any live class that mixes in [cls] implements [type]. |
162 bool hasAnySubclassOfMixinUseThatImplements(ClassElement cls, | 155 bool hasAnySubclassOfMixinUseThatImplements( |
163 ClassElement type); | 156 ClassElement cls, ClassElement type); |
164 | 157 |
165 /// Returns `true` if any live class that mixes in [mixin] is also a subclass | 158 /// Returns `true` if any live class that mixes in [mixin] is also a subclass |
166 /// of [superclass]. | 159 /// of [superclass]. |
167 bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin); | 160 bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin); |
168 | 161 |
169 /// Returns `true` if any subclass of [superclass] implements [type]. | 162 /// Returns `true` if any subclass of [superclass] implements [type]. |
170 bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type); | 163 bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type); |
171 | 164 |
172 /// Returns `true` if closed-world assumptions can be made, that is, | 165 /// Returns `true` if closed-world assumptions can be made, that is, |
173 /// incremental compilation isn't enabled. | 166 /// incremental compilation isn't enabled. |
(...skipping 14 matching lines...) Expand all Loading... |
188 ClassElement get doubleClass => coreClasses.doubleClass; | 181 ClassElement get doubleClass => coreClasses.doubleClass; |
189 ClassElement get stringClass => coreClasses.stringClass; | 182 ClassElement get stringClass => coreClasses.stringClass; |
190 ClassElement get nullClass => coreClasses.nullClass; | 183 ClassElement get nullClass => coreClasses.nullClass; |
191 | 184 |
192 /// Cache of [ti.FlatTypeMask]s grouped by the 8 possible values of the | 185 /// Cache of [ti.FlatTypeMask]s grouped by the 8 possible values of the |
193 /// [ti.FlatTypeMask.flags] property. | 186 /// [ti.FlatTypeMask.flags] property. |
194 List<Map<ClassElement, ti.TypeMask>> canonicalizedTypeMasks = | 187 List<Map<ClassElement, ti.TypeMask>> canonicalizedTypeMasks = |
195 new List<Map<ClassElement, ti.TypeMask>>.filled(8, null); | 188 new List<Map<ClassElement, ti.TypeMask>>.filled(8, null); |
196 | 189 |
197 bool checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { | 190 bool checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { |
198 return | 191 return invariant(cls, cls.isDeclaration, |
199 invariant(cls, cls.isDeclaration, | |
200 message: '$cls must be the declaration.') && | 192 message: '$cls must be the declaration.') && |
201 invariant(cls, cls.isResolved, | 193 invariant(cls, cls.isResolved, |
202 message: '$cls must be resolved.')/* && | 194 message: |
| 195 '$cls must be resolved.') /* && |
203 // TODO(johnniwinther): Reinsert this or similar invariant. | 196 // TODO(johnniwinther): Reinsert this or similar invariant. |
204 (!mustBeInstantiated || | 197 (!mustBeInstantiated || |
205 invariant(cls, isInstantiated(cls), | 198 invariant(cls, isInstantiated(cls), |
206 message: '$cls is not instantiated.'))*/; | 199 message: '$cls is not instantiated.'))*/ |
207 } | 200 ; |
| 201 } |
208 | 202 |
209 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an | 203 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an |
210 /// instance of [y]. | 204 /// instance of [y]. |
211 bool isSubtypeOf(ClassElement x, ClassElement y) { | 205 bool isSubtypeOf(ClassElement x, ClassElement y) { |
212 assert(checkInvariants(x)); | 206 assert(checkInvariants(x)); |
213 assert(checkInvariants(y, mustBeInstantiated: false)); | 207 assert(checkInvariants(y, mustBeInstantiated: false)); |
214 | 208 |
215 if (y == objectClass) return true; | 209 if (y == objectClass) return true; |
216 if (x == objectClass) return false; | 210 if (x == objectClass) return false; |
217 if (x.asInstanceOf(y) != null) return true; | 211 if (x.asInstanceOf(y) != null) return true; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 /// Returns `true` if [cls] is implemented by an instantiated class. | 248 /// Returns `true` if [cls] is implemented by an instantiated class. |
255 bool isImplemented(ClassElement cls) { | 249 bool isImplemented(ClassElement cls) { |
256 return compiler.resolverWorld.isImplemented(cls); | 250 return compiler.resolverWorld.isImplemented(cls); |
257 } | 251 } |
258 | 252 |
259 /// Returns an iterable over the directly instantiated classes that extend | 253 /// Returns an iterable over the directly instantiated classes that extend |
260 /// [cls] possibly including [cls] itself, if it is live. | 254 /// [cls] possibly including [cls] itself, if it is live. |
261 Iterable<ClassElement> subclassesOf(ClassElement cls) { | 255 Iterable<ClassElement> subclassesOf(ClassElement cls) { |
262 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; | 256 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; |
263 if (hierarchy == null) return const <ClassElement>[]; | 257 if (hierarchy == null) return const <ClassElement>[]; |
264 return hierarchy.subclassesByMask( | 258 return hierarchy.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); |
265 ClassHierarchyNode.DIRECTLY_INSTANTIATED); | |
266 } | 259 } |
267 | 260 |
268 /// Returns an iterable over the directly instantiated classes that extend | 261 /// Returns an iterable over the directly instantiated classes that extend |
269 /// [cls] _not_ including [cls] itself. | 262 /// [cls] _not_ including [cls] itself. |
270 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { | 263 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { |
271 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 264 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
272 if (subclasses == null) return const <ClassElement>[]; | 265 if (subclasses == null) return const <ClassElement>[]; |
273 return subclasses.subclassesByMask( | 266 return subclasses.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
274 ClassHierarchyNode.DIRECTLY_INSTANTIATED, strict: true); | 267 strict: true); |
275 } | 268 } |
276 | 269 |
277 /// Returns the number of live classes that extend [cls] _not_ | 270 /// Returns the number of live classes that extend [cls] _not_ |
278 /// including [cls] itself. | 271 /// including [cls] itself. |
279 int strictSubclassCount(ClassElement cls) { | 272 int strictSubclassCount(ClassElement cls) { |
280 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 273 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
281 if (subclasses == null) return 0; | 274 if (subclasses == null) return 0; |
282 return subclasses.instantiatedSubclassCount; | 275 return subclasses.instantiatedSubclassCount; |
283 } | 276 } |
284 | 277 |
285 /// Applies [f] to each live class that extend [cls] _not_ including [cls] | 278 /// Applies [f] to each live class that extend [cls] _not_ including [cls] |
286 /// itself. | 279 /// itself. |
287 void forEachStrictSubclassOf(ClassElement cls, | 280 void forEachStrictSubclassOf( |
288 IterationStep f(ClassElement cls)) { | 281 ClassElement cls, IterationStep f(ClassElement cls)) { |
289 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 282 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
290 if (subclasses == null) return; | 283 if (subclasses == null) return; |
291 subclasses.forEachSubclass( | 284 subclasses.forEachSubclass(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
292 f, | |
293 ClassHierarchyNode.DIRECTLY_INSTANTIATED, | |
294 strict: true); | 285 strict: true); |
295 } | 286 } |
296 | 287 |
297 /// Returns `true` if [predicate] applies to any live class that extend [cls] | 288 /// Returns `true` if [predicate] applies to any live class that extend [cls] |
298 /// _not_ including [cls] itself. | 289 /// _not_ including [cls] itself. |
299 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)) { | 290 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)) { |
300 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 291 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
301 if (subclasses == null) return false; | 292 if (subclasses == null) return false; |
302 return subclasses.anySubclass( | 293 return subclasses.anySubclass( |
303 predicate, | 294 predicate, ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
304 ClassHierarchyNode.DIRECTLY_INSTANTIATED, | |
305 strict: true); | 295 strict: true); |
306 } | 296 } |
307 | 297 |
308 /// Returns an iterable over the directly instantiated that implement [cls] | 298 /// Returns an iterable over the directly instantiated that implement [cls] |
309 /// possibly including [cls] itself, if it is live. | 299 /// possibly including [cls] itself, if it is live. |
310 Iterable<ClassElement> subtypesOf(ClassElement cls) { | 300 Iterable<ClassElement> subtypesOf(ClassElement cls) { |
311 ClassSet classSet = _classSets[cls.declaration]; | 301 ClassSet classSet = _classSets[cls.declaration]; |
312 if (classSet == null) { | 302 if (classSet == null) { |
313 return const <ClassElement>[]; | 303 return const <ClassElement>[]; |
314 } else { | 304 } else { |
315 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); | 305 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); |
316 } | 306 } |
317 } | 307 } |
318 | 308 |
319 /// Returns an iterable over the directly instantiated that implement [cls] | 309 /// Returns an iterable over the directly instantiated that implement [cls] |
320 /// _not_ including [cls]. | 310 /// _not_ including [cls]. |
321 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { | 311 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { |
322 ClassSet classSet = _classSets[cls.declaration]; | 312 ClassSet classSet = _classSets[cls.declaration]; |
323 if (classSet == null) { | 313 if (classSet == null) { |
324 return const <ClassElement>[]; | 314 return const <ClassElement>[]; |
325 } else { | 315 } else { |
326 return classSet.subtypesByMask( | 316 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
327 ClassHierarchyNode.DIRECTLY_INSTANTIATED, | |
328 strict: true); | 317 strict: true); |
329 } | 318 } |
330 } | 319 } |
331 | 320 |
332 /// Returns the number of live classes that implement [cls] _not_ | 321 /// Returns the number of live classes that implement [cls] _not_ |
333 /// including [cls] itself. | 322 /// including [cls] itself. |
334 int strictSubtypeCount(ClassElement cls) { | 323 int strictSubtypeCount(ClassElement cls) { |
335 ClassSet classSet = _classSets[cls.declaration]; | 324 ClassSet classSet = _classSets[cls.declaration]; |
336 if (classSet == null) return 0; | 325 if (classSet == null) return 0; |
337 return classSet.instantiatedSubtypeCount; | 326 return classSet.instantiatedSubtypeCount; |
338 } | 327 } |
339 | 328 |
340 /// Applies [f] to each live class that implements [cls] _not_ including [cls] | 329 /// Applies [f] to each live class that implements [cls] _not_ including [cls] |
341 /// itself. | 330 /// itself. |
342 void forEachStrictSubtypeOf(ClassElement cls, | 331 void forEachStrictSubtypeOf( |
343 IterationStep f(ClassElement cls)) { | 332 ClassElement cls, IterationStep f(ClassElement cls)) { |
344 ClassSet classSet = _classSets[cls.declaration]; | 333 ClassSet classSet = _classSets[cls.declaration]; |
345 if (classSet == null) return; | 334 if (classSet == null) return; |
346 classSet.forEachSubtype( | 335 classSet.forEachSubtype(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
347 f, | |
348 ClassHierarchyNode.DIRECTLY_INSTANTIATED, | |
349 strict: true); | 336 strict: true); |
350 } | 337 } |
351 | 338 |
352 /// Returns `true` if [predicate] applies to any live class that extend [cls] | 339 /// Returns `true` if [predicate] applies to any live class that extend [cls] |
353 /// _not_ including [cls] itself. | 340 /// _not_ including [cls] itself. |
354 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)) { | 341 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)) { |
355 ClassSet classSet = _classSets[cls.declaration]; | 342 ClassSet classSet = _classSets[cls.declaration]; |
356 if (classSet == null) return false; | 343 if (classSet == null) return false; |
357 return classSet.anySubtype( | 344 return classSet.anySubtype( |
358 predicate, | 345 predicate, ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
359 ClassHierarchyNode.DIRECTLY_INSTANTIATED, | |
360 strict: true); | 346 strict: true); |
361 } | 347 } |
362 | 348 |
363 /// Returns `true` if [a] and [b] have any known common subtypes. | 349 /// Returns `true` if [a] and [b] have any known common subtypes. |
364 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) { | 350 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) { |
365 ClassSet classSetA = _classSets[a.declaration]; | 351 ClassSet classSetA = _classSets[a.declaration]; |
366 ClassSet classSetB = _classSets[b.declaration]; | 352 ClassSet classSetB = _classSets[b.declaration]; |
367 if (classSetA == null || classSetB == null) return false; | 353 if (classSetA == null || classSetB == null) return false; |
368 // TODO(johnniwinther): Implement an optimized query on [ClassSet]. | 354 // TODO(johnniwinther): Implement an optimized query on [ClassSet]. |
369 Set<ClassElement> subtypesOfB = classSetB.subtypes().toSet(); | 355 Set<ClassElement> subtypesOfB = classSetB.subtypes().toSet(); |
(...skipping 29 matching lines...) Expand all Loading... |
399 // Vacuously true. | 385 // Vacuously true. |
400 return true; | 386 return true; |
401 } | 387 } |
402 return classSet.hasOnlyInstantiatedSubclasses; | 388 return classSet.hasOnlyInstantiatedSubclasses; |
403 } | 389 } |
404 | 390 |
405 @override | 391 @override |
406 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) { | 392 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) { |
407 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; | 393 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; |
408 return hierarchy != null | 394 return hierarchy != null |
409 ? hierarchy.getLubOfInstantiatedSubclasses() : null; | 395 ? hierarchy.getLubOfInstantiatedSubclasses() |
| 396 : null; |
410 } | 397 } |
411 | 398 |
412 @override | 399 @override |
413 ClassElement getLubOfInstantiatedSubtypes(ClassElement cls) { | 400 ClassElement getLubOfInstantiatedSubtypes(ClassElement cls) { |
414 ClassSet classSet = _classSets[cls.declaration]; | 401 ClassSet classSet = _classSets[cls.declaration]; |
415 return classSet != null | 402 return classSet != null ? classSet.getLubOfInstantiatedSubtypes() : null; |
416 ? classSet.getLubOfInstantiatedSubtypes() : null; | |
417 } | 403 } |
418 | 404 |
419 /// Returns an iterable over the common supertypes of the [classes]. | 405 /// Returns an iterable over the common supertypes of the [classes]. |
420 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes) { | 406 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes) { |
421 Iterator<ClassElement> iterator = classes.iterator; | 407 Iterator<ClassElement> iterator = classes.iterator; |
422 if (!iterator.moveNext()) return const <ClassElement>[]; | 408 if (!iterator.moveNext()) return const <ClassElement>[]; |
423 | 409 |
424 ClassElement cls = iterator.current; | 410 ClassElement cls = iterator.current; |
425 assert(checkInvariants(cls)); | 411 assert(checkInvariants(cls)); |
426 OrderedTypeSet typeSet = cls.allSupertypesAndSelf; | 412 OrderedTypeSet typeSet = cls.allSupertypesAndSelf; |
427 if (!iterator.moveNext()) return typeSet.types.map((type) => type.element); | 413 if (!iterator.moveNext()) return typeSet.types.map((type) => type.element); |
428 | 414 |
429 int depth = typeSet.maxDepth; | 415 int depth = typeSet.maxDepth; |
430 Link<OrderedTypeSet> otherTypeSets = const Link<OrderedTypeSet>(); | 416 Link<OrderedTypeSet> otherTypeSets = const Link<OrderedTypeSet>(); |
431 do { | 417 do { |
432 ClassElement otherClass = iterator.current; | 418 ClassElement otherClass = iterator.current; |
433 assert(checkInvariants(otherClass)); | 419 assert(checkInvariants(otherClass)); |
434 OrderedTypeSet otherTypeSet = otherClass.allSupertypesAndSelf; | 420 OrderedTypeSet otherTypeSet = otherClass.allSupertypesAndSelf; |
435 otherTypeSets = otherTypeSets.prepend(otherTypeSet); | 421 otherTypeSets = otherTypeSets.prepend(otherTypeSet); |
436 if (otherTypeSet.maxDepth < depth) { | 422 if (otherTypeSet.maxDepth < depth) { |
437 depth = otherTypeSet.maxDepth; | 423 depth = otherTypeSet.maxDepth; |
438 } | 424 } |
439 } while (iterator.moveNext()); | 425 } while (iterator.moveNext()); |
440 | 426 |
441 List<ClassElement> commonSupertypes = <ClassElement>[]; | 427 List<ClassElement> commonSupertypes = <ClassElement>[]; |
442 OUTER: for (Link<DartType> link = typeSet[depth]; | 428 OUTER: for (Link<DartType> link = typeSet[depth]; |
443 link.head.element != objectClass; | 429 link.head.element != objectClass; |
444 link = link.tail) { | 430 link = link.tail) { |
445 ClassElement cls = link.head.element; | 431 ClassElement cls = link.head.element; |
446 for (Link<OrderedTypeSet> link = otherTypeSets; | 432 for (Link<OrderedTypeSet> link = otherTypeSets; |
447 !link.isEmpty; | 433 !link.isEmpty; |
448 link = link.tail) { | 434 link = link.tail) { |
449 if (link.head.asInstanceOf(cls) == null) { | 435 if (link.head.asInstanceOf(cls) == null) { |
450 continue OUTER; | 436 continue OUTER; |
451 } | 437 } |
452 } | 438 } |
453 commonSupertypes.add(cls); | 439 commonSupertypes.add(cls); |
454 } | 440 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 Iterable<MixinApplicationElement> uses = _liveMixinUses[cls]; | 476 Iterable<MixinApplicationElement> uses = _liveMixinUses[cls]; |
491 return uses != null ? uses : const <MixinApplicationElement>[]; | 477 return uses != null ? uses : const <MixinApplicationElement>[]; |
492 } | 478 } |
493 | 479 |
494 /// Returns `true` if [cls] is mixed into a live class. | 480 /// Returns `true` if [cls] is mixed into a live class. |
495 bool isUsedAsMixin(ClassElement cls) { | 481 bool isUsedAsMixin(ClassElement cls) { |
496 return !mixinUsesOf(cls).isEmpty; | 482 return !mixinUsesOf(cls).isEmpty; |
497 } | 483 } |
498 | 484 |
499 /// Returns `true` if any live class that mixes in [cls] implements [type]. | 485 /// Returns `true` if any live class that mixes in [cls] implements [type]. |
500 bool hasAnySubclassOfMixinUseThatImplements(ClassElement cls, | 486 bool hasAnySubclassOfMixinUseThatImplements( |
501 ClassElement type) { | 487 ClassElement cls, ClassElement type) { |
502 return mixinUsesOf(cls).any( | 488 return mixinUsesOf(cls) |
503 (use) => hasAnySubclassThatImplements(use, type)); | 489 .any((use) => hasAnySubclassThatImplements(use, type)); |
504 } | 490 } |
505 | 491 |
506 /// Returns `true` if any live class that mixes in [mixin] is also a subclass | 492 /// Returns `true` if any live class that mixes in [mixin] is also a subclass |
507 /// of [superclass]. | 493 /// of [superclass]. |
508 bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin) { | 494 bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin) { |
509 return mixinUsesOf(mixin).any((each) => each.isSubclassOf(superclass)); | 495 return mixinUsesOf(mixin).any((each) => each.isSubclassOf(superclass)); |
510 } | 496 } |
511 | 497 |
512 /// Returns `true` if any subclass of [superclass] implements [type]. | 498 /// Returns `true` if any subclass of [superclass] implements [type]. |
513 bool hasAnySubclassThatImplements(ClassElement superclass, | 499 bool hasAnySubclassThatImplements( |
514 ClassElement type) { | 500 ClassElement superclass, ClassElement type) { |
515 Set<ClassElement> subclasses = typesImplementedBySubclassesOf(superclass); | 501 Set<ClassElement> subclasses = typesImplementedBySubclassesOf(superclass); |
516 if (subclasses == null) return false; | 502 if (subclasses == null) return false; |
517 return subclasses.contains(type); | 503 return subclasses.contains(type); |
518 } | 504 } |
519 | 505 |
520 final Compiler compiler; | 506 final Compiler compiler; |
521 Backend get backend => compiler.backend; | 507 Backend get backend => compiler.backend; |
522 final FunctionSet allFunctions; | 508 final FunctionSet allFunctions; |
523 final Set<Element> functionsCalledInLoop = new Set<Element>(); | 509 final Set<Element> functionsCalledInLoop = new Set<Element>(); |
524 final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>(); | 510 final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>(); |
525 | 511 |
526 final Set<TypedefElement> allTypedefs = new Set<TypedefElement>(); | 512 final Set<TypedefElement> allTypedefs = new Set<TypedefElement>(); |
527 | 513 |
528 final Map<ClassElement, List<MixinApplicationElement>> _mixinUses = | 514 final Map<ClassElement, List<MixinApplicationElement>> _mixinUses = |
529 new Map<ClassElement, List<MixinApplicationElement>>(); | 515 new Map<ClassElement, List<MixinApplicationElement>>(); |
530 Map<ClassElement, List<MixinApplicationElement>> _liveMixinUses; | 516 Map<ClassElement, List<MixinApplicationElement>> _liveMixinUses; |
531 | 517 |
532 final Map<ClassElement, Set<ClassElement>> _typesImplementedBySubclasses = | 518 final Map<ClassElement, Set<ClassElement>> _typesImplementedBySubclasses = |
533 new Map<ClassElement, Set<ClassElement>>(); | 519 new Map<ClassElement, Set<ClassElement>>(); |
534 | 520 |
535 // We keep track of subtype and subclass relationships in four | 521 // We keep track of subtype and subclass relationships in four |
536 // distinct sets to make class hierarchy analysis faster. | 522 // distinct sets to make class hierarchy analysis faster. |
537 final Map<ClassElement, ClassHierarchyNode> _classHierarchyNodes = | 523 final Map<ClassElement, ClassHierarchyNode> _classHierarchyNodes = |
538 <ClassElement, ClassHierarchyNode>{}; | 524 <ClassElement, ClassHierarchyNode>{}; |
539 final Map<ClassElement, ClassSet> _classSets = | 525 final Map<ClassElement, ClassSet> _classSets = <ClassElement, ClassSet>{}; |
540 <ClassElement, ClassSet>{}; | |
541 | 526 |
542 final Set<Element> sideEffectsFreeElements = new Set<Element>(); | 527 final Set<Element> sideEffectsFreeElements = new Set<Element>(); |
543 | 528 |
544 final Set<Element> elementsThatCannotThrow = new Set<Element>(); | 529 final Set<Element> elementsThatCannotThrow = new Set<Element>(); |
545 | 530 |
546 final Set<Element> functionsThatMightBePassedToApply = | 531 final Set<Element> functionsThatMightBePassedToApply = |
547 new Set<FunctionElement>(); | 532 new Set<FunctionElement>(); |
548 | 533 |
549 final Set<Element> alreadyPopulated; | 534 final Set<Element> alreadyPopulated; |
550 | 535 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
631 if (cls != coreClasses.functionClass && | 616 if (cls != coreClasses.functionClass && |
632 cls.implementsFunction(coreClasses)) { | 617 cls.implementsFunction(coreClasses)) { |
633 ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass); | 618 ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass); |
634 subtypeSet.addSubtype(node); | 619 subtypeSet.addSubtype(node); |
635 } | 620 } |
636 if (!node.isInstantiated && node.parentNode != null) { | 621 if (!node.isInstantiated && node.parentNode != null) { |
637 _updateSuperClassHierarchyNodeForClass(node.parentNode); | 622 _updateSuperClassHierarchyNodeForClass(node.parentNode); |
638 } | 623 } |
639 } | 624 } |
640 | 625 |
641 void _updateClassHierarchyNodeForClass( | 626 void _updateClassHierarchyNodeForClass(ClassElement cls, |
642 ClassElement cls, | |
643 {bool directlyInstantiated: false}) { | 627 {bool directlyInstantiated: false}) { |
644 ClassHierarchyNode node = getClassHierarchyNode(cls); | 628 ClassHierarchyNode node = getClassHierarchyNode(cls); |
645 _updateSuperClassHierarchyNodeForClass(node); | 629 _updateSuperClassHierarchyNodeForClass(node); |
646 if (directlyInstantiated) { | 630 if (directlyInstantiated) { |
647 node.isDirectlyInstantiated = true; | 631 node.isDirectlyInstantiated = true; |
648 } | 632 } |
649 } | 633 } |
650 | 634 |
651 void populate() { | 635 void populate() { |
652 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` | 636 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
691 if (cls != null) { | 675 if (cls != null) { |
692 sb.write("Classes in the closed world related to $cls:\n"); | 676 sb.write("Classes in the closed world related to $cls:\n"); |
693 } else { | 677 } else { |
694 sb.write("Instantiated classes in the closed world:\n"); | 678 sb.write("Instantiated classes in the closed world:\n"); |
695 } | 679 } |
696 getClassHierarchyNode(coreClasses.objectClass) | 680 getClassHierarchyNode(coreClasses.objectClass) |
697 .printOn(sb, ' ', instantiatedOnly: cls == null, withRespectTo: cls); | 681 .printOn(sb, ' ', instantiatedOnly: cls == null, withRespectTo: cls); |
698 return sb.toString(); | 682 return sb.toString(); |
699 } | 683 } |
700 | 684 |
701 void registerMixinUse(MixinApplicationElement mixinApplication, | 685 void registerMixinUse( |
702 ClassElement mixin) { | 686 MixinApplicationElement mixinApplication, ClassElement mixin) { |
703 // TODO(johnniwinther): Add map restricted to live classes. | 687 // TODO(johnniwinther): Add map restricted to live classes. |
704 // We don't support patch classes as mixin. | 688 // We don't support patch classes as mixin. |
705 assert(mixin.isDeclaration); | 689 assert(mixin.isDeclaration); |
706 List<MixinApplicationElement> users = | 690 List<MixinApplicationElement> users = _mixinUses.putIfAbsent( |
707 _mixinUses.putIfAbsent(mixin, () => | 691 mixin, () => new List<MixinApplicationElement>()); |
708 new List<MixinApplicationElement>()); | |
709 users.add(mixinApplication); | 692 users.add(mixinApplication); |
710 } | 693 } |
711 | 694 |
712 bool hasAnyUserDefinedGetter(Selector selector, ti.TypeMask mask) { | 695 bool hasAnyUserDefinedGetter(Selector selector, ti.TypeMask mask) { |
713 return allFunctions.filter(selector, mask).any((each) => each.isGetter); | 696 return allFunctions.filter(selector, mask).any((each) => each.isGetter); |
714 } | 697 } |
715 | 698 |
716 void registerUsedElement(Element element) { | 699 void registerUsedElement(Element element) { |
717 if (element.isInstanceMember && !element.isAbstract) { | 700 if (element.isInstanceMember && !element.isAbstract) { |
718 allFunctions.add(element); | 701 allFunctions.add(element); |
719 } | 702 } |
720 } | 703 } |
721 | 704 |
722 VariableElement locateSingleField(Selector selector, ti.TypeMask mask) { | 705 VariableElement locateSingleField(Selector selector, ti.TypeMask mask) { |
723 Element result = locateSingleElement(selector, mask); | 706 Element result = locateSingleElement(selector, mask); |
724 return (result != null && result.isField) ? result : null; | 707 return (result != null && result.isField) ? result : null; |
725 } | 708 } |
726 | 709 |
727 Element locateSingleElement(Selector selector, ti.TypeMask mask) { | 710 Element locateSingleElement(Selector selector, ti.TypeMask mask) { |
728 mask = mask == null | 711 mask = mask == null ? compiler.typesTask.dynamicType : mask; |
729 ? compiler.typesTask.dynamicType | |
730 : mask; | |
731 return mask.locateSingleElement(selector, mask, compiler); | 712 return mask.locateSingleElement(selector, mask, compiler); |
732 } | 713 } |
733 | 714 |
734 ti.TypeMask extendMaskIfReachesAll(Selector selector, ti.TypeMask mask) { | 715 ti.TypeMask extendMaskIfReachesAll(Selector selector, ti.TypeMask mask) { |
735 bool canReachAll = true; | 716 bool canReachAll = true; |
736 if (mask != null) { | 717 if (mask != null) { |
737 canReachAll = | 718 canReachAll = compiler.enabledInvokeOn && |
738 compiler.enabledInvokeOn && | |
739 mask.needsNoSuchMethodHandling(selector, this); | 719 mask.needsNoSuchMethodHandling(selector, this); |
740 } | 720 } |
741 return canReachAll ? compiler.typesTask.dynamicType : mask; | 721 return canReachAll ? compiler.typesTask.dynamicType : mask; |
742 } | 722 } |
743 | 723 |
744 void addFunctionCalledInLoop(Element element) { | 724 void addFunctionCalledInLoop(Element element) { |
745 functionsCalledInLoop.add(element.declaration); | 725 functionsCalledInLoop.add(element.declaration); |
746 } | 726 } |
747 | 727 |
748 bool isCalledInLoop(Element element) { | 728 bool isCalledInLoop(Element element) { |
749 return functionsCalledInLoop.contains(element.declaration); | 729 return functionsCalledInLoop.contains(element.declaration); |
750 } | 730 } |
751 | 731 |
752 bool fieldNeverChanges(Element element) { | 732 bool fieldNeverChanges(Element element) { |
753 if (!element.isField) return false; | 733 if (!element.isField) return false; |
754 if (backend.isNative(element)) { | 734 if (backend.isNative(element)) { |
755 // Some native fields are views of data that may be changed by operations. | 735 // Some native fields are views of data that may be changed by operations. |
756 // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2). | 736 // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2). |
757 // TODO(sra): Refine the effect classification so that native effects are | 737 // TODO(sra): Refine the effect classification so that native effects are |
758 // distinct from ordinary Dart effects. | 738 // distinct from ordinary Dart effects. |
759 return false; | 739 return false; |
760 } | 740 } |
761 | 741 |
762 if (element.isFinal || element.isConst) { | 742 if (element.isFinal || element.isConst) { |
763 return true; | 743 return true; |
764 } | 744 } |
765 if (element.isInstanceMember) { | 745 if (element.isInstanceMember) { |
766 return !compiler.resolverWorld.hasInvokedSetter(element, this) && | 746 return !compiler.resolverWorld.hasInvokedSetter(element, this) && |
767 !compiler.resolverWorld.fieldSetters.contains(element); | 747 !compiler.resolverWorld.fieldSetters.contains(element); |
768 } | 748 } |
769 return false; | 749 return false; |
770 } | 750 } |
771 | 751 |
772 SideEffects getSideEffectsOfElement(Element element) { | 752 SideEffects getSideEffectsOfElement(Element element) { |
773 // The type inferrer (where the side effects are being computed), | 753 // The type inferrer (where the side effects are being computed), |
774 // does not see generative constructor bodies because they are | 754 // does not see generative constructor bodies because they are |
775 // created by the backend. Also, it does not make any distinction | 755 // created by the backend. Also, it does not make any distinction |
776 // between a constructor and its body for side effects. This | 756 // between a constructor and its body for side effects. This |
777 // implies that currently, the side effects of a constructor body | 757 // implies that currently, the side effects of a constructor body |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
837 // function expressions's element. | 817 // function expressions's element. |
838 // TODO(herhut): Generate classes for function expressions earlier. | 818 // TODO(herhut): Generate classes for function expressions earlier. |
839 if (element is SynthesizedCallMethodElementX) { | 819 if (element is SynthesizedCallMethodElementX) { |
840 return getMightBePassedToApply(element.expression); | 820 return getMightBePassedToApply(element.expression); |
841 } | 821 } |
842 return functionsThatMightBePassedToApply.contains(element); | 822 return functionsThatMightBePassedToApply.contains(element); |
843 } | 823 } |
844 | 824 |
845 bool get hasClosedWorldAssumption => !compiler.options.hasIncrementalSupport; | 825 bool get hasClosedWorldAssumption => !compiler.options.hasIncrementalSupport; |
846 } | 826 } |
OLD | NEW |