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