| 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 SynthesizedCallMethodElementX; | 7 import 'closure.dart' show SynthesizedCallMethodElementX; |
| 8 import 'common/backend_api.dart' show BackendClasses; | 8 import 'common/backend_api.dart' show BackendClasses; |
| 9 import 'common.dart'; | 9 import 'common.dart'; |
| 10 import 'compiler.dart' show Compiler; | 10 import 'compiler.dart' show Compiler; |
| 11 import 'core_types.dart' show CoreClasses; | 11 import 'core_types.dart' show CoreClasses; |
| 12 import 'dart_types.dart'; | 12 import 'dart_types.dart'; |
| 13 import 'elements/elements.dart' | 13 import 'elements/elements.dart' |
| 14 show | 14 show |
| 15 ClassElement, | 15 ClassElement, |
| 16 Element, | 16 Element, |
| 17 FunctionElement, | 17 FunctionElement, |
| 18 MixinApplicationElement, | 18 MixinApplicationElement, |
| 19 TypedefElement, | 19 TypedefElement, |
| 20 VariableElement; | 20 VariableElement; |
| 21 import 'js_backend/backend.dart' show JavaScriptBackend; | 21 import 'js_backend/backend.dart' show JavaScriptBackend; |
| 22 import 'ordered_typeset.dart'; | 22 import 'ordered_typeset.dart'; |
| 23 import 'types/masks.dart' show CommonMasks, FlatTypeMask, TypeMask; | 23 import 'types/masks.dart' show CommonMasks, FlatTypeMask, TypeMask; |
| 24 import 'universe/class_set.dart'; | 24 import 'universe/class_set.dart'; |
| 25 import 'universe/function_set.dart' show FunctionSet; | 25 import 'universe/function_set.dart' show FunctionSet; |
| 26 import 'universe/selector.dart' show Selector; | 26 import 'universe/selector.dart' show Selector; |
| 27 import 'universe/side_effects.dart' show SideEffects; | 27 import 'universe/side_effects.dart' show SideEffects; |
| 28 import 'util/enumset.dart'; |
| 28 import 'util/util.dart' show Link; | 29 import 'util/util.dart' show Link; |
| 29 | 30 |
| 30 /// Common superinterface for [OpenWorld] and [ClosedWorld]. | 31 /// Common superinterface for [OpenWorld] and [ClosedWorld]. |
| 31 abstract class World {} | 32 abstract class World {} |
| 32 | 33 |
| 33 /// The [ClosedWorld] represents the information known about a program when | 34 /// The [ClosedWorld] represents the information known about a program when |
| 34 /// compiling with closed-world semantics. | 35 /// compiling with closed-world semantics. |
| 35 /// | 36 /// |
| 36 /// Given the entrypoint of an application, we can track what's reachable from | 37 /// Given the entrypoint of an application, we can track what's reachable from |
| 37 /// it, what functions are called, what classes are allocated, which native | 38 /// it, what functions are called, what classes are allocated, which native |
| 38 /// JavaScript types are touched, what language features are used, and so on. | 39 /// JavaScript types are touched, what language features are used, and so on. |
| 39 /// This precise knowledge about what's live in the program is later used in | 40 /// This precise knowledge about what's live in the program is later used in |
| 40 /// optimizations and other compiler decisions during code generation. | 41 /// optimizations and other compiler decisions during code generation. |
| 41 abstract class ClosedWorld implements World { | 42 abstract class ClosedWorld implements World { |
| 42 /// Access to core classes used by the backend. | 43 /// Access to core classes used by the backend. |
| 43 BackendClasses get backendClasses; | 44 BackendClasses get backendClasses; |
| 44 | 45 |
| 45 /// Access to core classes used in the Dart language. | 46 /// Access to core classes used in the Dart language. |
| 46 CoreClasses get coreClasses; | 47 CoreClasses get coreClasses; |
| 47 | 48 |
| 48 /// Returns `true` if [cls] is either directly or indirectly instantiated. | 49 /// Returns `true` if [cls] is either directly or indirectly instantiated. |
| 49 bool isInstantiated(ClassElement cls); | 50 bool isInstantiated(ClassElement cls); |
| 50 | 51 |
| 51 /// Returns `true` if [cls] is directly instantiated. | 52 /// Returns `true` if [cls] is directly instantiated. This means that at |
| 53 /// runtime instances of exactly [cls] are assumed to exist. |
| 52 bool isDirectlyInstantiated(ClassElement cls); | 54 bool isDirectlyInstantiated(ClassElement cls); |
| 53 | 55 |
| 56 /// Returns `true` if [cls] is abstractly instantiated. This means that at |
| 57 /// runtime instances of [cls] or unknown subclasses of [cls] are assumed to |
| 58 /// exist. |
| 59 /// |
| 60 /// This is used to mark native and/or reflectable classes as instantiated. |
| 61 /// For native classes we do not know the exact class that instantiates [cls] |
| 62 /// so [cls] here represents the root of the subclasses. For reflectable |
| 63 /// classes we need event abstract classes to be 'live' even though they |
| 64 /// cannot themselves be instantiated. |
| 65 bool isAbstractlyInstantiated(ClassElement cls); |
| 66 |
| 67 /// Returns `true` if [cls] is either directly or abstractly instantiated. |
| 68 /// |
| 69 /// See [isDirectlyInstantiated] and [isAbstractlyInstantiated]. |
| 70 bool isExplicitlyInstantiated(ClassElement cls); |
| 71 |
| 54 /// Returns `true` if [cls] is indirectly instantiated, that is through a | 72 /// Returns `true` if [cls] is indirectly instantiated, that is through a |
| 55 /// subclass. | 73 /// subclass. |
| 56 bool isIndirectlyInstantiated(ClassElement cls); | 74 bool isIndirectlyInstantiated(ClassElement cls); |
| 57 | 75 |
| 58 /// Returns `true` if [cls] is abstract and thus can only be instantiated | 76 /// Returns `true` if [cls] is abstract and thus can only be instantiated |
| 59 /// through subclasses. | 77 /// through subclasses. |
| 60 bool isAbstract(ClassElement cls); | 78 bool isAbstract(ClassElement cls); |
| 61 | 79 |
| 62 /// Returns `true` if [cls] is implemented by an instantiated class. | 80 /// Returns `true` if [cls] is implemented by an instantiated class. |
| 63 bool isImplemented(ClassElement cls); | 81 bool isImplemented(ClassElement cls); |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 } | 404 } |
| 387 | 405 |
| 388 @override | 406 @override |
| 389 bool isDirectlyInstantiated(ClassElement cls) { | 407 bool isDirectlyInstantiated(ClassElement cls) { |
| 390 assert(isClosed); | 408 assert(isClosed); |
| 391 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; | 409 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; |
| 392 return node != null && node.isDirectlyInstantiated; | 410 return node != null && node.isDirectlyInstantiated; |
| 393 } | 411 } |
| 394 | 412 |
| 395 @override | 413 @override |
| 414 bool isAbstractlyInstantiated(ClassElement cls) { |
| 415 assert(isClosed); |
| 416 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; |
| 417 return node != null && node.isAbstractlyInstantiated; |
| 418 } |
| 419 |
| 420 @override |
| 421 bool isExplicitlyInstantiated(ClassElement cls) { |
| 422 assert(isClosed); |
| 423 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; |
| 424 return node != null && node.isExplicitlyInstantiated; |
| 425 } |
| 426 |
| 427 @override |
| 396 bool isIndirectlyInstantiated(ClassElement cls) { | 428 bool isIndirectlyInstantiated(ClassElement cls) { |
| 397 assert(isClosed); | 429 assert(isClosed); |
| 398 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; | 430 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; |
| 399 return node != null && node.isIndirectlyInstantiated; | 431 return node != null && node.isIndirectlyInstantiated; |
| 400 } | 432 } |
| 401 | 433 |
| 402 @override | 434 @override |
| 403 bool isAbstract(ClassElement cls) => cls.isAbstract; | 435 bool isAbstract(ClassElement cls) => cls.isAbstract; |
| 404 | 436 |
| 405 /// Returns `true` if [cls] is implemented by an instantiated class. | 437 /// Returns `true` if [cls] is implemented by an instantiated class. |
| 406 bool isImplemented(ClassElement cls) { | 438 bool isImplemented(ClassElement cls) { |
| 407 assert(isClosed); | 439 assert(isClosed); |
| 408 return _compiler.resolverWorld.isImplemented(cls); | 440 return _compiler.resolverWorld.isImplemented(cls); |
| 409 } | 441 } |
| 410 | 442 |
| 411 /// Returns an iterable over the directly instantiated classes that extend | 443 /// Returns an iterable over the directly instantiated classes that extend |
| 412 /// [cls] possibly including [cls] itself, if it is live. | 444 /// [cls] possibly including [cls] itself, if it is live. |
| 413 Iterable<ClassElement> subclassesOf(ClassElement cls) { | 445 Iterable<ClassElement> subclassesOf(ClassElement cls) { |
| 414 assert(isClosed); | 446 assert(isClosed); |
| 415 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; | 447 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; |
| 416 if (hierarchy == null) return const <ClassElement>[]; | 448 if (hierarchy == null) return const <ClassElement>[]; |
| 417 return hierarchy.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); | 449 return hierarchy |
| 450 .subclassesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED); |
| 418 } | 451 } |
| 419 | 452 |
| 420 /// Returns an iterable over the directly instantiated classes that extend | 453 /// Returns an iterable over the directly instantiated classes that extend |
| 421 /// [cls] _not_ including [cls] itself. | 454 /// [cls] _not_ including [cls] itself. |
| 422 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { | 455 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { |
| 423 assert(isClosed); | 456 assert(isClosed); |
| 424 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 457 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
| 425 if (subclasses == null) return const <ClassElement>[]; | 458 if (subclasses == null) return const <ClassElement>[]; |
| 426 return subclasses.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED, | 459 return subclasses.subclassesByMask( |
| 460 ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
| 427 strict: true); | 461 strict: true); |
| 428 } | 462 } |
| 429 | 463 |
| 430 /// Returns the number of live classes that extend [cls] _not_ | 464 /// Returns the number of live classes that extend [cls] _not_ |
| 431 /// including [cls] itself. | 465 /// including [cls] itself. |
| 432 int strictSubclassCount(ClassElement cls) { | 466 int strictSubclassCount(ClassElement cls) { |
| 433 assert(isClosed); | 467 assert(isClosed); |
| 434 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 468 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
| 435 if (subclasses == null) return 0; | 469 if (subclasses == null) return 0; |
| 436 return subclasses.instantiatedSubclassCount; | 470 return subclasses.instantiatedSubclassCount; |
| 437 } | 471 } |
| 438 | 472 |
| 439 /// Applies [f] to each live class that extend [cls] _not_ including [cls] | 473 /// Applies [f] to each live class that extend [cls] _not_ including [cls] |
| 440 /// itself. | 474 /// itself. |
| 441 void forEachStrictSubclassOf( | 475 void forEachStrictSubclassOf( |
| 442 ClassElement cls, IterationStep f(ClassElement cls)) { | 476 ClassElement cls, IterationStep f(ClassElement cls)) { |
| 443 assert(isClosed); | 477 assert(isClosed); |
| 444 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 478 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
| 445 if (subclasses == null) return; | 479 if (subclasses == null) return; |
| 446 subclasses.forEachSubclass(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED, | 480 subclasses.forEachSubclass(f, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
| 447 strict: true); | 481 strict: true); |
| 448 } | 482 } |
| 449 | 483 |
| 450 /// Returns `true` if [predicate] applies to any live class that extend [cls] | 484 /// Returns `true` if [predicate] applies to any live class that extend [cls] |
| 451 /// _not_ including [cls] itself. | 485 /// _not_ including [cls] itself. |
| 452 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)) { | 486 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)) { |
| 453 assert(isClosed); | 487 assert(isClosed); |
| 454 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 488 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
| 455 if (subclasses == null) return false; | 489 if (subclasses == null) return false; |
| 456 return subclasses.anySubclass( | 490 return subclasses.anySubclass( |
| 457 predicate, ClassHierarchyNode.DIRECTLY_INSTANTIATED, | 491 predicate, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
| 458 strict: true); | 492 strict: true); |
| 459 } | 493 } |
| 460 | 494 |
| 461 /// Returns an iterable over the directly instantiated that implement [cls] | 495 /// Returns an iterable over the directly instantiated that implement [cls] |
| 462 /// possibly including [cls] itself, if it is live. | 496 /// possibly including [cls] itself, if it is live. |
| 463 Iterable<ClassElement> subtypesOf(ClassElement cls) { | 497 Iterable<ClassElement> subtypesOf(ClassElement cls) { |
| 464 assert(isClosed); | 498 assert(isClosed); |
| 465 ClassSet classSet = _classSets[cls.declaration]; | 499 ClassSet classSet = _classSets[cls.declaration]; |
| 466 if (classSet == null) { | 500 if (classSet == null) { |
| 467 return const <ClassElement>[]; | 501 return const <ClassElement>[]; |
| 468 } else { | 502 } else { |
| 469 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); | 503 return classSet |
| 504 .subtypesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED); |
| 470 } | 505 } |
| 471 } | 506 } |
| 472 | 507 |
| 473 /// Returns an iterable over the directly instantiated that implement [cls] | 508 /// Returns an iterable over the directly instantiated that implement [cls] |
| 474 /// _not_ including [cls]. | 509 /// _not_ including [cls]. |
| 475 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { | 510 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { |
| 476 assert(isClosed); | 511 assert(isClosed); |
| 477 ClassSet classSet = _classSets[cls.declaration]; | 512 ClassSet classSet = _classSets[cls.declaration]; |
| 478 if (classSet == null) { | 513 if (classSet == null) { |
| 479 return const <ClassElement>[]; | 514 return const <ClassElement>[]; |
| 480 } else { | 515 } else { |
| 481 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED, | 516 return classSet.subtypesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
| 482 strict: true); | 517 strict: true); |
| 483 } | 518 } |
| 484 } | 519 } |
| 485 | 520 |
| 486 /// Returns the number of live classes that implement [cls] _not_ | 521 /// Returns the number of live classes that implement [cls] _not_ |
| 487 /// including [cls] itself. | 522 /// including [cls] itself. |
| 488 int strictSubtypeCount(ClassElement cls) { | 523 int strictSubtypeCount(ClassElement cls) { |
| 489 assert(isClosed); | 524 assert(isClosed); |
| 490 ClassSet classSet = _classSets[cls.declaration]; | 525 ClassSet classSet = _classSets[cls.declaration]; |
| 491 if (classSet == null) return 0; | 526 if (classSet == null) return 0; |
| 492 return classSet.instantiatedSubtypeCount; | 527 return classSet.instantiatedSubtypeCount; |
| 493 } | 528 } |
| 494 | 529 |
| 495 /// Applies [f] to each live class that implements [cls] _not_ including [cls] | 530 /// Applies [f] to each live class that implements [cls] _not_ including [cls] |
| 496 /// itself. | 531 /// itself. |
| 497 void forEachStrictSubtypeOf( | 532 void forEachStrictSubtypeOf( |
| 498 ClassElement cls, IterationStep f(ClassElement cls)) { | 533 ClassElement cls, IterationStep f(ClassElement cls)) { |
| 499 assert(isClosed); | 534 assert(isClosed); |
| 500 ClassSet classSet = _classSets[cls.declaration]; | 535 ClassSet classSet = _classSets[cls.declaration]; |
| 501 if (classSet == null) return; | 536 if (classSet == null) return; |
| 502 classSet.forEachSubtype(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED, | 537 classSet.forEachSubtype(f, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
| 503 strict: true); | 538 strict: true); |
| 504 } | 539 } |
| 505 | 540 |
| 506 /// Returns `true` if [predicate] applies to any live class that extend [cls] | 541 /// Returns `true` if [predicate] applies to any live class that extend [cls] |
| 507 /// _not_ including [cls] itself. | 542 /// _not_ including [cls] itself. |
| 508 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)) { | 543 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)) { |
| 509 assert(isClosed); | 544 assert(isClosed); |
| 510 ClassSet classSet = _classSets[cls.declaration]; | 545 ClassSet classSet = _classSets[cls.declaration]; |
| 511 if (classSet == null) return false; | 546 if (classSet == null) return false; |
| 512 return classSet.anySubtype( | 547 return classSet.anySubtype( |
| 513 predicate, ClassHierarchyNode.DIRECTLY_INSTANTIATED, | 548 predicate, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
| 514 strict: true); | 549 strict: true); |
| 515 } | 550 } |
| 516 | 551 |
| 517 /// Returns `true` if [a] and [b] have any known common subtypes. | 552 /// Returns `true` if [a] and [b] have any known common subtypes. |
| 518 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) { | 553 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) { |
| 519 assert(isClosed); | 554 assert(isClosed); |
| 520 ClassSet classSetA = _classSets[a.declaration]; | 555 ClassSet classSetA = _classSets[a.declaration]; |
| 521 ClassSet classSetB = _classSets[b.declaration]; | 556 ClassSet classSetB = _classSets[b.declaration]; |
| 522 if (classSetA == null || classSetB == null) return false; | 557 if (classSetA == null || classSetB == null) return false; |
| 523 // TODO(johnniwinther): Implement an optimized query on [ClassSet]. | 558 // TODO(johnniwinther): Implement an optimized query on [ClassSet]. |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 762 if (!rootNode.isInstantiated) { | 797 if (!rootNode.isInstantiated) { |
| 763 // No subclass needs noSuchMethod handling since they are all | 798 // No subclass needs noSuchMethod handling since they are all |
| 764 // uninstantiated. | 799 // uninstantiated. |
| 765 return false; | 800 return false; |
| 766 } | 801 } |
| 767 ClassElement rootClass = rootNode.cls; | 802 ClassElement rootClass = rootNode.cls; |
| 768 if (hasConcreteMatch(rootClass, selector)) { | 803 if (hasConcreteMatch(rootClass, selector)) { |
| 769 // The root subclass has a concrete implementation so no subclass needs | 804 // The root subclass has a concrete implementation so no subclass needs |
| 770 // noSuchMethod handling. | 805 // noSuchMethod handling. |
| 771 return false; | 806 return false; |
| 772 } else if (rootNode.isDirectlyInstantiated) { | 807 } else if (rootNode.isExplicitlyInstantiated) { |
| 773 // The root class need noSuchMethod handling. | 808 // The root class need noSuchMethod handling. |
| 774 return true; | 809 return true; |
| 775 } | 810 } |
| 776 IterationStep result = rootNode.forEachSubclass((ClassElement subclass) { | 811 IterationStep result = rootNode.forEachSubclass((ClassElement subclass) { |
| 777 if (hasConcreteMatch(subclass, selector, stopAtSuperclass: rootClass)) { | 812 if (hasConcreteMatch(subclass, selector, stopAtSuperclass: rootClass)) { |
| 778 // Found a match - skip all subclasses. | 813 // Found a match - skip all subclasses. |
| 779 return IterationStep.SKIP_SUBCLASSES; | 814 return IterationStep.SKIP_SUBCLASSES; |
| 780 } else { | 815 } else { |
| 781 // Stop fast - we found a need for noSuchMethod handling. | 816 // Stop fast - we found a need for noSuchMethod handling. |
| 782 return IterationStep.STOP; | 817 return IterationStep.STOP; |
| 783 } | 818 } |
| 784 }, ClassHierarchyNode.DIRECTLY_INSTANTIATED, strict: true); | 819 }, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, strict: true); |
| 785 // We stopped fast so we need noSuchMethod handling. | 820 // We stopped fast so we need noSuchMethod handling. |
| 786 return result == IterationStep.STOP; | 821 return result == IterationStep.STOP; |
| 787 } | 822 } |
| 788 | 823 |
| 789 ClassSet classSet = getClassSet(base); | 824 ClassSet classSet = getClassSet(base); |
| 790 ClassHierarchyNode node = classSet.node; | 825 ClassHierarchyNode node = classSet.node; |
| 791 if (query == ClassQuery.EXACT) { | 826 if (query == ClassQuery.EXACT) { |
| 792 return node.isDirectlyInstantiated && !hasConcreteMatch(base, selector); | 827 return node.isDirectlyInstantiated && !hasConcreteMatch(base, selector); |
| 793 } else if (query == ClassQuery.SUBCLASS) { | 828 } else if (query == ClassQuery.SUBCLASS) { |
| 794 return subclassesNeedNoSuchMethod(node); | 829 return subclassesNeedNoSuchMethod(node); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 936 cls.implementsFunction(coreClasses)) { | 971 cls.implementsFunction(coreClasses)) { |
| 937 ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass); | 972 ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass); |
| 938 subtypeSet.addSubtype(node); | 973 subtypeSet.addSubtype(node); |
| 939 } | 974 } |
| 940 if (!node.isInstantiated && node.parentNode != null) { | 975 if (!node.isInstantiated && node.parentNode != null) { |
| 941 _updateSuperClassHierarchyNodeForClass(node.parentNode); | 976 _updateSuperClassHierarchyNodeForClass(node.parentNode); |
| 942 } | 977 } |
| 943 } | 978 } |
| 944 | 979 |
| 945 void _updateClassHierarchyNodeForClass(ClassElement cls, | 980 void _updateClassHierarchyNodeForClass(ClassElement cls, |
| 946 {bool directlyInstantiated: false}) { | 981 {bool directlyInstantiated: false, bool abstractlyInstantiated: false}) { |
| 947 ClassHierarchyNode node = getClassHierarchyNode(cls); | 982 ClassHierarchyNode node = getClassHierarchyNode(cls); |
| 948 _updateSuperClassHierarchyNodeForClass(node); | 983 _updateSuperClassHierarchyNodeForClass(node); |
| 949 if (directlyInstantiated) { | 984 if (directlyInstantiated) { |
| 950 node.isDirectlyInstantiated = true; | 985 node.isDirectlyInstantiated = true; |
| 951 } | 986 } |
| 987 if (abstractlyInstantiated) { |
| 988 node.isAbstractlyInstantiated = true; |
| 989 } |
| 952 } | 990 } |
| 953 | 991 |
| 954 ClosedWorld closeWorld() { | 992 ClosedWorld closeWorld() { |
| 955 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` | 993 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` |
| 956 /// properties of the [ClassHierarchyNode] for [cls]. | 994 /// properties of the [ClassHierarchyNode] for [cls]. |
| 957 | 995 |
| 958 void addSubtypes(ClassElement cls) { | 996 void addSubtypes(ClassElement cls, EnumSet<Instantiation> instantiations) { |
| 959 if (_compiler.options.hasIncrementalSupport && | 997 if (_compiler.options.hasIncrementalSupport && |
| 960 !alreadyPopulated.add(cls)) { | 998 !alreadyPopulated.add(cls)) { |
| 961 return; | 999 return; |
| 962 } | 1000 } |
| 963 assert(cls.isDeclaration); | 1001 assert(cls.isDeclaration); |
| 964 if (!cls.isResolved) { | 1002 if (!cls.isResolved) { |
| 965 reporter.internalError(cls, 'Class "${cls.name}" is not resolved.'); | 1003 reporter.internalError(cls, 'Class "${cls.name}" is not resolved.'); |
| 966 } | 1004 } |
| 967 | 1005 |
| 968 _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); | 1006 _updateClassHierarchyNodeForClass(cls, |
| 1007 directlyInstantiated: |
| 1008 instantiations.contains(Instantiation.DIRECTLY_INSTANTIATED), |
| 1009 abstractlyInstantiated: |
| 1010 instantiations.contains(Instantiation.ABSTRACTLY_INSTANTIATED)); |
| 969 | 1011 |
| 970 // Walk through the superclasses, and record the types | 1012 // Walk through the superclasses, and record the types |
| 971 // implemented by that type on the superclasses. | 1013 // implemented by that type on the superclasses. |
| 972 ClassElement superclass = cls.superclass; | 1014 ClassElement superclass = cls.superclass; |
| 973 while (superclass != null) { | 1015 while (superclass != null) { |
| 974 Set<Element> typesImplementedBySubclassesOfCls = | 1016 Set<Element> typesImplementedBySubclassesOfCls = |
| 975 _typesImplementedBySubclasses.putIfAbsent( | 1017 _typesImplementedBySubclasses.putIfAbsent( |
| 976 superclass, () => new Set<ClassElement>()); | 1018 superclass, () => new Set<ClassElement>()); |
| 977 for (DartType current in cls.allSupertypes) { | 1019 for (DartType current in cls.allSupertypes) { |
| 978 typesImplementedBySubclassesOfCls.add(current.element); | 1020 typesImplementedBySubclassesOfCls.add(current.element); |
| 979 } | 1021 } |
| 980 superclass = superclass.superclass; | 1022 superclass = superclass.superclass; |
| 981 } | 1023 } |
| 982 } | 1024 } |
| 983 | 1025 |
| 984 // Use the [:seenClasses:] set to include non-instantiated | 1026 // Use the [:seenClasses:] set to include non-instantiated |
| 985 // classes: if the superclass of these classes require RTI, then | 1027 // classes: if the superclass of these classes require RTI, then |
| 986 // they also need RTI, so that a constructor passes the type | 1028 // they also need RTI, so that a constructor passes the type |
| 987 // variables to the super constructor. | 1029 // variables to the super constructor. |
| 988 _compiler.resolverWorld.directlyInstantiatedClasses.forEach(addSubtypes); | 1030 _compiler.resolverWorld.forEachInstantiatedClass(addSubtypes); |
| 989 | 1031 |
| 990 _closed = true; | 1032 _closed = true; |
| 991 return this; | 1033 return this; |
| 992 } | 1034 } |
| 993 | 1035 |
| 994 @override | 1036 @override |
| 995 String dump([ClassElement cls]) { | 1037 String dump([ClassElement cls]) { |
| 996 StringBuffer sb = new StringBuffer(); | 1038 StringBuffer sb = new StringBuffer(); |
| 997 if (cls != null) { | 1039 if (cls != null) { |
| 998 sb.write("Classes in the closed world related to $cls:\n"); | 1040 sb.write("Classes in the closed world related to $cls:\n"); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1160 /// Only the class itself is included. | 1202 /// Only the class itself is included. |
| 1161 EXACT, | 1203 EXACT, |
| 1162 | 1204 |
| 1163 /// The class and all subclasses (transitively) are included. | 1205 /// The class and all subclasses (transitively) are included. |
| 1164 SUBCLASS, | 1206 SUBCLASS, |
| 1165 | 1207 |
| 1166 /// The class and all classes that implement or subclass it (transitively) | 1208 /// The class and all classes that implement or subclass it (transitively) |
| 1167 /// are included. | 1209 /// are included. |
| 1168 SUBTYPE, | 1210 SUBTYPE, |
| 1169 } | 1211 } |
| OLD | NEW |