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

Side by Side Diff: pkg/compiler/lib/src/world.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
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
108 /// Returns an iterable over the directly instantiated that implement [cls] 96 /// Returns an iterable over the directly instantiated that implement [cls]
109 /// possibly including [cls] itself, if it is live. 97 /// possibly including [cls] itself, if it is live.
110 Iterable<ClassElement> subtypesOf(ClassElement cls); 98 Iterable<ClassElement> subtypesOf(ClassElement cls);
111 99
112 /// Returns an iterable over the live classes that implement [cls] _not_ 100 /// Returns an iterable over the live classes that implement [cls] _not_
113 /// including [cls] if it is live. 101 /// including [cls] if it is live.
114 Iterable<ClassElement> strictSubtypesOf(ClassElement cls); 102 Iterable<ClassElement> strictSubtypesOf(ClassElement cls);
115 103
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
128 /// Returns `true` if [a] and [b] have any known common subtypes. 104 /// Returns `true` if [a] and [b] have any known common subtypes.
129 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b); 105 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b);
130 106
131 /// Returns `true` if any live class other than [cls] extends [cls]. 107 /// Returns `true` if any live class other than [cls] extends [cls].
132 bool hasAnyStrictSubclass(ClassElement cls); 108 bool hasAnyStrictSubclass(ClassElement cls);
133 109
134 /// Returns `true` if any live class other than [cls] implements [cls]. 110 /// Returns `true` if any live class other than [cls] implements [cls].
135 bool hasAnyStrictSubtype(ClassElement cls); 111 bool hasAnyStrictSubtype(ClassElement cls);
136 112
137 /// Returns `true` if all live classes that implement [cls] extend it. 113 /// Returns `true` if all live classes that implement [cls] extend it.
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 241
266 /// Returns an iterable over the directly instantiated classes that extend 242 /// Returns an iterable over the directly instantiated classes that extend
267 /// [cls] _not_ including [cls] itself. 243 /// [cls] _not_ including [cls] itself.
268 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { 244 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) {
269 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; 245 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
270 if (subclasses == null) return const <ClassElement>[]; 246 if (subclasses == null) return const <ClassElement>[];
271 return subclasses.subclassesByMask( 247 return subclasses.subclassesByMask(
272 ClassHierarchyNode.DIRECTLY_INSTANTIATED, strict: true); 248 ClassHierarchyNode.DIRECTLY_INSTANTIATED, strict: true);
273 } 249 }
274 250
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
305 /// Returns an iterable over the directly instantiated that implement [cls] 251 /// Returns an iterable over the directly instantiated that implement [cls]
306 /// possibly including [cls] itself, if it is live. 252 /// possibly including [cls] itself, if it is live.
307 Iterable<ClassElement> subtypesOf(ClassElement cls) { 253 Iterable<ClassElement> subtypesOf(ClassElement cls) {
308 ClassSet classSet = _classSets[cls.declaration]; 254 ClassSet classSet = _classSets[cls.declaration];
309 if (classSet == null) { 255 if (classSet == null) {
310 return const <ClassElement>[]; 256 return const <ClassElement>[];
311 } else { 257 } else {
312 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); 258 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED);
313 } 259 }
314 } 260 }
315 261
316 /// Returns an iterable over the directly instantiated that implement [cls] 262 /// Returns an iterable over the directly instantiated that implement [cls]
317 /// _not_ including [cls]. 263 /// _not_ including [cls].
318 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { 264 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) {
319 ClassSet classSet = _classSets[cls.declaration]; 265 ClassSet classSet = _classSets[cls.declaration];
320 if (classSet == null) { 266 if (classSet == null) {
321 return const <ClassElement>[]; 267 return const <ClassElement>[];
322 } else { 268 } else {
323 return classSet.subtypesByMask( 269 return classSet.subtypesByMask(
324 ClassHierarchyNode.DIRECTLY_INSTANTIATED, 270 ClassHierarchyNode.DIRECTLY_INSTANTIATED,
325 strict: true); 271 strict: true);
326 } 272 }
327 } 273 }
328 274
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
359 /// Returns `true` if [a] and [b] have any known common subtypes. 275 /// Returns `true` if [a] and [b] have any known common subtypes.
360 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) { 276 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) {
361 ClassSet classSetA = _classSets[a.declaration]; 277 ClassSet classSetA = _classSets[a.declaration];
362 ClassSet classSetB = _classSets[b.declaration]; 278 ClassSet classSetB = _classSets[b.declaration];
363 if (classSetA == null || classSetB == null) return false; 279 if (classSetA == null || classSetB == null) return false;
364 // TODO(johnniwinther): Implement an optimized query on [ClassSet]. 280 // TODO(johnniwinther): Implement an optimized query on [ClassSet].
365 Set<ClassElement> subtypesOfB = classSetB.subtypes().toSet(); 281 Set<ClassElement> subtypesOfB = classSetB.subtypes().toSet();
366 for (ClassElement subtypeOfA in classSetA.subtypes()) { 282 for (ClassElement subtypeOfA in classSetA.subtypes()) {
367 if (subtypesOfB.contains(subtypeOfA)) { 283 if (subtypesOfB.contains(subtypeOfA)) {
368 return true; 284 return true;
369 } 285 }
370 } 286 }
371 return false; 287 return false;
372 } 288 }
373 289
374 /// Returns `true` if any directly instantiated class other than [cls] extends 290 /// Returns `true` if any directly instantiated class other than [cls] extends
375 /// [cls]. 291 /// [cls].
376 bool hasAnyStrictSubclass(ClassElement cls) { 292 bool hasAnyStrictSubclass(ClassElement cls) {
377 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; 293 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
378 if (subclasses == null) return false; 294 if (subclasses == null) return false;
379 return subclasses.isIndirectlyInstantiated; 295 return subclasses.isIndirectlyInstantiated;
380 } 296 }
381 297
382 /// Returns `true` if any directly instantiated class other than [cls] 298 /// Returns `true` if any directly instantiated class other than [cls]
383 /// implements [cls]. 299 /// implements [cls].
384 bool hasAnyStrictSubtype(ClassElement cls) { 300 bool hasAnyStrictSubtype(ClassElement cls) {
385 return strictSubtypeCount(cls) > 0; 301 return !strictSubtypesOf(cls).isEmpty;
386 } 302 }
387 303
388 /// Returns `true` if all directly instantiated classes that implement [cls] 304 /// Returns `true` if all directly instantiated classes that implement [cls]
389 /// extend it. 305 /// extend it.
390 bool hasOnlySubclasses(ClassElement cls) { 306 bool hasOnlySubclasses(ClassElement cls) {
391 // TODO(johnniwinther): move this to ClassSet? 307 // TODO(johnniwinther): move this to ClassSet?
392 if (cls == objectClass) return true; 308 if (cls == objectClass) return true;
393 ClassSet classSet = _classSets[cls.declaration]; 309 Iterable<ClassElement> subtypes = strictSubtypesOf(cls);
394 if (classSet == null) { 310 if (subtypes == null) return true;
395 // Vacuously true. 311 Iterable<ClassElement> subclasses = strictSubclassesOf(cls);
396 return true; 312 return subclasses != null && (subclasses.length == subtypes.length);
397 }
398 return classSet.hasOnlyInstantiatedSubclasses;
399 } 313 }
400 314
401 @override 315 @override
402 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) { 316 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) {
403 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; 317 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration];
404 return hierarchy != null 318 return hierarchy != null
405 ? hierarchy.getLubOfInstantiatedSubclasses() : null; 319 ? hierarchy.getLubOfInstantiatedSubclasses() : null;
406 } 320 }
407 321
408 @override 322 @override
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 /// 494 ///
581 /// This method is only provided for testing. For queries on classes, use the 495 /// This method is only provided for testing. For queries on classes, use the
582 /// methods defined in [ClassWorld]. 496 /// methods defined in [ClassWorld].
583 ClassHierarchyNode getClassHierarchyNode(ClassElement cls) { 497 ClassHierarchyNode getClassHierarchyNode(ClassElement cls) {
584 return _classHierarchyNodes[cls.declaration]; 498 return _classHierarchyNodes[cls.declaration];
585 } 499 }
586 500
587 ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) { 501 ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) {
588 cls = cls.declaration; 502 cls = cls.declaration;
589 return _classHierarchyNodes.putIfAbsent(cls, () { 503 return _classHierarchyNodes.putIfAbsent(cls, () {
590 ClassHierarchyNode parentNode; 504 ClassHierarchyNode node = new ClassHierarchyNode(cls);
591 if (cls.superclass != null) { 505 if (cls.superclass != null) {
592 parentNode = _ensureClassHierarchyNode(cls.superclass); 506 _ensureClassHierarchyNode(cls.superclass).addDirectSubclass(node);
593 } 507 }
594 return new ClassHierarchyNode(parentNode, cls); 508 return node;
595 }); 509 });
596 } 510 }
597 511
598 /// Returns [ClassSet] for [cls] used to model the extends and implements 512 /// Returns [ClassSet] for [cls] used to model the extends and implements
599 /// relations of known classes. 513 /// relations of known classes.
600 /// 514 ///
601 /// This method is only provided for testing. For queries on classes, use the 515 /// This method is only provided for testing. For queries on classes, use the
602 /// methods defined in [ClassWorld]. 516 /// methods defined in [ClassWorld].
603 ClassSet getClassSet(ClassElement cls) { 517 ClassSet getClassSet(ClassElement cls) {
604 return _classSets[cls.declaration]; 518 return _classSets[cls.declaration];
605 } 519 }
606 520
607 ClassSet _ensureClassSet(ClassElement cls) { 521 ClassSet _ensureClassSet(ClassElement cls) {
608 cls = cls.declaration; 522 cls = cls.declaration;
609 return _classSets.putIfAbsent(cls, () { 523 return _classSets.putIfAbsent(cls, () {
610 ClassHierarchyNode node = _ensureClassHierarchyNode(cls); 524 ClassHierarchyNode node = _ensureClassHierarchyNode(cls);
611 ClassSet classSet = new ClassSet(node); 525 ClassSet classSet = new ClassSet(node);
612 526
613 for (InterfaceType type in cls.allSupertypes) { 527 for (InterfaceType type in cls.allSupertypes) {
614 // TODO(johnniwinther): Optimization: Avoid adding [cls] to 528 // TODO(johnniwinther): Optimization: Avoid adding [cls] to
615 // superclasses. 529 // superclasses.
616 ClassSet subtypeSet = _ensureClassSet(type.element); 530 ClassSet subtypeSet = _ensureClassSet(type.element);
617 subtypeSet.addSubtype(node); 531 subtypeSet.addSubtype(node);
618 } 532 }
619 return classSet; 533 return classSet;
620 }); 534 });
621 } 535 }
622 536
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
637 void _updateClassHierarchyNodeForClass( 537 void _updateClassHierarchyNodeForClass(
638 ClassElement cls, 538 ClassElement cls,
639 {bool directlyInstantiated: false}) { 539 {bool directlyInstantiated: false,
540 bool indirectlyInstantiated: false}) {
640 ClassHierarchyNode node = getClassHierarchyNode(cls); 541 ClassHierarchyNode node = getClassHierarchyNode(cls);
641 _updateSuperClassHierarchyNodeForClass(node); 542 bool changed = false;
642 if (directlyInstantiated) { 543 if (directlyInstantiated && !node.isDirectlyInstantiated) {
643 node.isDirectlyInstantiated = true; 544 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);
644 } 561 }
645 } 562 }
646 563
647 void populate() { 564 void populate() {
648 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` 565 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated`
649 /// properties of the [ClassHierarchyNode] for [cls]. 566 /// properties of the [ClassHierarchyNode] for [cls].
650 567
651 void addSubtypes(ClassElement cls) { 568 void addSubtypes(ClassElement cls) {
652 if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) { 569 if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) {
653 return; 570 return;
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
832 // function expressions's element. 749 // function expressions's element.
833 // TODO(herhut): Generate classes for function expressions earlier. 750 // TODO(herhut): Generate classes for function expressions earlier.
834 if (element is SynthesizedCallMethodElementX) { 751 if (element is SynthesizedCallMethodElementX) {
835 return getMightBePassedToApply(element.expression); 752 return getMightBePassedToApply(element.expression);
836 } 753 }
837 return functionsThatMightBePassedToApply.contains(element); 754 return functionsThatMightBePassedToApply.contains(element);
838 } 755 }
839 756
840 bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport; 757 bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport;
841 } 758 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/universe/class_set.dart ('k') | tests/compiler/dart2js/class_set_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698