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

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

Issue 2693163002: Split backend implementation of EnqueuerListener (Closed)
Patch Set: Updated cf. comments 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
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/codegen.dart' show CodegenWorkItem; 9 import '../common/codegen.dart' show CodegenWorkItem;
10 import '../common/tasks.dart' show CompilerTask; 10 import '../common/tasks.dart' show CompilerTask;
(...skipping 21 matching lines...) Expand all
32 final String name; 32 final String name;
33 final EnqueuerStrategy strategy; 33 final EnqueuerStrategy strategy;
34 34
35 Set<ClassEntity> _recentClasses = new Setlet<ClassEntity>(); 35 Set<ClassEntity> _recentClasses = new Setlet<ClassEntity>();
36 final CodegenWorldBuilderImpl _universe; 36 final CodegenWorldBuilderImpl _universe;
37 final WorkItemBuilder _workItemBuilder; 37 final WorkItemBuilder _workItemBuilder;
38 38
39 bool queueIsClosed = false; 39 bool queueIsClosed = false;
40 final CompilerTask task; 40 final CompilerTask task;
41 final native.NativeEnqueuer nativeEnqueuer; 41 final native.NativeEnqueuer nativeEnqueuer;
42 final JavaScriptBackend _backend; 42 final EnqueuerListener _listener;
43 final CompilerOptions _options; 43 final CompilerOptions _options;
44 44
45 WorldImpactVisitor _impactVisitor; 45 WorldImpactVisitor _impactVisitor;
46 46
47 final Queue<WorkItem> _queue = new Queue<WorkItem>(); 47 final Queue<WorkItem> _queue = new Queue<WorkItem>();
48 48
49 /// All declaration elements that have been processed by codegen. 49 /// All declaration elements that have been processed by codegen.
50 final Set<Entity> _processedEntities = new Set<Entity>(); 50 final Set<Entity> _processedEntities = new Set<Entity>();
51 51
52 static const ImpactUseCase IMPACT_USE = 52 static const ImpactUseCase IMPACT_USE =
53 const ImpactUseCase('CodegenEnqueuer'); 53 const ImpactUseCase('CodegenEnqueuer');
54 54
55 CodegenEnqueuer(this.task, JavaScriptBackend backend, CompilerOptions options, 55 CodegenEnqueuer(this.task, JavaScriptBackend backend, CompilerOptions options,
56 this.strategy) 56 this.strategy)
57 : _universe = 57 : _universe =
58 new CodegenWorldBuilderImpl(backend, const TypeMaskStrategy()), 58 new CodegenWorldBuilderImpl(backend, const TypeMaskStrategy()),
59 _workItemBuilder = new CodegenWorkItemBuilder(backend, options), 59 _workItemBuilder = new CodegenWorkItemBuilder(backend, options),
60 nativeEnqueuer = backend.nativeCodegenEnqueuer(), 60 nativeEnqueuer = backend.nativeCodegenEnqueuer(),
61 this._backend = backend, 61 this._listener = backend.codegenEnqueuerListener,
62 this._options = options, 62 this._options = options,
63 this.name = 'codegen enqueuer' { 63 this.name = 'codegen enqueuer' {
64 _impactVisitor = new EnqueuerImplImpactVisitor(this); 64 _impactVisitor = new EnqueuerImplImpactVisitor(this);
65 } 65 }
66 66
67 CodegenWorldBuilder get worldBuilder => _universe; 67 CodegenWorldBuilder get worldBuilder => _universe;
68 68
69 bool get queueIsEmpty => _queue.isEmpty; 69 bool get queueIsEmpty => _queue.isEmpty;
70 70
71 /// Returns [:true:] if this enqueuer is the resolution enqueuer. 71 /// Returns [:true:] if this enqueuer is the resolution enqueuer.
72 bool get isResolutionQueue => false; 72 bool get isResolutionQueue => false;
73 73
74 /// Create a [WorkItem] for [entity] and add it to the work list if it has not 74 /// Create a [WorkItem] for [entity] and add it to the work list if it has not
75 /// already been processed. 75 /// already been processed.
76 void _addToWorkList(MemberEntity entity) { 76 void _addToWorkList(MemberEntity entity) {
77 if (_processedEntities.contains(entity)) return; 77 if (_processedEntities.contains(entity)) return;
78 78
79 WorkItem workItem = _workItemBuilder.createWorkItem(entity); 79 WorkItem workItem = _workItemBuilder.createWorkItem(entity);
80 if (workItem == null) return; 80 if (workItem == null) return;
81 81
82 if (queueIsClosed) { 82 if (queueIsClosed) {
83 throw new SpannableAssertionFailure( 83 throw new SpannableAssertionFailure(
84 entity, "Codegen work list is closed. Trying to add $entity"); 84 entity, "Codegen work list is closed. Trying to add $entity");
85 } 85 }
86 86
87 applyImpact(_backend.registerUsedElement(entity, forResolution: false)); 87 applyImpact(_listener.registerUsedElement(entity));
88 _queue.add(workItem); 88 _queue.add(workItem);
89 } 89 }
90 90
91 void applyImpact(WorldImpact worldImpact, {var impactSource}) { 91 void applyImpact(WorldImpact worldImpact, {var impactSource}) {
92 if (worldImpact.isEmpty) return; 92 if (worldImpact.isEmpty) return;
93 impactStrategy.visitImpact( 93 impactStrategy.visitImpact(
94 impactSource, worldImpact, _impactVisitor, impactUse); 94 impactSource, worldImpact, _impactVisitor, impactUse);
95 } 95 }
96 96
97 void _registerInstantiatedType(ResolutionInterfaceType type, 97 void _registerInstantiatedType(ResolutionInterfaceType type,
98 {bool mirrorUsage: false, bool nativeUsage: false}) { 98 {bool mirrorUsage: false, bool nativeUsage: false}) {
99 task.measure(() { 99 task.measure(() {
100 _universe.registerTypeInstantiation(type, _applyClassUse, 100 _universe.registerTypeInstantiation(type, _applyClassUse,
101 byMirrors: mirrorUsage); 101 byMirrors: mirrorUsage);
102 if (nativeUsage) { 102 if (nativeUsage) {
103 nativeEnqueuer.onInstantiatedType(type); 103 nativeEnqueuer.onInstantiatedType(type);
104 } 104 }
105 _backend.registerInstantiatedType(type); 105 _listener.registerInstantiatedType(type);
106 }); 106 });
107 } 107 }
108 108
109 bool checkNoEnqueuedInvokedInstanceMethods() { 109 bool checkNoEnqueuedInvokedInstanceMethods() {
110 return strategy.checkEnqueuerConsistency(this); 110 return strategy.checkEnqueuerConsistency(this);
111 } 111 }
112 112
113 void checkClass(ClassEntity cls) { 113 void checkClass(ClassEntity cls) {
114 _universe.processClassMembers(cls, (MemberEntity member, useSet) { 114 _universe.processClassMembers(cls, (MemberEntity member, useSet) {
115 if (useSet.isNotEmpty) { 115 if (useSet.isNotEmpty) {
116 _backend.compiler.reporter.internalError(member, 116 throw new SpannableAssertionFailure(member,
117 'Unenqueued use of $member: ${useSet.iterable(MemberUse.values)}'); 117 'Unenqueued use of $member: ${useSet.iterable(MemberUse.values)}');
118 } 118 }
119 }); 119 });
120 } 120 }
121 121
122 /// Callback for applying the use of a [cls]. 122 /// Callback for applying the use of a [cls].
123 void _applyClassUse(ClassEntity cls, EnumSet<ClassUse> useSet) { 123 void _applyClassUse(ClassEntity cls, EnumSet<ClassUse> useSet) {
124 if (useSet.contains(ClassUse.INSTANTIATED)) { 124 if (useSet.contains(ClassUse.INSTANTIATED)) {
125 _recentClasses.add(cls); 125 _recentClasses.add(cls);
126 _universe.processClassMembers(cls, _applyMemberUse); 126 _universe.processClassMembers(cls, _applyMemberUse);
127 // We only tell the backend once that [cls] was instantiated, so 127 // We only tell the backend once that [cls] was instantiated, so
128 // any additional dependencies must be treated as global 128 // any additional dependencies must be treated as global
129 // dependencies. 129 // dependencies.
130 applyImpact( 130 applyImpact(_listener.registerInstantiatedClass(cls));
131 _backend.registerInstantiatedClass(cls, forResolution: false));
132 } 131 }
133 if (useSet.contains(ClassUse.IMPLEMENTED)) { 132 if (useSet.contains(ClassUse.IMPLEMENTED)) {
134 applyImpact(_backend.registerImplementedClass(cls, forResolution: false)); 133 applyImpact(_listener.registerImplementedClass(cls));
135 } 134 }
136 } 135 }
137 136
138 /// Callback for applying the use of a [member]. 137 /// Callback for applying the use of a [member].
139 void _applyMemberUse(Entity member, EnumSet<MemberUse> useSet) { 138 void _applyMemberUse(Entity member, EnumSet<MemberUse> useSet) {
140 if (useSet.contains(MemberUse.NORMAL)) { 139 if (useSet.contains(MemberUse.NORMAL)) {
141 _addToWorkList(member); 140 _addToWorkList(member);
142 } 141 }
143 if (useSet.contains(MemberUse.CLOSURIZE_INSTANCE)) { 142 if (useSet.contains(MemberUse.CLOSURIZE_INSTANCE)) {
144 _registerClosurizedMember(member); 143 _registerClosurizedMember(member);
145 } 144 }
146 if (useSet.contains(MemberUse.CLOSURIZE_STATIC)) { 145 if (useSet.contains(MemberUse.CLOSURIZE_STATIC)) {
147 applyImpact(_backend.registerGetOfStaticFunction()); 146 applyImpact(_listener.registerGetOfStaticFunction());
148 } 147 }
149 } 148 }
150 149
151 void processDynamicUse(DynamicUse dynamicUse) { 150 void processDynamicUse(DynamicUse dynamicUse) {
152 task.measure(() { 151 task.measure(() {
153 _universe.registerDynamicUse(dynamicUse, _applyMemberUse); 152 _universe.registerDynamicUse(dynamicUse, _applyMemberUse);
154 }); 153 });
155 } 154 }
156 155
157 void processStaticUse(StaticUse staticUse) { 156 void processStaticUse(StaticUse staticUse) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 type = _universe.registerIsCheck(type); 197 type = _universe.registerIsCheck(type);
199 // Even in checked mode, type annotations for return type and argument 198 // Even in checked mode, type annotations for return type and argument
200 // types do not imply type checks, so there should never be a check 199 // types do not imply type checks, so there should never be a check
201 // against the type variable of a typedef. 200 // against the type variable of a typedef.
202 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); 201 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef);
203 } 202 }
204 203
205 void _registerClosurizedMember(TypedElement element) { 204 void _registerClosurizedMember(TypedElement element) {
206 assert(element.isInstanceMember); 205 assert(element.isInstanceMember);
207 if (element.type.containsTypeVariables) { 206 if (element.type.containsTypeVariables) {
208 applyImpact(_backend.registerClosureWithFreeTypeVariables(element, 207 MemberElement member = element;
209 forResolution: false)); 208 applyImpact(_listener.registerClosureWithFreeTypeVariables(member));
210 } 209 }
211 applyImpact(_backend.registerBoundClosure()); 210 applyImpact(_listener.registerBoundClosure());
212 } 211 }
213 212
214 void forEach(void f(WorkItem work)) { 213 void forEach(void f(WorkItem work)) {
215 do { 214 do {
216 while (_queue.isNotEmpty) { 215 while (_queue.isNotEmpty) {
217 // TODO(johnniwinther): Find an optimal process order. 216 // TODO(johnniwinther): Find an optimal process order.
218 WorkItem work = _queue.removeLast(); 217 WorkItem work = _queue.removeLast();
219 if (!_processedEntities.contains(work.element)) { 218 if (!_processedEntities.contains(work.element)) {
220 strategy.processWorkItem(f, work); 219 strategy.processWorkItem(f, work);
221 // TODO(johnniwinther): Register the processed element here. This 220 // TODO(johnniwinther): Register the processed element here. This
222 // is currently a side-effect of calling `work.run`. 221 // is currently a side-effect of calling `work.run`.
223 _processedEntities.add(work.element); 222 _processedEntities.add(work.element);
224 } 223 }
225 } 224 }
226 List recents = _recentClasses.toList(growable: false); 225 List recents = _recentClasses.toList(growable: false);
227 _recentClasses.clear(); 226 _recentClasses.clear();
228 if (!_onQueueEmpty(recents)) _recentClasses.addAll(recents); 227 if (!_onQueueEmpty(recents)) _recentClasses.addAll(recents);
229 } while (_queue.isNotEmpty || _recentClasses.isNotEmpty); 228 } while (_queue.isNotEmpty || _recentClasses.isNotEmpty);
230 } 229 }
231 230
232 /// [_onQueueEmpty] is called whenever the queue is drained. [recentClasses] 231 /// [_onQueueEmpty] is called whenever the queue is drained. [recentClasses]
233 /// contains the set of all classes seen for the first time since 232 /// contains the set of all classes seen for the first time since
234 /// [_onQueueEmpty] was called last. A return value of [true] indicates that 233 /// [_onQueueEmpty] was called last. A return value of [true] indicates that
235 /// the [recentClasses] have been processed and may be cleared. If [false] is 234 /// the [recentClasses] have been processed and may be cleared. If [false] is
236 /// returned, [_onQueueEmpty] will be called once the queue is empty again (or 235 /// returned, [_onQueueEmpty] will be called once the queue is empty again (or
237 /// still empty) and [recentClasses] will be a superset of the current value. 236 /// still empty) and [recentClasses] will be a superset of the current value.
238 bool _onQueueEmpty(Iterable<ClassEntity> recentClasses) { 237 bool _onQueueEmpty(Iterable<ClassEntity> recentClasses) {
239 return _backend.onQueueEmpty(this, recentClasses); 238 return _listener.onQueueEmpty(this, recentClasses);
240 } 239 }
241 240
242 void logSummary(log(message)) { 241 void logSummary(log(message)) {
243 log('Compiled ${_processedEntities.length} methods.'); 242 log('Compiled ${_processedEntities.length} methods.');
244 nativeEnqueuer.logSummary(log); 243 nativeEnqueuer.logSummary(log);
245 } 244 }
246 245
247 String toString() => 'Enqueuer($name)'; 246 String toString() => 'Enqueuer($name)';
248 247
249 ImpactUseCase get impactUse => IMPACT_USE; 248 ImpactUseCase get impactUse => IMPACT_USE;
(...skipping 24 matching lines...) Expand all
274 // code for checked setters. 273 // code for checked setters.
275 if (element.isField && element.isInstanceMember) { 274 if (element.isField && element.isInstanceMember) {
276 if (!_options.enableTypeAssertions || 275 if (!_options.enableTypeAssertions ||
277 element.enclosingElement.isClosure) { 276 element.enclosingElement.isClosure) {
278 return null; 277 return null;
279 } 278 }
280 } 279 }
281 return new CodegenWorkItem(_backend, element); 280 return new CodegenWorkItem(_backend, element);
282 } 281 }
283 } 282 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/backend_usage.dart ('k') | pkg/compiler/lib/src/js_backend/mirrors_data.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698