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 |