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

Side by Side Diff: pkg/compiler/lib/src/js_backend/enqueuer.dart

Issue 2531303002: Decouple WorkItem from Compiler (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.js.enqueue; 5 library dart2js.js.enqueue;
6 6
7 import 'dart:collection' show Queue; 7 import 'dart:collection' show Queue;
8 8
9 import '../common/backend_api.dart' show Backend; 9 import '../common/backend_api.dart' show Backend;
10 import '../common/codegen.dart' show CodegenWorkItem; 10 import '../common/codegen.dart' show CodegenWorkItem;
(...skipping 25 matching lines...) Expand all
36 import '../universe/selector.dart' show Selector; 36 import '../universe/selector.dart' show Selector;
37 import '../universe/world_builder.dart'; 37 import '../universe/world_builder.dart';
38 import '../universe/use.dart' 38 import '../universe/use.dart'
39 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; 39 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind;
40 import '../universe/world_impact.dart' 40 import '../universe/world_impact.dart'
41 show ImpactUseCase, ImpactStrategy, WorldImpact, WorldImpactVisitor; 41 show ImpactUseCase, ImpactStrategy, WorldImpact, WorldImpactVisitor;
42 import '../util/util.dart' show Setlet; 42 import '../util/util.dart' show Setlet;
43 import '../world.dart'; 43 import '../world.dart';
44 44
45 /// [Enqueuer] which is specific to code generation. 45 /// [Enqueuer] which is specific to code generation.
46 class CodegenEnqueuer implements Enqueuer { 46 class CodegenEnqueuer extends EnqueuerImpl {
47 final String name; 47 final String name;
48 @deprecated 48 @deprecated
49 final Compiler _compiler; // TODO(ahe): Remove this dependency. 49 final Compiler _compiler; // TODO(ahe): Remove this dependency.
50 final EnqueuerStrategy strategy; 50 final EnqueuerStrategy strategy;
51 final Map<String, Set<Element>> instanceMembersByName = 51 final Map<String, Set<Element>> instanceMembersByName =
52 new Map<String, Set<Element>>(); 52 new Map<String, Set<Element>>();
53 final Map<String, Set<Element>> instanceFunctionsByName = 53 final Map<String, Set<Element>> instanceFunctionsByName =
54 new Map<String, Set<Element>>(); 54 new Map<String, Set<Element>>();
55 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); 55 final Set<ClassElement> _processedClasses = new Set<ClassElement>();
56 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); 56 Set<ClassElement> recentClasses = new Setlet<ClassElement>();
57 final CodegenWorldBuilderImpl _universe = 57 final CodegenWorldBuilderImpl _universe =
58 new CodegenWorldBuilderImpl(const TypeMaskStrategy()); 58 new CodegenWorldBuilderImpl(const TypeMaskStrategy());
59 59
60 bool queueIsClosed = false; 60 bool queueIsClosed = false;
61 final CompilerTask task; 61 final CompilerTask task;
62 final native.NativeEnqueuer nativeEnqueuer; 62 final native.NativeEnqueuer nativeEnqueuer;
63 63
64 WorldImpactVisitor impactVisitor; 64 WorldImpactVisitor impactVisitor;
65 65
66 CodegenEnqueuer(this.task, Compiler compiler, this.strategy) 66 CodegenEnqueuer(this.task, Compiler compiler, this.strategy)
67 : queue = new Queue<CodegenWorkItem>(), 67 : queue = new Queue<CodegenWorkItem>(),
68 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), 68 newlyEnqueuedElements = compiler.cacheStrategy.newSet(),
69 newlySeenSelectors = compiler.cacheStrategy.newSet(), 69 newlySeenSelectors = compiler.cacheStrategy.newSet(),
70 nativeEnqueuer = compiler.backend.nativeCodegenEnqueuer(), 70 nativeEnqueuer = compiler.backend.nativeCodegenEnqueuer(),
71 this.name = 'codegen enqueuer', 71 this.name = 'codegen enqueuer',
72 this._compiler = compiler { 72 this._compiler = compiler {
73 impactVisitor = new _EnqueuerImpactVisitor(this); 73 impactVisitor = new EnqueuerImplImpactVisitor(this);
74 } 74 }
75 75
76 CodegenWorldBuilder get universe => _universe; 76 CodegenWorldBuilder get universe => _universe;
77 77
78 Backend get backend => _compiler.backend; 78 Backend get backend => _compiler.backend;
79 79
80 CompilerOptions get options => _compiler.options; 80 CompilerOptions get options => _compiler.options;
81 81
82 ClosedWorld get _world => _compiler.closedWorld; 82 ClosedWorld get _world => _compiler.closedWorld;
83 83
84 bool get queueIsEmpty => queue.isEmpty; 84 bool get queueIsEmpty => queue.isEmpty;
85 85
86 /// Returns [:true:] if this enqueuer is the resolution enqueuer. 86 /// Returns [:true:] if this enqueuer is the resolution enqueuer.
87 bool get isResolutionQueue => false; 87 bool get isResolutionQueue => false;
88 88
89 QueueFilter get filter => _compiler.enqueuerFilter;
90
91 DiagnosticReporter get reporter => _compiler.reporter; 89 DiagnosticReporter get reporter => _compiler.reporter;
92 90
93 /** 91 /**
94 * Documentation wanted -- johnniwinther 92 * Documentation wanted -- johnniwinther
95 * 93 *
96 * Invariant: [element] must be a declaration element. 94 * Invariant: [element] must be a declaration element.
97 */ 95 */
98 void addToWorkList(Element element) { 96 void addToWorkList(Element element) {
99 assert(invariant(element, element.isDeclaration)); 97 assert(invariant(element, element.isDeclaration));
100 // Don't generate code for foreign elements. 98 // Don't generate code for foreign elements.
101 if (backend.isForeign(element)) return; 99 if (backend.isForeign(element)) return;
102 100
103 // Codegen inlines field initializers. It only needs to generate 101 // Codegen inlines field initializers. It only needs to generate
104 // code for checked setters. 102 // code for checked setters.
105 if (element.isField && element.isInstanceMember) { 103 if (element.isField && element.isInstanceMember) {
106 if (!options.enableTypeAssertions || element.enclosingElement.isClosure) { 104 if (!options.enableTypeAssertions || element.enclosingElement.isClosure) {
107 return; 105 return;
108 } 106 }
109 } 107 }
110 108
111 if (options.hasIncrementalSupport && !isProcessed(element)) { 109 if (options.hasIncrementalSupport && !isProcessed(element)) {
112 newlyEnqueuedElements.add(element); 110 newlyEnqueuedElements.add(element);
113 } 111 }
114 112
115 if (queueIsClosed) { 113 if (queueIsClosed) {
116 throw new SpannableAssertionFailure( 114 throw new SpannableAssertionFailure(
117 element, "Codegen work list is closed. Trying to add $element"); 115 element, "Codegen work list is closed. Trying to add $element");
118 } 116 }
119 queue.add(new CodegenWorkItem(_compiler, element)); 117 queue.add(new CodegenWorkItem(backend, element));
120 // TODO(sigmund): add other missing dependencies (internals, selectors 118 // TODO(sigmund): add other missing dependencies (internals, selectors
121 // enqueued after allocations). 119 // enqueued after allocations).
122 _compiler.dumpInfoTask 120 _compiler.dumpInfoTask
123 .registerDependency(_compiler.currentElement, element); 121 .registerDependency(_compiler.currentElement, element);
124 } 122 }
125 123
126 void applyImpact(ImpactStrategy impactStrategy, WorldImpact worldImpact, 124 void applyImpact(WorldImpact worldImpact, {Element impactSource}) {
127 {Element impactSource}) { 125 if (worldImpact.isEmpty) return;
128 impactStrategy.visitImpact( 126 impactStrategy.visitImpact(
129 impactSource, worldImpact, impactVisitor, impactUse); 127 impactSource, worldImpact, impactVisitor, impactUse);
130 } 128 }
131 129
132 void registerInstantiatedType(InterfaceType type) { 130 void registerInstantiatedType(InterfaceType type) {
133 _registerInstantiatedType(type); 131 _registerInstantiatedType(type);
134 } 132 }
135 133
136 void _registerInstantiatedType(InterfaceType type, 134 void _registerInstantiatedType(InterfaceType type,
137 {bool mirrorUsage: false, bool nativeUsage: false}) { 135 {bool mirrorUsage: false, bool nativeUsage: false}) {
138 task.measure(() { 136 task.measure(() {
139 ClassElement cls = type.element; 137 ClassElement cls = type.element;
140 bool isNative = backend.isNative(cls); 138 bool isNative = backend.isNative(cls);
141 _universe.registerTypeInstantiation(type, 139 _universe.registerTypeInstantiation(type,
142 isNative: isNative, 140 isNative: isNative,
143 byMirrors: mirrorUsage, onImplemented: (ClassElement cls) { 141 byMirrors: mirrorUsage, onImplemented: (ClassElement cls) {
144 backend.registerImplementedClass(cls, this); 142 applyImpact(
143 backend.registerImplementedClass(cls, forResolution: false));
145 }); 144 });
146 if (nativeUsage) { 145 if (nativeUsage) {
147 nativeEnqueuer.onInstantiatedType(type); 146 nativeEnqueuer.onInstantiatedType(type);
148 } 147 }
149 backend.registerInstantiatedType(type); 148 backend.registerInstantiatedType(type);
150 // TODO(johnniwinther): Share this reasoning with [Universe]. 149 // TODO(johnniwinther): Share this reasoning with [Universe].
151 if (!cls.isAbstract || isNative || mirrorUsage) { 150 if (!cls.isAbstract || isNative || mirrorUsage) {
152 processInstantiatedClass(cls); 151 processInstantiatedClass(cls);
153 } 152 }
154 }); 153 });
155 } 154 }
156 155
157 bool checkNoEnqueuedInvokedInstanceMethods() { 156 bool checkNoEnqueuedInvokedInstanceMethods() {
158 return filter.checkNoEnqueuedInvokedInstanceMethods(this); 157 return strategy.checkEnqueuerConsistency(this);
159 } 158 }
160 159
161 void processInstantiatedClassMembers(ClassElement cls) { 160 void processInstantiatedClassMembers(ClassElement cls) {
162 strategy.processInstantiatedClass(this, cls); 161 strategy.processInstantiatedClass(this, cls);
163 } 162 }
164 163
165 void processInstantiatedClassMember(ClassElement cls, Element member) { 164 void processInstantiatedClassMember(ClassElement cls, Element member) {
166 assert(invariant(member, member.isDeclaration)); 165 assert(invariant(member, member.isDeclaration));
167 if (isProcessed(member)) return; 166 if (isProcessed(member)) return;
168 if (!member.isInstanceMember) return; 167 if (!member.isInstanceMember) return;
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 message: "Class $superclass has not been " 264 message: "Class $superclass has not been "
266 "processed in resolution.")); 265 "processed in resolution."));
267 */ 266 */
268 267
269 _processedClasses.add(superclass); 268 _processedClasses.add(superclass);
270 recentClasses.add(superclass); 269 recentClasses.add(superclass);
271 superclass.implementation.forEachMember(processInstantiatedClassMember); 270 superclass.implementation.forEachMember(processInstantiatedClassMember);
272 // We only tell the backend once that [superclass] was instantiated, so 271 // We only tell the backend once that [superclass] was instantiated, so
273 // any additional dependencies must be treated as global 272 // any additional dependencies must be treated as global
274 // dependencies. 273 // dependencies.
275 backend.registerInstantiatedClass(superclass, this); 274 applyImpact(backend.registerInstantiatedClass(superclass,
275 forResolution: false));
276 } 276 }
277 277
278 ClassElement superclass = cls; 278 ClassElement superclass = cls;
279 while (superclass != null) { 279 while (superclass != null) {
280 processClass(superclass); 280 processClass(superclass);
281 superclass = superclass.superclass; 281 superclass = superclass.superclass;
282 } 282 }
283 }); 283 });
284 } 284 }
285 285
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 */ 349 */
350 void registerStaticUse(StaticUse staticUse) { 350 void registerStaticUse(StaticUse staticUse) {
351 strategy.processStaticUse(this, staticUse); 351 strategy.processStaticUse(this, staticUse);
352 } 352 }
353 353
354 void registerStaticUseInternal(StaticUse staticUse) { 354 void registerStaticUseInternal(StaticUse staticUse) {
355 Element element = staticUse.element; 355 Element element = staticUse.element;
356 assert(invariant(element, element.isDeclaration, 356 assert(invariant(element, element.isDeclaration,
357 message: "Element ${element} is not the declaration.")); 357 message: "Element ${element} is not the declaration."));
358 _universe.registerStaticUse(staticUse); 358 _universe.registerStaticUse(staticUse);
359 backend.registerStaticUse(this, element); 359 applyImpact(backend.registerStaticUse(element, forResolution: false));
360 bool addElement = true; 360 bool addElement = true;
361 switch (staticUse.kind) { 361 switch (staticUse.kind) {
362 case StaticUseKind.STATIC_TEAR_OFF: 362 case StaticUseKind.STATIC_TEAR_OFF:
363 backend.registerGetOfStaticFunction(this); 363 applyImpact(backend.registerGetOfStaticFunction());
364 break; 364 break;
365 case StaticUseKind.FIELD_GET: 365 case StaticUseKind.FIELD_GET:
366 case StaticUseKind.FIELD_SET: 366 case StaticUseKind.FIELD_SET:
367 case StaticUseKind.CLOSURE: 367 case StaticUseKind.CLOSURE:
368 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and 368 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and
369 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. 369 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue.
370 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot 370 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot
371 // enqueue. 371 // enqueue.
372 addElement = false; 372 addElement = false;
373 break; 373 break;
374 case StaticUseKind.SUPER_FIELD_SET: 374 case StaticUseKind.SUPER_FIELD_SET:
375 case StaticUseKind.SUPER_TEAR_OFF: 375 case StaticUseKind.SUPER_TEAR_OFF:
376 case StaticUseKind.GENERAL: 376 case StaticUseKind.GENERAL:
377 case StaticUseKind.DIRECT_USE:
377 break; 378 break;
378 case StaticUseKind.CONSTRUCTOR_INVOKE: 379 case StaticUseKind.CONSTRUCTOR_INVOKE:
379 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: 380 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
380 case StaticUseKind.REDIRECTION: 381 case StaticUseKind.REDIRECTION:
381 registerTypeUse(new TypeUse.instantiation(staticUse.type)); 382 registerTypeUseInternal(new TypeUse.instantiation(staticUse.type));
382 break; 383 break;
383 case StaticUseKind.DIRECT_INVOKE: 384 case StaticUseKind.DIRECT_INVOKE:
384 _registerInstanceMethod(staticUse.element); 385 _registerInstanceMethod(staticUse.element);
385 break; 386 break;
386 } 387 }
387 if (addElement) { 388 if (addElement) {
388 addToWorkList(element); 389 addToWorkList(element);
389 } 390 }
390 } 391 }
391 392
392 void registerTypeUse(TypeUse typeUse) { 393 void registerTypeUse(TypeUse typeUse) {
394 strategy.processTypeUse(this, typeUse);
395 }
396
397 void registerTypeUseInternal(TypeUse typeUse) {
393 DartType type = typeUse.type; 398 DartType type = typeUse.type;
394 switch (typeUse.kind) { 399 switch (typeUse.kind) {
395 case TypeUseKind.INSTANTIATION: 400 case TypeUseKind.INSTANTIATION:
396 _registerInstantiatedType(type); 401 _registerInstantiatedType(type);
397 break; 402 break;
398 case TypeUseKind.MIRROR_INSTANTIATION: 403 case TypeUseKind.MIRROR_INSTANTIATION:
399 _registerInstantiatedType(type, mirrorUsage: true); 404 _registerInstantiatedType(type, mirrorUsage: true);
400 break; 405 break;
401 case TypeUseKind.NATIVE_INSTANTIATION: 406 case TypeUseKind.NATIVE_INSTANTIATION:
402 _registerInstantiatedType(type, nativeUsage: true); 407 _registerInstantiatedType(type, nativeUsage: true);
(...skipping 15 matching lines...) Expand all
418 423
419 void _registerIsCheck(DartType type) { 424 void _registerIsCheck(DartType type) {
420 type = _universe.registerIsCheck(type, _compiler.resolution); 425 type = _universe.registerIsCheck(type, _compiler.resolution);
421 // Even in checked mode, type annotations for return type and argument 426 // Even in checked mode, type annotations for return type and argument
422 // types do not imply type checks, so there should never be a check 427 // types do not imply type checks, so there should never be a check
423 // against the type variable of a typedef. 428 // against the type variable of a typedef.
424 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); 429 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef);
425 } 430 }
426 431
427 void registerCallMethodWithFreeTypeVariables(Element element) { 432 void registerCallMethodWithFreeTypeVariables(Element element) {
428 backend.registerCallMethodWithFreeTypeVariables(element, this); 433 applyImpact(backend.registerCallMethodWithFreeTypeVariables(element,
434 forResolution: false));
429 } 435 }
430 436
431 void registerClosurizedMember(TypedElement element) { 437 void registerClosurizedMember(TypedElement element) {
432 assert(element.isInstanceMember); 438 assert(element.isInstanceMember);
433 if (element.type.containsTypeVariables) { 439 if (element.type.containsTypeVariables) {
434 backend.registerClosureWithFreeTypeVariables(element, this); 440 applyImpact(backend.registerClosureWithFreeTypeVariables(element,
441 forResolution: false));
435 } 442 }
436 backend.registerBoundClosure(this); 443 applyImpact(backend.registerBoundClosure());
437 } 444 }
438 445
439 void forEach(void f(WorkItem work)) { 446 void forEach(void f(WorkItem work)) {
440 do { 447 do {
441 while (queue.isNotEmpty) { 448 while (queue.isNotEmpty) {
442 // TODO(johnniwinther): Find an optimal process order. 449 // TODO(johnniwinther): Find an optimal process order.
443 filter.processWorkItem(f, queue.removeLast()); 450 WorkItem work = queue.removeLast();
451 if (!isProcessed(work.element)) {
452 strategy.processWorkItem(f, work);
453 // TODO(johnniwinther): Register the processed element here. This
454 // is currently a side-effect of calling `work.run`.
455 }
444 } 456 }
445 List recents = recentClasses.toList(growable: false); 457 List recents = recentClasses.toList(growable: false);
446 recentClasses.clear(); 458 recentClasses.clear();
447 if (!onQueueEmpty(recents)) recentClasses.addAll(recents); 459 if (!onQueueEmpty(recents)) recentClasses.addAll(recents);
448 } while (queue.isNotEmpty || recentClasses.isNotEmpty); 460 } while (queue.isNotEmpty || recentClasses.isNotEmpty);
449 } 461 }
450 462
451 /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses] 463 /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses]
452 /// contains the set of all classes seen for the first time since 464 /// contains the set of all classes seen for the first time since
453 /// [onQueueEmpty] was called last. A return value of [true] indicates that 465 /// [onQueueEmpty] was called last. A return value of [true] indicates that
(...skipping 30 matching lines...) Expand all
484 static const ImpactUseCase IMPACT_USE = 496 static const ImpactUseCase IMPACT_USE =
485 const ImpactUseCase('CodegenEnqueuer'); 497 const ImpactUseCase('CodegenEnqueuer');
486 498
487 ImpactUseCase get impactUse => IMPACT_USE; 499 ImpactUseCase get impactUse => IMPACT_USE;
488 500
489 bool isProcessed(Element member) => 501 bool isProcessed(Element member) =>
490 member.isAbstract || generatedCode.containsKey(member); 502 member.isAbstract || generatedCode.containsKey(member);
491 503
492 void registerNoSuchMethod(Element element) { 504 void registerNoSuchMethod(Element element) {
493 if (!enabledNoSuchMethod && backend.enabledNoSuchMethod) { 505 if (!enabledNoSuchMethod && backend.enabledNoSuchMethod) {
494 backend.enableNoSuchMethod(this); 506 applyImpact(backend.enableNoSuchMethod());
495 enabledNoSuchMethod = true; 507 enabledNoSuchMethod = true;
496 } 508 }
497 } 509 }
498 510
499 void _logSpecificSummary(log(message)) { 511 void _logSpecificSummary(log(message)) {
500 log('Compiled ${generatedCode.length} methods.'); 512 log('Compiled ${generatedCode.length} methods.');
501 } 513 }
502 514
503 void forgetElement(Element element, Compiler compiler) { 515 void forgetElement(Element element, Compiler compiler) {
504 _forgetElement(element); 516 _forgetElement(element);
(...skipping 19 matching lines...) Expand all
524 536
525 @override 537 @override
526 Iterable<ClassElement> get processedClasses => _processedClasses; 538 Iterable<ClassElement> get processedClasses => _processedClasses;
527 } 539 }
528 540
529 void removeFromSet(Map<String, Set<Element>> map, Element element) { 541 void removeFromSet(Map<String, Set<Element>> map, Element element) {
530 Set<Element> set = map[element.name]; 542 Set<Element> set = map[element.name];
531 if (set == null) return; 543 if (set == null) return;
532 set.remove(element); 544 set.remove(element);
533 } 545 }
534
535 class _EnqueuerImpactVisitor implements WorldImpactVisitor {
536 final CodegenEnqueuer enqueuer;
537
538 _EnqueuerImpactVisitor(this.enqueuer);
539
540 @override
541 void visitDynamicUse(DynamicUse dynamicUse) {
542 enqueuer.registerDynamicUse(dynamicUse);
543 }
544
545 @override
546 void visitStaticUse(StaticUse staticUse) {
547 enqueuer.registerStaticUse(staticUse);
548 }
549
550 @override
551 void visitTypeUse(TypeUse typeUse) {
552 enqueuer.registerTypeUse(typeUse);
553 }
554 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/backend_impact.dart ('k') | pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698