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 |
8 SynthesizedCallMethodElementX; | 8 SynthesizedCallMethodElementX; |
9 import 'common.dart'; | 9 import 'common.dart'; |
10 import 'common/backend_api.dart' show | 10 import 'common/backend_api.dart' show |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 | 55 |
56 /// The [ClassElement] for the [int] class defined in 'dart:core'. | 56 /// The [ClassElement] for the [int] class defined in 'dart:core'. |
57 ClassElement get intClass; | 57 ClassElement get intClass; |
58 | 58 |
59 /// The [ClassElement] for the [double] class defined in 'dart:core'. | 59 /// The [ClassElement] for the [double] class defined in 'dart:core'. |
60 ClassElement get doubleClass; | 60 ClassElement get doubleClass; |
61 | 61 |
62 /// The [ClassElement] for the [String] class defined in 'dart:core'. | 62 /// The [ClassElement] for the [String] class defined in 'dart:core'. |
63 ClassElement get stringClass; | 63 ClassElement get stringClass; |
64 | 64 |
65 /// Returns `true` if [cls] is either directly or indirectly instantiated. | 65 /// Returns `true` if [cls] is instantiated. |
66 bool isInstantiated(ClassElement cls); | 66 bool isInstantiated(ClassElement cls); |
67 | 67 |
68 /// Returns `true` if [cls] is directly instantiated. | |
69 bool isDirectlyInstantiated(ClassElement cls); | |
70 | |
71 /// Returns `true` if [cls] is indirectly instantiated, that is through a | |
72 /// subclass. | |
73 bool isIndirectlyInstantiated(ClassElement cls); | |
74 | |
75 /// Returns `true` if [cls] is implemented by an instantiated class. | 68 /// Returns `true` if [cls] is implemented by an instantiated class. |
76 bool isImplemented(ClassElement cls); | 69 bool isImplemented(ClassElement cls); |
77 | 70 |
78 /// Returns `true` if the class world is closed. | 71 /// Returns `true` if the class world is closed. |
79 bool get isClosed; | 72 bool get isClosed; |
80 | 73 |
81 /// Return `true` if [x] is a subclass of [y]. | 74 /// Return `true` if [x] is a subclass of [y]. |
82 bool isSubclassOf(ClassElement x, ClassElement y); | 75 bool isSubclassOf(ClassElement x, ClassElement y); |
83 | 76 |
84 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an | 77 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an |
(...skipping 21 matching lines...) Expand all Loading... |
106 | 99 |
107 /// Returns `true` if any live class other than [cls] extends [cls]. | 100 /// Returns `true` if any live class other than [cls] extends [cls]. |
108 bool hasAnyStrictSubclass(ClassElement cls); | 101 bool hasAnyStrictSubclass(ClassElement cls); |
109 | 102 |
110 /// Returns `true` if any live class other than [cls] implements [cls]. | 103 /// Returns `true` if any live class other than [cls] implements [cls]. |
111 bool hasAnyStrictSubtype(ClassElement cls); | 104 bool hasAnyStrictSubtype(ClassElement cls); |
112 | 105 |
113 /// Returns `true` if all live classes that implement [cls] extend it. | 106 /// Returns `true` if all live classes that implement [cls] extend it. |
114 bool hasOnlySubclasses(ClassElement cls); | 107 bool hasOnlySubclasses(ClassElement cls); |
115 | 108 |
116 /// Returns the most specific subclass of [cls] (including [cls]) that is | |
117 /// directly instantiated or a superclass of all directly instantiated | |
118 /// subclasses. If [cls] is not instantiated, `null` is returned. | |
119 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls); | |
120 | |
121 /// Returns the most specific subtype of [cls] (including [cls]) that is | |
122 /// directly instantiated or a superclass of all directly instantiated | |
123 /// subtypes. If no subtypes of [cls] are instantiated, `null` is returned. | |
124 ClassElement getLubOfInstantiatedSubtypes(ClassElement cls); | |
125 | |
126 /// Returns an iterable over the common supertypes of the [classes]. | 109 /// Returns an iterable over the common supertypes of the [classes]. |
127 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes); | 110 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes); |
128 | 111 |
129 /// Returns an iterable over the live mixin applications that mixin [cls]. | 112 /// Returns an iterable over the live mixin applications that mixin [cls]. |
130 Iterable<MixinApplicationElement> mixinUsesOf(ClassElement cls); | 113 Iterable<MixinApplicationElement> mixinUsesOf(ClassElement cls); |
131 | 114 |
132 /// Returns `true` if [cls] is mixed into a live class. | 115 /// Returns `true` if [cls] is mixed into a live class. |
133 bool isUsedAsMixin(ClassElement cls); | 116 bool isUsedAsMixin(ClassElement cls); |
134 | 117 |
135 /// Returns `true` if any live class that mixes in [cls] implements [type]. | 118 /// Returns `true` if any live class that mixes in [cls] implements [type]. |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 | 183 |
201 if (y == objectClass) return true; | 184 if (y == objectClass) return true; |
202 if (x == objectClass) return false; | 185 if (x == objectClass) return false; |
203 while (x != null && x.hierarchyDepth >= y.hierarchyDepth) { | 186 while (x != null && x.hierarchyDepth >= y.hierarchyDepth) { |
204 if (x == y) return true; | 187 if (x == y) return true; |
205 x = x.superclass; | 188 x = x.superclass; |
206 } | 189 } |
207 return false; | 190 return false; |
208 } | 191 } |
209 | 192 |
210 @override | 193 /// Returns `true` if [cls] is instantiated either directly or through a |
| 194 /// subclass. |
211 bool isInstantiated(ClassElement cls) { | 195 bool isInstantiated(ClassElement cls) { |
212 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; | 196 return compiler.resolverWorld.isInstantiated(cls); |
213 return node != null && node.isInstantiated; | |
214 } | |
215 | |
216 @override | |
217 bool isDirectlyInstantiated(ClassElement cls) { | |
218 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; | |
219 return node != null && node.isDirectlyInstantiated; | |
220 } | |
221 | |
222 @override | |
223 bool isIndirectlyInstantiated(ClassElement cls) { | |
224 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; | |
225 return node != null && node.isIndirectlyInstantiated; | |
226 } | 197 } |
227 | 198 |
228 /// Returns `true` if [cls] is implemented by an instantiated class. | 199 /// Returns `true` if [cls] is implemented by an instantiated class. |
229 bool isImplemented(ClassElement cls) { | 200 bool isImplemented(ClassElement cls) { |
230 return compiler.resolverWorld.isImplemented(cls); | 201 return compiler.resolverWorld.isImplemented(cls); |
231 } | 202 } |
232 | 203 |
233 /// Returns an iterable over the directly instantiated classes that extend | 204 /// Returns an iterable over the directly instantiated classes that extend |
234 /// [cls] possibly including [cls] itself, if it is live. | 205 /// [cls] possibly including [cls] itself, if it is live. |
235 Iterable<ClassElement> subclassesOf(ClassElement cls) { | 206 Iterable<ClassElement> subclassesOf(ClassElement cls) { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 | 280 |
310 /// Returns `true` if all directly instantiated classes that implement [cls] | 281 /// Returns `true` if all directly instantiated classes that implement [cls] |
311 /// extend it. | 282 /// extend it. |
312 bool hasOnlySubclasses(ClassElement cls) { | 283 bool hasOnlySubclasses(ClassElement cls) { |
313 Iterable<ClassElement> subtypes = strictSubtypesOf(cls); | 284 Iterable<ClassElement> subtypes = strictSubtypesOf(cls); |
314 if (subtypes == null) return true; | 285 if (subtypes == null) return true; |
315 Iterable<ClassElement> subclasses = strictSubclassesOf(cls); | 286 Iterable<ClassElement> subclasses = strictSubclassesOf(cls); |
316 return subclasses != null && (subclasses.length == subtypes.length); | 287 return subclasses != null && (subclasses.length == subtypes.length); |
317 } | 288 } |
318 | 289 |
319 @override | |
320 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) { | |
321 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; | |
322 return hierarchy != null | |
323 ? hierarchy.getLubOfInstantiatedSubclasses() : null; | |
324 } | |
325 | |
326 @override | |
327 ClassElement getLubOfInstantiatedSubtypes(ClassElement cls) { | |
328 ClassSet classSet = _classSets[cls.declaration]; | |
329 return classSet != null | |
330 ? classSet.getLubOfInstantiatedSubtypes() : null; | |
331 } | |
332 | |
333 /// Returns an iterable over the common supertypes of the [classes]. | 290 /// Returns an iterable over the common supertypes of the [classes]. |
334 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes) { | 291 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes) { |
335 Iterator<ClassElement> iterator = classes.iterator; | 292 Iterator<ClassElement> iterator = classes.iterator; |
336 if (!iterator.moveNext()) return const <ClassElement>[]; | 293 if (!iterator.moveNext()) return const <ClassElement>[]; |
337 | 294 |
338 ClassElement cls = iterator.current; | 295 ClassElement cls = iterator.current; |
339 assert(checkInvariants(cls)); | 296 assert(checkInvariants(cls)); |
340 OrderedTypeSet typeSet = cls.allSupertypesAndSelf; | 297 OrderedTypeSet typeSet = cls.allSupertypesAndSelf; |
341 if (!iterator.moveNext()) return typeSet.types.map((type) => type.element); | 298 if (!iterator.moveNext()) return typeSet.types.map((type) => type.element); |
342 | 299 |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 alreadyPopulated = compiler.cacheStrategy.newSet(); | 436 alreadyPopulated = compiler.cacheStrategy.newSet(); |
480 | 437 |
481 CoreClasses get coreClasses => compiler.coreClasses; | 438 CoreClasses get coreClasses => compiler.coreClasses; |
482 | 439 |
483 DiagnosticReporter get reporter => compiler.reporter; | 440 DiagnosticReporter get reporter => compiler.reporter; |
484 | 441 |
485 /// Called to add [cls] to the set of known classes. | 442 /// Called to add [cls] to the set of known classes. |
486 /// | 443 /// |
487 /// This ensures that class hierarchy queries can be performed on [cls] and | 444 /// This ensures that class hierarchy queries can be performed on [cls] and |
488 /// classes that extend or implement it. | 445 /// classes that extend or implement it. |
489 void registerClass(ClassElement cls, {bool isDirectlyInstantiated: false}) { | 446 void registerClass(ClassElement cls) { |
490 _ensureClassSet(cls); | 447 _ensureClassSet(cls); |
491 if (isDirectlyInstantiated) { | |
492 _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); | |
493 } | |
494 } | 448 } |
495 | 449 |
496 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies | 450 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies |
497 /// of known classes. | 451 /// of known classes. |
498 /// | 452 /// |
499 /// This method is only provided for testing. For queries on classes, use the | 453 /// This method is only provided for testing. For queries on classes, use the |
500 /// methods defined in [ClassWorld]. | 454 /// methods defined in [ClassWorld]. |
501 ClassHierarchyNode getClassHierarchyNode(ClassElement cls) { | 455 ClassHierarchyNode getClassHierarchyNode(ClassElement cls) { |
502 return _classHierarchyNodes[cls.declaration]; | 456 return _classHierarchyNodes[cls.declaration]; |
503 } | 457 } |
(...skipping 27 matching lines...) Expand all Loading... |
531 for (InterfaceType type in cls.allSupertypes) { | 485 for (InterfaceType type in cls.allSupertypes) { |
532 // TODO(johnniwinther): Optimization: Avoid adding [cls] to | 486 // TODO(johnniwinther): Optimization: Avoid adding [cls] to |
533 // superclasses. | 487 // superclasses. |
534 ClassSet subtypeSet = _ensureClassSet(type.element); | 488 ClassSet subtypeSet = _ensureClassSet(type.element); |
535 subtypeSet.addSubtype(node); | 489 subtypeSet.addSubtype(node); |
536 } | 490 } |
537 return classSet; | 491 return classSet; |
538 }); | 492 }); |
539 } | 493 } |
540 | 494 |
541 void _updateClassHierarchyNodeForClass( | |
542 ClassElement cls, | |
543 {bool directlyInstantiated: false, | |
544 bool indirectlyInstantiated: false}) { | |
545 ClassHierarchyNode node = getClassHierarchyNode(cls); | |
546 bool changed = false; | |
547 if (directlyInstantiated && !node.isDirectlyInstantiated) { | |
548 node.isDirectlyInstantiated = true; | |
549 changed = true; | |
550 } | |
551 if (indirectlyInstantiated && !node.isIndirectlyInstantiated) { | |
552 node.isIndirectlyInstantiated = true; | |
553 changed = true; | |
554 } | |
555 if (changed && cls.superclass != null) { | |
556 _updateClassHierarchyNodeForClass( | |
557 cls.superclass, indirectlyInstantiated: true); | |
558 } | |
559 // Ensure that classes implicitly implementing `Function` are in its | |
560 // subtype set. | |
561 if (cls != coreClasses.functionClass && | |
562 cls.implementsFunction(compiler)) { | |
563 ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass); | |
564 subtypeSet.addSubtype(node); | |
565 } | |
566 } | |
567 | |
568 void populate() { | 495 void populate() { |
569 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` | 496 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` |
570 /// properties of the [ClassHierarchyNode] for [cls]. | 497 /// properties of the [ClassHierarchyNode] for [cls]. |
| 498 void updateClassHierarchyNodeForClass( |
| 499 ClassElement cls, |
| 500 {bool directlyInstantiated: false, |
| 501 bool indirectlyInstantiated: false}) { |
| 502 assert(!directlyInstantiated || isInstantiated(cls)); |
| 503 ClassHierarchyNode node = getClassHierarchyNode(cls); |
| 504 bool changed = false; |
| 505 if (directlyInstantiated && !node.isDirectlyInstantiated) { |
| 506 node.isDirectlyInstantiated = true; |
| 507 changed = true; |
| 508 } |
| 509 if (indirectlyInstantiated && !node.isIndirectlyInstantiated) { |
| 510 node.isIndirectlyInstantiated = true; |
| 511 changed = true; |
| 512 } |
| 513 if (changed && cls.superclass != null) { |
| 514 updateClassHierarchyNodeForClass( |
| 515 cls.superclass, indirectlyInstantiated: true); |
| 516 } |
| 517 } |
571 | 518 |
572 void addSubtypes(ClassElement cls) { | 519 void addSubtypes(ClassElement cls) { |
573 if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) { | 520 if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) { |
574 return; | 521 return; |
575 } | 522 } |
576 assert(cls.isDeclaration); | 523 assert(cls.isDeclaration); |
577 if (!cls.isResolved) { | 524 if (!cls.isResolved) { |
578 reporter.internalError(cls, 'Class "${cls.name}" is not resolved.'); | 525 reporter.internalError(cls, 'Class "${cls.name}" is not resolved.'); |
579 } | 526 } |
580 | 527 |
581 _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); | 528 updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); |
582 | 529 |
583 // Walk through the superclasses, and record the types | 530 // Walk through the superclasses, and record the types |
584 // implemented by that type on the superclasses. | 531 // implemented by that type on the superclasses. |
585 ClassElement superclass = cls.superclass; | 532 ClassElement superclass = cls.superclass; |
586 while (superclass != null) { | 533 while (superclass != null) { |
587 Set<Element> typesImplementedBySubclassesOfCls = | 534 Set<Element> typesImplementedBySubclassesOfCls = |
588 _typesImplementedBySubclasses.putIfAbsent( | 535 _typesImplementedBySubclasses.putIfAbsent( |
589 superclass, () => new Set<ClassElement>()); | 536 superclass, () => new Set<ClassElement>()); |
590 for (DartType current in cls.allSupertypes) { | 537 for (DartType current in cls.allSupertypes) { |
591 typesImplementedBySubclassesOfCls.add(current.element); | 538 typesImplementedBySubclassesOfCls.add(current.element); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 // function expressions's element. | 696 // function expressions's element. |
750 // TODO(herhut): Generate classes for function expressions earlier. | 697 // TODO(herhut): Generate classes for function expressions earlier. |
751 if (element is SynthesizedCallMethodElementX) { | 698 if (element is SynthesizedCallMethodElementX) { |
752 return getMightBePassedToApply(element.expression); | 699 return getMightBePassedToApply(element.expression); |
753 } | 700 } |
754 return functionsThatMightBePassedToApply.contains(element); | 701 return functionsThatMightBePassedToApply.contains(element); |
755 } | 702 } |
756 | 703 |
757 bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport; | 704 bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport; |
758 } | 705 } |
OLD | NEW |