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

Side by Side Diff: pkg/compiler/lib/src/world.dart

Issue 1627333002: Optimize subclass/subtype queries (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Use strictSubtypeCount Created 4 years, 10 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
OLDNEW
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 7 import 'closure.dart' show
8 SynthesizedCallMethodElementX; 8 SynthesizedCallMethodElementX;
9 import 'common.dart'; 9 import 'common.dart';
10 import 'common/backend_api.dart' show 10 import 'common/backend_api.dart' show
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 bool isSubtypeOf(ClassElement x, ClassElement y); 86 bool isSubtypeOf(ClassElement x, ClassElement y);
87 87
88 /// Returns an iterable over the live classes that extend [cls] including 88 /// Returns an iterable over the live classes that extend [cls] including
89 /// [cls] itself. 89 /// [cls] itself.
90 Iterable<ClassElement> subclassesOf(ClassElement cls); 90 Iterable<ClassElement> subclassesOf(ClassElement cls);
91 91
92 /// Returns an iterable over the live classes that extend [cls] _not_ 92 /// Returns an iterable over the live classes that extend [cls] _not_
93 /// including [cls] itself. 93 /// including [cls] itself.
94 Iterable<ClassElement> strictSubclassesOf(ClassElement cls); 94 Iterable<ClassElement> strictSubclassesOf(ClassElement cls);
95 95
96 /// Returns the number of live classes that extend [cls] _not_
97 /// including [cls] itself.
98 int strictSubclassCount(ClassElement cls);
99
100 /// Applies [f] to each live class that extend [cls] _not_ including [cls]
101 /// itself.
102 void forEachStrictSubclassOf(ClassElement cls, ForEach f(ClassElement cls));
103
104 /// Returns `true` if [predicate] applies to any live class that extend [cls]
105 /// _not_ including [cls] itself.
106 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls));
107
96 /// Returns an iterable over the directly instantiated that implement [cls] 108 /// Returns an iterable over the directly instantiated that implement [cls]
97 /// possibly including [cls] itself, if it is live. 109 /// possibly including [cls] itself, if it is live.
98 Iterable<ClassElement> subtypesOf(ClassElement cls); 110 Iterable<ClassElement> subtypesOf(ClassElement cls);
99 111
100 /// Returns an iterable over the live classes that implement [cls] _not_ 112 /// Returns an iterable over the live classes that implement [cls] _not_
101 /// including [cls] if it is live. 113 /// including [cls] if it is live.
102 Iterable<ClassElement> strictSubtypesOf(ClassElement cls); 114 Iterable<ClassElement> strictSubtypesOf(ClassElement cls);
103 115
116 /// Returns the number of live classes that implement [cls] _not_
117 /// including [cls] itself.
118 int strictSubtypeCount(ClassElement cls);
119
120 /// Applies [f] to each live class that implements [cls] _not_ including [cls]
121 /// itself.
122 void forEachStrictSubtypeOf(ClassElement cls, ForEach f(ClassElement cls));
123
124 /// Returns `true` if [predicate] applies to any live class that implements
125 /// [cls] _not_ including [cls] itself.
126 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls));
127
104 /// Returns `true` if [a] and [b] have any known common subtypes. 128 /// Returns `true` if [a] and [b] have any known common subtypes.
105 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b); 129 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b);
106 130
107 /// Returns `true` if any live class other than [cls] extends [cls]. 131 /// Returns `true` if any live class other than [cls] extends [cls].
108 bool hasAnyStrictSubclass(ClassElement cls); 132 bool hasAnyStrictSubclass(ClassElement cls);
109 133
110 /// Returns `true` if any live class other than [cls] implements [cls]. 134 /// Returns `true` if any live class other than [cls] implements [cls].
111 bool hasAnyStrictSubtype(ClassElement cls); 135 bool hasAnyStrictSubtype(ClassElement cls);
112 136
113 /// Returns `true` if all live classes that implement [cls] extend it. 137 /// Returns `true` if all live classes that implement [cls] extend it.
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 265
242 /// Returns an iterable over the directly instantiated classes that extend 266 /// Returns an iterable over the directly instantiated classes that extend
243 /// [cls] _not_ including [cls] itself. 267 /// [cls] _not_ including [cls] itself.
244 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { 268 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) {
245 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; 269 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
246 if (subclasses == null) return const <ClassElement>[]; 270 if (subclasses == null) return const <ClassElement>[];
247 return subclasses.subclassesByMask( 271 return subclasses.subclassesByMask(
248 ClassHierarchyNode.DIRECTLY_INSTANTIATED, strict: true); 272 ClassHierarchyNode.DIRECTLY_INSTANTIATED, strict: true);
249 } 273 }
250 274
275 /// Returns the number of live classes that extend [cls] _not_
276 /// including [cls] itself.
277 int strictSubclassCount(ClassElement cls) {
278 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
279 if (subclasses == null) return 0;
280 return subclasses.instantiatedSubclassCount;
281 }
282
283 /// Applies [f] to each live class that extend [cls] _not_ including [cls]
284 /// itself.
285 void forEachStrictSubclassOf(ClassElement cls, ForEach f(ClassElement cls)) {
286 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
287 if (subclasses == null) return;
288 subclasses.forEachSubclass(
289 f,
290 ClassHierarchyNode.DIRECTLY_INSTANTIATED,
291 strict: true);
292 }
293
294 /// Returns `true` if [predicate] applies to any live class that extend [cls]
295 /// _not_ including [cls] itself.
296 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)) {
297 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
298 if (subclasses == null) return false;
299 return subclasses.anySubclass(
300 predicate,
301 ClassHierarchyNode.DIRECTLY_INSTANTIATED,
302 strict: true);
303 }
304
251 /// Returns an iterable over the directly instantiated that implement [cls] 305 /// Returns an iterable over the directly instantiated that implement [cls]
252 /// possibly including [cls] itself, if it is live. 306 /// possibly including [cls] itself, if it is live.
253 Iterable<ClassElement> subtypesOf(ClassElement cls) { 307 Iterable<ClassElement> subtypesOf(ClassElement cls) {
254 ClassSet classSet = _classSets[cls.declaration]; 308 ClassSet classSet = _classSets[cls.declaration];
255 if (classSet == null) { 309 if (classSet == null) {
256 return const <ClassElement>[]; 310 return const <ClassElement>[];
257 } else { 311 } else {
258 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); 312 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED);
259 } 313 }
260 } 314 }
261 315
262 /// Returns an iterable over the directly instantiated that implement [cls] 316 /// Returns an iterable over the directly instantiated that implement [cls]
263 /// _not_ including [cls]. 317 /// _not_ including [cls].
264 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { 318 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) {
265 ClassSet classSet = _classSets[cls.declaration]; 319 ClassSet classSet = _classSets[cls.declaration];
266 if (classSet == null) { 320 if (classSet == null) {
267 return const <ClassElement>[]; 321 return const <ClassElement>[];
268 } else { 322 } else {
269 return classSet.subtypesByMask( 323 return classSet.subtypesByMask(
270 ClassHierarchyNode.DIRECTLY_INSTANTIATED, 324 ClassHierarchyNode.DIRECTLY_INSTANTIATED,
271 strict: true); 325 strict: true);
272 } 326 }
273 } 327 }
274 328
329 /// Returns the number of live classes that implement [cls] _not_
330 /// including [cls] itself.
331 int strictSubtypeCount(ClassElement cls) {
332 ClassSet classSet = _classSets[cls.declaration];
333 if (classSet == null) return 0;
334 return classSet.instantiatedSubtypeCount;
335 }
336
337 /// Applies [f] to each live class that implements [cls] _not_ including [cls]
338 /// itself.
339 void forEachStrictSubtypeOf(ClassElement cls, ForEach f(ClassElement cls)) {
340 ClassSet classSet = _classSets[cls.declaration];
341 if (classSet == null) return;
342 classSet.forEachSubtype(
343 f,
344 ClassHierarchyNode.DIRECTLY_INSTANTIATED,
345 strict: true);
346 }
347
348 /// Returns `true` if [predicate] applies to any live class that extend [cls]
349 /// _not_ including [cls] itself.
350 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)) {
351 ClassSet classSet = _classSets[cls.declaration];
352 if (classSet == null) return false;
353 return classSet.anySubtype(
354 predicate,
355 ClassHierarchyNode.DIRECTLY_INSTANTIATED,
356 strict: true);
357 }
358
275 /// Returns `true` if [a] and [b] have any known common subtypes. 359 /// Returns `true` if [a] and [b] have any known common subtypes.
276 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) { 360 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) {
277 ClassSet classSetA = _classSets[a.declaration]; 361 ClassSet classSetA = _classSets[a.declaration];
278 ClassSet classSetB = _classSets[b.declaration]; 362 ClassSet classSetB = _classSets[b.declaration];
279 if (classSetA == null || classSetB == null) return false; 363 if (classSetA == null || classSetB == null) return false;
280 // TODO(johnniwinther): Implement an optimized query on [ClassSet]. 364 // TODO(johnniwinther): Implement an optimized query on [ClassSet].
281 Set<ClassElement> subtypesOfB = classSetB.subtypes().toSet(); 365 Set<ClassElement> subtypesOfB = classSetB.subtypes().toSet();
282 for (ClassElement subtypeOfA in classSetA.subtypes()) { 366 for (ClassElement subtypeOfA in classSetA.subtypes()) {
283 if (subtypesOfB.contains(subtypeOfA)) { 367 if (subtypesOfB.contains(subtypeOfA)) {
284 return true; 368 return true;
285 } 369 }
286 } 370 }
287 return false; 371 return false;
288 } 372 }
289 373
290 /// Returns `true` if any directly instantiated class other than [cls] extends 374 /// Returns `true` if any directly instantiated class other than [cls] extends
291 /// [cls]. 375 /// [cls].
292 bool hasAnyStrictSubclass(ClassElement cls) { 376 bool hasAnyStrictSubclass(ClassElement cls) {
293 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; 377 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
294 if (subclasses == null) return false; 378 if (subclasses == null) return false;
295 return subclasses.isIndirectlyInstantiated; 379 return subclasses.isIndirectlyInstantiated;
296 } 380 }
297 381
298 /// Returns `true` if any directly instantiated class other than [cls] 382 /// Returns `true` if any directly instantiated class other than [cls]
299 /// implements [cls]. 383 /// implements [cls].
300 bool hasAnyStrictSubtype(ClassElement cls) { 384 bool hasAnyStrictSubtype(ClassElement cls) {
301 return !strictSubtypesOf(cls).isEmpty; 385 return strictSubtypeCount(cls) > 0;
302 } 386 }
303 387
304 /// Returns `true` if all directly instantiated classes that implement [cls] 388 /// Returns `true` if all directly instantiated classes that implement [cls]
305 /// extend it. 389 /// extend it.
306 bool hasOnlySubclasses(ClassElement cls) { 390 bool hasOnlySubclasses(ClassElement cls) {
307 // TODO(johnniwinther): move this to ClassSet? 391 // TODO(johnniwinther): move this to ClassSet?
308 if (cls == objectClass) return true; 392 if (cls == objectClass) return true;
309 Iterable<ClassElement> subtypes = strictSubtypesOf(cls); 393 ClassSet classSet = _classSets[cls.declaration];
310 if (subtypes == null) return true; 394 if (classSet == null) {
311 Iterable<ClassElement> subclasses = strictSubclassesOf(cls); 395 // Vacuously true.
312 return subclasses != null && (subclasses.length == subtypes.length); 396 return true;
397 }
398 return classSet.hasOnlyInstantiatedSubclasses;
313 } 399 }
314 400
315 @override 401 @override
316 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) { 402 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) {
317 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; 403 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration];
318 return hierarchy != null 404 return hierarchy != null
319 ? hierarchy.getLubOfInstantiatedSubclasses() : null; 405 ? hierarchy.getLubOfInstantiatedSubclasses() : null;
320 } 406 }
321 407
322 @override 408 @override
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 /// 580 ///
495 /// This method is only provided for testing. For queries on classes, use the 581 /// This method is only provided for testing. For queries on classes, use the
496 /// methods defined in [ClassWorld]. 582 /// methods defined in [ClassWorld].
497 ClassHierarchyNode getClassHierarchyNode(ClassElement cls) { 583 ClassHierarchyNode getClassHierarchyNode(ClassElement cls) {
498 return _classHierarchyNodes[cls.declaration]; 584 return _classHierarchyNodes[cls.declaration];
499 } 585 }
500 586
501 ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) { 587 ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) {
502 cls = cls.declaration; 588 cls = cls.declaration;
503 return _classHierarchyNodes.putIfAbsent(cls, () { 589 return _classHierarchyNodes.putIfAbsent(cls, () {
504 ClassHierarchyNode node = new ClassHierarchyNode(cls); 590 ClassHierarchyNode parentNode;
505 if (cls.superclass != null) { 591 if (cls.superclass != null) {
506 _ensureClassHierarchyNode(cls.superclass).addDirectSubclass(node); 592 parentNode = _ensureClassHierarchyNode(cls.superclass);
507 } 593 }
508 return node; 594 return new ClassHierarchyNode(parentNode, cls);
509 }); 595 });
510 } 596 }
511 597
512 /// Returns [ClassSet] for [cls] used to model the extends and implements 598 /// Returns [ClassSet] for [cls] used to model the extends and implements
513 /// relations of known classes. 599 /// relations of known classes.
514 /// 600 ///
515 /// This method is only provided for testing. For queries on classes, use the 601 /// This method is only provided for testing. For queries on classes, use the
516 /// methods defined in [ClassWorld]. 602 /// methods defined in [ClassWorld].
517 ClassSet getClassSet(ClassElement cls) { 603 ClassSet getClassSet(ClassElement cls) {
518 return _classSets[cls.declaration]; 604 return _classSets[cls.declaration];
519 } 605 }
520 606
521 ClassSet _ensureClassSet(ClassElement cls) { 607 ClassSet _ensureClassSet(ClassElement cls) {
522 cls = cls.declaration; 608 cls = cls.declaration;
523 return _classSets.putIfAbsent(cls, () { 609 return _classSets.putIfAbsent(cls, () {
524 ClassHierarchyNode node = _ensureClassHierarchyNode(cls); 610 ClassHierarchyNode node = _ensureClassHierarchyNode(cls);
525 ClassSet classSet = new ClassSet(node); 611 ClassSet classSet = new ClassSet(node);
526 612
527 for (InterfaceType type in cls.allSupertypes) { 613 for (InterfaceType type in cls.allSupertypes) {
528 // TODO(johnniwinther): Optimization: Avoid adding [cls] to 614 // TODO(johnniwinther): Optimization: Avoid adding [cls] to
529 // superclasses. 615 // superclasses.
530 ClassSet subtypeSet = _ensureClassSet(type.element); 616 ClassSet subtypeSet = _ensureClassSet(type.element);
531 subtypeSet.addSubtype(node); 617 subtypeSet.addSubtype(node);
532 } 618 }
533 return classSet; 619 return classSet;
534 }); 620 });
535 } 621 }
536 622
623 void _updateSuperClassHierarchyNodeForClass(ClassHierarchyNode node) {
624 // Ensure that classes implicitly implementing `Function` are in its
625 // subtype set.
626 ClassElement cls = node.cls;
627 if (cls != coreClasses.functionClass &&
628 cls.implementsFunction(coreClasses)) {
629 ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass);
630 subtypeSet.addSubtype(node);
631 }
632 if (!node.isInstantiated && node.parentNode != null) {
633 _updateSuperClassHierarchyNodeForClass(node.parentNode);
634 }
635 }
636
537 void _updateClassHierarchyNodeForClass( 637 void _updateClassHierarchyNodeForClass(
538 ClassElement cls, 638 ClassElement cls,
539 {bool directlyInstantiated: false, 639 {bool directlyInstantiated: false}) {
540 bool indirectlyInstantiated: false}) {
541 ClassHierarchyNode node = getClassHierarchyNode(cls); 640 ClassHierarchyNode node = getClassHierarchyNode(cls);
542 bool changed = false; 641 _updateSuperClassHierarchyNodeForClass(node);
543 if (directlyInstantiated && !node.isDirectlyInstantiated) { 642 if (directlyInstantiated) {
544 node.isDirectlyInstantiated = true; 643 node.isDirectlyInstantiated = true;
545 changed = true;
546 }
547 if (indirectlyInstantiated && !node.isIndirectlyInstantiated) {
548 node.isIndirectlyInstantiated = true;
549 changed = true;
550 }
551 if (changed && cls.superclass != null) {
552 _updateClassHierarchyNodeForClass(
553 cls.superclass, indirectlyInstantiated: true);
554 }
555 // Ensure that classes implicitly implementing `Function` are in its
556 // subtype set.
557 if (cls != coreClasses.functionClass &&
558 cls.implementsFunction(compiler)) {
559 ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass);
560 subtypeSet.addSubtype(node);
561 } 644 }
562 } 645 }
563 646
564 void populate() { 647 void populate() {
565 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` 648 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated`
566 /// properties of the [ClassHierarchyNode] for [cls]. 649 /// properties of the [ClassHierarchyNode] for [cls].
567 650
568 void addSubtypes(ClassElement cls) { 651 void addSubtypes(ClassElement cls) {
569 if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) { 652 if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) {
570 return; 653 return;
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 // function expressions's element. 832 // function expressions's element.
750 // TODO(herhut): Generate classes for function expressions earlier. 833 // TODO(herhut): Generate classes for function expressions earlier.
751 if (element is SynthesizedCallMethodElementX) { 834 if (element is SynthesizedCallMethodElementX) {
752 return getMightBePassedToApply(element.expression); 835 return getMightBePassedToApply(element.expression);
753 } 836 }
754 return functionsThatMightBePassedToApply.contains(element); 837 return functionsThatMightBePassedToApply.contains(element);
755 } 838 }
756 839
757 bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport; 840 bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport;
758 } 841 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698