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

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

Issue 2716713003: Move main and isolate handling to enqueuer listeners. (Closed)
Patch Set: Created 3 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
« no previous file with comments | « pkg/compiler/lib/src/compiler.dart ('k') | pkg/compiler/lib/src/js_backend/backend.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.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;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 _codegen = compiler.backend.createCodegenEnqueuer(this, compiler); 57 _codegen = compiler.backend.createCodegenEnqueuer(this, compiler);
58 } 58 }
59 59
60 ResolutionEnqueuer get resolution => _resolution; 60 ResolutionEnqueuer get resolution => _resolution;
61 Enqueuer get codegen => _codegen; 61 Enqueuer get codegen => _codegen;
62 } 62 }
63 63
64 abstract class Enqueuer { 64 abstract class Enqueuer {
65 WorldBuilder get worldBuilder; 65 WorldBuilder get worldBuilder;
66 native.NativeEnqueuer get nativeEnqueuer; 66 native.NativeEnqueuer get nativeEnqueuer;
67 ImpactStrategy get impactStrategy;
67 68
68 // TODO(johnniwinther): Initialize [_impactStrategy] to `null`. 69 void open(ImpactStrategy impactStrategy, FunctionEntity mainMethod,
69 ImpactStrategy _impactStrategy = const ImpactStrategy(); 70 Iterable<LibraryEntity> libraries);
70 71 void close();
71 ImpactStrategy get impactStrategy => _impactStrategy;
72
73 void open(ImpactStrategy impactStrategy) {
74 _impactStrategy = impactStrategy;
75 }
76
77 void close() {
78 // TODO(johnniwinther): Set [_impactStrategy] to `null` and [queueIsClosed]
79 // to `true` here.
80 _impactStrategy = const ImpactStrategy();
81 }
82 72
83 /// Returns [:true:] if this enqueuer is the resolution enqueuer. 73 /// Returns [:true:] if this enqueuer is the resolution enqueuer.
84 bool get isResolutionQueue; 74 bool get isResolutionQueue;
85 75
86 bool queueIsClosed; 76 bool queueIsClosed;
87 77
88 bool get queueIsEmpty; 78 bool get queueIsEmpty;
89 79
90 ImpactUseCase get impactUse; 80 ImpactUseCase get impactUse;
91 81
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 WorldImpact registerClosureWithFreeTypeVariables(MemberEntity member); 119 WorldImpact registerClosureWithFreeTypeVariables(MemberEntity member);
130 120
131 /// Called to register that a member has been closurized. Any backend specific 121 /// Called to register that a member has been closurized. Any backend specific
132 /// [WorldImpact] of this is returned. 122 /// [WorldImpact] of this is returned.
133 WorldImpact registerBoundClosure(); 123 WorldImpact registerBoundClosure();
134 124
135 /// Called to register that [element] is statically known to be used. Any 125 /// Called to register that [element] is statically known to be used. Any
136 /// backend specific [WorldImpact] of this is returned. 126 /// backend specific [WorldImpact] of this is returned.
137 WorldImpact registerUsedElement(MemberEntity member); 127 WorldImpact registerUsedElement(MemberEntity member);
138 128
129 void onQueueOpen(Enqueuer enqueuer, FunctionEntity mainMethod,
130 Iterable<LibraryEntity> libraries);
131
139 /// Called when [enqueuer]'s queue is empty, but before it is closed. 132 /// Called when [enqueuer]'s queue is empty, but before it is closed.
140 /// 133 ///
141 /// This is used, for example, by the JS backend to enqueue additional 134 /// This is used, for example, by the JS backend to enqueue additional
142 /// elements needed for reflection. [recentClasses] is a collection of 135 /// elements needed for reflection. [recentClasses] is a collection of
143 /// all classes seen for the first time by the [enqueuer] since the last call 136 /// all classes seen for the first time by the [enqueuer] since the last call
144 /// to [onQueueEmpty]. 137 /// to [onQueueEmpty].
145 /// 138 ///
146 /// A return value of `true` indicates that [recentClasses] has been 139 /// A return value of `true` indicates that [recentClasses] has been
147 /// processed and its elements do not need to be seen in the next round. When 140 /// processed and its elements do not need to be seen in the next round. When
148 /// `false` is returned, [onQueueEmpty] will be called again once the 141 /// `false` is returned, [onQueueEmpty] will be called again once the
149 /// resolution queue has drained and [recentClasses] will be a superset of the 142 /// resolution queue has drained and [recentClasses] will be a superset of the
150 /// current value. 143 /// current value.
151 /// 144 ///
152 /// There is no guarantee that a class is only present once in 145 /// There is no guarantee that a class is only present once in
153 /// [recentClasses], but every class seen by the [enqueuer] will be present in 146 /// [recentClasses], but every class seen by the [enqueuer] will be present in
154 /// [recentClasses] at least once. 147 /// [recentClasses] at least once.
155 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses); 148 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses);
156 } 149 }
157 150
158 abstract class EnqueuerImpl extends Enqueuer { 151 abstract class EnqueuerImpl extends Enqueuer {
159 CompilerTask get task; 152 CompilerTask get task;
160 EnqueuerStrategy get strategy; 153 EnqueuerStrategy get strategy;
161 void checkClass(ClassEntity cls); 154 void checkClass(ClassEntity cls);
162 void processStaticUse(StaticUse staticUse); 155 void processStaticUse(StaticUse staticUse);
163 void processTypeUse(TypeUse typeUse); 156 void processTypeUse(TypeUse typeUse);
164 void processDynamicUse(DynamicUse dynamicUse); 157 void processDynamicUse(DynamicUse dynamicUse);
158 EnqueuerListener get listener;
159
160 // TODO(johnniwinther): Initialize [_impactStrategy] to `null`.
161 ImpactStrategy _impactStrategy = const ImpactStrategy();
162
163 ImpactStrategy get impactStrategy => _impactStrategy;
164
165 void open(ImpactStrategy impactStrategy, FunctionEntity mainMethod,
166 Iterable<LibraryEntity> libraries) {
167 _impactStrategy = impactStrategy;
168 listener.onQueueOpen(this, mainMethod, libraries);
169 }
170
171 void close() {
172 // TODO(johnniwinther): Set [_impactStrategy] to `null` and [queueIsClosed]
173 // to `true` here.
174 _impactStrategy = const ImpactStrategy();
175 }
165 } 176 }
166 177
167 /// [Enqueuer] which is specific to resolution. 178 /// [Enqueuer] which is specific to resolution.
168 class ResolutionEnqueuer extends EnqueuerImpl { 179 class ResolutionEnqueuer extends EnqueuerImpl {
169 static const ImpactUseCase IMPACT_USE = 180 static const ImpactUseCase IMPACT_USE =
170 const ImpactUseCase('ResolutionEnqueuer'); 181 const ImpactUseCase('ResolutionEnqueuer');
171 182
172 final CompilerTask task; 183 final CompilerTask task;
173 final String name; 184 final String name;
174 final CompilerOptions _options; 185 final CompilerOptions _options;
175 final EnqueuerListener _listener; 186 final EnqueuerListener listener;
176 final native.NativeEnqueuer nativeEnqueuer; 187 final native.NativeEnqueuer nativeEnqueuer;
177 188
178 final EnqueuerStrategy strategy; 189 final EnqueuerStrategy strategy;
179 final Set<ClassEntity> _recentClasses = new Setlet<ClassEntity>(); 190 final Set<ClassEntity> _recentClasses = new Setlet<ClassEntity>();
180 final ResolutionWorldBuilderImpl _universe; 191 final ResolutionWorldBuilderImpl _universe;
181 final WorkItemBuilder _workItemBuilder; 192 final WorkItemBuilder _workItemBuilder;
182 final DiagnosticReporter _reporter; 193 final DiagnosticReporter _reporter;
183 194
184 bool queueIsClosed = false; 195 bool queueIsClosed = false;
185 196
186 WorldImpactVisitor _impactVisitor; 197 WorldImpactVisitor _impactVisitor;
187 198
188 /// All declaration elements that have been processed by the resolver. 199 /// All declaration elements that have been processed by the resolver.
189 final Set<Entity> _processedEntities = new Set<Entity>(); 200 final Set<Entity> _processedEntities = new Set<Entity>();
190 201
191 final Queue<WorkItem> _queue = new Queue<WorkItem>(); 202 final Queue<WorkItem> _queue = new Queue<WorkItem>();
192 203
193 /// Queue of deferred resolution actions to execute when the resolution queue 204 /// Queue of deferred resolution actions to execute when the resolution queue
194 /// has been emptied. 205 /// has been emptied.
195 final Queue<_DeferredAction> _deferredQueue = new Queue<_DeferredAction>(); 206 final Queue<_DeferredAction> _deferredQueue = new Queue<_DeferredAction>();
196 207
197 ResolutionEnqueuer( 208 ResolutionEnqueuer(this.task, this._options, this._reporter, this.strategy,
198 this.task, 209 this.listener, this.nativeEnqueuer, this._universe, this._workItemBuilder,
199 this._options,
200 this._reporter,
201 this.strategy,
202 this._listener,
203 this.nativeEnqueuer,
204 this._universe,
205 this._workItemBuilder,
206 [this.name = 'resolution enqueuer']) { 210 [this.name = 'resolution enqueuer']) {
207 _impactVisitor = new EnqueuerImplImpactVisitor(this); 211 _impactVisitor = new EnqueuerImplImpactVisitor(this);
208 } 212 }
209 213
210 ResolutionWorldBuilder get worldBuilder => _universe; 214 ResolutionWorldBuilder get worldBuilder => _universe;
211 215
212 bool get queueIsEmpty => _queue.isEmpty; 216 bool get queueIsEmpty => _queue.isEmpty;
213 217
214 @override 218 @override
215 void checkQueueIsEmpty() { 219 void checkQueueIsEmpty() {
(...skipping 18 matching lines...) Expand all
234 bool globalDependency: false, 238 bool globalDependency: false,
235 bool isRedirection: false}) { 239 bool isRedirection: false}) {
236 task.measure(() { 240 task.measure(() {
237 _universe.registerTypeInstantiation(type, _applyClassUse, 241 _universe.registerTypeInstantiation(type, _applyClassUse,
238 constructor: constructor, 242 constructor: constructor,
239 byMirrors: mirrorUsage, 243 byMirrors: mirrorUsage,
240 isRedirection: isRedirection); 244 isRedirection: isRedirection);
241 if (nativeUsage) { 245 if (nativeUsage) {
242 nativeEnqueuer.onInstantiatedType(type); 246 nativeEnqueuer.onInstantiatedType(type);
243 } 247 }
244 _listener.registerInstantiatedType(type, 248 listener.registerInstantiatedType(type,
245 isGlobal: globalDependency && !mirrorUsage); 249 isGlobal: globalDependency && !mirrorUsage);
246 }); 250 });
247 } 251 }
248 252
249 bool checkNoEnqueuedInvokedInstanceMethods() { 253 bool checkNoEnqueuedInvokedInstanceMethods() {
250 return strategy.checkEnqueuerConsistency(this); 254 return strategy.checkEnqueuerConsistency(this);
251 } 255 }
252 256
253 void checkClass(ClassEntity cls) { 257 void checkClass(ClassEntity cls) {
254 _universe.processClassMembers(cls, 258 _universe.processClassMembers(cls,
255 (MemberEntity member, EnumSet<MemberUse> useSet) { 259 (MemberEntity member, EnumSet<MemberUse> useSet) {
256 if (useSet.isNotEmpty) { 260 if (useSet.isNotEmpty) {
257 _reporter.internalError(member, 261 _reporter.internalError(member,
258 'Unenqueued use of $member: ${useSet.iterable(MemberUse.values)}'); 262 'Unenqueued use of $member: ${useSet.iterable(MemberUse.values)}');
259 } 263 }
260 }); 264 });
261 } 265 }
262 266
263 /// Callback for applying the use of a [member]. 267 /// Callback for applying the use of a [member].
264 void _applyMemberUse(Entity member, EnumSet<MemberUse> useSet) { 268 void _applyMemberUse(Entity member, EnumSet<MemberUse> useSet) {
265 if (useSet.contains(MemberUse.NORMAL)) { 269 if (useSet.contains(MemberUse.NORMAL)) {
266 _addToWorkList(member); 270 _addToWorkList(member);
267 } 271 }
268 if (useSet.contains(MemberUse.CLOSURIZE_INSTANCE)) { 272 if (useSet.contains(MemberUse.CLOSURIZE_INSTANCE)) {
269 _registerClosurizedMember(member); 273 _registerClosurizedMember(member);
270 } 274 }
271 if (useSet.contains(MemberUse.CLOSURIZE_STATIC)) { 275 if (useSet.contains(MemberUse.CLOSURIZE_STATIC)) {
272 applyImpact(_listener.registerGetOfStaticFunction()); 276 applyImpact(listener.registerGetOfStaticFunction());
273 } 277 }
274 } 278 }
275 279
276 /// Callback for applying the use of a [cls]. 280 /// Callback for applying the use of a [cls].
277 void _applyClassUse(ClassEntity cls, EnumSet<ClassUse> useSet) { 281 void _applyClassUse(ClassEntity cls, EnumSet<ClassUse> useSet) {
278 if (useSet.contains(ClassUse.INSTANTIATED)) { 282 if (useSet.contains(ClassUse.INSTANTIATED)) {
279 _recentClasses.add(cls); 283 _recentClasses.add(cls);
280 _universe.processClassMembers(cls, _applyMemberUse); 284 _universe.processClassMembers(cls, _applyMemberUse);
281 // We only tell the backend once that [cls] was instantiated, so 285 // We only tell the backend once that [cls] was instantiated, so
282 // any additional dependencies must be treated as global 286 // any additional dependencies must be treated as global
283 // dependencies. 287 // dependencies.
284 applyImpact(_listener.registerInstantiatedClass(cls)); 288 applyImpact(listener.registerInstantiatedClass(cls));
285 } 289 }
286 if (useSet.contains(ClassUse.IMPLEMENTED)) { 290 if (useSet.contains(ClassUse.IMPLEMENTED)) {
287 applyImpact(_listener.registerImplementedClass(cls)); 291 applyImpact(listener.registerImplementedClass(cls));
288 } 292 }
289 } 293 }
290 294
291 void processDynamicUse(DynamicUse dynamicUse) { 295 void processDynamicUse(DynamicUse dynamicUse) {
292 task.measure(() { 296 task.measure(() {
293 _universe.registerDynamicUse(dynamicUse, _applyMemberUse); 297 _universe.registerDynamicUse(dynamicUse, _applyMemberUse);
294 }); 298 });
295 } 299 }
296 300
297 void processStaticUse(StaticUse staticUse) { 301 void processStaticUse(StaticUse staticUse) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 type = _universe.registerIsCheck(type); 355 type = _universe.registerIsCheck(type);
352 // Even in checked mode, type annotations for return type and argument 356 // Even in checked mode, type annotations for return type and argument
353 // types do not imply type checks, so there should never be a check 357 // types do not imply type checks, so there should never be a check
354 // against the type variable of a typedef. 358 // against the type variable of a typedef.
355 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); 359 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef);
356 } 360 }
357 361
358 void _registerClosurizedMember(MemberElement element) { 362 void _registerClosurizedMember(MemberElement element) {
359 assert(element.isInstanceMember); 363 assert(element.isInstanceMember);
360 if (element.type.containsTypeVariables) { 364 if (element.type.containsTypeVariables) {
361 applyImpact(_listener.registerClosureWithFreeTypeVariables(element)); 365 applyImpact(listener.registerClosureWithFreeTypeVariables(element));
362 _universe.closuresWithFreeTypeVariables.add(element); 366 _universe.closuresWithFreeTypeVariables.add(element);
363 } 367 }
364 applyImpact(_listener.registerBoundClosure()); 368 applyImpact(listener.registerBoundClosure());
365 _universe.closurizedMembers.add(element); 369 _universe.closurizedMembers.add(element);
366 } 370 }
367 371
368 void forEach(void f(WorkItem work)) { 372 void forEach(void f(WorkItem work)) {
369 do { 373 do {
370 while (_queue.isNotEmpty) { 374 while (_queue.isNotEmpty) {
371 // TODO(johnniwinther): Find an optimal process order. 375 // TODO(johnniwinther): Find an optimal process order.
372 WorkItem work = _queue.removeLast(); 376 WorkItem work = _queue.removeLast();
373 if (!_processedEntities.contains(work.element)) { 377 if (!_processedEntities.contains(work.element)) {
374 strategy.processWorkItem(f, work); 378 strategy.processWorkItem(f, work);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 void _addToWorkList(MemberEntity entity) { 419 void _addToWorkList(MemberEntity entity) {
416 if (hasBeenProcessed(entity)) return; 420 if (hasBeenProcessed(entity)) return;
417 WorkItem workItem = _workItemBuilder.createWorkItem(entity); 421 WorkItem workItem = _workItemBuilder.createWorkItem(entity);
418 if (workItem == null) return; 422 if (workItem == null) return;
419 423
420 if (queueIsClosed) { 424 if (queueIsClosed) {
421 throw new SpannableAssertionFailure( 425 throw new SpannableAssertionFailure(
422 entity, "Resolution work list is closed. Trying to add $entity."); 426 entity, "Resolution work list is closed. Trying to add $entity.");
423 } 427 }
424 428
425 applyImpact(_listener.registerUsedElement(entity)); 429 applyImpact(listener.registerUsedElement(entity));
426 _universe.registerUsedElement(entity); 430 _universe.registerUsedElement(entity);
427 _queue.add(workItem); 431 _queue.add(workItem);
428 } 432 }
429 433
430 /// Adds an action to the deferred task queue. 434 /// Adds an action to the deferred task queue.
431 /// The action is performed the next time the resolution queue has been 435 /// The action is performed the next time the resolution queue has been
432 /// emptied. 436 /// emptied.
433 /// 437 ///
434 /// The queue is processed in FIFO order. 438 /// The queue is processed in FIFO order.
435 void addDeferredAction(Entity entity, void action()) { 439 void addDeferredAction(Entity entity, void action()) {
436 if (queueIsClosed) { 440 if (queueIsClosed) {
437 throw new SpannableAssertionFailure( 441 throw new SpannableAssertionFailure(
438 entity, 442 entity,
439 "Resolution work list is closed. " 443 "Resolution work list is closed. "
440 "Trying to add deferred action for $entity"); 444 "Trying to add deferred action for $entity");
441 } 445 }
442 _deferredQueue.add(new _DeferredAction(entity, action)); 446 _deferredQueue.add(new _DeferredAction(entity, action));
443 } 447 }
444 448
445 /// [_onQueueEmpty] is called whenever the queue is drained. [recentClasses] 449 /// [_onQueueEmpty] is called whenever the queue is drained. [recentClasses]
446 /// contains the set of all classes seen for the first time since 450 /// contains the set of all classes seen for the first time since
447 /// [_onQueueEmpty] was called last. A return value of [true] indicates that 451 /// [_onQueueEmpty] was called last. A return value of [true] indicates that
448 /// the [recentClasses] have been processed and may be cleared. If [false] is 452 /// the [recentClasses] have been processed and may be cleared. If [false] is
449 /// returned, [_onQueueEmpty] will be called once the queue is empty again (or 453 /// returned, [_onQueueEmpty] will be called once the queue is empty again (or
450 /// still empty) and [recentClasses] will be a superset of the current value. 454 /// still empty) and [recentClasses] will be a superset of the current value.
451 bool _onQueueEmpty(Iterable<ClassEntity> recentClasses) { 455 bool _onQueueEmpty(Iterable<ClassEntity> recentClasses) {
452 _emptyDeferredQueue(); 456 _emptyDeferredQueue();
453 457
454 return _listener.onQueueEmpty(this, recentClasses); 458 return listener.onQueueEmpty(this, recentClasses);
455 } 459 }
456 460
457 void emptyDeferredQueueForTesting() => _emptyDeferredQueue(); 461 void emptyDeferredQueueForTesting() => _emptyDeferredQueue();
458 462
459 void _emptyDeferredQueue() { 463 void _emptyDeferredQueue() {
460 while (!_deferredQueue.isEmpty) { 464 while (!_deferredQueue.isEmpty) {
461 _DeferredAction task = _deferredQueue.removeFirst(); 465 _DeferredAction task = _deferredQueue.removeFirst();
462 _reporter.withCurrentElement(task.element, task.action); 466 _reporter.withCurrentElement(task.element, task.action);
463 } 467 }
464 } 468 }
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 @override 581 @override
578 WorkItem createWorkItem(MemberElement element) { 582 WorkItem createWorkItem(MemberElement element) {
579 assert(invariant(element, element.isDeclaration)); 583 assert(invariant(element, element.isDeclaration));
580 if (element.isMalformed) return null; 584 if (element.isMalformed) return null;
581 585
582 assert(invariant(element, element is AnalyzableElement, 586 assert(invariant(element, element is AnalyzableElement,
583 message: 'Element $element is not analyzable.')); 587 message: 'Element $element is not analyzable.'));
584 return _resolution.createWorkItem(element); 588 return _resolution.createWorkItem(element);
585 } 589 }
586 } 590 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/compiler.dart ('k') | pkg/compiler/lib/src/js_backend/backend.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698