Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(177)

Side by Side Diff: pkg/compiler/lib/src/universe/class_set.dart

Issue 2443953002: Introduce isAbstractlyInstantiated to avoid exact masks of abstract classes. (Closed)
Patch Set: Cleanup #2 Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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.class_set; 5 library dart2js.world.class_set;
6 6
7 import 'dart:collection' show IterableBase; 7 import 'dart:collection' show IterableBase;
8 8
9 import '../common.dart';
9 import '../elements/elements.dart' show ClassElement; 10 import '../elements/elements.dart' show ClassElement;
10 import '../util/enumset.dart' show EnumSet; 11 import '../util/enumset.dart' show EnumSet;
11 import '../util/util.dart' show Link; 12 import '../util/util.dart' show Link;
12 13
13 /// Enum for the different kinds of instantiation of a class. 14 /// Enum for the different kinds of instantiation of a class.
14 enum Instantiation { 15 enum Instantiation {
15 UNINSTANTIATED, 16 UNINSTANTIATED,
16 DIRECTLY_INSTANTIATED, 17 DIRECTLY_INSTANTIATED,
17 INDIRECTLY_INSTANTIATED, 18 INDIRECTLY_INSTANTIATED,
19 ABSTRACTLY_INSTANTIATED,
18 } 20 }
19 21
20 /// Node for [cls] in a tree forming the subclass relation of [ClassElement]s. 22 /// Node for [cls] in a tree forming the subclass relation of [ClassElement]s.
21 /// 23 ///
22 /// This is used by the [ClosedWorld] to perform queries on subclass and subtype 24 /// This is used by the [ClosedWorld] to perform queries on subclass and subtype
23 /// relations. 25 /// relations.
24 /// 26 ///
25 /// For this class hierarchy: 27 /// For this class hierarchy:
26 /// 28 ///
27 /// class A {} 29 /// class A {}
(...skipping 14 matching lines...) Expand all
42 /// | 44 /// |
43 /// E 45 /// E
44 /// 46 ///
45 class ClassHierarchyNode { 47 class ClassHierarchyNode {
46 /// Enum set for selecting instantiated classes in 48 /// Enum set for selecting instantiated classes in
47 /// [ClassHierarchyNode.subclassesByMask], 49 /// [ClassHierarchyNode.subclassesByMask],
48 /// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask]. 50 /// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask].
49 static final EnumSet<Instantiation> INSTANTIATED = 51 static final EnumSet<Instantiation> INSTANTIATED =
50 new EnumSet<Instantiation>.fromValues(const <Instantiation>[ 52 new EnumSet<Instantiation>.fromValues(const <Instantiation>[
51 Instantiation.DIRECTLY_INSTANTIATED, 53 Instantiation.DIRECTLY_INSTANTIATED,
52 Instantiation.INDIRECTLY_INSTANTIATED 54 Instantiation.INDIRECTLY_INSTANTIATED,
55 Instantiation.ABSTRACTLY_INSTANTIATED,
53 ], fixed: true); 56 ], fixed: true);
54 57
55 /// Enum set for selecting directly instantiated classes in 58 /// Enum set for selecting directly and abstractly instantiated classes in
56 /// [ClassHierarchyNode.subclassesByMask], 59 /// [ClassHierarchyNode.subclassesByMask],
57 /// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask]. 60 /// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask].
58 static final EnumSet<Instantiation> DIRECTLY_INSTANTIATED = 61 static final EnumSet<Instantiation> ROOT_INSTANTIATED =
59 new EnumSet<Instantiation>.fromValues( 62 new EnumSet<Instantiation>.fromValues(const <Instantiation>[
60 const <Instantiation>[Instantiation.DIRECTLY_INSTANTIATED], 63 Instantiation.DIRECTLY_INSTANTIATED,
61 fixed: true); 64 Instantiation.ABSTRACTLY_INSTANTIATED
65 ], fixed: true);
62 66
63 /// Enum set for selecting all classes in 67 /// Enum set for selecting all classes in
64 /// [ClassHierarchyNode.subclassesByMask], 68 /// [ClassHierarchyNode.subclassesByMask],
65 /// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask]. 69 /// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask].
66 static final EnumSet<Instantiation> ALL = 70 static final EnumSet<Instantiation> ALL =
67 new EnumSet<Instantiation>.fromValues(Instantiation.values, fixed: true); 71 new EnumSet<Instantiation>.fromValues(Instantiation.values, fixed: true);
68 72
69 /// Creates an enum set for selecting the returned classes in 73 /// Creates an enum set for selecting the returned classes in
70 /// [ClassHierarchyNode.subclassesByMask], 74 /// [ClassHierarchyNode.subclassesByMask],
71 /// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask]. 75 /// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask].
72 static EnumSet<Instantiation> createMask( 76 static EnumSet<Instantiation> createMask(
73 {bool includeDirectlyInstantiated: true, 77 {bool includeDirectlyInstantiated: true,
74 bool includeIndirectlyInstantiated: true, 78 bool includeIndirectlyInstantiated: true,
75 bool includeUninstantiated: true}) { 79 bool includeUninstantiated: true,
80 bool includeAbstractlyInstantiated: true}) {
76 EnumSet<Instantiation> mask = new EnumSet<Instantiation>(); 81 EnumSet<Instantiation> mask = new EnumSet<Instantiation>();
77 if (includeDirectlyInstantiated) { 82 if (includeDirectlyInstantiated) {
78 mask.add(Instantiation.DIRECTLY_INSTANTIATED); 83 mask.add(Instantiation.DIRECTLY_INSTANTIATED);
79 } 84 }
80 if (includeIndirectlyInstantiated) { 85 if (includeIndirectlyInstantiated) {
81 mask.add(Instantiation.INDIRECTLY_INSTANTIATED); 86 mask.add(Instantiation.INDIRECTLY_INSTANTIATED);
82 } 87 }
83 if (includeUninstantiated) { 88 if (includeUninstantiated) {
84 mask.add(Instantiation.UNINSTANTIATED); 89 mask.add(Instantiation.UNINSTANTIATED);
85 } 90 }
91 if (includeAbstractlyInstantiated) {
92 mask.add(Instantiation.ABSTRACTLY_INSTANTIATED);
93 }
86 return mask; 94 return mask;
87 } 95 }
88 96
89 final ClassHierarchyNode parentNode; 97 final ClassHierarchyNode parentNode;
90 final ClassElement cls; 98 final ClassElement cls;
91 final EnumSet<Instantiation> _mask = new EnumSet<Instantiation>.fromValues( 99 final EnumSet<Instantiation> _mask = new EnumSet<Instantiation>.fromValues(
92 const <Instantiation>[Instantiation.UNINSTANTIATED]); 100 const <Instantiation>[Instantiation.UNINSTANTIATED]);
93 101
94 ClassElement _leastUpperInstantiatedSubclass; 102 ClassElement _leastUpperInstantiatedSubclass;
95 int _instantiatedSubclassCount = 0; 103 int _instantiatedSubclassCount = 0;
96 104
97 /// `true` if [cls] has been directly instantiated. 105 /// `true` if [cls] has been directly instantiated.
98 /// 106 ///
99 /// For instance `C` but _not_ `B` in: 107 /// For instance `C` but _not_ `B` in:
100 /// class B {} 108 /// class B {}
101 /// class C extends B {} 109 /// class C extends B {}
102 /// main() => new C(); 110 /// main() => new C();
103 /// 111 ///
104 bool get isDirectlyInstantiated => 112 bool get isDirectlyInstantiated =>
105 _mask.contains(Instantiation.DIRECTLY_INSTANTIATED); 113 _mask.contains(Instantiation.DIRECTLY_INSTANTIATED);
106 114
107 void set isDirectlyInstantiated(bool value) { 115 void set isDirectlyInstantiated(bool value) {
108 if (value != isDirectlyInstantiated) { 116 if (value != isDirectlyInstantiated) {
109 ClassHierarchyNode parent = parentNode; 117 _updateParentInstantiatedSubclassCount(
110 if (value) { 118 Instantiation.DIRECTLY_INSTANTIATED,
111 _mask.remove(Instantiation.UNINSTANTIATED); 119 add: value);
112 _mask.add(Instantiation.DIRECTLY_INSTANTIATED); 120 }
113 while (parent != null) { 121 }
114 parent._updateInstantiatedSubclassCount(1); 122
115 parent = parent.parentNode; 123 /// `true` if [cls] has been abstractly instantiated.
Siggi Cherem (dart-lang) 2016/10/27 13:22:07 it would be good to add here the definition of "ab
Johnni Winther 2016/11/01 11:26:34 Done.
116 } 124 ///
Siggi Cherem (dart-lang) 2016/10/27 13:22:07 nit: delete line
Johnni Winther 2016/11/01 11:26:35 Done.
117 } else { 125 bool get isAbstractlyInstantiated =>
118 _mask.remove(Instantiation.DIRECTLY_INSTANTIATED); 126 _mask.contains(Instantiation.ABSTRACTLY_INSTANTIATED);
119 if (_mask.isEmpty) { 127
120 _mask.add(Instantiation.UNINSTANTIATED); 128 void set isAbstractlyInstantiated(bool value) {
121 } 129 if (value != isAbstractlyInstantiated) {
122 while (parent != null) { 130 _updateParentInstantiatedSubclassCount(
123 parent._updateInstantiatedSubclassCount(-1); 131 Instantiation.ABSTRACTLY_INSTANTIATED,
124 parent = parent.parentNode; 132 add: value);
125 } 133 }
134 }
135
136 /// `true` if [cls] is either directly or abstactly instantiated.
137 bool get isRootInstantiated =>
Siggi Cherem (dart-lang) 2016/10/27 13:22:07 I'm trying to think of other names for this - root
Johnni Winther 2016/11/01 11:26:35 isExplicitlyInstantiated it is!
138 isDirectlyInstantiated || isAbstractlyInstantiated;
139
140 void _updateParentInstantiatedSubclassCount(Instantiation instantiation,
141 {bool add}) {
142 ClassHierarchyNode parent = parentNode;
143 if (add) {
144 _mask.remove(Instantiation.UNINSTANTIATED);
145 _mask.add(instantiation);
146 while (parent != null) {
147 parent._updateInstantiatedSubclassCount(1);
148 parent = parent.parentNode;
149 }
150 } else {
151 _mask.remove(instantiation);
152 if (_mask.isEmpty) {
153 _mask.add(Instantiation.UNINSTANTIATED);
154 }
155 while (parent != null) {
156 parent._updateInstantiatedSubclassCount(-1);
157 parent = parent.parentNode;
126 } 158 }
127 } 159 }
128 } 160 }
129 161
130 /// `true` if [cls] has been instantiated through subclasses. 162 /// `true` if [cls] has been instantiated through subclasses.
131 /// 163 ///
132 /// For instance `A` and `B` but _not_ `C` in: 164 /// For instance `A` and `B` but _not_ `C` in:
133 /// class A {} 165 /// class A {}
134 /// class B extends A {} 166 /// class B extends A {}
135 /// class C extends B {} 167 /// class C extends B {}
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 /// This means that [other] is a subclass of [cls]. 213 /// This means that [other] is a subclass of [cls].
182 bool contains(ClassElement other) { 214 bool contains(ClassElement other) {
183 while (other != null) { 215 while (other != null) {
184 if (cls == other) return true; 216 if (cls == other) return true;
185 if (cls.hierarchyDepth >= other.hierarchyDepth) return false; 217 if (cls.hierarchyDepth >= other.hierarchyDepth) return false;
186 other = other.superclass; 218 other = other.superclass;
187 } 219 }
188 return false; 220 return false;
189 } 221 }
190 222
191 /// `true` if [cls] has been directly or indirectly instantiated. 223 /// `true` if [cls] has been directly, indirectly, or abstractly instantiated.
192 bool get isInstantiated => isDirectlyInstantiated || isIndirectlyInstantiated; 224 bool get isInstantiated => isRootInstantiated || isIndirectlyInstantiated;
193 225
194 /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls]. 226 /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
195 /// 227 ///
196 /// Subclasses are included if their instantiation properties intersect with 228 /// Subclasses are included if their instantiation properties intersect with
197 /// their corresponding [Instantiation] values in [mask]. If [strict] is 229 /// their corresponding [Instantiation] values in [mask]. If [strict] is
198 /// `true`, [cls] itself is _not_ returned. 230 /// `true`, [cls] itself is _not_ returned.
199 Iterable<ClassElement> subclassesByMask(EnumSet<Instantiation> mask, 231 Iterable<ClassElement> subclassesByMask(EnumSet<Instantiation> mask,
200 {bool strict: false}) { 232 {bool strict: false}) {
201 return new ClassHierarchyNodeIterable(this, mask, includeRoot: !strict); 233 return new ClassHierarchyNodeIterable(this, mask, includeRoot: !strict);
202 } 234 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 ClassElement getLubOfInstantiatedSubclasses() { 295 ClassElement getLubOfInstantiatedSubclasses() {
264 if (!isInstantiated) return null; 296 if (!isInstantiated) return null;
265 if (_leastUpperInstantiatedSubclass == null) { 297 if (_leastUpperInstantiatedSubclass == null) {
266 _leastUpperInstantiatedSubclass = 298 _leastUpperInstantiatedSubclass =
267 _computeLeastUpperInstantiatedSubclass(); 299 _computeLeastUpperInstantiatedSubclass();
268 } 300 }
269 return _leastUpperInstantiatedSubclass; 301 return _leastUpperInstantiatedSubclass;
270 } 302 }
271 303
272 ClassElement _computeLeastUpperInstantiatedSubclass() { 304 ClassElement _computeLeastUpperInstantiatedSubclass() {
273 if (isDirectlyInstantiated) { 305 if (isRootInstantiated) {
274 return cls; 306 return cls;
275 } 307 }
308 if (!isInstantiated) {
309 return null;
310 }
276 ClassHierarchyNode subclass; 311 ClassHierarchyNode subclass;
277 for (Link<ClassHierarchyNode> link = _directSubclasses; 312 for (Link<ClassHierarchyNode> link = _directSubclasses;
278 !link.isEmpty; 313 !link.isEmpty;
279 link = link.tail) { 314 link = link.tail) {
280 if (link.head.isInstantiated) { 315 if (link.head.isInstantiated) {
281 if (subclass == null) { 316 if (subclass == null) {
282 subclass = link.head; 317 subclass = link.head;
283 } else { 318 } else {
284 return cls; 319 return cls;
285 } 320 }
(...skipping 18 matching lines...) Expand all
304 if (cls.isAbstract) { 339 if (cls.isAbstract) {
305 sb.write('abstract '); 340 sb.write('abstract ');
306 } 341 }
307 sb.write('class ${cls.name}:'); 342 sb.write('class ${cls.name}:');
308 if (isDirectlyInstantiated) { 343 if (isDirectlyInstantiated) {
309 sb.write(' directly'); 344 sb.write(' directly');
310 } 345 }
311 if (isIndirectlyInstantiated) { 346 if (isIndirectlyInstantiated) {
312 sb.write(' indirectly'); 347 sb.write(' indirectly');
313 } 348 }
349 if (isAbstractlyInstantiated) {
350 sb.write(' abstractly');
351 }
314 sb.write(' ['); 352 sb.write(' [');
315 if (_directSubclasses.isEmpty) { 353 if (_directSubclasses.isEmpty) {
316 sb.write(']'); 354 sb.write(']');
317 } else { 355 } else {
318 var subclasses = _directSubclasses; 356 var subclasses = _directSubclasses;
319 if (sorted) { 357 if (sorted) {
320 subclasses = _directSubclasses.toList() 358 subclasses = _directSubclasses.toList()
321 ..sort((a, b) { 359 ..sort((a, b) {
322 return a.cls.name.compareTo(b.cls.name); 360 return a.cls.name.compareTo(b.cls.name);
323 }); 361 });
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 470
433 ClassSet(this.node); 471 ClassSet(this.node);
434 472
435 ClassElement get cls => node.cls; 473 ClassElement get cls => node.cls;
436 474
437 /// Returns the number of directly instantiated subtypes of [cls]. 475 /// Returns the number of directly instantiated subtypes of [cls].
438 int get instantiatedSubtypeCount { 476 int get instantiatedSubtypeCount {
439 int count = node.instantiatedSubclassCount; 477 int count = node.instantiatedSubclassCount;
440 if (_subtypes != null) { 478 if (_subtypes != null) {
441 for (ClassHierarchyNode subtypeNode in _subtypes) { 479 for (ClassHierarchyNode subtypeNode in _subtypes) {
442 if (subtypeNode.isDirectlyInstantiated) { 480 if (subtypeNode.isDirectlyInstantiated ||
Siggi Cherem (dart-lang) 2016/10/27 13:22:07 can we use isRootInstantiated here too?
Johnni Winther 2016/11/01 11:26:35 Done.
481 subtypeNode.isAbstractlyInstantiated) {
443 count++; 482 count++;
444 } 483 }
445 count += subtypeNode.instantiatedSubclassCount; 484 count += subtypeNode.instantiatedSubclassCount;
446 } 485 }
447 } 486 }
448 return count; 487 return count;
449 } 488 }
450 489
451 /// Returns `true` if all instantiated subtypes of [cls] are subclasses of 490 /// Returns `true` if all instantiated subtypes of [cls] are subclasses of
452 /// [cls]. 491 /// [cls].
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 /// directly instantiated or a superclass of all directly instantiated 679 /// directly instantiated or a superclass of all directly instantiated
641 /// subtypes. If no subtypes of [cls] are instantiated, `null` is returned. 680 /// subtypes. If no subtypes of [cls] are instantiated, `null` is returned.
642 ClassElement getLubOfInstantiatedSubtypes() { 681 ClassElement getLubOfInstantiatedSubtypes() {
643 if (_leastUpperInstantiatedSubtype == null) { 682 if (_leastUpperInstantiatedSubtype == null) {
644 _leastUpperInstantiatedSubtype = _computeLeastUpperInstantiatedSubtype(); 683 _leastUpperInstantiatedSubtype = _computeLeastUpperInstantiatedSubtype();
645 } 684 }
646 return _leastUpperInstantiatedSubtype; 685 return _leastUpperInstantiatedSubtype;
647 } 686 }
648 687
649 ClassElement _computeLeastUpperInstantiatedSubtype() { 688 ClassElement _computeLeastUpperInstantiatedSubtype() {
650 if (node.isDirectlyInstantiated) { 689 if (node.isRootInstantiated) {
651 return cls; 690 return cls;
652 } 691 }
653 if (_subtypes == null) { 692 if (_subtypes == null) {
654 return node.getLubOfInstantiatedSubclasses(); 693 return node.getLubOfInstantiatedSubclasses();
655 } 694 }
656 ClassHierarchyNode subtype; 695 ClassHierarchyNode subtype;
657 if (node.isInstantiated) { 696 if (node.isInstantiated) {
658 subtype = node; 697 subtype = node;
659 } 698 }
660 for (ClassHierarchyNode subnode in _subtypes) { 699 for (ClassHierarchyNode subnode in _subtypes) {
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
854 STOP, 893 STOP,
855 894
856 /// Iteration skips the subclasses of the current class. 895 /// Iteration skips the subclasses of the current class.
857 SKIP_SUBCLASSES, 896 SKIP_SUBCLASSES,
858 } 897 }
859 898
860 /// Visiting function used for the `forEachX` functions of [ClassHierarchyNode] 899 /// Visiting function used for the `forEachX` functions of [ClassHierarchyNode]
861 /// and [ClassSet]. The return value controls the continued iteration. If `null` 900 /// and [ClassSet]. The return value controls the continued iteration. If `null`
862 /// is returned, iteration continues to the end. 901 /// is returned, iteration continues to the end.
863 typedef IterationStep ForEachFunction(ClassElement cls); 902 typedef IterationStep ForEachFunction(ClassElement cls);
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/types/union_type_mask.dart ('k') | pkg/compiler/lib/src/universe/world_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698