| 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 |