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

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

Issue 1638863002: Revert "Optimize subclass/subtype queries" (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 4 years, 11 months 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
« no previous file with comments | « pkg/compiler/lib/src/types/union_type_mask.dart ('k') | pkg/compiler/lib/src/world.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 7 import 'dart:collection' show
8 IterableBase; 8 IterableBase;
9 import '../common.dart';
10 import '../elements/elements.dart' show 9 import '../elements/elements.dart' show
11 ClassElement; 10 ClassElement;
12 import '../util/enumset.dart' show 11 import '../util/enumset.dart' show
13 EnumSet; 12 EnumSet;
14 import '../util/util.dart' show 13 import '../util/util.dart' show
15 Link; 14 Link;
16 15
17 /// Enum for the different kinds of instantiation of a class. 16 /// Enum for the different kinds of instantiation of a class.
18 enum Instantiation { 17 enum Instantiation {
19 UNINSTANTIATED, 18 UNINSTANTIATED,
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 } 85 }
87 if (includeIndirectlyInstantiated) { 86 if (includeIndirectlyInstantiated) {
88 mask.add(Instantiation.INDIRECTLY_INSTANTIATED); 87 mask.add(Instantiation.INDIRECTLY_INSTANTIATED);
89 } 88 }
90 if (includeUninstantiated) { 89 if (includeUninstantiated) {
91 mask.add(Instantiation.UNINSTANTIATED); 90 mask.add(Instantiation.UNINSTANTIATED);
92 } 91 }
93 return mask; 92 return mask;
94 } 93 }
95 94
96 final ClassHierarchyNode parentNode;
97 final ClassElement cls; 95 final ClassElement cls;
98 final EnumSet<Instantiation> _mask = 96 final EnumSet<Instantiation> _mask =
99 new EnumSet<Instantiation>.fromValues( 97 new EnumSet<Instantiation>.fromValues(
100 const <Instantiation>[Instantiation.UNINSTANTIATED]); 98 const <Instantiation>[Instantiation.UNINSTANTIATED]);
101 99
102 ClassElement _leastUpperInstantiatedSubclass; 100 ClassElement _leastUpperInstantiatedSubclass;
103 int _instantiatedSubclassCount = 0;
104 101
105 /// `true` if [cls] has been directly instantiated. 102 /// `true` if [cls] has been directly instantiated.
106 /// 103 ///
107 /// For instance `C` but _not_ `B` in: 104 /// For instance `C` but _not_ `B` in:
108 /// class B {} 105 /// class B {}
109 /// class C extends B {} 106 /// class C extends B {}
110 /// main() => new C(); 107 /// main() => new C();
111 /// 108 ///
112 bool get isDirectlyInstantiated => 109 bool get isDirectlyInstantiated =>
113 _mask.contains(Instantiation.DIRECTLY_INSTANTIATED); 110 _mask.contains(Instantiation.DIRECTLY_INSTANTIATED);
114 111
115 void set isDirectlyInstantiated(bool value) { 112 void set isDirectlyInstantiated(bool value) {
116 if (value != isDirectlyInstantiated) { 113 if (value != isDirectlyInstantiated) {
117 ClassHierarchyNode parent = parentNode;
118 if (value) { 114 if (value) {
119 _mask.remove(Instantiation.UNINSTANTIATED); 115 _mask.remove(Instantiation.UNINSTANTIATED);
120 _mask.add(Instantiation.DIRECTLY_INSTANTIATED); 116 _mask.add(Instantiation.DIRECTLY_INSTANTIATED);
121 while (parent != null) {
122 parent._updateInstantiatedSubclassCount(1);
123 parent = parent.parentNode;
124 }
125 } else { 117 } else {
126 _mask.remove(Instantiation.DIRECTLY_INSTANTIATED); 118 _mask.remove(Instantiation.DIRECTLY_INSTANTIATED);
127 if (_mask.isEmpty) { 119 if (_mask.isEmpty) {
128 _mask.add(Instantiation.UNINSTANTIATED); 120 _mask.add(Instantiation.UNINSTANTIATED);
129 } 121 }
130 while (parent != null) {
131 parent._updateInstantiatedSubclassCount(-1);
132 parent = parent.parentNode;
133 }
134 } 122 }
135 } 123 }
136 } 124 }
137 125
138 /// `true` if [cls] has been instantiated through subclasses. 126 /// `true` if [cls] has been instantiated through subclasses.
139 /// 127 ///
140 /// For instance `A` and `B` but _not_ `C` in: 128 /// For instance `A` and `B` but _not_ `C` in:
141 /// class A {} 129 /// class A {}
142 /// class B extends A {} 130 /// class B extends A {}
143 /// class C extends B {} 131 /// class C extends B {}
144 /// main() => [new B(), new C()]; 132 /// main() => [new B(), new C()];
145 /// 133 ///
146 bool get isIndirectlyInstantiated => _instantiatedSubclassCount > 0; 134 bool get isIndirectlyInstantiated =>
135 _mask.contains(Instantiation.INDIRECTLY_INSTANTIATED);
147 136
148 /// The number of strict subclasses that are directly or indirectly 137 void set isIndirectlyInstantiated(bool value) {
149 /// instantiated. 138 if (value != isIndirectlyInstantiated) {
150 int get instantiatedSubclassCount => _instantiatedSubclassCount; 139 if (value) {
151
152 void _updateInstantiatedSubclassCount(int change) {
153 bool before = isIndirectlyInstantiated;
154 _instantiatedSubclassCount += change;
155 bool after = isIndirectlyInstantiated;
156 if (before != after) {
157 if (after) {
158 _mask.remove(Instantiation.UNINSTANTIATED); 140 _mask.remove(Instantiation.UNINSTANTIATED);
159 _mask.add(Instantiation.INDIRECTLY_INSTANTIATED); 141 _mask.add(Instantiation.INDIRECTLY_INSTANTIATED);
160 } else { 142 } else {
161 _mask.remove(Instantiation.INDIRECTLY_INSTANTIATED); 143 _mask.remove(Instantiation.INDIRECTLY_INSTANTIATED);
162 if (_mask.isEmpty) { 144 if (_mask.isEmpty) {
163 _mask.add(Instantiation.UNINSTANTIATED); 145 _mask.add(Instantiation.UNINSTANTIATED);
164 } 146 }
165 } 147 }
166 } 148 }
167 } 149 }
168 150
169 /// The nodes for the direct subclasses of [cls]. 151 /// The nodes for the direct subclasses of [cls].
170 Link<ClassHierarchyNode> _directSubclasses = const Link<ClassHierarchyNode>(); 152 Link<ClassHierarchyNode> _directSubclasses = const Link<ClassHierarchyNode>();
171 153
172 ClassHierarchyNode(this.parentNode, this.cls) { 154 ClassHierarchyNode(this.cls);
173 if (parentNode != null) {
174 parentNode.addDirectSubclass(this);
175 }
176 }
177 155
178 /// Adds [subclass] as a direct subclass of [cls]. 156 /// Adds [subclass] as a direct subclass of [cls].
179 void addDirectSubclass(ClassHierarchyNode subclass) { 157 void addDirectSubclass(ClassHierarchyNode subclass) {
180 assert(subclass.cls.superclass == cls); 158 assert(subclass.cls.superclass == cls);
181 assert(!_directSubclasses.contains(subclass)); 159 assert(!_directSubclasses.contains(subclass));
182 _directSubclasses = _directSubclasses.prepend(subclass); 160 _directSubclasses = _directSubclasses.prepend(subclass);
183 } 161 }
184 162
185 /// Returns `true` if [other] is contained in the subtree of this node. 163 /// Returns `true` if [other] is contained in the subtree of this node.
186 /// 164 ///
187 /// This means that [other] is a subclass of [cls]. 165 /// This means that [other] is a subclass of [cls].
188 bool contains(ClassElement other) { 166 bool contains(ClassElement other) {
189 while (other != null) { 167 while (other != null) {
190 if (cls == other) return true; 168 if (cls == other) return true;
191 if (cls.hierarchyDepth >= other.hierarchyDepth) return false; 169 if (cls.hierarchyDepth >= other.hierarchyDepth) return false;
192 other = other.superclass; 170 other = other.superclass;
193 } 171 }
194 return false; 172 return false;
195 } 173 }
196 174
197 /// `true` if [cls] has been directly or indirectly instantiated. 175 /// `true` if [cls] has been directly or indirectly instantiated.
198 bool get isInstantiated => isDirectlyInstantiated || isIndirectlyInstantiated; 176 bool get isInstantiated => isDirectlyInstantiated || isIndirectlyInstantiated;
199 177
200 /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls]. 178 /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
201 /// 179 ///
180 /// The directly instantiated, indirectly instantiated and uninstantiated
181 /// subclasses of [cls] are returned if [includeDirectlyInstantiated],
182 /// [includeIndirectlyInstantiated], and [includeUninstantiated] are `true`,
183 /// respectively. If [strict] is `true`, [cls] itself is _not_ returned.
184 Iterable<ClassElement> subclasses(
185 {bool includeDirectlyInstantiated: true,
186 bool includeIndirectlyInstantiated: true,
187 bool includeUninstantiated: true,
188 bool strict: false}) {
189 EnumSet<Instantiation> mask = createMask(
190 includeDirectlyInstantiated: includeDirectlyInstantiated,
191 includeIndirectlyInstantiated:includeIndirectlyInstantiated,
192 includeUninstantiated: includeUninstantiated);
193 return subclassesByMask(mask, strict: strict);
194 }
195
196 /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
197 ///
202 /// Subclasses are included if their instantiation properties intersect with 198 /// Subclasses are included if their instantiation properties intersect with
203 /// their corresponding [Instantiation] values in [mask]. If [strict] is 199 /// their corresponding [Instantiation] values in [mask]. If [strict] is
204 /// `true`, [cls] itself is _not_ returned. 200 /// `true`, [cls] itself is _not_ returned.
205 Iterable<ClassElement> subclassesByMask( 201 Iterable<ClassElement> subclassesByMask(
206 EnumSet<Instantiation> mask, 202 EnumSet<Instantiation> mask,
207 {bool strict: false}) { 203 {bool strict: false}) {
208 return new ClassHierarchyNodeIterable( 204 return new ClassHierarchyNodeIterable(
209 this, mask, includeRoot: !strict); 205 this, mask, includeRoot: !strict);
210 } 206 }
211 207
212 /// Applies [predicate] to each subclass of [cls] matching the criteria
213 /// specified by [mask] and [strict]. If [predicate] returns `true` on a
214 /// class, visitation is stopped immediately and the function returns `true`.
215 ///
216 /// [predicate] is applied to subclasses if their instantiation properties
217 /// intersect with their corresponding [Instantiation] values in [mask]. If
218 /// [strict] is `true`, [predicate] is _not_ called on [cls] itself.
219 bool anySubclass(
220 bool predicate(ClassElement cls),
221 EnumSet<Instantiation> mask,
222 {bool strict: false}) {
223
224 ForEach wrapper(ClassElement cls) {
225 return predicate(cls) ? ForEach.STOP : ForEach.CONTINUE;
226 }
227 return forEachSubclass(wrapper, mask, strict: strict) == ForEach.STOP;
228 }
229
230 /// Applies [f] to each subclass of [cls] matching the criteria specified by
231 /// [mask] and [strict].
232 ///
233 /// [f] is a applied to subclasses if their instantiation properties intersect
234 /// with their corresponding [Instantiation] values in [mask]. If [strict] is
235 /// `true`, [f] is _not_ called on [cls] itself.
236 ///
237 /// The visitation of subclasses can be cut short by the return value of [f].
238 /// If [ForEach.STOP] is returned, no further classes are visited and the
239 /// function stops immediately. If [ForEach.SKIP_CHILDREN] is returned, the
240 /// subclasses of the last visited class are skipped, but visitation
241 /// continues. The return value of the function is either [ForEach.STOP], if
242 /// visitation was stopped, or [ForEach.CONTINUE] if visitation continued to
243 /// the end.
244 ForEach forEachSubclass(
245 ForEachFunction f,
246 EnumSet<Instantiation> mask,
247 {bool strict: false}) {
248 ForEach forEach;
249 if (!strict && mask.intersects(_mask)) {
250 forEach = f(cls);
251 }
252 // Interpret `forEach == null` as `forEach == ForEach.CONTINUE`.
253 forEach ??= ForEach.CONTINUE;
254
255 if (!mask.contains(Instantiation.UNINSTANTIATED) && !isInstantiated) {
256 // Bypass children since all are uninstantiated.
257 return forEach;
258 }
259 if (forEach == ForEach.CONTINUE) {
260 for (ClassHierarchyNode subclass in _directSubclasses) {
261 ForEach subForEach = subclass.forEachSubclass(f, mask);
262 if (subForEach == ForEach.STOP) {
263 return subForEach;
264 }
265 }
266 }
267 return forEach;
268 }
269
270 /// Returns the most specific subclass of [cls] (including [cls]) that is 208 /// Returns the most specific subclass of [cls] (including [cls]) that is
271 /// directly instantiated or a superclass of all directly instantiated 209 /// directly instantiated or a superclass of all directly instantiated
272 /// subclasses. If [cls] is not instantiated, `null` is returned. 210 /// subclasses. If [cls] is not instantiated, `null` is returned.
273 ClassElement getLubOfInstantiatedSubclasses() { 211 ClassElement getLubOfInstantiatedSubclasses() {
274 if (!isInstantiated) return null; 212 if (!isInstantiated) return null;
275 if (_leastUpperInstantiatedSubclass == null) { 213 if (_leastUpperInstantiatedSubclass == null) {
276 _leastUpperInstantiatedSubclass = 214 _leastUpperInstantiatedSubclass =
277 _computeLeastUpperInstantiatedSubclass(); 215 _computeLeastUpperInstantiatedSubclass();
278 } 216 }
279 return _leastUpperInstantiatedSubclass; 217 return _leastUpperInstantiatedSubclass;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 if (sorted) { 268 if (sorted) {
331 subclasses = _directSubclasses.toList()..sort((a, b) { 269 subclasses = _directSubclasses.toList()..sort((a, b) {
332 return a.cls.name.compareTo(b.cls.name); 270 return a.cls.name.compareTo(b.cls.name);
333 }); 271 });
334 } 272 }
335 bool needsComma = false; 273 bool needsComma = false;
336 for (ClassHierarchyNode child in subclasses) { 274 for (ClassHierarchyNode child in subclasses) {
337 if (instantiatedOnly && !child.isInstantiated) { 275 if (instantiatedOnly && !child.isInstantiated) {
338 continue; 276 continue;
339 } 277 }
340 if (withRespectTo != null && 278 if (withRespectTo != null && !child.subclasses().any(isRelatedTo)) {
341 !child.anySubclass(isRelatedTo, ClassHierarchyNode.ALL)) {
342 continue; 279 continue;
343 } 280 }
344 if (needsComma) { 281 if (needsComma) {
345 sb.write(',\n'); 282 sb.write(',\n');
346 } else { 283 } else {
347 sb.write('\n'); 284 sb.write('\n');
348 } 285 }
349 child.printOn( 286 child.printOn(
350 sb, 287 sb,
351 '$indentation ', 288 '$indentation ',
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 class ClassSet { 360 class ClassSet {
424 final ClassHierarchyNode node; 361 final ClassHierarchyNode node;
425 ClassElement _leastUpperInstantiatedSubtype; 362 ClassElement _leastUpperInstantiatedSubtype;
426 363
427 List<ClassHierarchyNode> _directSubtypes; 364 List<ClassHierarchyNode> _directSubtypes;
428 365
429 ClassSet(this.node); 366 ClassSet(this.node);
430 367
431 ClassElement get cls => node.cls; 368 ClassElement get cls => node.cls;
432 369
433 /// Returns the number of directly instantiated subtypes of [cls]. 370 /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
434 int get instantiatedSubtypeCount { 371 ///
435 int count = node.instantiatedSubclassCount; 372 /// The directly instantiated, indirectly instantiated and uninstantiated
436 if (_directSubtypes != null) { 373 /// subclasses of [cls] are returned if [includeDirectlyInstantiated],
437 for (ClassHierarchyNode subtypeNode in _directSubtypes) { 374 /// [includeIndirectlyInstantiated], and [includeUninstantiated] are `true`,
438 if (subtypeNode.isDirectlyInstantiated) { 375 /// respectively. If [strict] is `true`, [cls] itself is _not_ returned.
439 count++; 376 Iterable<ClassElement> subclasses(
440 } 377 {bool includeDirectlyInstantiated: true,
441 count += subtypeNode.instantiatedSubclassCount; 378 bool includeIndirectlyInstantiated: true,
442 } 379 bool includeUninstantiated: true,
443 } 380 bool strict: false}) {
444 return count; 381 EnumSet<Instantiation> mask = ClassHierarchyNode.createMask(
445 } 382 includeDirectlyInstantiated: includeDirectlyInstantiated,
446 383 includeIndirectlyInstantiated:includeIndirectlyInstantiated,
447 /// Returns `true` if all instantiated subtypes of [cls] are subclasses of 384 includeUninstantiated: includeUninstantiated);
448 /// [cls]. 385 return subclassesByMask(mask, strict: strict);
449 bool get hasOnlyInstantiatedSubclasses {
450 if (_directSubtypes != null) {
451 for (ClassHierarchyNode subtypeNode in _directSubtypes) {
452 if (subtypeNode.isInstantiated) {
453 return false;
454 }
455 }
456 }
457 return true;
458 } 386 }
459 387
460 /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls]. 388 /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
461 /// 389 ///
462 /// Subclasses are included if their instantiation properties intersect with 390 /// Subclasses are included if their instantiation properties intersect with
463 /// their corresponding [Instantiation] values in [mask]. If [strict] is 391 /// their corresponding [Instantiation] values in [mask]. If [strict] is
464 /// `true`, [cls] itself is _not_ returned. 392 /// `true`, [cls] itself is _not_ returned.
465 Iterable<ClassElement> subclassesByMask( 393 Iterable<ClassElement> subclassesByMask(
466 EnumSet<Instantiation> mask, 394 EnumSet<Instantiation> mask,
467 {bool strict: false}) { 395 {bool strict: false}) {
(...skipping 11 matching lines...) Expand all
479 bool includeIndirectlyInstantiated: true, 407 bool includeIndirectlyInstantiated: true,
480 bool includeUninstantiated: true, 408 bool includeUninstantiated: true,
481 bool strict: false}) { 409 bool strict: false}) {
482 EnumSet<Instantiation> mask = ClassHierarchyNode.createMask( 410 EnumSet<Instantiation> mask = ClassHierarchyNode.createMask(
483 includeDirectlyInstantiated: includeDirectlyInstantiated, 411 includeDirectlyInstantiated: includeDirectlyInstantiated,
484 includeIndirectlyInstantiated:includeIndirectlyInstantiated, 412 includeIndirectlyInstantiated:includeIndirectlyInstantiated,
485 includeUninstantiated: includeUninstantiated); 413 includeUninstantiated: includeUninstantiated);
486 return subtypesByMask(mask, strict: strict); 414 return subtypesByMask(mask, strict: strict);
487 } 415 }
488 416
417
489 /// Returns an [Iterable] of the subtypes of [cls] possibly including [cls]. 418 /// Returns an [Iterable] of the subtypes of [cls] possibly including [cls].
490 /// 419 ///
491 /// Subtypes are included if their instantiation properties intersect with 420 /// Subtypes are included if their instantiation properties intersect with
492 /// their corresponding [Instantiation] values in [mask]. If [strict] is 421 /// their corresponding [Instantiation] values in [mask]. If [strict] is
493 /// `true`, [cls] itself is _not_ returned. 422 /// `true`, [cls] itself is _not_ returned.
494 Iterable<ClassElement> subtypesByMask( 423 Iterable<ClassElement> subtypesByMask(
495 EnumSet<Instantiation> mask, 424 EnumSet<Instantiation> mask,
496 {bool strict: false}) { 425 {bool strict: false}) {
497 if (_directSubtypes == null) { 426 if (_directSubtypes == null) {
498 return node.subclassesByMask( 427 return node.subclassesByMask(
499 mask, 428 mask,
500 strict: strict); 429 strict: strict);
501 } 430 }
502 431
503 return new SubtypesIterable.SubtypesIterator(this, 432 return new SubtypesIterable.SubtypesIterator(this,
504 mask, 433 mask,
505 includeRoot: !strict); 434 includeRoot: !strict);
506 } 435 }
507 436
508 /// Applies [predicate] to each subclass of [cls] matching the criteria
509 /// specified by [mask] and [strict]. If [predicate] returns `true` on a
510 /// class, visitation is stopped immediately and the function returns `true`.
511 ///
512 /// [predicate] is applied to subclasses if their instantiation properties
513 /// intersect with their corresponding [Instantiation] values in [mask]. If
514 /// [strict] is `true`, [predicate] is _not_ called on [cls] itself.
515 bool anySubclass(
516 bool predicate(ClassElement cls),
517 EnumSet<Instantiation> mask,
518 {bool strict: false}) {
519 return node.anySubclass(predicate, mask, strict: strict);
520 }
521
522 /// Applies [f] to each subclass of [cls] matching the criteria specified by
523 /// [mask] and [strict].
524 ///
525 /// [f] is a applied to subclasses if their instantiation properties intersect
526 /// with their corresponding [Instantiation] values in [mask]. If [strict] is
527 /// `true`, [f] is _not_ called on [cls] itself.
528 ///
529 /// The visitation of subclasses can be cut short by the return value of [f].
530 /// If [ForEach.STOP] is returned, no further classes are visited and the
531 /// function stops immediately. If [ForEach.SKIP_CHILDREN] is returned, the
532 /// subclasses of the last visited class are skipped, but visitation
533 /// continues. The return value of the function is either [ForEach.STOP], if
534 /// visitation was stopped, or [ForEach.CONTINUE] if visitation continued to
535 /// the end.
536 ForEach forEachSubclass(
537 ForEachFunction f,
538 EnumSet<Instantiation> mask,
539 {bool strict: false}) {
540 return node.forEachSubclass(f, mask, strict: strict);
541 }
542
543 /// Applies [predicate] to each subtype of [cls] matching the criteria
544 /// specified by [mask] and [strict]. If [predicate] returns `true` on a
545 /// class, visitation is stopped immediately and the function returns `true`.
546 ///
547 /// [predicate] is applied to subtypes if their instantiation properties
548 /// intersect with their corresponding [Instantiation] values in [mask]. If
549 /// [strict] is `true`, [predicate] is _not_ called on [cls] itself.
550 bool anySubtype(
551 bool predicate(ClassElement cls),
552 EnumSet<Instantiation> mask,
553 {bool strict: false}) {
554
555 ForEach wrapper(ClassElement cls) {
556 return predicate(cls) ? ForEach.STOP : ForEach.CONTINUE;
557 }
558 return forEachSubtype(wrapper, mask, strict: strict) == ForEach.STOP;
559 }
560
561 /// Applies [f] to each subtype of [cls] matching the criteria specified by
562 /// [mask] and [strict].
563 ///
564 /// [f] is a applied to subtypes if their instantiation properties intersect
565 /// with their corresponding [Instantiation] values in [mask]. If [strict] is
566 /// `true`, [f] is _not_ called on [cls] itself.
567 ///
568 /// The visitation of subtypes can be cut short by the return value of [f].
569 /// If [ForEach.STOP] is returned, no further classes are visited and the
570 /// function stops immediately. If [ForEach.SKIP_CHILDREN] is returned, the
571 /// subclasses of the last visited class are skipped, but visitation
572 /// continues. The return value of the function is either [ForEach.STOP], if
573 /// visitation was stopped, or [ForEach.CONTINUE] if visitation continued to
574 /// the end.
575 ForEach forEachSubtype(
576 ForEachFunction f,
577 EnumSet<Instantiation> mask,
578 {bool strict: false}) {
579 if (!mask.contains(Instantiation.UNINSTANTIATED) && !node.isInstantiated) {
580 // Bypass children since all are uninstantiated.
581 return ForEach.CONTINUE;
582 }
583 ForEach forEach = node.forEachSubclass(f, mask, strict: strict);
584 forEach ??= ForEach.CONTINUE;
585 if (forEach == ForEach.CONTINUE && _directSubtypes != null) {
586 for (ClassHierarchyNode subclass in _directSubtypes) {
587 ForEach subForEach = subclass.forEachSubclass(f, mask);
588 if (subForEach == ForEach.STOP) {
589 return subForEach;
590 }
591 }
592 }
593 return forEach;
594 }
595
596 /// Adds [subtype] as a subtype of [cls]. 437 /// Adds [subtype] as a subtype of [cls].
597 void addSubtype(ClassHierarchyNode subtype) { 438 void addSubtype(ClassHierarchyNode subtype) {
598 if (node.contains(subtype.cls)) { 439 if (node.contains(subtype.cls)) {
599 return; 440 return;
600 } 441 }
601 if (_directSubtypes == null) { 442 if (_directSubtypes == null) {
602 _directSubtypes = <ClassHierarchyNode>[subtype]; 443 _directSubtypes = <ClassHierarchyNode>[subtype];
603 } else { 444 } else {
604 int hierarchyDepth = subtype.cls.hierarchyDepth; 445 int hierarchyDepth = subtype.cls.hierarchyDepth;
605 List<ClassHierarchyNode> newSubtypes = <ClassHierarchyNode>[]; 446 List<ClassHierarchyNode> newSubtypes = <ClassHierarchyNode>[];
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
847 } 688 }
848 while (hierarchyNodes.moveNext()) { 689 while (hierarchyNodes.moveNext()) {
849 elements = hierarchyNodes.current.subclassesByMask(mask).iterator; 690 elements = hierarchyNodes.current.subclassesByMask(mask).iterator;
850 if (elements.moveNext()) { 691 if (elements.moveNext()) {
851 return true; 692 return true;
852 } 693 }
853 } 694 }
854 return false; 695 return false;
855 } 696 }
856 } 697 }
857
858 /// Enum values returned from the [ForEachFunction] provided to the `forEachX`
859 /// functions of [ClassHierarchyNode] and [ClassSet]. The value is used to
860 /// control the continued iteration.
861 enum ForEach {
862 /// Iteration continues.
863 CONTINUE,
864 /// Iteration stops immediately.
865 STOP,
866 /// Iteration skips the child classes of the current class.
867 SKIP_CHILDREN,
868 }
869
870 /// Visiting function used for the `forEachX` functions of [ClassHierarchyNode]
871 /// and [ClassSet]. The return value controls the continued iteration. If `null`
872 /// is returned, iteration continues to the end.
873 typedef ForEach ForEachFunction(ClassElement cls);
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/types/union_type_mask.dart ('k') | pkg/compiler/lib/src/world.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698