| 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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 bool isSubtypeOf(ClassElement x, ClassElement y); | 86 bool isSubtypeOf(ClassElement x, ClassElement y); |
| 87 | 87 |
| 88 /// Returns an iterable over the live classes that extend [cls] including | 88 /// Returns an iterable over the live classes that extend [cls] including |
| 89 /// [cls] itself. | 89 /// [cls] itself. |
| 90 Iterable<ClassElement> subclassesOf(ClassElement cls); | 90 Iterable<ClassElement> subclassesOf(ClassElement cls); |
| 91 | 91 |
| 92 /// Returns an iterable over the live classes that extend [cls] _not_ | 92 /// Returns an iterable over the live classes that extend [cls] _not_ |
| 93 /// including [cls] itself. | 93 /// including [cls] itself. |
| 94 Iterable<ClassElement> strictSubclassesOf(ClassElement cls); | 94 Iterable<ClassElement> strictSubclassesOf(ClassElement cls); |
| 95 | 95 |
| 96 /// Returns the number of live classes that extend [cls] _not_ |
| 97 /// including [cls] itself. |
| 98 int strictSubclassCount(ClassElement cls); |
| 99 |
| 100 /// Applies [f] to each live class that extend [cls] _not_ including [cls] |
| 101 /// itself. |
| 102 void forEachStrictSubclassOf(ClassElement cls, ForEach f(ClassElement cls)); |
| 103 |
| 104 /// Returns `true` if [predicate] applies to any live class that extend [cls] |
| 105 /// _not_ including [cls] itself. |
| 106 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)); |
| 107 |
| 96 /// Returns an iterable over the directly instantiated that implement [cls] | 108 /// Returns an iterable over the directly instantiated that implement [cls] |
| 97 /// possibly including [cls] itself, if it is live. | 109 /// possibly including [cls] itself, if it is live. |
| 98 Iterable<ClassElement> subtypesOf(ClassElement cls); | 110 Iterable<ClassElement> subtypesOf(ClassElement cls); |
| 99 | 111 |
| 100 /// Returns an iterable over the live classes that implement [cls] _not_ | 112 /// Returns an iterable over the live classes that implement [cls] _not_ |
| 101 /// including [cls] if it is live. | 113 /// including [cls] if it is live. |
| 102 Iterable<ClassElement> strictSubtypesOf(ClassElement cls); | 114 Iterable<ClassElement> strictSubtypesOf(ClassElement cls); |
| 103 | 115 |
| 116 /// Returns the number of live classes that implement [cls] _not_ |
| 117 /// including [cls] itself. |
| 118 int strictSubtypeCount(ClassElement cls); |
| 119 |
| 120 /// Applies [f] to each live class that implements [cls] _not_ including [cls] |
| 121 /// itself. |
| 122 void forEachStrictSubtypeOf(ClassElement cls, ForEach f(ClassElement cls)); |
| 123 |
| 124 /// Returns `true` if [predicate] applies to any live class that implements |
| 125 /// [cls] _not_ including [cls] itself. |
| 126 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)); |
| 127 |
| 104 /// Returns `true` if [a] and [b] have any known common subtypes. | 128 /// Returns `true` if [a] and [b] have any known common subtypes. |
| 105 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b); | 129 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b); |
| 106 | 130 |
| 107 /// Returns `true` if any live class other than [cls] extends [cls]. | 131 /// Returns `true` if any live class other than [cls] extends [cls]. |
| 108 bool hasAnyStrictSubclass(ClassElement cls); | 132 bool hasAnyStrictSubclass(ClassElement cls); |
| 109 | 133 |
| 110 /// Returns `true` if any live class other than [cls] implements [cls]. | 134 /// Returns `true` if any live class other than [cls] implements [cls]. |
| 111 bool hasAnyStrictSubtype(ClassElement cls); | 135 bool hasAnyStrictSubtype(ClassElement cls); |
| 112 | 136 |
| 113 /// Returns `true` if all live classes that implement [cls] extend it. | 137 /// Returns `true` if all live classes that implement [cls] extend it. |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 | 265 |
| 242 /// Returns an iterable over the directly instantiated classes that extend | 266 /// Returns an iterable over the directly instantiated classes that extend |
| 243 /// [cls] _not_ including [cls] itself. | 267 /// [cls] _not_ including [cls] itself. |
| 244 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { | 268 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { |
| 245 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 269 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
| 246 if (subclasses == null) return const <ClassElement>[]; | 270 if (subclasses == null) return const <ClassElement>[]; |
| 247 return subclasses.subclassesByMask( | 271 return subclasses.subclassesByMask( |
| 248 ClassHierarchyNode.DIRECTLY_INSTANTIATED, strict: true); | 272 ClassHierarchyNode.DIRECTLY_INSTANTIATED, strict: true); |
| 249 } | 273 } |
| 250 | 274 |
| 275 /// Returns the number of live classes that extend [cls] _not_ |
| 276 /// including [cls] itself. |
| 277 int strictSubclassCount(ClassElement cls) { |
| 278 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
| 279 if (subclasses == null) return 0; |
| 280 return subclasses.instantiatedSubclassCount; |
| 281 } |
| 282 |
| 283 /// Applies [f] to each live class that extend [cls] _not_ including [cls] |
| 284 /// itself. |
| 285 void forEachStrictSubclassOf(ClassElement cls, ForEach f(ClassElement cls)) { |
| 286 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
| 287 if (subclasses == null) return; |
| 288 subclasses.forEachSubclass( |
| 289 f, |
| 290 ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
| 291 strict: true); |
| 292 } |
| 293 |
| 294 /// Returns `true` if [predicate] applies to any live class that extend [cls] |
| 295 /// _not_ including [cls] itself. |
| 296 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)) { |
| 297 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
| 298 if (subclasses == null) return false; |
| 299 return subclasses.anySubclass( |
| 300 predicate, |
| 301 ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
| 302 strict: true); |
| 303 } |
| 304 |
| 251 /// Returns an iterable over the directly instantiated that implement [cls] | 305 /// Returns an iterable over the directly instantiated that implement [cls] |
| 252 /// possibly including [cls] itself, if it is live. | 306 /// possibly including [cls] itself, if it is live. |
| 253 Iterable<ClassElement> subtypesOf(ClassElement cls) { | 307 Iterable<ClassElement> subtypesOf(ClassElement cls) { |
| 254 ClassSet classSet = _classSets[cls.declaration]; | 308 ClassSet classSet = _classSets[cls.declaration]; |
| 255 if (classSet == null) { | 309 if (classSet == null) { |
| 256 return const <ClassElement>[]; | 310 return const <ClassElement>[]; |
| 257 } else { | 311 } else { |
| 258 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); | 312 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); |
| 259 } | 313 } |
| 260 } | 314 } |
| 261 | 315 |
| 262 /// Returns an iterable over the directly instantiated that implement [cls] | 316 /// Returns an iterable over the directly instantiated that implement [cls] |
| 263 /// _not_ including [cls]. | 317 /// _not_ including [cls]. |
| 264 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { | 318 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { |
| 265 ClassSet classSet = _classSets[cls.declaration]; | 319 ClassSet classSet = _classSets[cls.declaration]; |
| 266 if (classSet == null) { | 320 if (classSet == null) { |
| 267 return const <ClassElement>[]; | 321 return const <ClassElement>[]; |
| 268 } else { | 322 } else { |
| 269 return classSet.subtypesByMask( | 323 return classSet.subtypesByMask( |
| 270 ClassHierarchyNode.DIRECTLY_INSTANTIATED, | 324 ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
| 271 strict: true); | 325 strict: true); |
| 272 } | 326 } |
| 273 } | 327 } |
| 274 | 328 |
| 329 /// Returns the number of live classes that implement [cls] _not_ |
| 330 /// including [cls] itself. |
| 331 int strictSubtypeCount(ClassElement cls) { |
| 332 ClassSet classSet = _classSets[cls.declaration]; |
| 333 if (classSet == null) return 0; |
| 334 return classSet.instantiatedSubtypeCount; |
| 335 } |
| 336 |
| 337 /// Applies [f] to each live class that implements [cls] _not_ including [cls] |
| 338 /// itself. |
| 339 void forEachStrictSubtypeOf(ClassElement cls, ForEach f(ClassElement cls)) { |
| 340 ClassSet classSet = _classSets[cls.declaration]; |
| 341 if (classSet == null) return; |
| 342 classSet.forEachSubtype( |
| 343 f, |
| 344 ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
| 345 strict: true); |
| 346 } |
| 347 |
| 348 /// Returns `true` if [predicate] applies to any live class that extend [cls] |
| 349 /// _not_ including [cls] itself. |
| 350 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)) { |
| 351 ClassSet classSet = _classSets[cls.declaration]; |
| 352 if (classSet == null) return false; |
| 353 return classSet.anySubtype( |
| 354 predicate, |
| 355 ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
| 356 strict: true); |
| 357 } |
| 358 |
| 275 /// Returns `true` if [a] and [b] have any known common subtypes. | 359 /// Returns `true` if [a] and [b] have any known common subtypes. |
| 276 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) { | 360 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) { |
| 277 ClassSet classSetA = _classSets[a.declaration]; | 361 ClassSet classSetA = _classSets[a.declaration]; |
| 278 ClassSet classSetB = _classSets[b.declaration]; | 362 ClassSet classSetB = _classSets[b.declaration]; |
| 279 if (classSetA == null || classSetB == null) return false; | 363 if (classSetA == null || classSetB == null) return false; |
| 280 // TODO(johnniwinther): Implement an optimized query on [ClassSet]. | 364 // TODO(johnniwinther): Implement an optimized query on [ClassSet]. |
| 281 Set<ClassElement> subtypesOfB = classSetB.subtypes().toSet(); | 365 Set<ClassElement> subtypesOfB = classSetB.subtypes().toSet(); |
| 282 for (ClassElement subtypeOfA in classSetA.subtypes()) { | 366 for (ClassElement subtypeOfA in classSetA.subtypes()) { |
| 283 if (subtypesOfB.contains(subtypeOfA)) { | 367 if (subtypesOfB.contains(subtypeOfA)) { |
| 284 return true; | 368 return true; |
| 285 } | 369 } |
| 286 } | 370 } |
| 287 return false; | 371 return false; |
| 288 } | 372 } |
| 289 | 373 |
| 290 /// Returns `true` if any directly instantiated class other than [cls] extends | 374 /// Returns `true` if any directly instantiated class other than [cls] extends |
| 291 /// [cls]. | 375 /// [cls]. |
| 292 bool hasAnyStrictSubclass(ClassElement cls) { | 376 bool hasAnyStrictSubclass(ClassElement cls) { |
| 293 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 377 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
| 294 if (subclasses == null) return false; | 378 if (subclasses == null) return false; |
| 295 return subclasses.isIndirectlyInstantiated; | 379 return subclasses.isIndirectlyInstantiated; |
| 296 } | 380 } |
| 297 | 381 |
| 298 /// Returns `true` if any directly instantiated class other than [cls] | 382 /// Returns `true` if any directly instantiated class other than [cls] |
| 299 /// implements [cls]. | 383 /// implements [cls]. |
| 300 bool hasAnyStrictSubtype(ClassElement cls) { | 384 bool hasAnyStrictSubtype(ClassElement cls) { |
| 301 return !strictSubtypesOf(cls).isEmpty; | 385 return strictSubtypeCount(cls) > 0; |
| 302 } | 386 } |
| 303 | 387 |
| 304 /// Returns `true` if all directly instantiated classes that implement [cls] | 388 /// Returns `true` if all directly instantiated classes that implement [cls] |
| 305 /// extend it. | 389 /// extend it. |
| 306 bool hasOnlySubclasses(ClassElement cls) { | 390 bool hasOnlySubclasses(ClassElement cls) { |
| 307 // TODO(johnniwinther): move this to ClassSet? | 391 // TODO(johnniwinther): move this to ClassSet? |
| 308 if (cls == objectClass) return true; | 392 if (cls == objectClass) return true; |
| 309 Iterable<ClassElement> subtypes = strictSubtypesOf(cls); | 393 ClassSet classSet = _classSets[cls.declaration]; |
| 310 if (subtypes == null) return true; | 394 if (classSet == null) { |
| 311 Iterable<ClassElement> subclasses = strictSubclassesOf(cls); | 395 // Vacuously true. |
| 312 return subclasses != null && (subclasses.length == subtypes.length); | 396 return true; |
| 397 } |
| 398 return classSet.hasOnlyInstantiatedSubclasses; |
| 313 } | 399 } |
| 314 | 400 |
| 315 @override | 401 @override |
| 316 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) { | 402 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) { |
| 317 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; | 403 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; |
| 318 return hierarchy != null | 404 return hierarchy != null |
| 319 ? hierarchy.getLubOfInstantiatedSubclasses() : null; | 405 ? hierarchy.getLubOfInstantiatedSubclasses() : null; |
| 320 } | 406 } |
| 321 | 407 |
| 322 @override | 408 @override |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 494 /// | 580 /// |
| 495 /// This method is only provided for testing. For queries on classes, use the | 581 /// This method is only provided for testing. For queries on classes, use the |
| 496 /// methods defined in [ClassWorld]. | 582 /// methods defined in [ClassWorld]. |
| 497 ClassHierarchyNode getClassHierarchyNode(ClassElement cls) { | 583 ClassHierarchyNode getClassHierarchyNode(ClassElement cls) { |
| 498 return _classHierarchyNodes[cls.declaration]; | 584 return _classHierarchyNodes[cls.declaration]; |
| 499 } | 585 } |
| 500 | 586 |
| 501 ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) { | 587 ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) { |
| 502 cls = cls.declaration; | 588 cls = cls.declaration; |
| 503 return _classHierarchyNodes.putIfAbsent(cls, () { | 589 return _classHierarchyNodes.putIfAbsent(cls, () { |
| 504 ClassHierarchyNode node = new ClassHierarchyNode(cls); | 590 ClassHierarchyNode parentNode; |
| 505 if (cls.superclass != null) { | 591 if (cls.superclass != null) { |
| 506 _ensureClassHierarchyNode(cls.superclass).addDirectSubclass(node); | 592 parentNode = _ensureClassHierarchyNode(cls.superclass); |
| 507 } | 593 } |
| 508 return node; | 594 return new ClassHierarchyNode(parentNode, cls); |
| 509 }); | 595 }); |
| 510 } | 596 } |
| 511 | 597 |
| 512 /// Returns [ClassSet] for [cls] used to model the extends and implements | 598 /// Returns [ClassSet] for [cls] used to model the extends and implements |
| 513 /// relations of known classes. | 599 /// relations of known classes. |
| 514 /// | 600 /// |
| 515 /// This method is only provided for testing. For queries on classes, use the | 601 /// This method is only provided for testing. For queries on classes, use the |
| 516 /// methods defined in [ClassWorld]. | 602 /// methods defined in [ClassWorld]. |
| 517 ClassSet getClassSet(ClassElement cls) { | 603 ClassSet getClassSet(ClassElement cls) { |
| 518 return _classSets[cls.declaration]; | 604 return _classSets[cls.declaration]; |
| 519 } | 605 } |
| 520 | 606 |
| 521 ClassSet _ensureClassSet(ClassElement cls) { | 607 ClassSet _ensureClassSet(ClassElement cls) { |
| 522 cls = cls.declaration; | 608 cls = cls.declaration; |
| 523 return _classSets.putIfAbsent(cls, () { | 609 return _classSets.putIfAbsent(cls, () { |
| 524 ClassHierarchyNode node = _ensureClassHierarchyNode(cls); | 610 ClassHierarchyNode node = _ensureClassHierarchyNode(cls); |
| 525 ClassSet classSet = new ClassSet(node); | 611 ClassSet classSet = new ClassSet(node); |
| 526 | 612 |
| 527 for (InterfaceType type in cls.allSupertypes) { | 613 for (InterfaceType type in cls.allSupertypes) { |
| 528 // TODO(johnniwinther): Optimization: Avoid adding [cls] to | 614 // TODO(johnniwinther): Optimization: Avoid adding [cls] to |
| 529 // superclasses. | 615 // superclasses. |
| 530 ClassSet subtypeSet = _ensureClassSet(type.element); | 616 ClassSet subtypeSet = _ensureClassSet(type.element); |
| 531 subtypeSet.addSubtype(node); | 617 subtypeSet.addSubtype(node); |
| 532 } | 618 } |
| 533 return classSet; | 619 return classSet; |
| 534 }); | 620 }); |
| 535 } | 621 } |
| 536 | 622 |
| 623 void _updateSuperClassHierarchyNodeForClass(ClassHierarchyNode node) { |
| 624 // Ensure that classes implicitly implementing `Function` are in its |
| 625 // subtype set. |
| 626 ClassElement cls = node.cls; |
| 627 if (cls != coreClasses.functionClass && |
| 628 cls.implementsFunction(coreClasses)) { |
| 629 ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass); |
| 630 subtypeSet.addSubtype(node); |
| 631 } |
| 632 if (!node.isInstantiated && node.parentNode != null) { |
| 633 _updateSuperClassHierarchyNodeForClass(node.parentNode); |
| 634 } |
| 635 } |
| 636 |
| 537 void _updateClassHierarchyNodeForClass( | 637 void _updateClassHierarchyNodeForClass( |
| 538 ClassElement cls, | 638 ClassElement cls, |
| 539 {bool directlyInstantiated: false, | 639 {bool directlyInstantiated: false}) { |
| 540 bool indirectlyInstantiated: false}) { | |
| 541 ClassHierarchyNode node = getClassHierarchyNode(cls); | 640 ClassHierarchyNode node = getClassHierarchyNode(cls); |
| 542 bool changed = false; | 641 _updateSuperClassHierarchyNodeForClass(node); |
| 543 if (directlyInstantiated && !node.isDirectlyInstantiated) { | 642 if (directlyInstantiated) { |
| 544 node.isDirectlyInstantiated = true; | 643 node.isDirectlyInstantiated = true; |
| 545 changed = true; | |
| 546 } | |
| 547 if (indirectlyInstantiated && !node.isIndirectlyInstantiated) { | |
| 548 node.isIndirectlyInstantiated = true; | |
| 549 changed = true; | |
| 550 } | |
| 551 if (changed && cls.superclass != null) { | |
| 552 _updateClassHierarchyNodeForClass( | |
| 553 cls.superclass, indirectlyInstantiated: true); | |
| 554 } | |
| 555 // Ensure that classes implicitly implementing `Function` are in its | |
| 556 // subtype set. | |
| 557 if (cls != coreClasses.functionClass && | |
| 558 cls.implementsFunction(compiler)) { | |
| 559 ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass); | |
| 560 subtypeSet.addSubtype(node); | |
| 561 } | 644 } |
| 562 } | 645 } |
| 563 | 646 |
| 564 void populate() { | 647 void populate() { |
| 565 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` | 648 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` |
| 566 /// properties of the [ClassHierarchyNode] for [cls]. | 649 /// properties of the [ClassHierarchyNode] for [cls]. |
| 567 | 650 |
| 568 void addSubtypes(ClassElement cls) { | 651 void addSubtypes(ClassElement cls) { |
| 569 if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) { | 652 if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) { |
| 570 return; | 653 return; |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 749 // function expressions's element. | 832 // function expressions's element. |
| 750 // TODO(herhut): Generate classes for function expressions earlier. | 833 // TODO(herhut): Generate classes for function expressions earlier. |
| 751 if (element is SynthesizedCallMethodElementX) { | 834 if (element is SynthesizedCallMethodElementX) { |
| 752 return getMightBePassedToApply(element.expression); | 835 return getMightBePassedToApply(element.expression); |
| 753 } | 836 } |
| 754 return functionsThatMightBePassedToApply.contains(element); | 837 return functionsThatMightBePassedToApply.contains(element); |
| 755 } | 838 } |
| 756 | 839 |
| 757 bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport; | 840 bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport; |
| 758 } | 841 } |
| OLD | NEW |