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 instantiated. | 65 /// Returns `true` if [cls] is either directly or indirectly 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 |
68 /// Returns `true` if [cls] is implemented by an instantiated class. | 75 /// Returns `true` if [cls] is implemented by an instantiated class. |
69 bool isImplemented(ClassElement cls); | 76 bool isImplemented(ClassElement cls); |
70 | 77 |
71 /// Returns `true` if the class world is closed. | 78 /// Returns `true` if the class world is closed. |
72 bool get isClosed; | 79 bool get isClosed; |
73 | 80 |
74 /// Return `true` if [x] is a subclass of [y]. | 81 /// Return `true` if [x] is a subclass of [y]. |
75 bool isSubclassOf(ClassElement x, ClassElement y); | 82 bool isSubclassOf(ClassElement x, ClassElement y); |
76 | 83 |
77 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an | 84 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an |
(...skipping 21 matching lines...) Expand all Loading... |
99 | 106 |
100 /// Returns `true` if any live class other than [cls] extends [cls]. | 107 /// Returns `true` if any live class other than [cls] extends [cls]. |
101 bool hasAnyStrictSubclass(ClassElement cls); | 108 bool hasAnyStrictSubclass(ClassElement cls); |
102 | 109 |
103 /// Returns `true` if any live class other than [cls] implements [cls]. | 110 /// Returns `true` if any live class other than [cls] implements [cls]. |
104 bool hasAnyStrictSubtype(ClassElement cls); | 111 bool hasAnyStrictSubtype(ClassElement cls); |
105 | 112 |
106 /// Returns `true` if all live classes that implement [cls] extend it. | 113 /// Returns `true` if all live classes that implement [cls] extend it. |
107 bool hasOnlySubclasses(ClassElement cls); | 114 bool hasOnlySubclasses(ClassElement cls); |
108 | 115 |
| 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 |
109 /// Returns an iterable over the common supertypes of the [classes]. | 126 /// Returns an iterable over the common supertypes of the [classes]. |
110 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes); | 127 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes); |
111 | 128 |
112 /// Returns an iterable over the live mixin applications that mixin [cls]. | 129 /// Returns an iterable over the live mixin applications that mixin [cls]. |
113 Iterable<MixinApplicationElement> mixinUsesOf(ClassElement cls); | 130 Iterable<MixinApplicationElement> mixinUsesOf(ClassElement cls); |
114 | 131 |
115 /// Returns `true` if [cls] is mixed into a live class. | 132 /// Returns `true` if [cls] is mixed into a live class. |
116 bool isUsedAsMixin(ClassElement cls); | 133 bool isUsedAsMixin(ClassElement cls); |
117 | 134 |
118 /// Returns `true` if any live class that mixes in [cls] implements [type]. | 135 /// 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... |
183 | 200 |
184 if (y == objectClass) return true; | 201 if (y == objectClass) return true; |
185 if (x == objectClass) return false; | 202 if (x == objectClass) return false; |
186 while (x != null && x.hierarchyDepth >= y.hierarchyDepth) { | 203 while (x != null && x.hierarchyDepth >= y.hierarchyDepth) { |
187 if (x == y) return true; | 204 if (x == y) return true; |
188 x = x.superclass; | 205 x = x.superclass; |
189 } | 206 } |
190 return false; | 207 return false; |
191 } | 208 } |
192 | 209 |
193 /// Returns `true` if [cls] is instantiated either directly or through a | 210 @override |
194 /// subclass. | |
195 bool isInstantiated(ClassElement cls) { | 211 bool isInstantiated(ClassElement cls) { |
196 return compiler.resolverWorld.isInstantiated(cls); | 212 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; |
| 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; |
197 } | 226 } |
198 | 227 |
199 /// Returns `true` if [cls] is implemented by an instantiated class. | 228 /// Returns `true` if [cls] is implemented by an instantiated class. |
200 bool isImplemented(ClassElement cls) { | 229 bool isImplemented(ClassElement cls) { |
201 return compiler.resolverWorld.isImplemented(cls); | 230 return compiler.resolverWorld.isImplemented(cls); |
202 } | 231 } |
203 | 232 |
204 /// Returns an iterable over the directly instantiated classes that extend | 233 /// Returns an iterable over the directly instantiated classes that extend |
205 /// [cls] possibly including [cls] itself, if it is live. | 234 /// [cls] possibly including [cls] itself, if it is live. |
206 Iterable<ClassElement> subclassesOf(ClassElement cls) { | 235 Iterable<ClassElement> subclassesOf(ClassElement cls) { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 | 309 |
281 /// Returns `true` if all directly instantiated classes that implement [cls] | 310 /// Returns `true` if all directly instantiated classes that implement [cls] |
282 /// extend it. | 311 /// extend it. |
283 bool hasOnlySubclasses(ClassElement cls) { | 312 bool hasOnlySubclasses(ClassElement cls) { |
284 Iterable<ClassElement> subtypes = strictSubtypesOf(cls); | 313 Iterable<ClassElement> subtypes = strictSubtypesOf(cls); |
285 if (subtypes == null) return true; | 314 if (subtypes == null) return true; |
286 Iterable<ClassElement> subclasses = strictSubclassesOf(cls); | 315 Iterable<ClassElement> subclasses = strictSubclassesOf(cls); |
287 return subclasses != null && (subclasses.length == subtypes.length); | 316 return subclasses != null && (subclasses.length == subtypes.length); |
288 } | 317 } |
289 | 318 |
| 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 |
290 /// Returns an iterable over the common supertypes of the [classes]. | 333 /// Returns an iterable over the common supertypes of the [classes]. |
291 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes) { | 334 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes) { |
292 Iterator<ClassElement> iterator = classes.iterator; | 335 Iterator<ClassElement> iterator = classes.iterator; |
293 if (!iterator.moveNext()) return const <ClassElement>[]; | 336 if (!iterator.moveNext()) return const <ClassElement>[]; |
294 | 337 |
295 ClassElement cls = iterator.current; | 338 ClassElement cls = iterator.current; |
296 assert(checkInvariants(cls)); | 339 assert(checkInvariants(cls)); |
297 OrderedTypeSet typeSet = cls.allSupertypesAndSelf; | 340 OrderedTypeSet typeSet = cls.allSupertypesAndSelf; |
298 if (!iterator.moveNext()) return typeSet.types.map((type) => type.element); | 341 if (!iterator.moveNext()) return typeSet.types.map((type) => type.element); |
299 | 342 |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 alreadyPopulated = compiler.cacheStrategy.newSet(); | 479 alreadyPopulated = compiler.cacheStrategy.newSet(); |
437 | 480 |
438 CoreClasses get coreClasses => compiler.coreClasses; | 481 CoreClasses get coreClasses => compiler.coreClasses; |
439 | 482 |
440 DiagnosticReporter get reporter => compiler.reporter; | 483 DiagnosticReporter get reporter => compiler.reporter; |
441 | 484 |
442 /// Called to add [cls] to the set of known classes. | 485 /// Called to add [cls] to the set of known classes. |
443 /// | 486 /// |
444 /// This ensures that class hierarchy queries can be performed on [cls] and | 487 /// This ensures that class hierarchy queries can be performed on [cls] and |
445 /// classes that extend or implement it. | 488 /// classes that extend or implement it. |
446 void registerClass(ClassElement cls) { | 489 void registerClass(ClassElement cls, {bool isDirectlyInstantiated: false}) { |
447 _ensureClassSet(cls); | 490 _ensureClassSet(cls); |
| 491 if (isDirectlyInstantiated) { |
| 492 _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); |
| 493 } |
448 } | 494 } |
449 | 495 |
450 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies | 496 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies |
451 /// of known classes. | 497 /// of known classes. |
452 /// | 498 /// |
453 /// This method is only provided for testing. For queries on classes, use the | 499 /// This method is only provided for testing. For queries on classes, use the |
454 /// methods defined in [ClassWorld]. | 500 /// methods defined in [ClassWorld]. |
455 ClassHierarchyNode getClassHierarchyNode(ClassElement cls) { | 501 ClassHierarchyNode getClassHierarchyNode(ClassElement cls) { |
456 return _classHierarchyNodes[cls.declaration]; | 502 return _classHierarchyNodes[cls.declaration]; |
457 } | 503 } |
(...skipping 27 matching lines...) Expand all Loading... |
485 for (InterfaceType type in cls.allSupertypes) { | 531 for (InterfaceType type in cls.allSupertypes) { |
486 // TODO(johnniwinther): Optimization: Avoid adding [cls] to | 532 // TODO(johnniwinther): Optimization: Avoid adding [cls] to |
487 // superclasses. | 533 // superclasses. |
488 ClassSet subtypeSet = _ensureClassSet(type.element); | 534 ClassSet subtypeSet = _ensureClassSet(type.element); |
489 subtypeSet.addSubtype(node); | 535 subtypeSet.addSubtype(node); |
490 } | 536 } |
491 return classSet; | 537 return classSet; |
492 }); | 538 }); |
493 } | 539 } |
494 | 540 |
| 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 |
495 void populate() { | 568 void populate() { |
496 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` | 569 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` |
497 /// properties of the [ClassHierarchyNode] for [cls]. | 570 /// 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 } | |
518 | 571 |
519 void addSubtypes(ClassElement cls) { | 572 void addSubtypes(ClassElement cls) { |
520 if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) { | 573 if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) { |
521 return; | 574 return; |
522 } | 575 } |
523 assert(cls.isDeclaration); | 576 assert(cls.isDeclaration); |
524 if (!cls.isResolved) { | 577 if (!cls.isResolved) { |
525 reporter.internalError(cls, 'Class "${cls.name}" is not resolved.'); | 578 reporter.internalError(cls, 'Class "${cls.name}" is not resolved.'); |
526 } | 579 } |
527 | 580 |
528 updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); | 581 _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); |
529 | 582 |
530 // Walk through the superclasses, and record the types | 583 // Walk through the superclasses, and record the types |
531 // implemented by that type on the superclasses. | 584 // implemented by that type on the superclasses. |
532 ClassElement superclass = cls.superclass; | 585 ClassElement superclass = cls.superclass; |
533 while (superclass != null) { | 586 while (superclass != null) { |
534 Set<Element> typesImplementedBySubclassesOfCls = | 587 Set<Element> typesImplementedBySubclassesOfCls = |
535 _typesImplementedBySubclasses.putIfAbsent( | 588 _typesImplementedBySubclasses.putIfAbsent( |
536 superclass, () => new Set<ClassElement>()); | 589 superclass, () => new Set<ClassElement>()); |
537 for (DartType current in cls.allSupertypes) { | 590 for (DartType current in cls.allSupertypes) { |
538 typesImplementedBySubclassesOfCls.add(current.element); | 591 typesImplementedBySubclassesOfCls.add(current.element); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
696 // function expressions's element. | 749 // function expressions's element. |
697 // TODO(herhut): Generate classes for function expressions earlier. | 750 // TODO(herhut): Generate classes for function expressions earlier. |
698 if (element is SynthesizedCallMethodElementX) { | 751 if (element is SynthesizedCallMethodElementX) { |
699 return getMightBePassedToApply(element.expression); | 752 return getMightBePassedToApply(element.expression); |
700 } | 753 } |
701 return functionsThatMightBePassedToApply.contains(element); | 754 return functionsThatMightBePassedToApply.contains(element); |
702 } | 755 } |
703 | 756 |
704 bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport; | 757 bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport; |
705 } | 758 } |
OLD | NEW |