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 'common/resolution.dart' show Resolution; | 9 import 'common/resolution.dart' show Resolution; |
10 import 'common/tasks.dart' show CompilerTask; | 10 import 'common/tasks.dart' show CompilerTask; |
11 import 'common/work.dart' show WorkItem; | 11 import 'common/work.dart' show WorkItem; |
12 import 'common.dart'; | 12 import 'common.dart'; |
13 import 'compiler.dart' show Compiler; | 13 import 'compiler.dart' show Compiler; |
14 import 'options.dart'; | 14 import 'options.dart'; |
15 import 'elements/elements.dart' | 15 import 'elements/elements.dart' |
16 show AnalyzableElement, ClassElement, MemberElement; | 16 show AnalyzableElement, ClassElement, MemberElement; |
17 import 'elements/entities.dart'; | 17 import 'elements/entities.dart'; |
18 import 'elements/resolution_types.dart' show ResolutionTypedefType; | 18 import 'elements/resolution_types.dart' show ResolutionTypedefType; |
19 import 'elements/types.dart'; | 19 import 'elements/types.dart'; |
20 import 'native/native.dart' as native; | |
21 import 'universe/world_builder.dart'; | 20 import 'universe/world_builder.dart'; |
22 import 'universe/use.dart' | 21 import 'universe/use.dart' |
23 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; | 22 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; |
24 import 'universe/world_impact.dart' | 23 import 'universe/world_impact.dart' |
25 show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor; | 24 show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor; |
26 import 'util/enumset.dart'; | 25 import 'util/enumset.dart'; |
27 import 'util/util.dart' show Setlet; | 26 import 'util/util.dart' show Setlet; |
28 | 27 |
29 class EnqueueTask extends CompilerTask { | 28 class EnqueueTask extends CompilerTask { |
30 ResolutionEnqueuer _resolution; | 29 ResolutionEnqueuer _resolution; |
31 Enqueuer _codegen; | 30 Enqueuer _codegen; |
32 final Compiler compiler; | 31 final Compiler compiler; |
33 | 32 |
34 String get name => 'Enqueue'; | 33 String get name => 'Enqueue'; |
35 | 34 |
36 EnqueueTask(Compiler compiler) | 35 EnqueueTask(Compiler compiler) |
37 : this.compiler = compiler, | 36 : this.compiler = compiler, |
38 super(compiler.measurer) { | 37 super(compiler.measurer) { |
39 _resolution = new ResolutionEnqueuer( | 38 _resolution = new ResolutionEnqueuer( |
40 this, | 39 this, |
41 compiler.options, | 40 compiler.options, |
42 compiler.reporter, | 41 compiler.reporter, |
43 compiler.options.analyzeOnly && compiler.options.analyzeMain | 42 compiler.options.analyzeOnly && compiler.options.analyzeMain |
44 ? const DirectEnqueuerStrategy() | 43 ? const DirectEnqueuerStrategy() |
45 : const TreeShakingEnqueuerStrategy(), | 44 : const TreeShakingEnqueuerStrategy(), |
46 compiler.backend.resolutionEnqueuerListener, | 45 compiler.backend.resolutionEnqueuerListener, |
47 compiler.backend.nativeResolutionEnqueuer(), | |
48 new ElementResolutionWorldBuilder( | 46 new ElementResolutionWorldBuilder( |
49 compiler.backend, compiler.resolution, const OpenWorldStrategy()), | 47 compiler.backend, compiler.resolution, const OpenWorldStrategy()), |
50 new ResolutionWorkItemBuilder(compiler.resolution)); | 48 new ResolutionWorkItemBuilder(compiler.resolution)); |
51 _codegen = compiler.backend.createCodegenEnqueuer(this, compiler); | 49 _codegen = compiler.backend.createCodegenEnqueuer(this, compiler); |
52 } | 50 } |
53 | 51 |
54 ResolutionEnqueuer get resolution => _resolution; | 52 ResolutionEnqueuer get resolution => _resolution; |
55 Enqueuer get codegen => _codegen; | 53 Enqueuer get codegen => _codegen; |
56 } | 54 } |
57 | 55 |
58 abstract class Enqueuer { | 56 abstract class Enqueuer { |
59 WorldBuilder get worldBuilder; | 57 WorldBuilder get worldBuilder; |
60 native.NativeEnqueuer get nativeEnqueuer; | |
61 ImpactStrategy get impactStrategy; | 58 ImpactStrategy get impactStrategy; |
62 | 59 |
63 void open(ImpactStrategy impactStrategy, FunctionEntity mainMethod, | 60 void open(ImpactStrategy impactStrategy, FunctionEntity mainMethod, |
64 Iterable<LibraryEntity> libraries); | 61 Iterable<LibraryEntity> libraries); |
65 void close(); | 62 void close(); |
66 | 63 |
67 /// Returns [:true:] if this enqueuer is the resolution enqueuer. | 64 /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
68 bool get isResolutionQueue; | 65 bool get isResolutionQueue; |
69 | 66 |
70 bool queueIsClosed; | 67 bool queueIsClosed; |
71 | 68 |
72 bool get queueIsEmpty; | 69 bool get queueIsEmpty; |
73 | 70 |
74 ImpactUseCase get impactUse; | 71 ImpactUseCase get impactUse; |
75 | 72 |
76 void forEach(void f(WorkItem work)); | 73 void forEach(void f(WorkItem work)); |
77 | 74 |
78 /// Apply the [worldImpact] to this enqueuer. If the [impactSource] is | 75 /// Apply the [worldImpact] to this enqueuer. If the [impactSource] is |
79 /// provided the impact strategy will remove it from the element impact cache, | 76 /// provided the impact strategy will remove it from the element impact cache, |
80 /// if it is no longer needed. | 77 /// if it is no longer needed. |
81 void applyImpact(WorldImpact worldImpact, {var impactSource}); | 78 void applyImpact(WorldImpact worldImpact, {var impactSource}); |
82 bool checkNoEnqueuedInvokedInstanceMethods(); | 79 bool checkNoEnqueuedInvokedInstanceMethods(); |
83 | 80 |
84 /// Check the enqueuer queue is empty or fail otherwise. | 81 /// Check the enqueuer queue is empty or fail otherwise. |
85 void checkQueueIsEmpty(); | 82 void checkQueueIsEmpty(); |
86 void logSummary(log(message)); | 83 void logSummary(void log(String message)); |
87 | 84 |
88 Iterable<Entity> get processedEntities; | 85 Iterable<Entity> get processedEntities; |
89 | 86 |
90 Iterable<ClassEntity> get processedClasses; | 87 Iterable<ClassEntity> get processedClasses; |
91 } | 88 } |
92 | 89 |
93 abstract class EnqueuerListener { | 90 abstract class EnqueuerListener { |
94 /// Called to instruct to the backend that [type] has been instantiated. | 91 /// Called to instruct to the backend that [type] has been instantiated. |
95 void registerInstantiatedType(InterfaceType type, {bool isGlobal}); | 92 void registerInstantiatedType(InterfaceType type, |
93 {bool isGlobal: false, bool nativeUsage: false}); | |
96 | 94 |
97 /// Called to notify to the backend that a class is being instantiated. Any | 95 /// Called to notify to the backend that a class is being instantiated. Any |
98 /// backend specific [WorldImpact] of this is returned. | 96 /// backend specific [WorldImpact] of this is returned. |
99 WorldImpact registerInstantiatedClass(ClassEntity cls); | 97 WorldImpact registerInstantiatedClass(ClassEntity cls); |
100 | 98 |
101 /// Called to notify to the backend that a class is implemented by an | 99 /// Called to notify to the backend that a class is implemented by an |
102 /// instantiated class. Any backend specific [WorldImpact] of this is | 100 /// instantiated class. Any backend specific [WorldImpact] of this is |
103 /// returned. | 101 /// returned. |
104 WorldImpact registerImplementedClass(ClassEntity cls); | 102 WorldImpact registerImplementedClass(ClassEntity cls); |
105 | 103 |
(...skipping 22 matching lines...) Expand all Loading... | |
128 /// A return value of `true` indicates that [recentClasses] has been | 126 /// A return value of `true` indicates that [recentClasses] has been |
129 /// processed and its elements do not need to be seen in the next round. When | 127 /// processed and its elements do not need to be seen in the next round. When |
130 /// `false` is returned, [onQueueEmpty] will be called again once the | 128 /// `false` is returned, [onQueueEmpty] will be called again once the |
131 /// resolution queue has drained and [recentClasses] will be a superset of the | 129 /// resolution queue has drained and [recentClasses] will be a superset of the |
132 /// current value. | 130 /// current value. |
133 /// | 131 /// |
134 /// There is no guarantee that a class is only present once in | 132 /// There is no guarantee that a class is only present once in |
135 /// [recentClasses], but every class seen by the [enqueuer] will be present in | 133 /// [recentClasses], but every class seen by the [enqueuer] will be present in |
136 /// [recentClasses] at least once. | 134 /// [recentClasses] at least once. |
137 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses); | 135 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses); |
136 | |
137 /// Called when to the queue is emptied. | |
Siggi Cherem (dart-lang)
2017/03/14 03:10:50
mmm... "when to the"?
Johnni Winther
2017/03/15 09:02:58
Good English not?
| |
138 void logSummary(void log(String message)); | |
138 } | 139 } |
139 | 140 |
140 abstract class EnqueuerImpl extends Enqueuer { | 141 abstract class EnqueuerImpl extends Enqueuer { |
141 CompilerTask get task; | 142 CompilerTask get task; |
142 EnqueuerStrategy get strategy; | 143 EnqueuerStrategy get strategy; |
143 void checkClass(ClassEntity cls); | 144 void checkClass(ClassEntity cls); |
144 void processStaticUse(StaticUse staticUse); | 145 void processStaticUse(StaticUse staticUse); |
145 void processTypeUse(TypeUse typeUse); | 146 void processTypeUse(TypeUse typeUse); |
146 void processDynamicUse(DynamicUse dynamicUse); | 147 void processDynamicUse(DynamicUse dynamicUse); |
147 EnqueuerListener get listener; | 148 EnqueuerListener get listener; |
(...skipping 18 matching lines...) Expand all Loading... | |
166 | 167 |
167 /// [Enqueuer] which is specific to resolution. | 168 /// [Enqueuer] which is specific to resolution. |
168 class ResolutionEnqueuer extends EnqueuerImpl { | 169 class ResolutionEnqueuer extends EnqueuerImpl { |
169 static const ImpactUseCase IMPACT_USE = | 170 static const ImpactUseCase IMPACT_USE = |
170 const ImpactUseCase('ResolutionEnqueuer'); | 171 const ImpactUseCase('ResolutionEnqueuer'); |
171 | 172 |
172 final CompilerTask task; | 173 final CompilerTask task; |
173 final String name; | 174 final String name; |
174 final CompilerOptions _options; | 175 final CompilerOptions _options; |
175 final EnqueuerListener listener; | 176 final EnqueuerListener listener; |
176 final native.NativeEnqueuer nativeEnqueuer; | |
177 | 177 |
178 final EnqueuerStrategy strategy; | 178 final EnqueuerStrategy strategy; |
179 final Set<ClassEntity> _recentClasses = new Setlet<ClassEntity>(); | 179 final Set<ClassEntity> _recentClasses = new Setlet<ClassEntity>(); |
180 final ResolutionEnqueuerWorldBuilder _worldBuilder; | 180 final ResolutionEnqueuerWorldBuilder _worldBuilder; |
181 final WorkItemBuilder _workItemBuilder; | 181 final WorkItemBuilder _workItemBuilder; |
182 final DiagnosticReporter _reporter; | 182 final DiagnosticReporter _reporter; |
183 | 183 |
184 bool queueIsClosed = false; | 184 bool queueIsClosed = false; |
185 | 185 |
186 WorldImpactVisitor _impactVisitor; | 186 WorldImpactVisitor _impactVisitor; |
187 | 187 |
188 /// All declaration elements that have been processed by the resolver. | 188 /// All declaration elements that have been processed by the resolver. |
189 final Set<Entity> _processedEntities = new Set<Entity>(); | 189 final Set<Entity> _processedEntities = new Set<Entity>(); |
190 | 190 |
191 final Queue<WorkItem> _queue = new Queue<WorkItem>(); | 191 final Queue<WorkItem> _queue = new Queue<WorkItem>(); |
192 | 192 |
193 /// Queue of deferred resolution actions to execute when the resolution queue | 193 /// Queue of deferred resolution actions to execute when the resolution queue |
194 /// has been emptied. | 194 /// has been emptied. |
195 final Queue<_DeferredAction> _deferredQueue = new Queue<_DeferredAction>(); | 195 final Queue<_DeferredAction> _deferredQueue = new Queue<_DeferredAction>(); |
196 | 196 |
197 ResolutionEnqueuer( | 197 ResolutionEnqueuer(this.task, this._options, this._reporter, this.strategy, |
198 this.task, | 198 this.listener, this._worldBuilder, this._workItemBuilder, |
199 this._options, | |
200 this._reporter, | |
201 this.strategy, | |
202 this.listener, | |
203 this.nativeEnqueuer, | |
204 this._worldBuilder, | |
205 this._workItemBuilder, | |
206 [this.name = 'resolution enqueuer']) { | 199 [this.name = 'resolution enqueuer']) { |
207 _impactVisitor = new EnqueuerImplImpactVisitor(this); | 200 _impactVisitor = new EnqueuerImplImpactVisitor(this); |
208 } | 201 } |
209 | 202 |
210 ResolutionWorldBuilder get worldBuilder => _worldBuilder; | 203 ResolutionWorldBuilder get worldBuilder => _worldBuilder; |
211 | 204 |
212 bool get queueIsEmpty => _queue.isEmpty; | 205 bool get queueIsEmpty => _queue.isEmpty; |
213 | 206 |
214 @override | 207 @override |
215 void checkQueueIsEmpty() { | 208 void checkQueueIsEmpty() { |
(...skipping 15 matching lines...) Expand all Loading... | |
231 {ConstructorEntity constructor, | 224 {ConstructorEntity constructor, |
232 bool mirrorUsage: false, | 225 bool mirrorUsage: false, |
233 bool nativeUsage: false, | 226 bool nativeUsage: false, |
234 bool globalDependency: false, | 227 bool globalDependency: false, |
235 bool isRedirection: false}) { | 228 bool isRedirection: false}) { |
236 task.measure(() { | 229 task.measure(() { |
237 _worldBuilder.registerTypeInstantiation(type, _applyClassUse, | 230 _worldBuilder.registerTypeInstantiation(type, _applyClassUse, |
238 constructor: constructor, | 231 constructor: constructor, |
239 byMirrors: mirrorUsage, | 232 byMirrors: mirrorUsage, |
240 isRedirection: isRedirection); | 233 isRedirection: isRedirection); |
241 if (nativeUsage) { | |
242 nativeEnqueuer.onInstantiatedType(type); | |
243 } | |
244 listener.registerInstantiatedType(type, | 234 listener.registerInstantiatedType(type, |
245 isGlobal: globalDependency && !mirrorUsage); | 235 isGlobal: globalDependency && !mirrorUsage, nativeUsage: nativeUsage); |
246 }); | 236 }); |
247 } | 237 } |
248 | 238 |
249 bool checkNoEnqueuedInvokedInstanceMethods() { | 239 bool checkNoEnqueuedInvokedInstanceMethods() { |
250 return strategy.checkEnqueuerConsistency(this); | 240 return strategy.checkEnqueuerConsistency(this); |
251 } | 241 } |
252 | 242 |
253 void checkClass(ClassEntity cls) { | 243 void checkClass(ClassEntity cls) { |
254 _worldBuilder.processClassMembers(cls, | 244 _worldBuilder.processClassMembers(cls, |
255 (MemberEntity member, EnumSet<MemberUse> useSet) { | 245 (MemberEntity member, EnumSet<MemberUse> useSet) { |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
369 } | 359 } |
370 } | 360 } |
371 List recents = _recentClasses.toList(growable: false); | 361 List recents = _recentClasses.toList(growable: false); |
372 _recentClasses.clear(); | 362 _recentClasses.clear(); |
373 if (!_onQueueEmpty(recents)) { | 363 if (!_onQueueEmpty(recents)) { |
374 _recentClasses.addAll(recents); | 364 _recentClasses.addAll(recents); |
375 } | 365 } |
376 } while (_queue.isNotEmpty || _recentClasses.isNotEmpty); | 366 } while (_queue.isNotEmpty || _recentClasses.isNotEmpty); |
377 } | 367 } |
378 | 368 |
379 void logSummary(log(message)) { | 369 void logSummary(void log(String message)) { |
380 log('Resolved ${_processedEntities.length} elements.'); | 370 log('Resolved ${_processedEntities.length} elements.'); |
381 nativeEnqueuer.logSummary(log); | 371 listener.logSummary(log); |
382 } | 372 } |
383 | 373 |
384 String toString() => 'Enqueuer($name)'; | 374 String toString() => 'Enqueuer($name)'; |
385 | 375 |
386 Iterable<Entity> get processedEntities => _processedEntities; | 376 Iterable<Entity> get processedEntities => _processedEntities; |
387 | 377 |
388 ImpactUseCase get impactUse => IMPACT_USE; | 378 ImpactUseCase get impactUse => IMPACT_USE; |
389 | 379 |
390 bool get isResolutionQueue => true; | 380 bool get isResolutionQueue => true; |
391 | 381 |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
570 @override | 560 @override |
571 WorkItem createWorkItem(MemberElement element) { | 561 WorkItem createWorkItem(MemberElement element) { |
572 assert(invariant(element, element.isDeclaration)); | 562 assert(invariant(element, element.isDeclaration)); |
573 if (element.isMalformed) return null; | 563 if (element.isMalformed) return null; |
574 | 564 |
575 assert(invariant(element, element is AnalyzableElement, | 565 assert(invariant(element, element is AnalyzableElement, |
576 message: 'Element $element is not analyzable.')); | 566 message: 'Element $element is not analyzable.')); |
577 return _resolution.createWorkItem(element); | 567 return _resolution.createWorkItem(element); |
578 } | 568 } |
579 } | 569 } |
OLD | NEW |