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