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 isRootInstantiated(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 isRootInstantiated(ClassElement cls) { |
| 422 assert(isClosed); |
| 423 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; |
| 424 return node != null && node.isRootInstantiated; |
| 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.subclassesByMask(ClassHierarchyNode.ROOT_INSTANTIATED); |
418 } | 450 } |
419 | 451 |
420 /// Returns an iterable over the directly instantiated classes that extend | 452 /// Returns an iterable over the directly instantiated classes that extend |
421 /// [cls] _not_ including [cls] itself. | 453 /// [cls] _not_ including [cls] itself. |
422 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { | 454 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { |
423 assert(isClosed); | 455 assert(isClosed); |
424 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 456 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
425 if (subclasses == null) return const <ClassElement>[]; | 457 if (subclasses == null) return const <ClassElement>[]; |
426 return subclasses.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED, | 458 return subclasses.subclassesByMask(ClassHierarchyNode.ROOT_INSTANTIATED, |
427 strict: true); | 459 strict: true); |
428 } | 460 } |
429 | 461 |
430 /// Returns the number of live classes that extend [cls] _not_ | 462 /// Returns the number of live classes that extend [cls] _not_ |
431 /// including [cls] itself. | 463 /// including [cls] itself. |
432 int strictSubclassCount(ClassElement cls) { | 464 int strictSubclassCount(ClassElement cls) { |
433 assert(isClosed); | 465 assert(isClosed); |
434 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 466 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
435 if (subclasses == null) return 0; | 467 if (subclasses == null) return 0; |
436 return subclasses.instantiatedSubclassCount; | 468 return subclasses.instantiatedSubclassCount; |
437 } | 469 } |
438 | 470 |
439 /// Applies [f] to each live class that extend [cls] _not_ including [cls] | 471 /// Applies [f] to each live class that extend [cls] _not_ including [cls] |
440 /// itself. | 472 /// itself. |
441 void forEachStrictSubclassOf( | 473 void forEachStrictSubclassOf( |
442 ClassElement cls, IterationStep f(ClassElement cls)) { | 474 ClassElement cls, IterationStep f(ClassElement cls)) { |
443 assert(isClosed); | 475 assert(isClosed); |
444 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 476 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
445 if (subclasses == null) return; | 477 if (subclasses == null) return; |
446 subclasses.forEachSubclass(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED, | 478 subclasses.forEachSubclass(f, ClassHierarchyNode.ROOT_INSTANTIATED, |
447 strict: true); | 479 strict: true); |
448 } | 480 } |
449 | 481 |
450 /// Returns `true` if [predicate] applies to any live class that extend [cls] | 482 /// Returns `true` if [predicate] applies to any live class that extend [cls] |
451 /// _not_ including [cls] itself. | 483 /// _not_ including [cls] itself. |
452 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)) { | 484 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)) { |
453 assert(isClosed); | 485 assert(isClosed); |
454 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 486 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
455 if (subclasses == null) return false; | 487 if (subclasses == null) return false; |
456 return subclasses.anySubclass( | 488 return subclasses.anySubclass( |
457 predicate, ClassHierarchyNode.DIRECTLY_INSTANTIATED, | 489 predicate, ClassHierarchyNode.ROOT_INSTANTIATED, |
458 strict: true); | 490 strict: true); |
459 } | 491 } |
460 | 492 |
461 /// Returns an iterable over the directly instantiated that implement [cls] | 493 /// Returns an iterable over the directly instantiated that implement [cls] |
462 /// possibly including [cls] itself, if it is live. | 494 /// possibly including [cls] itself, if it is live. |
463 Iterable<ClassElement> subtypesOf(ClassElement cls) { | 495 Iterable<ClassElement> subtypesOf(ClassElement cls) { |
464 assert(isClosed); | 496 assert(isClosed); |
465 ClassSet classSet = _classSets[cls.declaration]; | 497 ClassSet classSet = _classSets[cls.declaration]; |
466 if (classSet == null) { | 498 if (classSet == null) { |
467 return const <ClassElement>[]; | 499 return const <ClassElement>[]; |
468 } else { | 500 } else { |
469 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); | 501 return classSet.subtypesByMask(ClassHierarchyNode.ROOT_INSTANTIATED); |
470 } | 502 } |
471 } | 503 } |
472 | 504 |
473 /// Returns an iterable over the directly instantiated that implement [cls] | 505 /// Returns an iterable over the directly instantiated that implement [cls] |
474 /// _not_ including [cls]. | 506 /// _not_ including [cls]. |
475 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { | 507 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { |
476 assert(isClosed); | 508 assert(isClosed); |
477 ClassSet classSet = _classSets[cls.declaration]; | 509 ClassSet classSet = _classSets[cls.declaration]; |
478 if (classSet == null) { | 510 if (classSet == null) { |
479 return const <ClassElement>[]; | 511 return const <ClassElement>[]; |
480 } else { | 512 } else { |
481 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED, | 513 return classSet.subtypesByMask(ClassHierarchyNode.ROOT_INSTANTIATED, |
482 strict: true); | 514 strict: true); |
483 } | 515 } |
484 } | 516 } |
485 | 517 |
486 /// Returns the number of live classes that implement [cls] _not_ | 518 /// Returns the number of live classes that implement [cls] _not_ |
487 /// including [cls] itself. | 519 /// including [cls] itself. |
488 int strictSubtypeCount(ClassElement cls) { | 520 int strictSubtypeCount(ClassElement cls) { |
489 assert(isClosed); | 521 assert(isClosed); |
490 ClassSet classSet = _classSets[cls.declaration]; | 522 ClassSet classSet = _classSets[cls.declaration]; |
491 if (classSet == null) return 0; | 523 if (classSet == null) return 0; |
492 return classSet.instantiatedSubtypeCount; | 524 return classSet.instantiatedSubtypeCount; |
493 } | 525 } |
494 | 526 |
495 /// Applies [f] to each live class that implements [cls] _not_ including [cls] | 527 /// Applies [f] to each live class that implements [cls] _not_ including [cls] |
496 /// itself. | 528 /// itself. |
497 void forEachStrictSubtypeOf( | 529 void forEachStrictSubtypeOf( |
498 ClassElement cls, IterationStep f(ClassElement cls)) { | 530 ClassElement cls, IterationStep f(ClassElement cls)) { |
499 assert(isClosed); | 531 assert(isClosed); |
500 ClassSet classSet = _classSets[cls.declaration]; | 532 ClassSet classSet = _classSets[cls.declaration]; |
501 if (classSet == null) return; | 533 if (classSet == null) return; |
502 classSet.forEachSubtype(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED, | 534 classSet.forEachSubtype(f, ClassHierarchyNode.ROOT_INSTANTIATED, |
503 strict: true); | 535 strict: true); |
504 } | 536 } |
505 | 537 |
506 /// Returns `true` if [predicate] applies to any live class that extend [cls] | 538 /// Returns `true` if [predicate] applies to any live class that extend [cls] |
507 /// _not_ including [cls] itself. | 539 /// _not_ including [cls] itself. |
508 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)) { | 540 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)) { |
509 assert(isClosed); | 541 assert(isClosed); |
510 ClassSet classSet = _classSets[cls.declaration]; | 542 ClassSet classSet = _classSets[cls.declaration]; |
511 if (classSet == null) return false; | 543 if (classSet == null) return false; |
512 return classSet.anySubtype( | 544 return classSet.anySubtype(predicate, ClassHierarchyNode.ROOT_INSTANTIATED, |
513 predicate, ClassHierarchyNode.DIRECTLY_INSTANTIATED, | |
514 strict: true); | 545 strict: true); |
515 } | 546 } |
516 | 547 |
517 /// Returns `true` if [a] and [b] have any known common subtypes. | 548 /// Returns `true` if [a] and [b] have any known common subtypes. |
518 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) { | 549 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) { |
519 assert(isClosed); | 550 assert(isClosed); |
520 ClassSet classSetA = _classSets[a.declaration]; | 551 ClassSet classSetA = _classSets[a.declaration]; |
521 ClassSet classSetB = _classSets[b.declaration]; | 552 ClassSet classSetB = _classSets[b.declaration]; |
522 if (classSetA == null || classSetB == null) return false; | 553 if (classSetA == null || classSetB == null) return false; |
523 // TODO(johnniwinther): Implement an optimized query on [ClassSet]. | 554 // 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) { | 793 if (!rootNode.isInstantiated) { |
763 // No subclass needs noSuchMethod handling since they are all | 794 // No subclass needs noSuchMethod handling since they are all |
764 // uninstantiated. | 795 // uninstantiated. |
765 return false; | 796 return false; |
766 } | 797 } |
767 ClassElement rootClass = rootNode.cls; | 798 ClassElement rootClass = rootNode.cls; |
768 if (hasConcreteMatch(rootClass, selector)) { | 799 if (hasConcreteMatch(rootClass, selector)) { |
769 // The root subclass has a concrete implementation so no subclass needs | 800 // The root subclass has a concrete implementation so no subclass needs |
770 // noSuchMethod handling. | 801 // noSuchMethod handling. |
771 return false; | 802 return false; |
772 } else if (rootNode.isDirectlyInstantiated) { | 803 } else if (rootNode.isRootInstantiated) { |
773 // The root class need noSuchMethod handling. | 804 // The root class need noSuchMethod handling. |
774 return true; | 805 return true; |
775 } | 806 } |
776 IterationStep result = rootNode.forEachSubclass((ClassElement subclass) { | 807 IterationStep result = rootNode.forEachSubclass((ClassElement subclass) { |
777 if (hasConcreteMatch(subclass, selector, stopAtSuperclass: rootClass)) { | 808 if (hasConcreteMatch(subclass, selector, stopAtSuperclass: rootClass)) { |
778 // Found a match - skip all subclasses. | 809 // Found a match - skip all subclasses. |
779 return IterationStep.SKIP_SUBCLASSES; | 810 return IterationStep.SKIP_SUBCLASSES; |
780 } else { | 811 } else { |
781 // Stop fast - we found a need for noSuchMethod handling. | 812 // Stop fast - we found a need for noSuchMethod handling. |
782 return IterationStep.STOP; | 813 return IterationStep.STOP; |
783 } | 814 } |
784 }, ClassHierarchyNode.DIRECTLY_INSTANTIATED, strict: true); | 815 }, ClassHierarchyNode.ROOT_INSTANTIATED, strict: true); |
785 // We stopped fast so we need noSuchMethod handling. | 816 // We stopped fast so we need noSuchMethod handling. |
786 return result == IterationStep.STOP; | 817 return result == IterationStep.STOP; |
787 } | 818 } |
788 | 819 |
789 ClassSet classSet = getClassSet(base); | 820 ClassSet classSet = getClassSet(base); |
790 ClassHierarchyNode node = classSet.node; | 821 ClassHierarchyNode node = classSet.node; |
791 if (query == ClassQuery.EXACT) { | 822 if (query == ClassQuery.EXACT) { |
792 return node.isDirectlyInstantiated && !hasConcreteMatch(base, selector); | 823 return node.isDirectlyInstantiated && !hasConcreteMatch(base, selector); |
793 } else if (query == ClassQuery.SUBCLASS) { | 824 } else if (query == ClassQuery.SUBCLASS) { |
794 return subclassesNeedNoSuchMethod(node); | 825 return subclassesNeedNoSuchMethod(node); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
936 cls.implementsFunction(coreClasses)) { | 967 cls.implementsFunction(coreClasses)) { |
937 ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass); | 968 ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass); |
938 subtypeSet.addSubtype(node); | 969 subtypeSet.addSubtype(node); |
939 } | 970 } |
940 if (!node.isInstantiated && node.parentNode != null) { | 971 if (!node.isInstantiated && node.parentNode != null) { |
941 _updateSuperClassHierarchyNodeForClass(node.parentNode); | 972 _updateSuperClassHierarchyNodeForClass(node.parentNode); |
942 } | 973 } |
943 } | 974 } |
944 | 975 |
945 void _updateClassHierarchyNodeForClass(ClassElement cls, | 976 void _updateClassHierarchyNodeForClass(ClassElement cls, |
946 {bool directlyInstantiated: false}) { | 977 {bool directlyInstantiated: false, bool abstractlyInstantiated: false}) { |
947 ClassHierarchyNode node = getClassHierarchyNode(cls); | 978 ClassHierarchyNode node = getClassHierarchyNode(cls); |
948 _updateSuperClassHierarchyNodeForClass(node); | 979 _updateSuperClassHierarchyNodeForClass(node); |
949 if (directlyInstantiated) { | 980 if (directlyInstantiated) { |
950 node.isDirectlyInstantiated = true; | 981 node.isDirectlyInstantiated = true; |
951 } | 982 } |
| 983 if (abstractlyInstantiated) { |
| 984 node.isAbstractlyInstantiated = true; |
| 985 } |
952 } | 986 } |
953 | 987 |
954 ClosedWorld closeWorld() { | 988 ClosedWorld closeWorld() { |
955 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` | 989 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` |
956 /// properties of the [ClassHierarchyNode] for [cls]. | 990 /// properties of the [ClassHierarchyNode] for [cls]. |
957 | 991 |
958 void addSubtypes(ClassElement cls) { | 992 void addSubtypes(ClassElement cls, EnumSet<Instantiation> instantiations) { |
959 if (_compiler.options.hasIncrementalSupport && | 993 if (_compiler.options.hasIncrementalSupport && |
960 !alreadyPopulated.add(cls)) { | 994 !alreadyPopulated.add(cls)) { |
961 return; | 995 return; |
962 } | 996 } |
963 assert(cls.isDeclaration); | 997 assert(cls.isDeclaration); |
964 if (!cls.isResolved) { | 998 if (!cls.isResolved) { |
965 reporter.internalError(cls, 'Class "${cls.name}" is not resolved.'); | 999 reporter.internalError(cls, 'Class "${cls.name}" is not resolved.'); |
966 } | 1000 } |
967 | 1001 |
968 _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); | 1002 _updateClassHierarchyNodeForClass(cls, |
| 1003 directlyInstantiated: |
| 1004 instantiations.contains(Instantiation.DIRECTLY_INSTANTIATED), |
| 1005 abstractlyInstantiated: |
| 1006 instantiations.contains(Instantiation.ABSTRACTLY_INSTANTIATED)); |
969 | 1007 |
970 // Walk through the superclasses, and record the types | 1008 // Walk through the superclasses, and record the types |
971 // implemented by that type on the superclasses. | 1009 // implemented by that type on the superclasses. |
972 ClassElement superclass = cls.superclass; | 1010 ClassElement superclass = cls.superclass; |
973 while (superclass != null) { | 1011 while (superclass != null) { |
974 Set<Element> typesImplementedBySubclassesOfCls = | 1012 Set<Element> typesImplementedBySubclassesOfCls = |
975 _typesImplementedBySubclasses.putIfAbsent( | 1013 _typesImplementedBySubclasses.putIfAbsent( |
976 superclass, () => new Set<ClassElement>()); | 1014 superclass, () => new Set<ClassElement>()); |
977 for (DartType current in cls.allSupertypes) { | 1015 for (DartType current in cls.allSupertypes) { |
978 typesImplementedBySubclassesOfCls.add(current.element); | 1016 typesImplementedBySubclassesOfCls.add(current.element); |
979 } | 1017 } |
980 superclass = superclass.superclass; | 1018 superclass = superclass.superclass; |
981 } | 1019 } |
982 } | 1020 } |
983 | 1021 |
984 // Use the [:seenClasses:] set to include non-instantiated | 1022 // Use the [:seenClasses:] set to include non-instantiated |
985 // classes: if the superclass of these classes require RTI, then | 1023 // classes: if the superclass of these classes require RTI, then |
986 // they also need RTI, so that a constructor passes the type | 1024 // they also need RTI, so that a constructor passes the type |
987 // variables to the super constructor. | 1025 // variables to the super constructor. |
988 _compiler.resolverWorld.directlyInstantiatedClasses.forEach(addSubtypes); | 1026 _compiler.resolverWorld.forEachInstantiatedClass(addSubtypes); |
989 | 1027 |
990 _closed = true; | 1028 _closed = true; |
991 return this; | 1029 return this; |
992 } | 1030 } |
993 | 1031 |
994 @override | 1032 @override |
995 String dump([ClassElement cls]) { | 1033 String dump([ClassElement cls]) { |
996 StringBuffer sb = new StringBuffer(); | 1034 StringBuffer sb = new StringBuffer(); |
997 if (cls != null) { | 1035 if (cls != null) { |
998 sb.write("Classes in the closed world related to $cls:\n"); | 1036 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. | 1198 /// Only the class itself is included. |
1161 EXACT, | 1199 EXACT, |
1162 | 1200 |
1163 /// The class and all subclasses (transitively) are included. | 1201 /// The class and all subclasses (transitively) are included. |
1164 SUBCLASS, | 1202 SUBCLASS, |
1165 | 1203 |
1166 /// The class and all classes that implement or subclass it (transitively) | 1204 /// The class and all classes that implement or subclass it (transitively) |
1167 /// are included. | 1205 /// are included. |
1168 SUBTYPE, | 1206 SUBTYPE, |
1169 } | 1207 } |
OLD | NEW |