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

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

Issue 2549423002: Change Enqueuer to use Entity instead of Element. (Closed)
Patch Set: Updated cf. comments. Created 4 years 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.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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 compiler.globalDependencies, 60 compiler.globalDependencies,
61 compiler.backend, 61 compiler.backend,
62 compiler.coreClasses, 62 compiler.coreClasses,
63 compiler.cacheStrategy); 63 compiler.cacheStrategy);
64 _codegen = compiler.backend.createCodegenEnqueuer(this, compiler); 64 _codegen = compiler.backend.createCodegenEnqueuer(this, compiler);
65 } 65 }
66 66
67 ResolutionEnqueuer get resolution => _resolution; 67 ResolutionEnqueuer get resolution => _resolution;
68 Enqueuer get codegen => _codegen; 68 Enqueuer get codegen => _codegen;
69 69
70 void forgetElement(Element element) { 70 void forgetEntity(Entity entity) {
71 resolution.forgetElement(element, compiler); 71 resolution.forgetEntity(entity, compiler);
72 codegen.forgetElement(element, compiler); 72 codegen.forgetEntity(entity, compiler);
73 } 73 }
74 } 74 }
75 75
76 abstract class Enqueuer { 76 abstract class Enqueuer {
77 WorldBuilder get universe; 77 WorldBuilder get universe;
78 native.NativeEnqueuer get nativeEnqueuer; 78 native.NativeEnqueuer get nativeEnqueuer;
79 void forgetElement(Element element, Compiler compiler); 79 void forgetEntity(Entity entity, Compiler compiler);
80 80
81 // TODO(johnniwinther): Initialize [_impactStrategy] to `null`. 81 // TODO(johnniwinther): Initialize [_impactStrategy] to `null`.
82 ImpactStrategy _impactStrategy = const ImpactStrategy(); 82 ImpactStrategy _impactStrategy = const ImpactStrategy();
83 83
84 ImpactStrategy get impactStrategy => _impactStrategy; 84 ImpactStrategy get impactStrategy => _impactStrategy;
85 85
86 void open(ImpactStrategy impactStrategy) { 86 void open(ImpactStrategy impactStrategy) {
87 _impactStrategy = impactStrategy; 87 _impactStrategy = impactStrategy;
88 } 88 }
89 89
(...skipping 10 matching lines...) Expand all
100 100
101 bool get queueIsEmpty; 101 bool get queueIsEmpty;
102 102
103 ImpactUseCase get impactUse; 103 ImpactUseCase get impactUse;
104 104
105 void forEach(void f(WorkItem work)); 105 void forEach(void f(WorkItem work));
106 106
107 /// Apply the [worldImpact] to this enqueuer. If the [impactSource] is 107 /// Apply the [worldImpact] to this enqueuer. If the [impactSource] is
108 /// provided the impact strategy will remove it from the element impact cache, 108 /// provided the impact strategy will remove it from the element impact cache,
109 /// if it is no longer needed. 109 /// if it is no longer needed.
110 void applyImpact(WorldImpact worldImpact, {Element impactSource}); 110 void applyImpact(WorldImpact worldImpact, {var impactSource});
111 bool checkNoEnqueuedInvokedInstanceMethods(); 111 bool checkNoEnqueuedInvokedInstanceMethods();
112 void logSummary(log(message)); 112 void logSummary(log(message));
113 113
114 /// Returns [:true:] if [member] has been processed by this enqueuer.
115 bool isProcessed(Element member);
116
117 Iterable<Entity> get processedEntities; 114 Iterable<Entity> get processedEntities;
118 115
119 Iterable<ClassElement> get processedClasses; 116 Iterable<ClassEntity> get processedClasses;
120 } 117 }
121 118
122 abstract class EnqueuerImpl extends Enqueuer { 119 abstract class EnqueuerImpl extends Enqueuer {
123 CompilerTask get task; 120 CompilerTask get task;
124 EnqueuerStrategy get strategy; 121 EnqueuerStrategy get strategy;
125 void checkClass(ClassElement cls); 122 void checkClass(ClassEntity cls);
126 void processStaticUse(StaticUse staticUse); 123 void processStaticUse(StaticUse staticUse);
127 void processTypeUse(TypeUse typeUse); 124 void processTypeUse(TypeUse typeUse);
128 void processDynamicUse(DynamicUse dynamicUse); 125 void processDynamicUse(DynamicUse dynamicUse);
129 } 126 }
130 127
131 /// [Enqueuer] which is specific to resolution. 128 /// [Enqueuer] which is specific to resolution.
132 class ResolutionEnqueuer extends EnqueuerImpl { 129 class ResolutionEnqueuer extends EnqueuerImpl {
133 static const ImpactUseCase IMPACT_USE = 130 static const ImpactUseCase IMPACT_USE =
134 const ImpactUseCase('ResolutionEnqueuer'); 131 const ImpactUseCase('ResolutionEnqueuer');
135 132
136 final CompilerTask task; 133 final CompilerTask task;
137 final String name; 134 final String name;
138 final Resolution _resolution; 135 final Resolution _resolution;
139 final CompilerOptions _options; 136 final CompilerOptions _options;
140 final Backend backend; 137 final Backend backend;
141 final GlobalDependencyRegistry _globalDependencies; 138 final GlobalDependencyRegistry _globalDependencies;
142 final CommonElements _commonElements; 139 final CommonElements _commonElements;
143 final native.NativeEnqueuer nativeEnqueuer; 140 final native.NativeEnqueuer nativeEnqueuer;
144 141
145 final EnqueuerStrategy strategy; 142 final EnqueuerStrategy strategy;
146 Set<ClassElement> _recentClasses = new Setlet<ClassElement>(); 143 Set<ClassEntity> _recentClasses = new Setlet<ClassEntity>();
147 final ResolutionWorldBuilderImpl _universe; 144 final ResolutionWorldBuilderImpl _universe;
148 145
149 bool queueIsClosed = false; 146 bool queueIsClosed = false;
150 147
151 WorldImpactVisitor _impactVisitor; 148 WorldImpactVisitor _impactVisitor;
152 149
153 /// All declaration elements that have been processed by the resolver. 150 /// All declaration elements that have been processed by the resolver.
154 final Set<AstElement> processedElements = new Set<AstElement>(); 151 final Set<AstElement> _processedElements = new Set<AstElement>();
155 152
156 final Queue<WorkItem> _queue = new Queue<WorkItem>(); 153 final Queue<WorkItem> _queue = new Queue<WorkItem>();
157 154
158 /// Queue of deferred resolution actions to execute when the resolution queue 155 /// Queue of deferred resolution actions to execute when the resolution queue
159 /// has been emptied. 156 /// has been emptied.
160 final Queue<_DeferredAction> _deferredQueue = new Queue<_DeferredAction>(); 157 final Queue<_DeferredAction> _deferredQueue = new Queue<_DeferredAction>();
161 158
162 ResolutionEnqueuer( 159 ResolutionEnqueuer(
163 this.task, 160 this.task,
164 this._options, 161 this._options,
(...skipping 13 matching lines...) Expand all
178 } 175 }
179 176
180 ResolutionWorldBuilder get universe => _universe; 177 ResolutionWorldBuilder get universe => _universe;
181 178
182 OpenWorld get _openWorld => universe.openWorld; 179 OpenWorld get _openWorld => universe.openWorld;
183 180
184 bool get queueIsEmpty => _queue.isEmpty; 181 bool get queueIsEmpty => _queue.isEmpty;
185 182
186 DiagnosticReporter get _reporter => _resolution.reporter; 183 DiagnosticReporter get _reporter => _resolution.reporter;
187 184
188 Iterable<ClassElement> get processedClasses => _universe.processedClasses; 185 Iterable<ClassEntity> get processedClasses => _universe.processedClasses;
189 186
190 void applyImpact(WorldImpact worldImpact, {Element impactSource}) { 187 void applyImpact(WorldImpact worldImpact, {var impactSource}) {
191 if (worldImpact.isEmpty) return; 188 if (worldImpact.isEmpty) return;
192 impactStrategy.visitImpact( 189 impactStrategy.visitImpact(
193 impactSource, worldImpact, _impactVisitor, impactUse); 190 impactSource, worldImpact, _impactVisitor, impactUse);
194 } 191 }
195 192
196 void _registerInstantiatedType(InterfaceType type, 193 void _registerInstantiatedType(InterfaceType type,
197 {ConstructorElement constructor, 194 {ConstructorElement constructor,
198 bool mirrorUsage: false, 195 bool mirrorUsage: false,
199 bool nativeUsage: false, 196 bool nativeUsage: false,
200 bool globalDependency: false, 197 bool globalDependency: false,
(...skipping 10 matching lines...) Expand all
211 nativeEnqueuer.onInstantiatedType(type); 208 nativeEnqueuer.onInstantiatedType(type);
212 } 209 }
213 backend.registerInstantiatedType(type); 210 backend.registerInstantiatedType(type);
214 }); 211 });
215 } 212 }
216 213
217 bool checkNoEnqueuedInvokedInstanceMethods() { 214 bool checkNoEnqueuedInvokedInstanceMethods() {
218 return strategy.checkEnqueuerConsistency(this); 215 return strategy.checkEnqueuerConsistency(this);
219 } 216 }
220 217
221 void checkClass(ClassElement cls) { 218 void checkClass(ClassEntity cls) {
222 _universe.processClassMembers(cls, 219 _universe.processClassMembers(cls,
223 (MemberElement member, EnumSet<MemberUse> useSet) { 220 (MemberEntity member, EnumSet<MemberUse> useSet) {
224 if (useSet.isNotEmpty) { 221 if (useSet.isNotEmpty) {
225 _reporter.internalError(member, 222 _reporter.internalError(member,
226 'Unenqueued use of $member: ${useSet.iterable(MemberUse.values)}'); 223 'Unenqueued use of $member: ${useSet.iterable(MemberUse.values)}');
227 } 224 }
228 }); 225 });
229 } 226 }
230 227
231 /// Callback for applying the first seen use of a [member]. 228 /// Callback for applying the first seen use of a [member].
232 void _applyFirstMemberUse(MemberElement member, EnumSet<MemberUse> useSet) { 229 void _applyFirstMemberUse(MemberElement member, EnumSet<MemberUse> useSet) {
233 ClassElement cls = member.enclosingClass; 230 ClassElement cls = member.enclosingClass;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 task.measure(() { 269 task.measure(() {
273 _universe.registerDynamicUse(dynamicUse, _applyMemberUse); 270 _universe.registerDynamicUse(dynamicUse, _applyMemberUse);
274 }); 271 });
275 } 272 }
276 273
277 void processStaticUse(StaticUse staticUse) { 274 void processStaticUse(StaticUse staticUse) {
278 Element element = staticUse.element; 275 Element element = staticUse.element;
279 assert(invariant(element, element.isDeclaration, 276 assert(invariant(element, element.isDeclaration,
280 message: "Element ${element} is not the declaration.")); 277 message: "Element ${element} is not the declaration."));
281 _universe.registerStaticUse(staticUse); 278 _universe.registerStaticUse(staticUse);
282 applyImpact(backend.registerStaticUse(element, forResolution: true));
283 bool addElement = true; 279 bool addElement = true;
284 switch (staticUse.kind) { 280 switch (staticUse.kind) {
285 case StaticUseKind.STATIC_TEAR_OFF: 281 case StaticUseKind.STATIC_TEAR_OFF:
286 applyImpact(backend.registerGetOfStaticFunction()); 282 applyImpact(backend.registerGetOfStaticFunction());
287 break; 283 break;
288 case StaticUseKind.FIELD_GET: 284 case StaticUseKind.FIELD_GET:
289 case StaticUseKind.FIELD_SET: 285 case StaticUseKind.FIELD_SET:
290 case StaticUseKind.CLOSURE: 286 case StaticUseKind.CLOSURE:
291 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and 287 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and
292 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. 288 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 } 372 }
377 applyImpact(backend.registerBoundClosure()); 373 applyImpact(backend.registerBoundClosure());
378 _universe.closurizedMembers.add(element); 374 _universe.closurizedMembers.add(element);
379 } 375 }
380 376
381 void forEach(void f(WorkItem work)) { 377 void forEach(void f(WorkItem work)) {
382 do { 378 do {
383 while (_queue.isNotEmpty) { 379 while (_queue.isNotEmpty) {
384 // TODO(johnniwinther): Find an optimal process order. 380 // TODO(johnniwinther): Find an optimal process order.
385 WorkItem work = _queue.removeLast(); 381 WorkItem work = _queue.removeLast();
386 if (!isProcessed(work.element)) { 382 if (!_processedElements.contains(work.element)) {
387 strategy.processWorkItem(f, work); 383 strategy.processWorkItem(f, work);
388 registerProcessedElement(work.element); 384 registerProcessedElement(work.element);
389 } 385 }
390 } 386 }
391 List recents = _recentClasses.toList(growable: false); 387 List recents = _recentClasses.toList(growable: false);
392 _recentClasses.clear(); 388 _recentClasses.clear();
393 if (!_onQueueEmpty(recents)) { 389 if (!_onQueueEmpty(recents)) {
394 _recentClasses.addAll(recents); 390 _recentClasses.addAll(recents);
395 } 391 }
396 } while (_queue.isNotEmpty || _recentClasses.isNotEmpty); 392 } while (_queue.isNotEmpty || _recentClasses.isNotEmpty);
397 } 393 }
398 394
399 void logSummary(log(message)) { 395 void logSummary(log(message)) {
400 log('Resolved ${processedElements.length} elements.'); 396 log('Resolved ${_processedElements.length} elements.');
401 nativeEnqueuer.logSummary(log); 397 nativeEnqueuer.logSummary(log);
402 } 398 }
403 399
404 String toString() => 'Enqueuer($name)'; 400 String toString() => 'Enqueuer($name)';
405 401
406 Iterable<Entity> get processedEntities => processedElements; 402 Iterable<Entity> get processedEntities => _processedElements;
407 403
408 ImpactUseCase get impactUse => IMPACT_USE; 404 ImpactUseCase get impactUse => IMPACT_USE;
409 405
410 bool get isResolutionQueue => true; 406 bool get isResolutionQueue => true;
411 407
412 bool isProcessed(Element member) => processedElements.contains(member);
413
414 /// Returns `true` if [element] has been processed by the resolution enqueuer. 408 /// Returns `true` if [element] has been processed by the resolution enqueuer.
415 bool hasBeenProcessed(Element element) { 409 bool hasBeenProcessed(Element element) {
416 return processedElements.contains(element.analyzableElement.declaration); 410 return _processedElements.contains(element.analyzableElement.declaration);
417 } 411 }
418 412
419 /// Registers [element] as processed by the resolution enqueuer. 413 /// Registers [element] as processed by the resolution enqueuer.
420 void registerProcessedElement(AstElement element) { 414 void registerProcessedElement(AstElement element) {
421 processedElements.add(element); 415 _processedElements.add(element);
422 backend.onElementResolved(element);
423 } 416 }
424 417
425 /// Adds [element] to the work list if it has not already been processed. 418 /// Adds [element] to the work list if it has not already been processed.
426 /// 419 ///
427 /// Invariant: [element] must be a declaration element. 420 /// Invariant: [element] must be a declaration element.
428 void _addToWorkList(Element element) { 421 void _addToWorkList(Element element) {
429 assert(invariant(element, element.isDeclaration)); 422 assert(invariant(element, element.isDeclaration));
430 if (element.isMalformed) return; 423 if (element.isMalformed) return;
431 424
432 assert(invariant(element, element is AnalyzableElement, 425 assert(invariant(element, element is AnalyzableElement,
433 message: 'Element $element is not analyzable.')); 426 message: 'Element $element is not analyzable.'));
434 if (hasBeenProcessed(element)) return; 427 if (hasBeenProcessed(element)) return;
435 if (queueIsClosed) { 428 if (queueIsClosed) {
436 throw new SpannableAssertionFailure( 429 throw new SpannableAssertionFailure(
437 element, "Resolution work list is closed. Trying to add $element."); 430 element, "Resolution work list is closed. Trying to add $element.");
438 } 431 }
439 432
433 applyImpact(backend.registerUsedElement(element, forResolution: true));
440 _openWorld.registerUsedElement(element); 434 _openWorld.registerUsedElement(element);
441 435
442 ResolutionWorkItem workItem = _resolution.createWorkItem(element); 436 ResolutionWorkItem workItem = _resolution.createWorkItem(element);
443 _queue.add(workItem); 437 _queue.add(workItem);
444 438
445 // Enable isolate support if we start using something from the isolate 439 // Enable isolate support if we start using something from the isolate
446 // library, or timers for the async library. We exclude constant fields, 440 // library, or timers for the async library. We exclude constant fields,
447 // which are ending here because their initializing expression is compiled. 441 // which are ending here because their initializing expression is compiled.
448 LibraryElement library = element.library; 442 LibraryElement library = element.library;
449 if (!universe.hasIsolateSupport && (!element.isField || !element.isConst)) { 443 if (!universe.hasIsolateSupport && (!element.isField || !element.isConst)) {
(...skipping 25 matching lines...) Expand all
475 469
476 void _registerNoSuchMethod(Element element) { 470 void _registerNoSuchMethod(Element element) {
477 backend.registerNoSuchMethod(element); 471 backend.registerNoSuchMethod(element);
478 } 472 }
479 473
480 void _enableIsolateSupport() { 474 void _enableIsolateSupport() {
481 _universe.hasIsolateSupport = true; 475 _universe.hasIsolateSupport = true;
482 applyImpact(backend.enableIsolateSupport(forResolution: true)); 476 applyImpact(backend.enableIsolateSupport(forResolution: true));
483 } 477 }
484 478
485 /** 479 /// Adds an action to the deferred task queue.
486 * Adds an action to the deferred task queue. 480 /// The action is performed the next time the resolution queue has been
487 * 481 /// emptied.
488 * The action is performed the next time the resolution queue has been 482 ///
489 * emptied. 483 /// The queue is processed in FIFO order.
490 * 484 void addDeferredAction(Entity entity, void action()) {
491 * The queue is processed in FIFO order.
492 */
493 void addDeferredAction(Element element, void action()) {
494 if (queueIsClosed) { 485 if (queueIsClosed) {
495 throw new SpannableAssertionFailure( 486 throw new SpannableAssertionFailure(
496 element, 487 entity,
497 "Resolution work list is closed. " 488 "Resolution work list is closed. "
498 "Trying to add deferred action for $element"); 489 "Trying to add deferred action for $entity");
499 } 490 }
500 _deferredQueue.add(new _DeferredAction(element, action)); 491 _deferredQueue.add(new _DeferredAction(entity, action));
501 } 492 }
502 493
503 /// [_onQueueEmpty] is called whenever the queue is drained. [recentClasses] 494 /// [_onQueueEmpty] is called whenever the queue is drained. [recentClasses]
504 /// contains the set of all classes seen for the first time since 495 /// contains the set of all classes seen for the first time since
505 /// [_onQueueEmpty] was called last. A return value of [true] indicates that 496 /// [_onQueueEmpty] was called last. A return value of [true] indicates that
506 /// the [recentClasses] have been processed and may be cleared. If [false] is 497 /// the [recentClasses] have been processed and may be cleared. If [false] is
507 /// returned, [_onQueueEmpty] will be called once the queue is empty again (or 498 /// returned, [_onQueueEmpty] will be called once the queue is empty again (or
508 /// still empty) and [recentClasses] will be a superset of the current value. 499 /// still empty) and [recentClasses] will be a superset of the current value.
509 bool _onQueueEmpty(Iterable<ClassElement> recentClasses) { 500 bool _onQueueEmpty(Iterable<ClassEntity> recentClasses) {
510 _emptyDeferredQueue(); 501 _emptyDeferredQueue();
511 502
512 return backend.onQueueEmpty(this, recentClasses); 503 return backend.onQueueEmpty(this, recentClasses);
513 } 504 }
514 505
515 void emptyDeferredQueueForTesting() => _emptyDeferredQueue(); 506 void emptyDeferredQueueForTesting() => _emptyDeferredQueue();
516 507
517 void _emptyDeferredQueue() { 508 void _emptyDeferredQueue() {
518 while (!_deferredQueue.isEmpty) { 509 while (!_deferredQueue.isEmpty) {
519 _DeferredAction task = _deferredQueue.removeFirst(); 510 _DeferredAction task = _deferredQueue.removeFirst();
520 _reporter.withCurrentElement(task.element, task.action); 511 _reporter.withCurrentElement(task.element, task.action);
521 } 512 }
522 } 513 }
523 514
524 void forgetElement(Element element, Compiler compiler) { 515 void forgetEntity(Entity entity, Compiler compiler) {
525 _universe.forgetElement(element, compiler); 516 _universe.forgetEntity(entity, compiler);
526 processedElements.remove(element); 517 _processedElements.remove(entity);
527 } 518 }
528 } 519 }
529 520
530 void removeFromSet(Map<String, Set<Element>> map, Element element) {
531 Set<Element> set = map[element.name];
532 if (set == null) return;
533 set.remove(element);
534 }
535
536 /// Strategy used by the enqueuer to populate the world. 521 /// Strategy used by the enqueuer to populate the world.
537 class EnqueuerStrategy { 522 class EnqueuerStrategy {
538 const EnqueuerStrategy(); 523 const EnqueuerStrategy();
539 524
540 /// Process a static use of and element in live code. 525 /// Process a static use of and element in live code.
541 void processStaticUse(EnqueuerImpl enqueuer, StaticUse staticUse) {} 526 void processStaticUse(EnqueuerImpl enqueuer, StaticUse staticUse) {}
542 527
543 /// Process a type use in live code. 528 /// Process a type use in live code.
544 void processTypeUse(EnqueuerImpl enqueuer, TypeUse typeUse) {} 529 void processTypeUse(EnqueuerImpl enqueuer, TypeUse typeUse) {}
545 530
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 } 608 }
624 609
625 typedef void _DeferredActionFunction(); 610 typedef void _DeferredActionFunction();
626 611
627 class _DeferredAction { 612 class _DeferredAction {
628 final Element element; 613 final Element element;
629 final _DeferredActionFunction action; 614 final _DeferredActionFunction action;
630 615
631 _DeferredAction(this.element, this.action); 616 _DeferredAction(this.element, this.action);
632 } 617 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/dump_info.dart ('k') | pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698