| 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 |