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

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

Issue 2535143003: More refactoring of enqueuers (Closed)
Patch Set: 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
« no previous file with comments | « pkg/compiler/lib/src/enqueue.dart ('k') | pkg/compiler/lib/src/universe/world_builder.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.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 30 matching lines...) Expand all
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 extends EnqueuerImpl { 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
66 final Queue<WorkItem> queue = new Queue<WorkItem>();
67 final Map<Element, js.Expression> generatedCode = <Element, js.Expression>{};
68
69 final Set<Element> newlyEnqueuedElements;
70
71 final Set<DynamicUse> newlySeenSelectors;
72
73 bool _enabledNoSuchMethod = false;
74
75 static const ImpactUseCase IMPACT_USE =
76 const ImpactUseCase('CodegenEnqueuer');
65 77
66 CodegenEnqueuer(this.task, Compiler compiler, this.strategy) 78 CodegenEnqueuer(this.task, Compiler compiler, this.strategy)
67 : queue = new Queue<CodegenWorkItem>(), 79 : newlyEnqueuedElements = compiler.cacheStrategy.newSet(),
68 newlyEnqueuedElements = compiler.cacheStrategy.newSet(),
69 newlySeenSelectors = compiler.cacheStrategy.newSet(), 80 newlySeenSelectors = compiler.cacheStrategy.newSet(),
70 nativeEnqueuer = compiler.backend.nativeCodegenEnqueuer(), 81 nativeEnqueuer = compiler.backend.nativeCodegenEnqueuer(),
71 this.name = 'codegen enqueuer', 82 this.name = 'codegen enqueuer',
72 this._compiler = compiler { 83 this._compiler = compiler {
73 impactVisitor = new EnqueuerImplImpactVisitor(this); 84 _impactVisitor = new EnqueuerImplImpactVisitor(this);
74 } 85 }
75 86
76 CodegenWorldBuilder get universe => _universe; 87 CodegenWorldBuilder get universe => _universe;
77 88
78 Backend get backend => _compiler.backend; 89 Backend get _backend => _compiler.backend;
79 90
80 CompilerOptions get options => _compiler.options; 91 CompilerOptions get _options => _compiler.options;
81 92
82 ClosedWorld get _world => _compiler.closedWorld; 93 ClosedWorld get _world => _compiler.closedWorld;
83 94
84 bool get queueIsEmpty => queue.isEmpty; 95 bool get queueIsEmpty => queue.isEmpty;
85 96
86 /// Returns [:true:] if this enqueuer is the resolution enqueuer. 97 /// Returns [:true:] if this enqueuer is the resolution enqueuer.
87 bool get isResolutionQueue => false; 98 bool get isResolutionQueue => false;
88 99
89 DiagnosticReporter get reporter => _compiler.reporter;
90
91 /** 100 /**
92 * Documentation wanted -- johnniwinther 101 * Documentation wanted -- johnniwinther
93 * 102 *
94 * Invariant: [element] must be a declaration element. 103 * Invariant: [element] must be a declaration element.
95 */ 104 */
96 void addToWorkList(Element element) { 105 void _addToWorkList(Element element) {
97 assert(invariant(element, element.isDeclaration)); 106 assert(invariant(element, element.isDeclaration));
98 // Don't generate code for foreign elements. 107 // Don't generate code for foreign elements.
99 if (backend.isForeign(element)) return; 108 if (_backend.isForeign(element)) return;
100 109
101 // Codegen inlines field initializers. It only needs to generate 110 // Codegen inlines field initializers. It only needs to generate
102 // code for checked setters. 111 // code for checked setters.
103 if (element.isField && element.isInstanceMember) { 112 if (element.isField && element.isInstanceMember) {
104 if (!options.enableTypeAssertions || element.enclosingElement.isClosure) { 113 if (!_options.enableTypeAssertions ||
114 element.enclosingElement.isClosure) {
105 return; 115 return;
106 } 116 }
107 } 117 }
108 118
109 if (options.hasIncrementalSupport && !isProcessed(element)) { 119 if (_options.hasIncrementalSupport && !isProcessed(element)) {
110 newlyEnqueuedElements.add(element); 120 newlyEnqueuedElements.add(element);
111 } 121 }
112 122
113 if (queueIsClosed) { 123 if (queueIsClosed) {
114 throw new SpannableAssertionFailure( 124 throw new SpannableAssertionFailure(
115 element, "Codegen work list is closed. Trying to add $element"); 125 element, "Codegen work list is closed. Trying to add $element");
116 } 126 }
117 queue.add(new CodegenWorkItem(backend, element)); 127 queue.add(new CodegenWorkItem(_backend, element));
118 // TODO(sigmund): add other missing dependencies (internals, selectors 128 // TODO(sigmund): add other missing dependencies (internals, selectors
119 // enqueued after allocations). 129 // enqueued after allocations).
120 _compiler.dumpInfoTask 130 _compiler.dumpInfoTask
121 .registerDependency(_compiler.currentElement, element); 131 .registerDependency(_compiler.currentElement, element);
122 } 132 }
123 133
124 void applyImpact(WorldImpact worldImpact, {Element impactSource}) { 134 void applyImpact(WorldImpact worldImpact, {Element impactSource}) {
125 if (worldImpact.isEmpty) return; 135 if (worldImpact.isEmpty) return;
126 impactStrategy.visitImpact( 136 impactStrategy.visitImpact(
127 impactSource, worldImpact, impactVisitor, impactUse); 137 impactSource, worldImpact, _impactVisitor, impactUse);
128 }
129
130 void registerInstantiatedType(InterfaceType type) {
131 _registerInstantiatedType(type);
132 } 138 }
133 139
134 void _registerInstantiatedType(InterfaceType type, 140 void _registerInstantiatedType(InterfaceType type,
135 {bool mirrorUsage: false, bool nativeUsage: false}) { 141 {bool mirrorUsage: false, bool nativeUsage: false}) {
136 task.measure(() { 142 task.measure(() {
137 ClassElement cls = type.element; 143 ClassElement cls = type.element;
138 bool isNative = backend.isNative(cls); 144 bool isNative = _backend.isNative(cls);
139 _universe.registerTypeInstantiation(type, 145 _universe.registerTypeInstantiation(type,
140 isNative: isNative, 146 isNative: isNative,
141 byMirrors: mirrorUsage, onImplemented: (ClassElement cls) { 147 byMirrors: mirrorUsage, onImplemented: (ClassElement cls) {
142 applyImpact( 148 applyImpact(
143 backend.registerImplementedClass(cls, forResolution: false)); 149 _backend.registerImplementedClass(cls, forResolution: false));
144 }); 150 });
145 if (nativeUsage) { 151 if (nativeUsage) {
146 nativeEnqueuer.onInstantiatedType(type); 152 nativeEnqueuer.onInstantiatedType(type);
147 } 153 }
148 backend.registerInstantiatedType(type); 154 _backend.registerInstantiatedType(type);
149 // TODO(johnniwinther): Share this reasoning with [Universe]. 155 // TODO(johnniwinther): Share this reasoning with [Universe].
150 if (!cls.isAbstract || isNative || mirrorUsage) { 156 if (!cls.isAbstract || isNative || mirrorUsage) {
151 processInstantiatedClass(cls); 157 _processInstantiatedClass(cls);
152 } 158 }
153 }); 159 });
154 } 160 }
155 161
156 bool checkNoEnqueuedInvokedInstanceMethods() { 162 bool checkNoEnqueuedInvokedInstanceMethods() {
157 return strategy.checkEnqueuerConsistency(this); 163 return strategy.checkEnqueuerConsistency(this);
158 } 164 }
159 165
160 void processInstantiatedClassMembers(ClassElement cls) { 166 void processInstantiatedClassMembers(ClassElement cls) {
161 strategy.processInstantiatedClass(this, cls); 167 strategy.processInstantiatedClass(this, cls);
162 } 168 }
163 169
164 void processInstantiatedClassMember(ClassElement cls, Element member) { 170 void processInstantiatedClassMember(ClassElement cls, Element member) {
165 assert(invariant(member, member.isDeclaration)); 171 assert(invariant(member, member.isDeclaration));
166 if (isProcessed(member)) return; 172 if (isProcessed(member)) return;
167 if (!member.isInstanceMember) return; 173 if (!member.isInstanceMember) return;
168 String memberName = member.name; 174 String memberName = member.name;
169 175
170 if (member.isField) { 176 if (member.isField) {
171 // The obvious thing to test here would be "member.isNative", 177 // The obvious thing to test here would be "member.isNative",
172 // however, that only works after metadata has been parsed/analyzed, 178 // however, that only works after metadata has been parsed/analyzed,
173 // and that may not have happened yet. 179 // and that may not have happened yet.
174 // So instead we use the enclosing class, which we know have had 180 // So instead we use the enclosing class, which we know have had
175 // its metadata parsed and analyzed. 181 // its metadata parsed and analyzed.
176 // Note: this assumes that there are no non-native fields on native 182 // Note: this assumes that there are no non-native fields on native
177 // classes, which may not be the case when a native class is subclassed. 183 // classes, which may not be the case when a native class is subclassed.
178 if (backend.isNative(cls)) { 184 if (_backend.isNative(cls)) {
179 if (_universe.hasInvokedGetter(member, _world) || 185 if (_universe.hasInvokedGetter(member, _world) ||
180 _universe.hasInvocation(member, _world)) { 186 _universe.hasInvocation(member, _world)) {
181 addToWorkList(member); 187 _addToWorkList(member);
182 return; 188 return;
183 } else if (universe.hasInvokedSetter(member, _world)) { 189 } else if (universe.hasInvokedSetter(member, _world)) {
184 addToWorkList(member); 190 _addToWorkList(member);
185 return; 191 return;
186 } 192 }
187 // Native fields need to go into instanceMembersByName as they 193 // Native fields need to go into instanceMembersByName as they
188 // are virtual instantiation points and escape points. 194 // are virtual instantiation points and escape points.
189 } else { 195 } else {
190 // All field initializers must be resolved as they could 196 // All field initializers must be resolved as they could
191 // have an observable side-effect (and cannot be tree-shaken 197 // have an observable side-effect (and cannot be tree-shaken
192 // away). 198 // away).
193 addToWorkList(member); 199 _addToWorkList(member);
194 return; 200 return;
195 } 201 }
196 } else if (member.isFunction) { 202 } else if (member.isFunction) {
197 FunctionElement function = member; 203 FunctionElement function = member;
198 if (function.name == Identifiers.noSuchMethod_) { 204 if (function.name == Identifiers.noSuchMethod_) {
199 registerNoSuchMethod(function); 205 _registerNoSuchMethod(function);
200 } 206 }
201 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { 207 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) {
202 registerCallMethodWithFreeTypeVariables(function); 208 _registerCallMethodWithFreeTypeVariables(function);
203 } 209 }
204 // If there is a property access with the same name as a method we 210 // If there is a property access with the same name as a method we
205 // need to emit the method. 211 // need to emit the method.
206 if (_universe.hasInvokedGetter(function, _world)) { 212 if (_universe.hasInvokedGetter(function, _world)) {
207 registerClosurizedMember(function); 213 _registerClosurizedMember(function);
208 addToWorkList(function); 214 _addToWorkList(function);
209 return; 215 return;
210 } 216 }
211 _registerInstanceMethod(function); 217 _registerInstanceMethod(function);
212 if (_universe.hasInvocation(function, _world)) { 218 if (_universe.hasInvocation(function, _world)) {
213 addToWorkList(function); 219 _addToWorkList(function);
214 return; 220 return;
215 } 221 }
216 } else if (member.isGetter) { 222 } else if (member.isGetter) {
217 FunctionElement getter = member; 223 FunctionElement getter = member;
218 if (_universe.hasInvokedGetter(getter, _world)) { 224 if (_universe.hasInvokedGetter(getter, _world)) {
219 addToWorkList(getter); 225 _addToWorkList(getter);
220 return; 226 return;
221 } 227 }
222 // We don't know what selectors the returned closure accepts. If 228 // We don't know what selectors the returned closure accepts. If
223 // the set contains any selector we have to assume that it matches. 229 // the set contains any selector we have to assume that it matches.
224 if (_universe.hasInvocation(getter, _world)) { 230 if (_universe.hasInvocation(getter, _world)) {
225 addToWorkList(getter); 231 _addToWorkList(getter);
226 return; 232 return;
227 } 233 }
228 } else if (member.isSetter) { 234 } else if (member.isSetter) {
229 FunctionElement setter = member; 235 FunctionElement setter = member;
230 if (_universe.hasInvokedSetter(setter, _world)) { 236 if (_universe.hasInvokedSetter(setter, _world)) {
231 addToWorkList(setter); 237 _addToWorkList(setter);
232 return; 238 return;
233 } 239 }
234 } 240 }
235 241
236 // The element is not yet used. Add it to the list of instance 242 // The element is not yet used. Add it to the list of instance
237 // members to still be processed. 243 // members to still be processed.
238 instanceMembersByName 244 _instanceMembersByName
239 .putIfAbsent(memberName, () => new Set<Element>()) 245 .putIfAbsent(memberName, () => new Set<Element>())
240 .add(member); 246 .add(member);
241 } 247 }
242 248
243 // Store the member in [instanceFunctionsByName] to catch 249 // Store the member in [instanceFunctionsByName] to catch
244 // getters on the function. 250 // getters on the function.
245 void _registerInstanceMethod(MethodElement element) { 251 void _registerInstanceMethod(MethodElement element) {
246 instanceFunctionsByName 252 _instanceFunctionsByName
247 .putIfAbsent(element.name, () => new Set<Element>()) 253 .putIfAbsent(element.name, () => new Set<Element>())
248 .add(element); 254 .add(element);
249 } 255 }
250 256
251 void enableIsolateSupport() {} 257 void _processInstantiatedClass(ClassElement cls) {
Harry Terkelsen 2016/11/29 22:25:03 can we remove all enableIsolateSupport calls?
Johnni Winther 2016/11/30 08:05:23 This is only for the codegen enqueuer. The resolut
252
253 void processInstantiatedClass(ClassElement cls) {
254 task.measure(() { 258 task.measure(() {
255 if (_processedClasses.contains(cls)) return; 259 if (_processedClasses.contains(cls)) return;
256 260
257 void processClass(ClassElement superclass) { 261 void processClass(ClassElement superclass) {
258 if (_processedClasses.contains(superclass)) return; 262 if (_processedClasses.contains(superclass)) return;
259 // TODO(johnniwinther): Re-insert this invariant when unittests don't 263 // TODO(johnniwinther): Re-insert this invariant when unittests don't
260 // fail. There is already a similar invariant on the members. 264 // fail. There is already a similar invariant on the members.
261 /*assert(invariant(superclass, 265 /*assert(invariant(superclass,
262 superclass.isClosure || 266 superclass.isClosure ||
263 _compiler.enqueuer.resolution.isClassProcessed(superclass), 267 _compiler.enqueuer.resolution.isClassProcessed(superclass),
264 message: "Class $superclass has not been " 268 message: "Class $superclass has not been "
265 "processed in resolution.")); 269 "processed in resolution."));
266 */ 270 */
267 271
268 _processedClasses.add(superclass); 272 _processedClasses.add(superclass);
269 recentClasses.add(superclass); 273 _recentClasses.add(superclass);
270 superclass.implementation.forEachMember(processInstantiatedClassMember); 274 superclass.implementation.forEachMember(processInstantiatedClassMember);
271 // We only tell the backend once that [superclass] was instantiated, so 275 // We only tell the backend once that [superclass] was instantiated, so
272 // any additional dependencies must be treated as global 276 // any additional dependencies must be treated as global
273 // dependencies. 277 // dependencies.
274 applyImpact(backend.registerInstantiatedClass(superclass, 278 applyImpact(_backend.registerInstantiatedClass(superclass,
275 forResolution: false)); 279 forResolution: false));
276 } 280 }
277 281
278 ClassElement superclass = cls; 282 ClassElement superclass = cls;
279 while (superclass != null) { 283 while (superclass != null) {
280 processClass(superclass); 284 processClass(superclass);
281 superclass = superclass.superclass; 285 superclass = superclass.superclass;
282 } 286 }
283 }); 287 });
284 } 288 }
285 289
286 void registerDynamicUse(DynamicUse dynamicUse) { 290 void processDynamicUse(DynamicUse dynamicUse) {
287 task.measure(() { 291 task.measure(() {
288 if (_universe.registerDynamicUse(dynamicUse)) { 292 if (_universe.registerDynamicUse(dynamicUse)) {
289 handleUnseenSelector(dynamicUse); 293 _handleUnseenSelector(dynamicUse);
290 } 294 }
291 }); 295 });
292 } 296 }
293 297
294 void processSet( 298 void _processSet(
295 Map<String, Set<Element>> map, String memberName, bool f(Element e)) { 299 Map<String, Set<Element>> map, String memberName, bool f(Element e)) {
296 Set<Element> members = map[memberName]; 300 Set<Element> members = map[memberName];
297 if (members == null) return; 301 if (members == null) return;
298 // [f] might add elements to [: map[memberName] :] during the loop below 302 // [f] might add elements to [: map[memberName] :] during the loop below
299 // so we create a new list for [: map[memberName] :] and prepend the 303 // so we create a new list for [: map[memberName] :] and prepend the
300 // [remaining] members after the loop. 304 // [remaining] members after the loop.
301 map[memberName] = new Set<Element>(); 305 map[memberName] = new Set<Element>();
302 Set<Element> remaining = new Set<Element>(); 306 Set<Element> remaining = new Set<Element>();
303 for (Element member in members) { 307 for (Element member in members) {
304 if (!f(member)) remaining.add(member); 308 if (!f(member)) remaining.add(member);
305 } 309 }
306 map[memberName].addAll(remaining); 310 map[memberName].addAll(remaining);
307 } 311 }
308 312
309 processInstanceMembers(String n, bool f(Element e)) { 313 void _processInstanceMembers(String n, bool f(Element e)) {
310 processSet(instanceMembersByName, n, f); 314 _processSet(_instanceMembersByName, n, f);
311 } 315 }
312 316
313 processInstanceFunctions(String n, bool f(Element e)) { 317 void _processInstanceFunctions(String n, bool f(Element e)) {
314 processSet(instanceFunctionsByName, n, f); 318 _processSet(_instanceFunctionsByName, n, f);
315 } 319 }
316 320
317 void _handleUnseenSelector(DynamicUse universeSelector) { 321 void _handleUnseenSelector(DynamicUse dynamicUse) {
318 strategy.processDynamicUse(this, universeSelector); 322 if (_options.hasIncrementalSupport) {
319 } 323 newlySeenSelectors.add(dynamicUse);
320 324 }
321 void handleUnseenSelectorInternal(DynamicUse dynamicUse) {
322 Selector selector = dynamicUse.selector; 325 Selector selector = dynamicUse.selector;
323 String methodName = selector.name; 326 String methodName = selector.name;
324 processInstanceMembers(methodName, (Element member) { 327 _processInstanceMembers(methodName, (Element member) {
325 if (dynamicUse.appliesUnnamed(member, _world)) { 328 if (dynamicUse.appliesUnnamed(member, _world)) {
326 if (member.isFunction && selector.isGetter) { 329 if (member.isFunction && selector.isGetter) {
327 registerClosurizedMember(member); 330 _registerClosurizedMember(member);
328 } 331 }
329 addToWorkList(member); 332 _addToWorkList(member);
330 return true; 333 return true;
331 } 334 }
332 return false; 335 return false;
333 }); 336 });
334 if (selector.isGetter) { 337 if (selector.isGetter) {
335 processInstanceFunctions(methodName, (Element member) { 338 _processInstanceFunctions(methodName, (Element member) {
336 if (dynamicUse.appliesUnnamed(member, _world)) { 339 if (dynamicUse.appliesUnnamed(member, _world)) {
337 registerClosurizedMember(member); 340 _registerClosurizedMember(member);
338 return true; 341 return true;
339 } 342 }
340 return false; 343 return false;
341 }); 344 });
342 } 345 }
343 } 346 }
344 347
345 /** 348 void processStaticUse(StaticUse staticUse) {
346 * Documentation wanted -- johnniwinther
347 *
348 * Invariant: [element] must be a declaration element.
349 */
350 void registerStaticUse(StaticUse staticUse) {
351 strategy.processStaticUse(this, staticUse);
352 }
353
354 void registerStaticUseInternal(StaticUse staticUse) {
355 Element element = staticUse.element; 349 Element element = staticUse.element;
356 assert(invariant(element, element.isDeclaration, 350 assert(invariant(element, element.isDeclaration,
357 message: "Element ${element} is not the declaration.")); 351 message: "Element ${element} is not the declaration."));
358 _universe.registerStaticUse(staticUse); 352 _universe.registerStaticUse(staticUse);
359 applyImpact(backend.registerStaticUse(element, forResolution: false)); 353 applyImpact(_backend.registerStaticUse(element, forResolution: false));
360 bool addElement = true; 354 bool addElement = true;
361 switch (staticUse.kind) { 355 switch (staticUse.kind) {
362 case StaticUseKind.STATIC_TEAR_OFF: 356 case StaticUseKind.STATIC_TEAR_OFF:
363 applyImpact(backend.registerGetOfStaticFunction()); 357 applyImpact(_backend.registerGetOfStaticFunction());
364 break; 358 break;
365 case StaticUseKind.FIELD_GET: 359 case StaticUseKind.FIELD_GET:
366 case StaticUseKind.FIELD_SET: 360 case StaticUseKind.FIELD_SET:
367 case StaticUseKind.CLOSURE: 361 case StaticUseKind.CLOSURE:
368 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and 362 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and
369 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. 363 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue.
370 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot 364 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot
371 // enqueue. 365 // enqueue.
372 addElement = false; 366 addElement = false;
373 break; 367 break;
374 case StaticUseKind.SUPER_FIELD_SET: 368 case StaticUseKind.SUPER_FIELD_SET:
375 case StaticUseKind.SUPER_TEAR_OFF: 369 case StaticUseKind.SUPER_TEAR_OFF:
376 case StaticUseKind.GENERAL: 370 case StaticUseKind.GENERAL:
377 case StaticUseKind.DIRECT_USE: 371 case StaticUseKind.DIRECT_USE:
378 break; 372 break;
379 case StaticUseKind.CONSTRUCTOR_INVOKE: 373 case StaticUseKind.CONSTRUCTOR_INVOKE:
380 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: 374 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
381 case StaticUseKind.REDIRECTION: 375 case StaticUseKind.REDIRECTION:
382 registerTypeUseInternal(new TypeUse.instantiation(staticUse.type)); 376 processTypeUse(new TypeUse.instantiation(staticUse.type));
383 break; 377 break;
384 case StaticUseKind.DIRECT_INVOKE: 378 case StaticUseKind.DIRECT_INVOKE:
385 _registerInstanceMethod(staticUse.element); 379 _registerInstanceMethod(staticUse.element);
386 break; 380 break;
387 } 381 }
388 if (addElement) { 382 if (addElement) {
389 addToWorkList(element); 383 _addToWorkList(element);
390 } 384 }
391 } 385 }
392 386
393 void registerTypeUse(TypeUse typeUse) { 387 void processTypeUse(TypeUse typeUse) {
394 strategy.processTypeUse(this, typeUse);
395 }
396
397 void registerTypeUseInternal(TypeUse typeUse) {
398 DartType type = typeUse.type; 388 DartType type = typeUse.type;
399 switch (typeUse.kind) { 389 switch (typeUse.kind) {
400 case TypeUseKind.INSTANTIATION: 390 case TypeUseKind.INSTANTIATION:
401 _registerInstantiatedType(type); 391 _registerInstantiatedType(type);
402 break; 392 break;
403 case TypeUseKind.MIRROR_INSTANTIATION: 393 case TypeUseKind.MIRROR_INSTANTIATION:
404 _registerInstantiatedType(type, mirrorUsage: true); 394 _registerInstantiatedType(type, mirrorUsage: true);
405 break; 395 break;
406 case TypeUseKind.NATIVE_INSTANTIATION: 396 case TypeUseKind.NATIVE_INSTANTIATION:
407 _registerInstantiatedType(type, nativeUsage: true); 397 _registerInstantiatedType(type, nativeUsage: true);
408 break; 398 break;
409 case TypeUseKind.IS_CHECK: 399 case TypeUseKind.IS_CHECK:
410 case TypeUseKind.AS_CAST: 400 case TypeUseKind.AS_CAST:
411 case TypeUseKind.CATCH_TYPE: 401 case TypeUseKind.CATCH_TYPE:
412 _registerIsCheck(type); 402 _registerIsCheck(type);
413 break; 403 break;
414 case TypeUseKind.CHECKED_MODE_CHECK: 404 case TypeUseKind.CHECKED_MODE_CHECK:
415 if (options.enableTypeAssertions) { 405 if (_options.enableTypeAssertions) {
416 _registerIsCheck(type); 406 _registerIsCheck(type);
417 } 407 }
418 break; 408 break;
419 case TypeUseKind.TYPE_LITERAL: 409 case TypeUseKind.TYPE_LITERAL:
420 break; 410 break;
421 } 411 }
422 } 412 }
423 413
424 void _registerIsCheck(DartType type) { 414 void _registerIsCheck(DartType type) {
425 type = _universe.registerIsCheck(type, _compiler.resolution); 415 type = _universe.registerIsCheck(type, _compiler.resolution);
426 // Even in checked mode, type annotations for return type and argument 416 // Even in checked mode, type annotations for return type and argument
427 // types do not imply type checks, so there should never be a check 417 // types do not imply type checks, so there should never be a check
428 // against the type variable of a typedef. 418 // against the type variable of a typedef.
429 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); 419 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef);
430 } 420 }
431 421
432 void registerCallMethodWithFreeTypeVariables(Element element) { 422 void _registerCallMethodWithFreeTypeVariables(Element element) {
433 applyImpact(backend.registerCallMethodWithFreeTypeVariables(element, 423 applyImpact(_backend.registerCallMethodWithFreeTypeVariables(element,
434 forResolution: false)); 424 forResolution: false));
435 } 425 }
436 426
437 void registerClosurizedMember(TypedElement element) { 427 void _registerClosurizedMember(TypedElement element) {
438 assert(element.isInstanceMember); 428 assert(element.isInstanceMember);
439 if (element.type.containsTypeVariables) { 429 if (element.type.containsTypeVariables) {
440 applyImpact(backend.registerClosureWithFreeTypeVariables(element, 430 applyImpact(_backend.registerClosureWithFreeTypeVariables(element,
441 forResolution: false)); 431 forResolution: false));
442 } 432 }
443 applyImpact(backend.registerBoundClosure()); 433 applyImpact(_backend.registerBoundClosure());
444 } 434 }
445 435
446 void forEach(void f(WorkItem work)) { 436 void forEach(void f(WorkItem work)) {
447 do { 437 do {
448 while (queue.isNotEmpty) { 438 while (queue.isNotEmpty) {
449 // TODO(johnniwinther): Find an optimal process order. 439 // TODO(johnniwinther): Find an optimal process order.
450 WorkItem work = queue.removeLast(); 440 WorkItem work = queue.removeLast();
451 if (!isProcessed(work.element)) { 441 if (!isProcessed(work.element)) {
452 strategy.processWorkItem(f, work); 442 strategy.processWorkItem(f, work);
453 // TODO(johnniwinther): Register the processed element here. This 443 // TODO(johnniwinther): Register the processed element here. This
454 // is currently a side-effect of calling `work.run`. 444 // is currently a side-effect of calling `work.run`.
455 } 445 }
456 } 446 }
457 List recents = recentClasses.toList(growable: false); 447 List recents = _recentClasses.toList(growable: false);
458 recentClasses.clear(); 448 _recentClasses.clear();
459 if (!onQueueEmpty(recents)) recentClasses.addAll(recents); 449 if (!_onQueueEmpty(recents)) _recentClasses.addAll(recents);
460 } while (queue.isNotEmpty || recentClasses.isNotEmpty); 450 } while (queue.isNotEmpty || _recentClasses.isNotEmpty);
461 } 451 }
462 452
463 /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses] 453 /// [_onQueueEmpty] is called whenever the queue is drained. [recentClasses]
464 /// contains the set of all classes seen for the first time since 454 /// contains the set of all classes seen for the first time since
465 /// [onQueueEmpty] was called last. A return value of [true] indicates that 455 /// [_onQueueEmpty] was called last. A return value of [true] indicates that
466 /// the [recentClasses] have been processed and may be cleared. If [false] is 456 /// the [recentClasses] have been processed and may be cleared. If [false] is
467 /// returned, [onQueueEmpty] will be called once the queue is empty again (or 457 /// returned, [_onQueueEmpty] will be called once the queue is empty again (or
468 /// still empty) and [recentClasses] will be a superset of the current value. 458 /// still empty) and [recentClasses] will be a superset of the current value.
469 bool onQueueEmpty(Iterable<ClassElement> recentClasses) { 459 bool _onQueueEmpty(Iterable<ClassElement> recentClasses) {
470 return backend.onQueueEmpty(this, recentClasses); 460 return _backend.onQueueEmpty(this, recentClasses);
471 } 461 }
472 462
473 void logSummary(log(message)) { 463 void logSummary(log(message)) {
474 _logSpecificSummary(log); 464 log('Compiled ${generatedCode.length} methods.');
475 nativeEnqueuer.logSummary(log); 465 nativeEnqueuer.logSummary(log);
476 } 466 }
477 467
478 String toString() => 'Enqueuer($name)'; 468 String toString() => 'Enqueuer($name)';
479 469
480 void _forgetElement(Element element) { 470 void _forgetElement(Element element) {
481 _universe.forgetElement(element, _compiler); 471 _universe.forgetElement(element, _compiler);
482 _processedClasses.remove(element); 472 _processedClasses.remove(element);
483 instanceMembersByName[element.name]?.remove(element); 473 _instanceMembersByName[element.name]?.remove(element);
484 instanceFunctionsByName[element.name]?.remove(element); 474 _instanceFunctionsByName[element.name]?.remove(element);
485 } 475 }
486 476
487 final Queue<CodegenWorkItem> queue;
488 final Map<Element, js.Expression> generatedCode = <Element, js.Expression>{};
489
490 final Set<Element> newlyEnqueuedElements;
491
492 final Set<DynamicUse> newlySeenSelectors;
493
494 bool enabledNoSuchMethod = false;
495
496 static const ImpactUseCase IMPACT_USE =
497 const ImpactUseCase('CodegenEnqueuer');
498
499 ImpactUseCase get impactUse => IMPACT_USE; 477 ImpactUseCase get impactUse => IMPACT_USE;
500 478
501 bool isProcessed(Element member) => 479 bool isProcessed(Element member) =>
502 member.isAbstract || generatedCode.containsKey(member); 480 member.isAbstract || generatedCode.containsKey(member);
503 481
504 void registerNoSuchMethod(Element element) { 482 void _registerNoSuchMethod(Element element) {
505 if (!enabledNoSuchMethod && backend.enabledNoSuchMethod) { 483 if (!_enabledNoSuchMethod && _backend.enabledNoSuchMethod) {
506 applyImpact(backend.enableNoSuchMethod()); 484 applyImpact(_backend.enableNoSuchMethod());
507 enabledNoSuchMethod = true; 485 _enabledNoSuchMethod = true;
508 } 486 }
509 } 487 }
510 488
511 void _logSpecificSummary(log(message)) {
512 log('Compiled ${generatedCode.length} methods.');
513 }
514
515 void forgetElement(Element element, Compiler compiler) { 489 void forgetElement(Element element, Compiler compiler) {
516 _forgetElement(element); 490 _forgetElement(element);
517 generatedCode.remove(element); 491 generatedCode.remove(element);
518 if (element is MemberElement) { 492 if (element is MemberElement) {
519 for (Element closure in element.nestedClosures) { 493 for (Element closure in element.nestedClosures) {
520 generatedCode.remove(closure); 494 generatedCode.remove(closure);
521 removeFromSet(instanceMembersByName, closure); 495 removeFromSet(_instanceMembersByName, closure);
522 removeFromSet(instanceFunctionsByName, closure); 496 removeFromSet(_instanceFunctionsByName, closure);
523 } 497 }
524 } 498 }
525 } 499 }
526 500
527 void handleUnseenSelector(DynamicUse dynamicUse) {
528 if (options.hasIncrementalSupport) {
529 newlySeenSelectors.add(dynamicUse);
530 }
531 _handleUnseenSelector(dynamicUse);
532 }
533
534 @override 501 @override
535 Iterable<Entity> get processedEntities => generatedCode.keys; 502 Iterable<Entity> get processedEntities => generatedCode.keys;
536 503
537 @override 504 @override
538 Iterable<ClassElement> get processedClasses => _processedClasses; 505 Iterable<ClassElement> get processedClasses => _processedClasses;
539 } 506 }
540 507
541 void removeFromSet(Map<String, Set<Element>> map, Element element) { 508 void removeFromSet(Map<String, Set<Element>> map, Element element) {
542 Set<Element> set = map[element.name]; 509 Set<Element> set = map[element.name];
543 if (set == null) return; 510 if (set == null) return;
544 set.remove(element); 511 set.remove(element);
545 } 512 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/enqueue.dart ('k') | pkg/compiler/lib/src/universe/world_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698