OLD | NEW |
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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 /// Returns [:true:] if [member] has been processed by this enqueuer. | 114 /// Returns [:true:] if [member] has been processed by this enqueuer. |
115 bool isProcessed(Element member); | 115 bool isProcessed(Element member); |
116 | 116 |
117 Iterable<Entity> get processedEntities; | 117 Iterable<Entity> get processedEntities; |
118 | 118 |
119 Iterable<ClassElement> get processedClasses; | 119 Iterable<ClassElement> get processedClasses; |
120 } | 120 } |
121 | 121 |
122 abstract class EnqueuerImpl extends Enqueuer { | 122 abstract class EnqueuerImpl extends Enqueuer { |
123 CompilerTask get task; | 123 CompilerTask get task; |
| 124 EnqueuerStrategy get strategy; |
124 void processInstantiatedClassMembers(ClassElement cls); | 125 void processInstantiatedClassMembers(ClassElement cls); |
125 void processInstantiatedClassMember(ClassElement cls, Element member); | 126 void processInstantiatedClassMember(ClassElement cls, Element member); |
126 void registerStaticUse(StaticUse staticUse); | 127 void processStaticUse(StaticUse staticUse); |
127 void registerStaticUseInternal(StaticUse staticUse); | 128 void processTypeUse(TypeUse typeUse); |
128 void registerTypeUse(TypeUse typeUse); | 129 void processDynamicUse(DynamicUse dynamicUse); |
129 void registerTypeUseInternal(TypeUse typeUse); | |
130 void registerDynamicUse(DynamicUse dynamicUse); | |
131 void handleUnseenSelectorInternal(DynamicUse dynamicUse); | |
132 } | 130 } |
133 | 131 |
134 /// [Enqueuer] which is specific to resolution. | 132 /// [Enqueuer] which is specific to resolution. |
135 class ResolutionEnqueuer extends EnqueuerImpl { | 133 class ResolutionEnqueuer extends EnqueuerImpl { |
| 134 static const ImpactUseCase IMPACT_USE = |
| 135 const ImpactUseCase('ResolutionEnqueuer'); |
| 136 |
136 final CompilerTask task; | 137 final CompilerTask task; |
137 final String name; | 138 final String name; |
138 final Resolution resolution; | 139 final Resolution _resolution; |
139 final CompilerOptions options; | 140 final CompilerOptions _options; |
140 final Backend backend; | 141 final Backend backend; |
141 final GlobalDependencyRegistry globalDependencies; | 142 final GlobalDependencyRegistry _globalDependencies; |
142 final CommonElements commonElements; | 143 final CommonElements _commonElements; |
143 final native.NativeEnqueuer nativeEnqueuer; | 144 final native.NativeEnqueuer nativeEnqueuer; |
144 | 145 |
145 final EnqueuerStrategy strategy; | 146 final EnqueuerStrategy strategy; |
146 final Map<String, Set<Element>> instanceMembersByName = | 147 final Map<String, Set<Element>> _instanceMembersByName = |
147 new Map<String, Set<Element>>(); | 148 new Map<String, Set<Element>>(); |
148 final Map<String, Set<Element>> instanceFunctionsByName = | 149 final Map<String, Set<Element>> _instanceFunctionsByName = |
149 new Map<String, Set<Element>>(); | 150 new Map<String, Set<Element>>(); |
150 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); | 151 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); |
151 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); | 152 Set<ClassElement> _recentClasses = new Setlet<ClassElement>(); |
152 final ResolutionWorldBuilderImpl _universe; | 153 final ResolutionWorldBuilderImpl _universe; |
153 | 154 |
154 bool queueIsClosed = false; | 155 bool queueIsClosed = false; |
155 | 156 |
156 WorldImpactVisitor impactVisitor; | 157 WorldImpactVisitor _impactVisitor; |
| 158 |
| 159 /// All declaration elements that have been processed by the resolver. |
| 160 final Set<AstElement> processedElements = new Set<AstElement>(); |
| 161 |
| 162 final Queue<WorkItem> _queue = new Queue<WorkItem>(); |
| 163 |
| 164 /// Queue of deferred resolution actions to execute when the resolution queue |
| 165 /// has been emptied. |
| 166 final Queue<_DeferredAction> _deferredQueue = new Queue<_DeferredAction>(); |
157 | 167 |
158 ResolutionEnqueuer( | 168 ResolutionEnqueuer( |
159 this.task, | 169 this.task, |
160 this.options, | 170 this._options, |
161 this.resolution, | 171 this._resolution, |
162 this.strategy, | 172 this.strategy, |
163 this.globalDependencies, | 173 this._globalDependencies, |
164 Backend backend, | 174 Backend backend, |
165 CommonElements commonElements, | 175 CommonElements commonElements, |
166 CacheStrategy cacheStrategy, | 176 CacheStrategy cacheStrategy, |
167 [this.name = 'resolution enqueuer']) | 177 [this.name = 'resolution enqueuer']) |
168 : this.backend = backend, | 178 : this.backend = backend, |
169 this.commonElements = commonElements, | 179 this._commonElements = commonElements, |
170 this.nativeEnqueuer = backend.nativeResolutionEnqueuer(), | 180 this.nativeEnqueuer = backend.nativeResolutionEnqueuer(), |
171 processedElements = new Set<AstElement>(), | |
172 queue = new Queue<ResolutionWorkItem>(), | |
173 deferredQueue = new Queue<_DeferredAction>(), | |
174 _universe = new ResolutionWorldBuilderImpl( | 181 _universe = new ResolutionWorldBuilderImpl( |
175 backend, commonElements, cacheStrategy, const TypeMaskStrategy()) { | 182 backend, commonElements, cacheStrategy, const TypeMaskStrategy()) { |
176 impactVisitor = new EnqueuerImplImpactVisitor(this); | 183 _impactVisitor = new EnqueuerImplImpactVisitor(this); |
177 } | 184 } |
178 | 185 |
179 ResolutionWorldBuilder get universe => _universe; | 186 ResolutionWorldBuilder get universe => _universe; |
180 | 187 |
181 OpenWorld get openWorld => universe.openWorld; | 188 OpenWorld get _openWorld => universe.openWorld; |
182 | 189 |
183 bool get queueIsEmpty => queue.isEmpty; | 190 bool get queueIsEmpty => _queue.isEmpty; |
184 | 191 |
185 DiagnosticReporter get reporter => resolution.reporter; | 192 DiagnosticReporter get _reporter => _resolution.reporter; |
186 | |
187 bool isClassProcessed(ClassElement cls) => _processedClasses.contains(cls); | |
188 | 193 |
189 Iterable<ClassElement> get processedClasses => _processedClasses; | 194 Iterable<ClassElement> get processedClasses => _processedClasses; |
190 | 195 |
191 /** | |
192 * Documentation wanted -- johnniwinther | |
193 * | |
194 * Invariant: [element] must be a declaration element. | |
195 */ | |
196 void addToWorkList(Element element) { | |
197 assert(invariant(element, element.isDeclaration)); | |
198 internalAddToWorkList(element); | |
199 } | |
200 | |
201 void applyImpact(WorldImpact worldImpact, {Element impactSource}) { | 196 void applyImpact(WorldImpact worldImpact, {Element impactSource}) { |
202 if (worldImpact.isEmpty) return; | 197 if (worldImpact.isEmpty) return; |
203 impactStrategy.visitImpact( | 198 impactStrategy.visitImpact( |
204 impactSource, worldImpact, impactVisitor, impactUse); | 199 impactSource, worldImpact, _impactVisitor, impactUse); |
205 } | |
206 | |
207 void registerInstantiatedType(InterfaceType type) { | |
208 _registerInstantiatedType(type, globalDependency: true); | |
209 } | 200 } |
210 | 201 |
211 void _registerInstantiatedType(InterfaceType type, | 202 void _registerInstantiatedType(InterfaceType type, |
212 {ConstructorElement constructor, | 203 {ConstructorElement constructor, |
213 bool mirrorUsage: false, | 204 bool mirrorUsage: false, |
214 bool nativeUsage: false, | 205 bool nativeUsage: false, |
215 bool globalDependency: false, | 206 bool globalDependency: false, |
216 bool isRedirection: false}) { | 207 bool isRedirection: false}) { |
217 task.measure(() { | 208 task.measure(() { |
218 ClassElement cls = type.element; | 209 ClassElement cls = type.element; |
219 cls.ensureResolved(resolution); | 210 cls.ensureResolved(_resolution); |
220 bool isNative = backend.isNative(cls); | 211 bool isNative = backend.isNative(cls); |
221 _universe.registerTypeInstantiation(type, | 212 _universe.registerTypeInstantiation(type, |
222 constructor: constructor, | 213 constructor: constructor, |
223 isNative: isNative, | 214 isNative: isNative, |
224 byMirrors: mirrorUsage, | 215 byMirrors: mirrorUsage, |
225 isRedirection: isRedirection, onImplemented: (ClassElement cls) { | 216 isRedirection: isRedirection, onImplemented: (ClassElement cls) { |
226 applyImpact(backend.registerImplementedClass(cls, forResolution: true)); | 217 applyImpact(backend.registerImplementedClass(cls, forResolution: true)); |
227 }); | 218 }); |
228 if (globalDependency && !mirrorUsage) { | 219 if (globalDependency && !mirrorUsage) { |
229 globalDependencies.registerDependency(type.element); | 220 _globalDependencies.registerDependency(type.element); |
230 } | 221 } |
231 if (nativeUsage) { | 222 if (nativeUsage) { |
232 nativeEnqueuer.onInstantiatedType(type); | 223 nativeEnqueuer.onInstantiatedType(type); |
233 } | 224 } |
234 backend.registerInstantiatedType(type); | 225 backend.registerInstantiatedType(type); |
235 // TODO(johnniwinther): Share this reasoning with [Universe]. | 226 // TODO(johnniwinther): Share this reasoning with [Universe]. |
236 if (!cls.isAbstract || isNative || mirrorUsage) { | 227 if (!cls.isAbstract || isNative || mirrorUsage) { |
237 processInstantiatedClass(cls); | 228 _processInstantiatedClass(cls); |
238 } | 229 } |
239 }); | 230 }); |
240 } | 231 } |
241 | 232 |
242 bool checkNoEnqueuedInvokedInstanceMethods() { | 233 bool checkNoEnqueuedInvokedInstanceMethods() { |
243 return strategy.checkEnqueuerConsistency(this); | 234 return strategy.checkEnqueuerConsistency(this); |
244 } | 235 } |
245 | 236 |
246 void processInstantiatedClassMembers(ClassElement cls) { | 237 void processInstantiatedClassMembers(ClassElement cls) { |
247 strategy.processInstantiatedClass(this, cls); | 238 strategy.processInstantiatedClass(this, cls); |
248 } | 239 } |
249 | 240 |
250 void processInstantiatedClassMember(ClassElement cls, Element member) { | 241 void processInstantiatedClassMember(ClassElement cls, Element member) { |
251 assert(invariant(member, member.isDeclaration)); | 242 assert(invariant(member, member.isDeclaration)); |
252 if (isProcessed(member)) return; | 243 if (isProcessed(member)) return; |
253 if (!member.isInstanceMember) return; | 244 if (!member.isInstanceMember) return; |
254 String memberName = member.name; | 245 String memberName = member.name; |
255 | 246 |
256 if (member.isField) { | 247 if (member.isField) { |
257 // The obvious thing to test here would be "member.isNative", | 248 // The obvious thing to test here would be "member.isNative", |
258 // however, that only works after metadata has been parsed/analyzed, | 249 // however, that only works after metadata has been parsed/analyzed, |
259 // and that may not have happened yet. | 250 // and that may not have happened yet. |
260 // So instead we use the enclosing class, which we know have had | 251 // So instead we use the enclosing class, which we know have had |
261 // its metadata parsed and analyzed. | 252 // its metadata parsed and analyzed. |
262 // Note: this assumes that there are no non-native fields on native | 253 // Note: this assumes that there are no non-native fields on native |
263 // classes, which may not be the case when a native class is subclassed. | 254 // classes, which may not be the case when a native class is subclassed. |
264 if (backend.isNative(cls)) { | 255 if (backend.isNative(cls)) { |
265 openWorld.registerUsedElement(member); | 256 _openWorld.registerUsedElement(member); |
266 if (_universe.hasInvokedGetter(member, openWorld) || | 257 if (_universe.hasInvokedGetter(member, _openWorld) || |
267 _universe.hasInvocation(member, openWorld)) { | 258 _universe.hasInvocation(member, _openWorld)) { |
268 addToWorkList(member); | 259 _addToWorkList(member); |
269 return; | 260 return; |
270 } | 261 } |
271 if (_universe.hasInvokedSetter(member, openWorld)) { | 262 if (_universe.hasInvokedSetter(member, _openWorld)) { |
272 addToWorkList(member); | 263 _addToWorkList(member); |
273 return; | 264 return; |
274 } | 265 } |
275 // Native fields need to go into instanceMembersByName as they | 266 // Native fields need to go into instanceMembersByName as they |
276 // are virtual instantiation points and escape points. | 267 // are virtual instantiation points and escape points. |
277 } else { | 268 } else { |
278 // All field initializers must be resolved as they could | 269 // All field initializers must be resolved as they could |
279 // have an observable side-effect (and cannot be tree-shaken | 270 // have an observable side-effect (and cannot be tree-shaken |
280 // away). | 271 // away). |
281 addToWorkList(member); | 272 _addToWorkList(member); |
282 return; | 273 return; |
283 } | 274 } |
284 } else if (member.isFunction) { | 275 } else if (member.isFunction) { |
285 FunctionElement function = member; | 276 FunctionElement function = member; |
286 function.computeType(resolution); | 277 function.computeType(_resolution); |
287 if (function.name == Identifiers.noSuchMethod_) { | 278 if (function.name == Identifiers.noSuchMethod_) { |
288 registerNoSuchMethod(function); | 279 _registerNoSuchMethod(function); |
289 } | 280 } |
290 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { | 281 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { |
291 _registerCallMethodWithFreeTypeVariables(function); | 282 _registerCallMethodWithFreeTypeVariables(function); |
292 } | 283 } |
293 // If there is a property access with the same name as a method we | 284 // If there is a property access with the same name as a method we |
294 // need to emit the method. | 285 // need to emit the method. |
295 if (_universe.hasInvokedGetter(function, openWorld)) { | 286 if (_universe.hasInvokedGetter(function, _openWorld)) { |
296 registerClosurizedMember(function); | 287 _registerClosurizedMember(function); |
297 addToWorkList(function); | 288 _addToWorkList(function); |
298 return; | 289 return; |
299 } | 290 } |
300 // Store the member in [instanceFunctionsByName] to catch | 291 // Store the member in [instanceFunctionsByName] to catch |
301 // getters on the function. | 292 // getters on the function. |
302 instanceFunctionsByName | 293 _instanceFunctionsByName |
303 .putIfAbsent(memberName, () => new Set<Element>()) | 294 .putIfAbsent(memberName, () => new Set<Element>()) |
304 .add(member); | 295 .add(member); |
305 if (_universe.hasInvocation(function, openWorld)) { | 296 if (_universe.hasInvocation(function, _openWorld)) { |
306 addToWorkList(function); | 297 _addToWorkList(function); |
307 return; | 298 return; |
308 } | 299 } |
309 } else if (member.isGetter) { | 300 } else if (member.isGetter) { |
310 FunctionElement getter = member; | 301 FunctionElement getter = member; |
311 getter.computeType(resolution); | 302 getter.computeType(_resolution); |
312 if (_universe.hasInvokedGetter(getter, openWorld)) { | 303 if (_universe.hasInvokedGetter(getter, _openWorld)) { |
313 addToWorkList(getter); | 304 _addToWorkList(getter); |
314 return; | 305 return; |
315 } | 306 } |
316 // We don't know what selectors the returned closure accepts. If | 307 // We don't know what selectors the returned closure accepts. If |
317 // the set contains any selector we have to assume that it matches. | 308 // the set contains any selector we have to assume that it matches. |
318 if (_universe.hasInvocation(getter, openWorld)) { | 309 if (_universe.hasInvocation(getter, _openWorld)) { |
319 addToWorkList(getter); | 310 _addToWorkList(getter); |
320 return; | 311 return; |
321 } | 312 } |
322 } else if (member.isSetter) { | 313 } else if (member.isSetter) { |
323 FunctionElement setter = member; | 314 FunctionElement setter = member; |
324 setter.computeType(resolution); | 315 setter.computeType(_resolution); |
325 if (_universe.hasInvokedSetter(setter, openWorld)) { | 316 if (_universe.hasInvokedSetter(setter, _openWorld)) { |
326 addToWorkList(setter); | 317 _addToWorkList(setter); |
327 return; | 318 return; |
328 } | 319 } |
329 } | 320 } |
330 | 321 |
331 // The element is not yet used. Add it to the list of instance | 322 // The element is not yet used. Add it to the list of instance |
332 // members to still be processed. | 323 // members to still be processed. |
333 instanceMembersByName | 324 _instanceMembersByName |
334 .putIfAbsent(memberName, () => new Set<Element>()) | 325 .putIfAbsent(memberName, () => new Set<Element>()) |
335 .add(member); | 326 .add(member); |
336 } | 327 } |
337 | 328 |
338 void processInstantiatedClass(ClassElement cls) { | 329 void _processInstantiatedClass(ClassElement cls) { |
339 task.measure(() { | 330 task.measure(() { |
340 if (_processedClasses.contains(cls)) return; | 331 if (_processedClasses.contains(cls)) return; |
341 // The class must be resolved to compute the set of all | 332 // The class must be resolved to compute the set of all |
342 // supertypes. | 333 // supertypes. |
343 cls.ensureResolved(resolution); | 334 cls.ensureResolved(_resolution); |
344 | 335 |
345 void processClass(ClassElement superclass) { | 336 void processClass(ClassElement superclass) { |
346 if (_processedClasses.contains(superclass)) return; | 337 if (_processedClasses.contains(superclass)) return; |
347 | 338 |
348 _processedClasses.add(superclass); | 339 _processedClasses.add(superclass); |
349 recentClasses.add(superclass); | 340 _recentClasses.add(superclass); |
350 superclass.ensureResolved(resolution); | 341 superclass.ensureResolved(_resolution); |
351 superclass.implementation.forEachMember(processInstantiatedClassMember); | 342 superclass.implementation.forEachMember(processInstantiatedClassMember); |
352 resolution.ensureClassMembers(superclass); | 343 _resolution.ensureClassMembers(superclass); |
353 // We only tell the backend once that [superclass] was instantiated, so | 344 // We only tell the backend once that [superclass] was instantiated, so |
354 // any additional dependencies must be treated as global | 345 // any additional dependencies must be treated as global |
355 // dependencies. | 346 // dependencies. |
356 applyImpact( | 347 applyImpact( |
357 backend.registerInstantiatedClass(superclass, forResolution: true)); | 348 backend.registerInstantiatedClass(superclass, forResolution: true)); |
358 } | 349 } |
359 | 350 |
360 ClassElement superclass = cls; | 351 ClassElement superclass = cls; |
361 while (superclass != null) { | 352 while (superclass != null) { |
362 processClass(superclass); | 353 processClass(superclass); |
363 superclass = superclass.superclass; | 354 superclass = superclass.superclass; |
364 } | 355 } |
365 }); | 356 }); |
366 } | 357 } |
367 | 358 |
368 void registerDynamicUse(DynamicUse dynamicUse) { | 359 void processDynamicUse(DynamicUse dynamicUse) { |
369 task.measure(() { | 360 task.measure(() { |
370 if (_universe.registerDynamicUse(dynamicUse)) { | 361 if (_universe.registerDynamicUse(dynamicUse)) { |
371 handleUnseenSelector(dynamicUse); | 362 _handleUnseenSelector(dynamicUse); |
372 } | 363 } |
373 }); | 364 }); |
374 } | 365 } |
375 | 366 |
376 void processSet( | 367 void _processSet( |
377 Map<String, Set<Element>> map, String memberName, bool f(Element e)) { | 368 Map<String, Set<Element>> map, String memberName, bool f(Element e)) { |
378 Set<Element> members = map[memberName]; | 369 Set<Element> members = map[memberName]; |
379 if (members == null) return; | 370 if (members == null) return; |
380 // [f] might add elements to [: map[memberName] :] during the loop below | 371 // [f] might add elements to [: map[memberName] :] during the loop below |
381 // so we create a new list for [: map[memberName] :] and prepend the | 372 // so we create a new list for [: map[memberName] :] and prepend the |
382 // [remaining] members after the loop. | 373 // [remaining] members after the loop. |
383 map[memberName] = new Set<Element>(); | 374 map[memberName] = new Set<Element>(); |
384 Set<Element> remaining = new Set<Element>(); | 375 Set<Element> remaining = new Set<Element>(); |
385 for (Element member in members) { | 376 for (Element member in members) { |
386 if (!f(member)) remaining.add(member); | 377 if (!f(member)) remaining.add(member); |
387 } | 378 } |
388 map[memberName].addAll(remaining); | 379 map[memberName].addAll(remaining); |
389 } | 380 } |
390 | 381 |
391 processInstanceMembers(String n, bool f(Element e)) { | 382 void _processInstanceMembers(String n, bool f(Element e)) { |
392 processSet(instanceMembersByName, n, f); | 383 _processSet(_instanceMembersByName, n, f); |
393 } | 384 } |
394 | 385 |
395 processInstanceFunctions(String n, bool f(Element e)) { | 386 void _processInstanceFunctions(String n, bool f(Element e)) { |
396 processSet(instanceFunctionsByName, n, f); | 387 _processSet(_instanceFunctionsByName, n, f); |
397 } | 388 } |
398 | 389 |
399 void handleUnseenSelector(DynamicUse universeSelector) { | 390 void _handleUnseenSelector(DynamicUse dynamicUse) { |
400 strategy.processDynamicUse(this, universeSelector); | |
401 } | |
402 | |
403 void handleUnseenSelectorInternal(DynamicUse dynamicUse) { | |
404 Selector selector = dynamicUse.selector; | 391 Selector selector = dynamicUse.selector; |
405 String methodName = selector.name; | 392 String methodName = selector.name; |
406 processInstanceMembers(methodName, (Element member) { | 393 _processInstanceMembers(methodName, (Element member) { |
407 if (dynamicUse.appliesUnnamed(member, openWorld)) { | 394 if (dynamicUse.appliesUnnamed(member, _openWorld)) { |
408 if (member.isFunction && selector.isGetter) { | 395 if (member.isFunction && selector.isGetter) { |
409 registerClosurizedMember(member); | 396 _registerClosurizedMember(member); |
410 } | 397 } |
411 addToWorkList(member); | 398 _addToWorkList(member); |
412 return true; | 399 return true; |
413 } | 400 } |
414 return false; | 401 return false; |
415 }); | 402 }); |
416 if (selector.isGetter) { | 403 if (selector.isGetter) { |
417 processInstanceFunctions(methodName, (Element member) { | 404 _processInstanceFunctions(methodName, (Element member) { |
418 if (dynamicUse.appliesUnnamed(member, openWorld)) { | 405 if (dynamicUse.appliesUnnamed(member, _openWorld)) { |
419 registerClosurizedMember(member); | 406 _registerClosurizedMember(member); |
420 return true; | 407 return true; |
421 } | 408 } |
422 return false; | 409 return false; |
423 }); | 410 }); |
424 } | 411 } |
425 } | 412 } |
426 | 413 |
427 /** | 414 void processStaticUse(StaticUse staticUse) { |
428 * Documentation wanted -- johnniwinther | |
429 * | |
430 * Invariant: [element] must be a declaration element. | |
431 */ | |
432 void registerStaticUse(StaticUse staticUse) { | |
433 strategy.processStaticUse(this, staticUse); | |
434 } | |
435 | |
436 void registerStaticUseInternal(StaticUse staticUse) { | |
437 Element element = staticUse.element; | 415 Element element = staticUse.element; |
438 assert(invariant(element, element.isDeclaration, | 416 assert(invariant(element, element.isDeclaration, |
439 message: "Element ${element} is not the declaration.")); | 417 message: "Element ${element} is not the declaration.")); |
440 _universe.registerStaticUse(staticUse); | 418 _universe.registerStaticUse(staticUse); |
441 applyImpact(backend.registerStaticUse(element, forResolution: true)); | 419 applyImpact(backend.registerStaticUse(element, forResolution: true)); |
442 bool addElement = true; | 420 bool addElement = true; |
443 switch (staticUse.kind) { | 421 switch (staticUse.kind) { |
444 case StaticUseKind.STATIC_TEAR_OFF: | 422 case StaticUseKind.STATIC_TEAR_OFF: |
445 applyImpact(backend.registerGetOfStaticFunction()); | 423 applyImpact(backend.registerGetOfStaticFunction()); |
446 break; | 424 break; |
447 case StaticUseKind.FIELD_GET: | 425 case StaticUseKind.FIELD_GET: |
448 case StaticUseKind.FIELD_SET: | 426 case StaticUseKind.FIELD_SET: |
449 case StaticUseKind.CLOSURE: | 427 case StaticUseKind.CLOSURE: |
450 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and | 428 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and |
451 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. | 429 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. |
452 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot | 430 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot |
453 // enqueue. | 431 // enqueue. |
454 LocalFunctionElement closure = staticUse.element; | 432 LocalFunctionElement closure = staticUse.element; |
455 if (closure.type.containsTypeVariables) { | 433 if (closure.type.containsTypeVariables) { |
456 universe.closuresWithFreeTypeVariables.add(closure); | 434 _universe.closuresWithFreeTypeVariables.add(closure); |
457 } | 435 } |
458 addElement = false; | 436 addElement = false; |
459 break; | 437 break; |
460 case StaticUseKind.SUPER_FIELD_SET: | 438 case StaticUseKind.SUPER_FIELD_SET: |
461 case StaticUseKind.SUPER_TEAR_OFF: | 439 case StaticUseKind.SUPER_TEAR_OFF: |
462 case StaticUseKind.GENERAL: | 440 case StaticUseKind.GENERAL: |
463 case StaticUseKind.DIRECT_USE: | 441 case StaticUseKind.DIRECT_USE: |
464 break; | 442 break; |
465 case StaticUseKind.CONSTRUCTOR_INVOKE: | 443 case StaticUseKind.CONSTRUCTOR_INVOKE: |
466 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: | 444 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: |
467 _registerInstantiatedType(staticUse.type, | 445 _registerInstantiatedType(staticUse.type, |
468 constructor: staticUse.element, globalDependency: false); | 446 constructor: staticUse.element, globalDependency: false); |
469 break; | 447 break; |
470 case StaticUseKind.REDIRECTION: | 448 case StaticUseKind.REDIRECTION: |
471 _registerInstantiatedType(staticUse.type, | 449 _registerInstantiatedType(staticUse.type, |
472 constructor: staticUse.element, | 450 constructor: staticUse.element, |
473 globalDependency: false, | 451 globalDependency: false, |
474 isRedirection: true); | 452 isRedirection: true); |
475 break; | 453 break; |
476 case StaticUseKind.DIRECT_INVOKE: | 454 case StaticUseKind.DIRECT_INVOKE: |
477 invariant( | 455 invariant( |
478 element, 'Direct static use is not supported for resolution.'); | 456 element, 'Direct static use is not supported for resolution.'); |
479 break; | 457 break; |
480 } | 458 } |
481 if (addElement) { | 459 if (addElement) { |
482 addToWorkList(element); | 460 _addToWorkList(element); |
483 } | 461 } |
484 } | 462 } |
485 | 463 |
486 void registerTypeUse(TypeUse typeUse) { | 464 void processTypeUse(TypeUse typeUse) { |
487 strategy.processTypeUse(this, typeUse); | |
488 } | |
489 | |
490 void registerTypeUseInternal(TypeUse typeUse) { | |
491 DartType type = typeUse.type; | 465 DartType type = typeUse.type; |
492 switch (typeUse.kind) { | 466 switch (typeUse.kind) { |
493 case TypeUseKind.INSTANTIATION: | 467 case TypeUseKind.INSTANTIATION: |
494 _registerInstantiatedType(type, globalDependency: false); | 468 _registerInstantiatedType(type, globalDependency: false); |
495 break; | 469 break; |
496 case TypeUseKind.MIRROR_INSTANTIATION: | 470 case TypeUseKind.MIRROR_INSTANTIATION: |
497 _registerInstantiatedType(type, | 471 _registerInstantiatedType(type, |
498 mirrorUsage: true, globalDependency: false); | 472 mirrorUsage: true, globalDependency: false); |
499 break; | 473 break; |
500 case TypeUseKind.NATIVE_INSTANTIATION: | 474 case TypeUseKind.NATIVE_INSTANTIATION: |
501 _registerInstantiatedType(type, | 475 _registerInstantiatedType(type, |
502 nativeUsage: true, globalDependency: true); | 476 nativeUsage: true, globalDependency: true); |
503 break; | 477 break; |
504 case TypeUseKind.IS_CHECK: | 478 case TypeUseKind.IS_CHECK: |
505 case TypeUseKind.AS_CAST: | 479 case TypeUseKind.AS_CAST: |
506 case TypeUseKind.CATCH_TYPE: | 480 case TypeUseKind.CATCH_TYPE: |
507 _registerIsCheck(type); | 481 _registerIsCheck(type); |
508 break; | 482 break; |
509 case TypeUseKind.CHECKED_MODE_CHECK: | 483 case TypeUseKind.CHECKED_MODE_CHECK: |
510 if (options.enableTypeAssertions) { | 484 if (_options.enableTypeAssertions) { |
511 _registerIsCheck(type); | 485 _registerIsCheck(type); |
512 } | 486 } |
513 break; | 487 break; |
514 case TypeUseKind.TYPE_LITERAL: | 488 case TypeUseKind.TYPE_LITERAL: |
515 break; | 489 break; |
516 } | 490 } |
517 } | 491 } |
518 | 492 |
519 void _registerIsCheck(DartType type) { | 493 void _registerIsCheck(DartType type) { |
520 type = _universe.registerIsCheck(type, resolution); | 494 type = _universe.registerIsCheck(type, _resolution); |
521 // Even in checked mode, type annotations for return type and argument | 495 // Even in checked mode, type annotations for return type and argument |
522 // types do not imply type checks, so there should never be a check | 496 // types do not imply type checks, so there should never be a check |
523 // against the type variable of a typedef. | 497 // against the type variable of a typedef. |
524 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); | 498 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); |
525 } | 499 } |
526 | 500 |
527 void _registerCallMethodWithFreeTypeVariables(Element element) { | 501 void _registerCallMethodWithFreeTypeVariables(Element element) { |
528 applyImpact(backend.registerCallMethodWithFreeTypeVariables(element, | 502 applyImpact(backend.registerCallMethodWithFreeTypeVariables(element, |
529 forResolution: true)); | 503 forResolution: true)); |
530 _universe.callMethodsWithFreeTypeVariables.add(element); | 504 _universe.callMethodsWithFreeTypeVariables.add(element); |
531 } | 505 } |
532 | 506 |
533 void registerClosurizedMember(TypedElement element) { | 507 void _registerClosurizedMember(TypedElement element) { |
534 assert(element.isInstanceMember); | 508 assert(element.isInstanceMember); |
535 if (element.computeType(resolution).containsTypeVariables) { | 509 if (element.computeType(_resolution).containsTypeVariables) { |
536 applyImpact(backend.registerClosureWithFreeTypeVariables(element, | 510 applyImpact(backend.registerClosureWithFreeTypeVariables(element, |
537 forResolution: true)); | 511 forResolution: true)); |
538 _universe.closuresWithFreeTypeVariables.add(element); | 512 _universe.closuresWithFreeTypeVariables.add(element); |
539 } | 513 } |
540 applyImpact(backend.registerBoundClosure()); | 514 applyImpact(backend.registerBoundClosure()); |
541 _universe.closurizedMembers.add(element); | 515 _universe.closurizedMembers.add(element); |
542 } | 516 } |
543 | 517 |
544 void forEach(void f(WorkItem work)) { | 518 void forEach(void f(WorkItem work)) { |
545 do { | 519 do { |
546 while (queue.isNotEmpty) { | 520 while (_queue.isNotEmpty) { |
547 // TODO(johnniwinther): Find an optimal process order. | 521 // TODO(johnniwinther): Find an optimal process order. |
548 WorkItem work = queue.removeLast(); | 522 WorkItem work = _queue.removeLast(); |
549 if (!isProcessed(work.element)) { | 523 if (!isProcessed(work.element)) { |
550 strategy.processWorkItem(f, work); | 524 strategy.processWorkItem(f, work); |
551 registerProcessedElement(work.element); | 525 registerProcessedElement(work.element); |
552 } | 526 } |
553 } | 527 } |
554 List recents = recentClasses.toList(growable: false); | 528 List recents = _recentClasses.toList(growable: false); |
555 recentClasses.clear(); | 529 _recentClasses.clear(); |
556 if (!onQueueEmpty(recents)) recentClasses.addAll(recents); | 530 if (!_onQueueEmpty(recents)) { |
557 } while (queue.isNotEmpty || recentClasses.isNotEmpty); | 531 _recentClasses.addAll(recents); |
| 532 } |
| 533 } while (_queue.isNotEmpty || _recentClasses.isNotEmpty); |
558 } | 534 } |
559 | 535 |
560 void logSummary(log(message)) { | 536 void logSummary(log(message)) { |
561 log('Resolved ${processedElements.length} elements.'); | 537 log('Resolved ${processedElements.length} elements.'); |
562 nativeEnqueuer.logSummary(log); | 538 nativeEnqueuer.logSummary(log); |
563 } | 539 } |
564 | 540 |
565 String toString() => 'Enqueuer($name)'; | 541 String toString() => 'Enqueuer($name)'; |
566 | 542 |
567 /// All declaration elements that have been processed by the resolver. | |
568 final Set<AstElement> processedElements; | |
569 | |
570 Iterable<Entity> get processedEntities => processedElements; | 543 Iterable<Entity> get processedEntities => processedElements; |
571 | 544 |
572 final Queue<ResolutionWorkItem> queue; | |
573 | |
574 /// Queue of deferred resolution actions to execute when the resolution queue | |
575 /// has been emptied. | |
576 final Queue<_DeferredAction> deferredQueue; | |
577 | |
578 static const ImpactUseCase IMPACT_USE = | |
579 const ImpactUseCase('ResolutionEnqueuer'); | |
580 | |
581 ImpactUseCase get impactUse => IMPACT_USE; | 545 ImpactUseCase get impactUse => IMPACT_USE; |
582 | 546 |
583 bool get isResolutionQueue => true; | 547 bool get isResolutionQueue => true; |
584 | 548 |
585 bool isProcessed(Element member) => processedElements.contains(member); | 549 bool isProcessed(Element member) => processedElements.contains(member); |
586 | 550 |
587 /// Returns `true` if [element] has been processed by the resolution enqueuer. | 551 /// Returns `true` if [element] has been processed by the resolution enqueuer. |
588 bool hasBeenProcessed(Element element) { | 552 bool hasBeenProcessed(Element element) { |
589 return processedElements.contains(element.analyzableElement.declaration); | 553 return processedElements.contains(element.analyzableElement.declaration); |
590 } | 554 } |
591 | 555 |
592 /// Registers [element] as processed by the resolution enqueuer. | 556 /// Registers [element] as processed by the resolution enqueuer. |
593 void registerProcessedElement(AstElement element) { | 557 void registerProcessedElement(AstElement element) { |
594 processedElements.add(element); | 558 processedElements.add(element); |
595 backend.onElementResolved(element); | 559 backend.onElementResolved(element); |
596 } | 560 } |
597 | 561 |
598 /** | 562 /// Adds [element] to the work list if it has not already been processed. |
599 * Adds [element] to the work list if it has not already been processed. | 563 /// |
600 * | 564 /// Invariant: [element] must be a declaration element. |
601 * Returns [true] if the element was actually added to the queue. | 565 void _addToWorkList(Element element) { |
602 */ | 566 assert(invariant(element, element.isDeclaration)); |
603 bool internalAddToWorkList(Element element) { | 567 if (element.isMalformed) return; |
604 if (element.isMalformed) return false; | |
605 | 568 |
606 assert(invariant(element, element is AnalyzableElement, | 569 assert(invariant(element, element is AnalyzableElement, |
607 message: 'Element $element is not analyzable.')); | 570 message: 'Element $element is not analyzable.')); |
608 if (hasBeenProcessed(element)) return false; | 571 if (hasBeenProcessed(element)) return; |
609 if (queueIsClosed) { | 572 if (queueIsClosed) { |
610 throw new SpannableAssertionFailure( | 573 throw new SpannableAssertionFailure( |
611 element, "Resolution work list is closed. Trying to add $element."); | 574 element, "Resolution work list is closed. Trying to add $element."); |
612 } | 575 } |
613 | 576 |
614 openWorld.registerUsedElement(element); | 577 _openWorld.registerUsedElement(element); |
615 | 578 |
616 ResolutionWorkItem workItem = resolution.createWorkItem(element); | 579 ResolutionWorkItem workItem = _resolution.createWorkItem(element); |
617 queue.add(workItem); | 580 _queue.add(workItem); |
618 | 581 |
619 // Enable isolate support if we start using something from the isolate | 582 // Enable isolate support if we start using something from the isolate |
620 // library, or timers for the async library. We exclude constant fields, | 583 // library, or timers for the async library. We exclude constant fields, |
621 // which are ending here because their initializing expression is compiled. | 584 // which are ending here because their initializing expression is compiled. |
622 LibraryElement library = element.library; | 585 LibraryElement library = element.library; |
623 if (!universe.hasIsolateSupport && (!element.isField || !element.isConst)) { | 586 if (!universe.hasIsolateSupport && (!element.isField || !element.isConst)) { |
624 String uri = library.canonicalUri.toString(); | 587 String uri = library.canonicalUri.toString(); |
625 if (uri == 'dart:isolate') { | 588 if (uri == 'dart:isolate') { |
626 enableIsolateSupport(); | 589 _enableIsolateSupport(); |
627 } else if (uri == 'dart:async') { | 590 } else if (uri == 'dart:async') { |
628 if (element.name == '_createTimer' || | 591 if (element.name == '_createTimer' || |
629 element.name == '_createPeriodicTimer') { | 592 element.name == '_createPeriodicTimer') { |
630 // The [:Timer:] class uses the event queue of the isolate | 593 // The [:Timer:] class uses the event queue of the isolate |
631 // library, so we make sure that event queue is generated. | 594 // library, so we make sure that event queue is generated. |
632 enableIsolateSupport(); | 595 _enableIsolateSupport(); |
633 } | 596 } |
634 } | 597 } |
635 } | 598 } |
636 | 599 |
637 if (element.isGetter && element.name == Identifiers.runtimeType_) { | 600 if (element.isGetter && element.name == Identifiers.runtimeType_) { |
638 // Enable runtime type support if we discover a getter called runtimeType. | 601 // Enable runtime type support if we discover a getter called runtimeType. |
639 // We have to enable runtime type before hitting the codegen, so | 602 // We have to enable runtime type before hitting the codegen, so |
640 // that constructors know whether they need to generate code for | 603 // that constructors know whether they need to generate code for |
641 // runtime type. | 604 // runtime type. |
642 _universe.hasRuntimeTypeSupport = true; | 605 _universe.hasRuntimeTypeSupport = true; |
643 // TODO(ahe): Record precise dependency here. | 606 // TODO(ahe): Record precise dependency here. |
644 applyImpact(backend.registerRuntimeType()); | 607 applyImpact(backend.registerRuntimeType()); |
645 } else if (commonElements.isFunctionApplyMethod(element)) { | 608 } else if (_commonElements.isFunctionApplyMethod(element)) { |
646 _universe.hasFunctionApplySupport = true; | 609 _universe.hasFunctionApplySupport = true; |
647 } | 610 } |
648 | |
649 return true; | |
650 } | 611 } |
651 | 612 |
652 void registerNoSuchMethod(Element element) { | 613 void _registerNoSuchMethod(Element element) { |
653 backend.registerNoSuchMethod(element); | 614 backend.registerNoSuchMethod(element); |
654 } | 615 } |
655 | 616 |
656 void enableIsolateSupport() { | 617 void _enableIsolateSupport() { |
657 _universe.hasIsolateSupport = true; | 618 _universe.hasIsolateSupport = true; |
658 applyImpact(backend.enableIsolateSupport(forResolution: true)); | 619 applyImpact(backend.enableIsolateSupport(forResolution: true)); |
659 } | 620 } |
660 | 621 |
661 /** | 622 /** |
662 * Adds an action to the deferred task queue. | 623 * Adds an action to the deferred task queue. |
663 * | 624 * |
664 * The action is performed the next time the resolution queue has been | 625 * The action is performed the next time the resolution queue has been |
665 * emptied. | 626 * emptied. |
666 * | 627 * |
667 * The queue is processed in FIFO order. | 628 * The queue is processed in FIFO order. |
668 */ | 629 */ |
669 void addDeferredAction(Element element, void action()) { | 630 void addDeferredAction(Element element, void action()) { |
670 if (queueIsClosed) { | 631 if (queueIsClosed) { |
671 throw new SpannableAssertionFailure( | 632 throw new SpannableAssertionFailure( |
672 element, | 633 element, |
673 "Resolution work list is closed. " | 634 "Resolution work list is closed. " |
674 "Trying to add deferred action for $element"); | 635 "Trying to add deferred action for $element"); |
675 } | 636 } |
676 deferredQueue.add(new _DeferredAction(element, action)); | 637 _deferredQueue.add(new _DeferredAction(element, action)); |
677 } | 638 } |
678 | 639 |
679 /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses] | 640 /// [_onQueueEmpty] is called whenever the queue is drained. [recentClasses] |
680 /// contains the set of all classes seen for the first time since | 641 /// contains the set of all classes seen for the first time since |
681 /// [onQueueEmpty] was called last. A return value of [true] indicates that | 642 /// [_onQueueEmpty] was called last. A return value of [true] indicates that |
682 /// the [recentClasses] have been processed and may be cleared. If [false] is | 643 /// the [recentClasses] have been processed and may be cleared. If [false] is |
683 /// returned, [onQueueEmpty] will be called once the queue is empty again (or | 644 /// returned, [_onQueueEmpty] will be called once the queue is empty again (or |
684 /// still empty) and [recentClasses] will be a superset of the current value. | 645 /// still empty) and [recentClasses] will be a superset of the current value. |
685 bool onQueueEmpty(Iterable<ClassElement> recentClasses) { | 646 bool _onQueueEmpty(Iterable<ClassElement> recentClasses) { |
686 _emptyDeferredQueue(); | 647 _emptyDeferredQueue(); |
687 | 648 |
688 return backend.onQueueEmpty(this, recentClasses); | 649 return backend.onQueueEmpty(this, recentClasses); |
689 } | 650 } |
690 | 651 |
691 void emptyDeferredQueueForTesting() => _emptyDeferredQueue(); | 652 void emptyDeferredQueueForTesting() => _emptyDeferredQueue(); |
692 | 653 |
693 void _emptyDeferredQueue() { | 654 void _emptyDeferredQueue() { |
694 while (!deferredQueue.isEmpty) { | 655 while (!_deferredQueue.isEmpty) { |
695 _DeferredAction task = deferredQueue.removeFirst(); | 656 _DeferredAction task = _deferredQueue.removeFirst(); |
696 reporter.withCurrentElement(task.element, task.action); | 657 _reporter.withCurrentElement(task.element, task.action); |
697 } | 658 } |
698 } | 659 } |
699 | 660 |
700 void forgetElement(Element element, Compiler compiler) { | 661 void forgetElement(Element element, Compiler compiler) { |
701 _universe.forgetElement(element, compiler); | 662 _universe.forgetElement(element, compiler); |
702 _processedClasses.remove(element); | 663 _processedClasses.remove(element); |
703 instanceMembersByName[element.name]?.remove(element); | 664 _instanceMembersByName[element.name]?.remove(element); |
704 instanceFunctionsByName[element.name]?.remove(element); | 665 _instanceFunctionsByName[element.name]?.remove(element); |
705 processedElements.remove(element); | 666 processedElements.remove(element); |
706 } | 667 } |
707 } | 668 } |
708 | 669 |
709 void removeFromSet(Map<String, Set<Element>> map, Element element) { | 670 void removeFromSet(Map<String, Set<Element>> map, Element element) { |
710 Set<Element> set = map[element.name]; | 671 Set<Element> set = map[element.name]; |
711 if (set == null) return; | 672 if (set == null) return; |
712 set.remove(element); | 673 set.remove(element); |
713 } | 674 } |
714 | 675 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
748 void processWorkItem(void f(WorkItem work), WorkItem work) { | 709 void processWorkItem(void f(WorkItem work), WorkItem work) { |
749 f(work); | 710 f(work); |
750 } | 711 } |
751 } | 712 } |
752 | 713 |
753 /// Strategy that only enqueues directly used elements. | 714 /// Strategy that only enqueues directly used elements. |
754 class DirectEnqueuerStrategy extends EnqueuerStrategy { | 715 class DirectEnqueuerStrategy extends EnqueuerStrategy { |
755 const DirectEnqueuerStrategy(); | 716 const DirectEnqueuerStrategy(); |
756 void processStaticUse(EnqueuerImpl enqueuer, StaticUse staticUse) { | 717 void processStaticUse(EnqueuerImpl enqueuer, StaticUse staticUse) { |
757 if (staticUse.kind == StaticUseKind.DIRECT_USE) { | 718 if (staticUse.kind == StaticUseKind.DIRECT_USE) { |
758 enqueuer.registerStaticUseInternal(staticUse); | 719 enqueuer.processStaticUse(staticUse); |
759 } | 720 } |
760 } | 721 } |
761 } | 722 } |
762 | 723 |
763 /// Strategy used for tree-shaking. | 724 /// Strategy used for tree-shaking. |
764 class TreeShakingEnqueuerStrategy extends EnqueuerStrategy { | 725 class TreeShakingEnqueuerStrategy extends EnqueuerStrategy { |
765 const TreeShakingEnqueuerStrategy(); | 726 const TreeShakingEnqueuerStrategy(); |
766 | 727 |
767 @override | 728 @override |
768 void processInstantiatedClass(EnqueuerImpl enqueuer, ClassElement cls) { | 729 void processInstantiatedClass(EnqueuerImpl enqueuer, ClassElement cls) { |
769 cls.implementation.forEachMember(enqueuer.processInstantiatedClassMember); | 730 cls.implementation.forEachMember(enqueuer.processInstantiatedClassMember); |
770 } | 731 } |
771 | 732 |
772 @override | 733 @override |
773 void processStaticUse(EnqueuerImpl enqueuer, StaticUse staticUse) { | 734 void processStaticUse(EnqueuerImpl enqueuer, StaticUse staticUse) { |
774 enqueuer.registerStaticUseInternal(staticUse); | 735 enqueuer.processStaticUse(staticUse); |
775 } | 736 } |
776 | 737 |
777 @override | 738 @override |
778 void processTypeUse(EnqueuerImpl enqueuer, TypeUse typeUse) { | 739 void processTypeUse(EnqueuerImpl enqueuer, TypeUse typeUse) { |
779 enqueuer.registerTypeUseInternal(typeUse); | 740 enqueuer.processTypeUse(typeUse); |
780 } | 741 } |
781 | 742 |
782 @override | 743 @override |
783 void processDynamicUse(EnqueuerImpl enqueuer, DynamicUse dynamicUse) { | 744 void processDynamicUse(EnqueuerImpl enqueuer, DynamicUse dynamicUse) { |
784 enqueuer.handleUnseenSelectorInternal(dynamicUse); | 745 enqueuer.processDynamicUse(dynamicUse); |
785 } | 746 } |
786 } | 747 } |
787 | 748 |
788 class EnqueuerImplImpactVisitor implements WorldImpactVisitor { | 749 class EnqueuerImplImpactVisitor implements WorldImpactVisitor { |
789 final EnqueuerImpl enqueuer; | 750 final EnqueuerImpl enqueuer; |
790 | 751 |
791 EnqueuerImplImpactVisitor(this.enqueuer); | 752 EnqueuerImplImpactVisitor(this.enqueuer); |
792 | 753 |
793 @override | 754 @override |
794 void visitDynamicUse(DynamicUse dynamicUse) { | 755 void visitDynamicUse(DynamicUse dynamicUse) { |
795 enqueuer.registerDynamicUse(dynamicUse); | 756 enqueuer.strategy.processDynamicUse(enqueuer, dynamicUse); |
796 } | 757 } |
797 | 758 |
798 @override | 759 @override |
799 void visitStaticUse(StaticUse staticUse) { | 760 void visitStaticUse(StaticUse staticUse) { |
800 enqueuer.registerStaticUse(staticUse); | 761 enqueuer.strategy.processStaticUse(enqueuer, staticUse); |
801 } | 762 } |
802 | 763 |
803 @override | 764 @override |
804 void visitTypeUse(TypeUse typeUse) { | 765 void visitTypeUse(TypeUse typeUse) { |
805 enqueuer.registerTypeUse(typeUse); | 766 enqueuer.strategy.processTypeUse(enqueuer, typeUse); |
806 } | 767 } |
807 } | 768 } |
808 | 769 |
809 typedef void _DeferredActionFunction(); | 770 typedef void _DeferredActionFunction(); |
810 | 771 |
811 class _DeferredAction { | 772 class _DeferredAction { |
812 final Element element; | 773 final Element element; |
813 final _DeferredActionFunction action; | 774 final _DeferredActionFunction action; |
814 | 775 |
815 _DeferredAction(this.element, this.action); | 776 _DeferredAction(this.element, this.action); |
816 } | 777 } |
OLD | NEW |