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 Backend; | 8 import 'common/backend_api.dart' show Backend; |
9 import 'common.dart'; | 9 import 'common.dart'; |
10 import 'compiler.dart' show Compiler; | 10 import 'compiler.dart' show Compiler; |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 bool isUsedAsMixin(ClassElement cls); | 160 bool isUsedAsMixin(ClassElement cls); |
161 | 161 |
162 /// Returns `true` if any live class that mixes in [cls] implements [type]. | 162 /// Returns `true` if any live class that mixes in [cls] implements [type]. |
163 bool hasAnySubclassOfMixinUseThatImplements( | 163 bool hasAnySubclassOfMixinUseThatImplements( |
164 ClassElement cls, ClassElement type); | 164 ClassElement cls, ClassElement type); |
165 | 165 |
166 /// Returns `true` if any live class that mixes in [mixin] is also a subclass | 166 /// Returns `true` if any live class that mixes in [mixin] is also a subclass |
167 /// of [superclass]. | 167 /// of [superclass]. |
168 bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin); | 168 bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin); |
169 | 169 |
| 170 /// Returns `true` if [cls] or any superclass mixes in [mixin]. |
| 171 bool isSubclassOfMixinUseOf(ClassElement cls, ClassElement mixin); |
| 172 |
| 173 /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass |
| 174 /// of a mixin application of [y]. |
| 175 bool everySubtypeIsSubclassOfOrMixinUseOf(ClassElement x, ClassElement y); |
| 176 |
170 /// Returns `true` if any subclass of [superclass] implements [type]. | 177 /// Returns `true` if any subclass of [superclass] implements [type]. |
171 bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type); | 178 bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type); |
172 | 179 |
173 /// Returns `true` if closed-world assumptions can be made, that is, | 180 /// Returns `true` if closed-world assumptions can be made, that is, |
174 /// incremental compilation isn't enabled. | 181 /// incremental compilation isn't enabled. |
175 bool get hasClosedWorldAssumption; | 182 bool get hasClosedWorldAssumption; |
176 | 183 |
177 /// Returns a string representation of the closed world. | 184 /// Returns a string representation of the closed world. |
178 /// | 185 /// |
179 /// If [cls] is provided, the dump will contain only classes related to [cls]. | 186 /// If [cls] is provided, the dump will contain only classes related to [cls]. |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 return mixinUsesOf(cls) | 504 return mixinUsesOf(cls) |
498 .any((use) => hasAnySubclassThatImplements(use, type)); | 505 .any((use) => hasAnySubclassThatImplements(use, type)); |
499 } | 506 } |
500 | 507 |
501 /// Returns `true` if any live class that mixes in [mixin] is also a subclass | 508 /// Returns `true` if any live class that mixes in [mixin] is also a subclass |
502 /// of [superclass]. | 509 /// of [superclass]. |
503 bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin) { | 510 bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin) { |
504 return mixinUsesOf(mixin).any((each) => each.isSubclassOf(superclass)); | 511 return mixinUsesOf(mixin).any((each) => each.isSubclassOf(superclass)); |
505 } | 512 } |
506 | 513 |
| 514 /// Returns `true` if [cls] or any superclass mixes in [mixin]. |
| 515 bool isSubclassOfMixinUseOf(ClassElement cls, ClassElement mixin) { |
| 516 if (isUsedAsMixin(mixin)) { |
| 517 ClassElement current = cls.declaration; |
| 518 mixin = mixin.declaration; |
| 519 while (current != null) { |
| 520 current = current.declaration; |
| 521 if (current.isMixinApplication) { |
| 522 MixinApplicationElement application = current; |
| 523 if (application.mixin.declaration == mixin) return true; |
| 524 } |
| 525 current = current.superclass; |
| 526 } |
| 527 } |
| 528 return false; |
| 529 } |
| 530 |
| 531 /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass |
| 532 /// of a mixin application of [y]. |
| 533 bool everySubtypeIsSubclassOfOrMixinUseOf(ClassElement x, ClassElement y) { |
| 534 x = x.declaration; |
| 535 y = y.declaration; |
| 536 Map<ClassElement, bool> secondMap = |
| 537 _subtypeCoveredByCache[x] ??= <ClassElement, bool>{}; |
| 538 return secondMap[y] ??= subtypesOf(x).every((ClassElement cls) => |
| 539 isSubclassOf(cls, y) || isSubclassOfMixinUseOf(cls, y)); |
| 540 } |
| 541 |
507 /// Returns `true` if any subclass of [superclass] implements [type]. | 542 /// Returns `true` if any subclass of [superclass] implements [type]. |
508 bool hasAnySubclassThatImplements( | 543 bool hasAnySubclassThatImplements( |
509 ClassElement superclass, ClassElement type) { | 544 ClassElement superclass, ClassElement type) { |
510 Set<ClassElement> subclasses = typesImplementedBySubclassesOf(superclass); | 545 Set<ClassElement> subclasses = typesImplementedBySubclassesOf(superclass); |
511 if (subclasses == null) return false; | 546 if (subclasses == null) return false; |
512 return subclasses.contains(type); | 547 return subclasses.contains(type); |
513 } | 548 } |
514 | 549 |
515 final Compiler compiler; | 550 final Compiler compiler; |
516 Backend get backend => compiler.backend; | 551 Backend get backend => compiler.backend; |
517 final FunctionSet allFunctions; | 552 final FunctionSet allFunctions; |
518 final Set<Element> functionsCalledInLoop = new Set<Element>(); | 553 final Set<Element> functionsCalledInLoop = new Set<Element>(); |
519 final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>(); | 554 final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>(); |
520 | 555 |
521 final Set<TypedefElement> allTypedefs = new Set<TypedefElement>(); | 556 final Set<TypedefElement> allTypedefs = new Set<TypedefElement>(); |
522 | 557 |
523 final Map<ClassElement, Set<MixinApplicationElement>> _mixinUses = | 558 final Map<ClassElement, Set<MixinApplicationElement>> _mixinUses = |
524 new Map<ClassElement, Set<MixinApplicationElement>>(); | 559 new Map<ClassElement, Set<MixinApplicationElement>>(); |
525 Map<ClassElement, List<MixinApplicationElement>> _liveMixinUses; | 560 Map<ClassElement, List<MixinApplicationElement>> _liveMixinUses; |
526 | 561 |
527 final Map<ClassElement, Set<ClassElement>> _typesImplementedBySubclasses = | 562 final Map<ClassElement, Set<ClassElement>> _typesImplementedBySubclasses = |
528 new Map<ClassElement, Set<ClassElement>>(); | 563 new Map<ClassElement, Set<ClassElement>>(); |
529 | 564 |
530 // We keep track of subtype and subclass relationships in four | 565 // We keep track of subtype and subclass relationships in four |
531 // distinct sets to make class hierarchy analysis faster. | 566 // distinct sets to make class hierarchy analysis faster. |
532 final Map<ClassElement, ClassHierarchyNode> _classHierarchyNodes = | 567 final Map<ClassElement, ClassHierarchyNode> _classHierarchyNodes = |
533 <ClassElement, ClassHierarchyNode>{}; | 568 <ClassElement, ClassHierarchyNode>{}; |
534 final Map<ClassElement, ClassSet> _classSets = <ClassElement, ClassSet>{}; | 569 final Map<ClassElement, ClassSet> _classSets = <ClassElement, ClassSet>{}; |
535 | 570 |
| 571 final Map<ClassElement, Map<ClassElement, bool>> _subtypeCoveredByCache = |
| 572 <ClassElement, Map<ClassElement, bool>>{}; |
| 573 |
536 final Set<Element> sideEffectsFreeElements = new Set<Element>(); | 574 final Set<Element> sideEffectsFreeElements = new Set<Element>(); |
537 | 575 |
538 final Set<Element> elementsThatCannotThrow = new Set<Element>(); | 576 final Set<Element> elementsThatCannotThrow = new Set<Element>(); |
539 | 577 |
540 final Set<Element> functionsThatMightBePassedToApply = | 578 final Set<Element> functionsThatMightBePassedToApply = |
541 new Set<FunctionElement>(); | 579 new Set<FunctionElement>(); |
542 | 580 |
543 final Set<Element> alreadyPopulated; | 581 final Set<Element> alreadyPopulated; |
544 | 582 |
545 bool get isClosed => compiler.phase > Compiler.PHASE_RESOLVING; | 583 bool get isClosed => compiler.phase > Compiler.PHASE_RESOLVING; |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
835 // function expressions's element. | 873 // function expressions's element. |
836 // TODO(herhut): Generate classes for function expressions earlier. | 874 // TODO(herhut): Generate classes for function expressions earlier. |
837 if (element is SynthesizedCallMethodElementX) { | 875 if (element is SynthesizedCallMethodElementX) { |
838 return getMightBePassedToApply(element.expression); | 876 return getMightBePassedToApply(element.expression); |
839 } | 877 } |
840 return functionsThatMightBePassedToApply.contains(element); | 878 return functionsThatMightBePassedToApply.contains(element); |
841 } | 879 } |
842 | 880 |
843 bool get hasClosedWorldAssumption => !compiler.options.hasIncrementalSupport; | 881 bool get hasClosedWorldAssumption => !compiler.options.hasIncrementalSupport; |
844 } | 882 } |
OLD | NEW |