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.enqueue; | 5 library dart2js.enqueue; |
6 | 6 |
7 import 'dart:collection' show Queue; | 7 import 'dart:collection' show Queue; |
8 | 8 |
9 import 'cache_strategy.dart'; | 9 import 'cache_strategy.dart'; |
10 import 'common/backend_api.dart' show Backend; | 10 import 'common/backend_api.dart' show Backend; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 | 49 |
50 EnqueueTask(Compiler compiler) | 50 EnqueueTask(Compiler compiler) |
51 : this.compiler = compiler, | 51 : this.compiler = compiler, |
52 super(compiler.measurer) { | 52 super(compiler.measurer) { |
53 _resolution = new ResolutionEnqueuer( | 53 _resolution = new ResolutionEnqueuer( |
54 this, | 54 this, |
55 compiler.options, | 55 compiler.options, |
56 compiler.resolution, | 56 compiler.resolution, |
57 compiler.enqueuerFilter, | 57 compiler.enqueuerFilter, |
58 compiler.options.analyzeOnly && compiler.options.analyzeMain | 58 compiler.options.analyzeOnly && compiler.options.analyzeMain |
59 ? const EnqueuerStrategy() | 59 ? const DirectEnqueuerStrategy() |
60 : const TreeShakingEnqueuerStrategy(), | 60 : const TreeShakingEnqueuerStrategy(), |
61 compiler.globalDependencies, | 61 compiler.globalDependencies, |
62 compiler.backend, | 62 compiler.backend, |
63 compiler.coreClasses, | 63 compiler.coreClasses, |
64 compiler.cacheStrategy); | 64 compiler.cacheStrategy); |
65 _codegen = compiler.backend.createCodegenEnqueuer(this, compiler); | 65 _codegen = compiler.backend.createCodegenEnqueuer(this, compiler); |
66 } | 66 } |
67 | 67 |
68 ResolutionEnqueuer get resolution => _resolution; | 68 ResolutionEnqueuer get resolution => _resolution; |
69 Enqueuer get codegen => _codegen; | 69 Enqueuer get codegen => _codegen; |
70 | 70 |
71 void forgetElement(Element element) { | 71 void forgetElement(Element element) { |
72 resolution.forgetElement(element, compiler); | 72 resolution.forgetElement(element, compiler); |
73 codegen.forgetElement(element, compiler); | 73 codegen.forgetElement(element, compiler); |
74 } | 74 } |
75 } | 75 } |
76 | 76 |
77 abstract class Enqueuer { | 77 abstract class Enqueuer { |
78 CompilerTask get task; | |
79 WorldBuilder get universe; | 78 WorldBuilder get universe; |
80 native.NativeEnqueuer get nativeEnqueuer; | 79 native.NativeEnqueuer get nativeEnqueuer; |
81 void forgetElement(Element element, Compiler compiler); | 80 void forgetElement(Element element, Compiler compiler); |
82 | 81 |
83 // TODO(johnniwinther): Initialize [_impactStrategy] to `null`. | 82 // TODO(johnniwinther): Initialize [_impactStrategy] to `null`. |
84 ImpactStrategy _impactStrategy = const ImpactStrategy(); | 83 ImpactStrategy _impactStrategy = const ImpactStrategy(); |
85 | 84 |
86 ImpactStrategy get impactStrategy => _impactStrategy; | 85 ImpactStrategy get impactStrategy => _impactStrategy; |
87 | 86 |
88 void open(ImpactStrategy impactStrategy) { | 87 void open(ImpactStrategy impactStrategy) { |
89 _impactStrategy = impactStrategy; | 88 _impactStrategy = impactStrategy; |
90 } | 89 } |
91 | 90 |
92 void close() { | 91 void close() { |
93 // TODO(johnniwinther): Set [_impactStrategy] to `null` and [queueIsClosed] | 92 // TODO(johnniwinther): Set [_impactStrategy] to `null` and [queueIsClosed] |
94 // to `false` here. | 93 // to `false` here. |
95 _impactStrategy = const ImpactStrategy(); | 94 _impactStrategy = const ImpactStrategy(); |
96 } | 95 } |
97 | 96 |
98 void processInstantiatedClassMembers(ClassElement cls); | |
99 void processInstantiatedClassMember(ClassElement cls, Element member); | |
100 void handleUnseenSelectorInternal(DynamicUse dynamicUse); | |
101 void registerStaticUse(StaticUse staticUse); | |
102 void registerStaticUseInternal(StaticUse staticUse); | |
103 void registerDynamicUse(DynamicUse dynamicUse); | |
104 | |
105 /// Returns [:true:] if this enqueuer is the resolution enqueuer. | 97 /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
106 bool get isResolutionQueue; | 98 bool get isResolutionQueue; |
107 | 99 |
108 bool queueIsClosed; | 100 bool queueIsClosed; |
109 | 101 |
110 bool get queueIsEmpty; | 102 bool get queueIsEmpty; |
111 | 103 |
112 ImpactUseCase get impactUse; | 104 ImpactUseCase get impactUse; |
113 | 105 |
114 /** | |
115 * Documentation wanted -- johnniwinther | |
116 * | |
117 * Invariant: [element] must be a declaration element. | |
118 */ | |
119 void addToWorkList(Element element); | |
120 | |
121 void enableIsolateSupport(); | |
122 | |
123 void registerInstantiatedType(InterfaceType type); | |
124 void forEach(void f(WorkItem work)); | 106 void forEach(void f(WorkItem work)); |
125 | 107 |
126 /// Apply the [worldImpact] to this enqueuer. If the [impactSource] is provide
d | 108 /// Apply the [worldImpact] to this enqueuer. If the [impactSource] is |
127 /// the impact strategy will remove it from the element impact cache, if it is | 109 /// provided the impact strategy will remove it from the element impact cache, |
128 /// no longer needed. | 110 /// if it is no longer needed. |
129 void applyImpact(WorldImpact worldImpact, {Element impactSource}); | 111 void applyImpact(WorldImpact worldImpact, {Element impactSource}); |
130 bool checkNoEnqueuedInvokedInstanceMethods(); | 112 bool checkNoEnqueuedInvokedInstanceMethods(); |
131 void logSummary(log(message)); | 113 void logSummary(log(message)); |
132 | 114 |
133 /// Returns [:true:] if [member] has been processed by this enqueuer. | 115 /// Returns [:true:] if [member] has been processed by this enqueuer. |
134 bool isProcessed(Element member); | 116 bool isProcessed(Element member); |
135 | 117 |
136 Iterable<Entity> get processedEntities; | 118 Iterable<Entity> get processedEntities; |
137 | 119 |
138 Iterable<ClassElement> get processedClasses; | 120 Iterable<ClassElement> get processedClasses; |
139 } | 121 } |
140 | 122 |
| 123 abstract class EnqueuerImpl extends Enqueuer { |
| 124 CompilerTask get task; |
| 125 void processInstantiatedClassMembers(ClassElement cls); |
| 126 void processInstantiatedClassMember(ClassElement cls, Element member); |
| 127 void registerStaticUse(StaticUse staticUse); |
| 128 void registerStaticUseInternal(StaticUse staticUse); |
| 129 void registerTypeUse(TypeUse typeUse); |
| 130 void registerTypeUseInternal(TypeUse typeUse); |
| 131 void registerDynamicUse(DynamicUse dynamicUse); |
| 132 void handleUnseenSelectorInternal(DynamicUse dynamicUse); |
| 133 } |
| 134 |
141 /// [Enqueuer] which is specific to resolution. | 135 /// [Enqueuer] which is specific to resolution. |
142 class ResolutionEnqueuer extends Enqueuer { | 136 class ResolutionEnqueuer extends EnqueuerImpl { |
143 final CompilerTask task; | 137 final CompilerTask task; |
144 final String name; | 138 final String name; |
145 final Resolution resolution; | 139 final Resolution resolution; |
146 final QueueFilter filter; | 140 final QueueFilter filter; |
147 final CompilerOptions options; | 141 final CompilerOptions options; |
148 final Backend backend; | 142 final Backend backend; |
149 final GlobalDependencyRegistry globalDependencies; | 143 final GlobalDependencyRegistry globalDependencies; |
150 final CommonElements commonElements; | 144 final CommonElements commonElements; |
151 final native.NativeEnqueuer nativeEnqueuer; | 145 final native.NativeEnqueuer nativeEnqueuer; |
152 | 146 |
(...skipping 22 matching lines...) Expand all Loading... |
175 CacheStrategy cacheStrategy, | 169 CacheStrategy cacheStrategy, |
176 [this.name = 'resolution enqueuer']) | 170 [this.name = 'resolution enqueuer']) |
177 : this.backend = backend, | 171 : this.backend = backend, |
178 this.commonElements = commonElements, | 172 this.commonElements = commonElements, |
179 this.nativeEnqueuer = backend.nativeResolutionEnqueuer(), | 173 this.nativeEnqueuer = backend.nativeResolutionEnqueuer(), |
180 processedElements = new Set<AstElement>(), | 174 processedElements = new Set<AstElement>(), |
181 queue = new Queue<ResolutionWorkItem>(), | 175 queue = new Queue<ResolutionWorkItem>(), |
182 deferredQueue = new Queue<_DeferredAction>(), | 176 deferredQueue = new Queue<_DeferredAction>(), |
183 _universe = new ResolutionWorldBuilderImpl( | 177 _universe = new ResolutionWorldBuilderImpl( |
184 backend, commonElements, cacheStrategy, const TypeMaskStrategy()) { | 178 backend, commonElements, cacheStrategy, const TypeMaskStrategy()) { |
185 impactVisitor = new _EnqueuerImpactVisitor(this); | 179 impactVisitor = new EnqueuerImplImpactVisitor(this); |
186 } | 180 } |
187 | 181 |
188 ResolutionWorldBuilder get universe => _universe; | 182 ResolutionWorldBuilder get universe => _universe; |
189 | 183 |
190 OpenWorld get openWorld => universe.openWorld; | 184 OpenWorld get openWorld => universe.openWorld; |
191 | 185 |
192 bool get queueIsEmpty => queue.isEmpty; | 186 bool get queueIsEmpty => queue.isEmpty; |
193 | 187 |
194 DiagnosticReporter get reporter => resolution.reporter; | 188 DiagnosticReporter get reporter => resolution.reporter; |
195 | 189 |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 // enqueue. | 456 // enqueue. |
463 LocalFunctionElement closure = staticUse.element; | 457 LocalFunctionElement closure = staticUse.element; |
464 if (closure.type.containsTypeVariables) { | 458 if (closure.type.containsTypeVariables) { |
465 universe.closuresWithFreeTypeVariables.add(closure); | 459 universe.closuresWithFreeTypeVariables.add(closure); |
466 } | 460 } |
467 addElement = false; | 461 addElement = false; |
468 break; | 462 break; |
469 case StaticUseKind.SUPER_FIELD_SET: | 463 case StaticUseKind.SUPER_FIELD_SET: |
470 case StaticUseKind.SUPER_TEAR_OFF: | 464 case StaticUseKind.SUPER_TEAR_OFF: |
471 case StaticUseKind.GENERAL: | 465 case StaticUseKind.GENERAL: |
| 466 case StaticUseKind.DIRECT_USE: |
472 break; | 467 break; |
473 case StaticUseKind.CONSTRUCTOR_INVOKE: | 468 case StaticUseKind.CONSTRUCTOR_INVOKE: |
474 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: | 469 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: |
475 _registerInstantiatedType(staticUse.type, | 470 _registerInstantiatedType(staticUse.type, |
476 constructor: staticUse.element, globalDependency: false); | 471 constructor: staticUse.element, globalDependency: false); |
477 break; | 472 break; |
478 case StaticUseKind.REDIRECTION: | 473 case StaticUseKind.REDIRECTION: |
479 _registerInstantiatedType(staticUse.type, | 474 _registerInstantiatedType(staticUse.type, |
480 constructor: staticUse.element, | 475 constructor: staticUse.element, |
481 globalDependency: false, | 476 globalDependency: false, |
482 isRedirection: true); | 477 isRedirection: true); |
483 break; | 478 break; |
484 case StaticUseKind.DIRECT_INVOKE: | 479 case StaticUseKind.DIRECT_INVOKE: |
485 invariant( | 480 invariant( |
486 element, 'Direct static use is not supported for resolution.'); | 481 element, 'Direct static use is not supported for resolution.'); |
487 break; | 482 break; |
488 } | 483 } |
489 if (addElement) { | 484 if (addElement) { |
490 addToWorkList(element); | 485 addToWorkList(element); |
491 } | 486 } |
492 } | 487 } |
493 | 488 |
494 void _registerTypeUse(TypeUse typeUse) { | 489 void registerTypeUse(TypeUse typeUse) { |
| 490 strategy.processTypeUse(this, typeUse); |
| 491 } |
| 492 |
| 493 void registerTypeUseInternal(TypeUse typeUse) { |
495 DartType type = typeUse.type; | 494 DartType type = typeUse.type; |
496 switch (typeUse.kind) { | 495 switch (typeUse.kind) { |
497 case TypeUseKind.INSTANTIATION: | 496 case TypeUseKind.INSTANTIATION: |
498 _registerInstantiatedType(type, globalDependency: false); | 497 _registerInstantiatedType(type, globalDependency: false); |
499 break; | 498 break; |
500 case TypeUseKind.MIRROR_INSTANTIATION: | 499 case TypeUseKind.MIRROR_INSTANTIATION: |
501 _registerInstantiatedType(type, | 500 _registerInstantiatedType(type, |
502 mirrorUsage: true, globalDependency: false); | 501 mirrorUsage: true, globalDependency: false); |
503 break; | 502 break; |
504 case TypeUseKind.NATIVE_INSTANTIATION: | 503 case TypeUseKind.NATIVE_INSTANTIATION: |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
701 _universe.forgetElement(element, compiler); | 700 _universe.forgetElement(element, compiler); |
702 _processedClasses.remove(element); | 701 _processedClasses.remove(element); |
703 instanceMembersByName[element.name]?.remove(element); | 702 instanceMembersByName[element.name]?.remove(element); |
704 instanceFunctionsByName[element.name]?.remove(element); | 703 instanceFunctionsByName[element.name]?.remove(element); |
705 processedElements.remove(element); | 704 processedElements.remove(element); |
706 } | 705 } |
707 } | 706 } |
708 | 707 |
709 /// Parameterizes filtering of which work items are enqueued. | 708 /// Parameterizes filtering of which work items are enqueued. |
710 class QueueFilter { | 709 class QueueFilter { |
711 bool checkNoEnqueuedInvokedInstanceMethods(Enqueuer enqueuer) { | 710 bool checkNoEnqueuedInvokedInstanceMethods(EnqueuerImpl enqueuer) { |
712 enqueuer.task.measure(() { | 711 enqueuer.task.measure(() { |
713 // Run through the classes and see if we need to compile methods. | 712 // Run through the classes and see if we need to compile methods. |
714 for (ClassElement classElement | 713 for (ClassElement classElement |
715 in enqueuer.universe.directlyInstantiatedClasses) { | 714 in enqueuer.universe.directlyInstantiatedClasses) { |
716 for (ClassElement currentClass = classElement; | 715 for (ClassElement currentClass = classElement; |
717 currentClass != null; | 716 currentClass != null; |
718 currentClass = currentClass.superclass) { | 717 currentClass = currentClass.superclass) { |
719 enqueuer.processInstantiatedClassMembers(currentClass); | 718 enqueuer.processInstantiatedClassMembers(currentClass); |
720 } | 719 } |
721 } | 720 } |
(...skipping 11 matching lines...) Expand all Loading... |
733 if (set == null) return; | 732 if (set == null) return; |
734 set.remove(element); | 733 set.remove(element); |
735 } | 734 } |
736 | 735 |
737 /// Strategy used by the enqueuer to populate the world. | 736 /// Strategy used by the enqueuer to populate the world. |
738 // TODO(johnniwinther): Merge this interface with [QueueFilter]. | 737 // TODO(johnniwinther): Merge this interface with [QueueFilter]. |
739 class EnqueuerStrategy { | 738 class EnqueuerStrategy { |
740 const EnqueuerStrategy(); | 739 const EnqueuerStrategy(); |
741 | 740 |
742 /// Process a class instantiated in live code. | 741 /// Process a class instantiated in live code. |
743 void processInstantiatedClass(Enqueuer enqueuer, ClassElement cls) {} | 742 void processInstantiatedClass(EnqueuerImpl enqueuer, ClassElement cls) {} |
744 | 743 |
745 /// Process a static use of and element in live code. | 744 /// Process a static use of and element in live code. |
746 void processStaticUse(Enqueuer enqueuer, StaticUse staticUse) {} | 745 void processStaticUse(EnqueuerImpl enqueuer, StaticUse staticUse) {} |
| 746 |
| 747 /// Process a type use in live code. |
| 748 void processTypeUse(EnqueuerImpl enqueuer, TypeUse typeUse) {} |
747 | 749 |
748 /// Process a dynamic use for a call site in live code. | 750 /// Process a dynamic use for a call site in live code. |
749 void processDynamicUse(Enqueuer enqueuer, DynamicUse dynamicUse) {} | 751 void processDynamicUse(EnqueuerImpl enqueuer, DynamicUse dynamicUse) {} |
750 } | 752 } |
751 | 753 |
| 754 /// Strategy that only enqueues directly used elements. |
| 755 class DirectEnqueuerStrategy extends EnqueuerStrategy { |
| 756 const DirectEnqueuerStrategy(); |
| 757 void processStaticUse(EnqueuerImpl enqueuer, StaticUse staticUse) { |
| 758 if (staticUse.kind == StaticUseKind.DIRECT_USE) { |
| 759 enqueuer.registerStaticUseInternal(staticUse); |
| 760 } |
| 761 } |
| 762 } |
| 763 |
| 764 /// Strategy used for tree-shaking. |
752 class TreeShakingEnqueuerStrategy implements EnqueuerStrategy { | 765 class TreeShakingEnqueuerStrategy implements EnqueuerStrategy { |
753 const TreeShakingEnqueuerStrategy(); | 766 const TreeShakingEnqueuerStrategy(); |
754 | 767 |
755 @override | 768 @override |
756 void processInstantiatedClass(Enqueuer enqueuer, ClassElement cls) { | 769 void processInstantiatedClass(EnqueuerImpl enqueuer, ClassElement cls) { |
757 cls.implementation.forEachMember(enqueuer.processInstantiatedClassMember); | 770 cls.implementation.forEachMember(enqueuer.processInstantiatedClassMember); |
758 } | 771 } |
759 | 772 |
760 @override | 773 @override |
761 void processStaticUse(Enqueuer enqueuer, StaticUse staticUse) { | 774 void processStaticUse(EnqueuerImpl enqueuer, StaticUse staticUse) { |
762 enqueuer.registerStaticUseInternal(staticUse); | 775 enqueuer.registerStaticUseInternal(staticUse); |
763 } | 776 } |
764 | 777 |
765 @override | 778 @override |
766 void processDynamicUse(Enqueuer enqueuer, DynamicUse dynamicUse) { | 779 void processTypeUse(EnqueuerImpl enqueuer, TypeUse typeUse) { |
| 780 enqueuer.registerTypeUseInternal(typeUse); |
| 781 } |
| 782 |
| 783 @override |
| 784 void processDynamicUse(EnqueuerImpl enqueuer, DynamicUse dynamicUse) { |
767 enqueuer.handleUnseenSelectorInternal(dynamicUse); | 785 enqueuer.handleUnseenSelectorInternal(dynamicUse); |
768 } | 786 } |
769 } | 787 } |
770 | 788 |
771 class _EnqueuerImpactVisitor implements WorldImpactVisitor { | 789 class EnqueuerImplImpactVisitor implements WorldImpactVisitor { |
772 final ResolutionEnqueuer enqueuer; | 790 final EnqueuerImpl enqueuer; |
773 | 791 |
774 _EnqueuerImpactVisitor(this.enqueuer); | 792 EnqueuerImplImpactVisitor(this.enqueuer); |
775 | 793 |
776 @override | 794 @override |
777 void visitDynamicUse(DynamicUse dynamicUse) { | 795 void visitDynamicUse(DynamicUse dynamicUse) { |
778 enqueuer.registerDynamicUse(dynamicUse); | 796 enqueuer.registerDynamicUse(dynamicUse); |
779 } | 797 } |
780 | 798 |
781 @override | 799 @override |
782 void visitStaticUse(StaticUse staticUse) { | 800 void visitStaticUse(StaticUse staticUse) { |
783 enqueuer.registerStaticUse(staticUse); | 801 enqueuer.registerStaticUse(staticUse); |
784 } | 802 } |
785 | 803 |
786 @override | 804 @override |
787 void visitTypeUse(TypeUse typeUse) { | 805 void visitTypeUse(TypeUse typeUse) { |
788 enqueuer._registerTypeUse(typeUse); | 806 enqueuer.registerTypeUse(typeUse); |
789 } | 807 } |
790 } | 808 } |
791 | 809 |
792 typedef void _DeferredActionFunction(); | 810 typedef void _DeferredActionFunction(); |
793 | 811 |
794 class _DeferredAction { | 812 class _DeferredAction { |
795 final Element element; | 813 final Element element; |
796 final _DeferredActionFunction action; | 814 final _DeferredActionFunction action; |
797 | 815 |
798 _DeferredAction(this.element, this.action); | 816 _DeferredAction(this.element, this.action); |
799 } | 817 } |
OLD | NEW |