| 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 'common/resolution.dart' show Resolution; | 9 import 'common/resolution.dart' show Resolution; |
| 10 import 'common/tasks.dart' show CompilerTask; | 10 import 'common/tasks.dart' show CompilerTask; |
| 11 import 'common/work.dart' show WorkItem; | 11 import 'common/work.dart' show WorkItem; |
| 12 import 'common.dart'; | 12 import 'common.dart'; |
| 13 import 'compiler.dart' show Compiler, GlobalDependencyRegistry; | 13 import 'compiler.dart' show Compiler, GlobalDependencyRegistry; |
| 14 import 'options.dart'; | 14 import 'options.dart'; |
| 15 import 'elements/elements.dart' | 15 import 'elements/elements.dart' |
| 16 show | 16 show |
| 17 AnalyzableElement, | 17 AnalyzableElement, |
| 18 ClassElement, | 18 ClassElement, |
| 19 ConstructorElement, | 19 ConstructorElement, |
| 20 Element, | 20 Element, |
| 21 MemberElement; | 21 MemberElement; |
| 22 import 'elements/entities.dart'; | 22 import 'elements/entities.dart'; |
| 23 import 'elements/resolution_types.dart' | 23 import 'elements/resolution_types.dart' |
| 24 show ResolutionDartType, ResolutionInterfaceType; | 24 show ResolutionDartType, ResolutionInterfaceType; |
| 25 import 'js_backend/backend.dart' show JavaScriptBackend; | 25 import 'elements/types.dart' show InterfaceType; |
| 26 import 'native/native.dart' as native; | 26 import 'native/native.dart' as native; |
| 27 import 'universe/world_builder.dart'; | 27 import 'universe/world_builder.dart'; |
| 28 import 'universe/use.dart' | 28 import 'universe/use.dart' |
| 29 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; | 29 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; |
| 30 import 'universe/world_impact.dart' | 30 import 'universe/world_impact.dart' |
| 31 show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor; | 31 show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor; |
| 32 import 'util/enumset.dart'; | 32 import 'util/enumset.dart'; |
| 33 import 'util/util.dart' show Setlet; | 33 import 'util/util.dart' show Setlet; |
| 34 | 34 |
| 35 class EnqueueTask extends CompilerTask { | 35 class EnqueueTask extends CompilerTask { |
| 36 ResolutionEnqueuer _resolution; | 36 ResolutionEnqueuer _resolution; |
| 37 Enqueuer _codegen; | 37 Enqueuer _codegen; |
| 38 final Compiler compiler; | 38 final Compiler compiler; |
| 39 | 39 |
| 40 String get name => 'Enqueue'; | 40 String get name => 'Enqueue'; |
| 41 | 41 |
| 42 EnqueueTask(Compiler compiler) | 42 EnqueueTask(Compiler compiler) |
| 43 : this.compiler = compiler, | 43 : this.compiler = compiler, |
| 44 super(compiler.measurer) { | 44 super(compiler.measurer) { |
| 45 _resolution = new ResolutionEnqueuer( | 45 _resolution = new ResolutionEnqueuer( |
| 46 this, | 46 this, |
| 47 compiler.options, | 47 compiler.options, |
| 48 compiler.resolution, | 48 compiler.reporter, |
| 49 compiler.options.analyzeOnly && compiler.options.analyzeMain | 49 compiler.options.analyzeOnly && compiler.options.analyzeMain |
| 50 ? const DirectEnqueuerStrategy() | 50 ? const DirectEnqueuerStrategy() |
| 51 : const TreeShakingEnqueuerStrategy(), | 51 : const TreeShakingEnqueuerStrategy(), |
| 52 compiler.globalDependencies, | 52 compiler.globalDependencies, |
| 53 compiler.backend); | 53 compiler.backend, |
| 54 compiler.backend.nativeResolutionEnqueuer(), |
| 55 new ResolutionWorldBuilderImpl( |
| 56 compiler.backend, compiler.resolution, const OpenWorldStrategy()), |
| 57 new ResolutionWorkItemBuilder(compiler.resolution)); |
| 54 _codegen = compiler.backend.createCodegenEnqueuer(this, compiler); | 58 _codegen = compiler.backend.createCodegenEnqueuer(this, compiler); |
| 55 } | 59 } |
| 56 | 60 |
| 57 ResolutionEnqueuer get resolution => _resolution; | 61 ResolutionEnqueuer get resolution => _resolution; |
| 58 Enqueuer get codegen => _codegen; | 62 Enqueuer get codegen => _codegen; |
| 59 } | 63 } |
| 60 | 64 |
| 61 abstract class Enqueuer { | 65 abstract class Enqueuer { |
| 62 WorldBuilder get worldBuilder; | 66 WorldBuilder get worldBuilder; |
| 63 native.NativeEnqueuer get nativeEnqueuer; | 67 native.NativeEnqueuer get nativeEnqueuer; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 93 /// if it is no longer needed. | 97 /// if it is no longer needed. |
| 94 void applyImpact(WorldImpact worldImpact, {var impactSource}); | 98 void applyImpact(WorldImpact worldImpact, {var impactSource}); |
| 95 bool checkNoEnqueuedInvokedInstanceMethods(); | 99 bool checkNoEnqueuedInvokedInstanceMethods(); |
| 96 void logSummary(log(message)); | 100 void logSummary(log(message)); |
| 97 | 101 |
| 98 Iterable<Entity> get processedEntities; | 102 Iterable<Entity> get processedEntities; |
| 99 | 103 |
| 100 Iterable<ClassEntity> get processedClasses; | 104 Iterable<ClassEntity> get processedClasses; |
| 101 } | 105 } |
| 102 | 106 |
| 107 abstract class EnqueuerListener { |
| 108 /// Called to instruct to the backend that [type] has been instantiated. |
| 109 void registerInstantiatedType(InterfaceType type); |
| 110 |
| 111 /// Called to notify to the backend that a class is being instantiated. Any |
| 112 /// backend specific [WorldImpact] of this is returned. |
| 113 WorldImpact registerInstantiatedClass(ClassEntity cls, {bool forResolution}); |
| 114 |
| 115 /// Called to notify to the backend that a class is implemented by an |
| 116 /// instantiated class. Any backend specific [WorldImpact] of this is |
| 117 /// returned. |
| 118 WorldImpact registerImplementedClass(ClassEntity cls, {bool forResolution}); |
| 119 |
| 120 /// Called to register that a static function has been closurized. Any backend |
| 121 /// specific [WorldImpact] of this is returned. |
| 122 WorldImpact registerGetOfStaticFunction(); |
| 123 |
| 124 /// Called to instruct the backend to register that a closure exists for a |
| 125 /// function on an instantiated generic class. Any backend specific |
| 126 /// [WorldImpact] of this is returned. |
| 127 WorldImpact registerClosureWithFreeTypeVariables(MemberEntity member, |
| 128 {bool forResolution}); |
| 129 |
| 130 /// Called to register that a member has been closurized. Any backend specific |
| 131 /// [WorldImpact] of this is returned. |
| 132 WorldImpact registerBoundClosure(); |
| 133 |
| 134 /// Called to register that [element] is statically known to be used. Any |
| 135 /// backend specific [WorldImpact] of this is returned. |
| 136 WorldImpact registerUsedElement(MemberEntity member, {bool forResolution}); |
| 137 |
| 138 /// Called when [enqueuer]'s queue is empty, but before it is closed. |
| 139 /// |
| 140 /// This is used, for example, by the JS backend to enqueue additional |
| 141 /// elements needed for reflection. [recentClasses] is a collection of |
| 142 /// all classes seen for the first time by the [enqueuer] since the last call |
| 143 /// to [onQueueEmpty]. |
| 144 /// |
| 145 /// A return value of `true` indicates that [recentClasses] has been |
| 146 /// processed and its elements do not need to be seen in the next round. When |
| 147 /// `false` is returned, [onQueueEmpty] will be called again once the |
| 148 /// resolution queue has drained and [recentClasses] will be a superset of the |
| 149 /// current value. |
| 150 /// |
| 151 /// There is no guarantee that a class is only present once in |
| 152 /// [recentClasses], but every class seen by the [enqueuer] will be present in |
| 153 /// [recentClasses] at least once. |
| 154 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses); |
| 155 } |
| 156 |
| 103 abstract class EnqueuerImpl extends Enqueuer { | 157 abstract class EnqueuerImpl extends Enqueuer { |
| 104 CompilerTask get task; | 158 CompilerTask get task; |
| 105 EnqueuerStrategy get strategy; | 159 EnqueuerStrategy get strategy; |
| 106 void checkClass(ClassEntity cls); | 160 void checkClass(ClassEntity cls); |
| 107 void processStaticUse(StaticUse staticUse); | 161 void processStaticUse(StaticUse staticUse); |
| 108 void processTypeUse(TypeUse typeUse); | 162 void processTypeUse(TypeUse typeUse); |
| 109 void processDynamicUse(DynamicUse dynamicUse); | 163 void processDynamicUse(DynamicUse dynamicUse); |
| 110 } | 164 } |
| 111 | 165 |
| 112 /// [Enqueuer] which is specific to resolution. | 166 /// [Enqueuer] which is specific to resolution. |
| 113 class ResolutionEnqueuer extends EnqueuerImpl { | 167 class ResolutionEnqueuer extends EnqueuerImpl { |
| 114 static const ImpactUseCase IMPACT_USE = | 168 static const ImpactUseCase IMPACT_USE = |
| 115 const ImpactUseCase('ResolutionEnqueuer'); | 169 const ImpactUseCase('ResolutionEnqueuer'); |
| 116 | 170 |
| 117 final CompilerTask task; | 171 final CompilerTask task; |
| 118 final String name; | 172 final String name; |
| 119 final Resolution _resolution; | |
| 120 final CompilerOptions _options; | 173 final CompilerOptions _options; |
| 121 final JavaScriptBackend backend; | 174 final EnqueuerListener _listener; |
| 122 final GlobalDependencyRegistry _globalDependencies; | 175 final GlobalDependencyRegistry _globalDependencies; |
| 123 final native.NativeEnqueuer nativeEnqueuer; | 176 final native.NativeEnqueuer nativeEnqueuer; |
| 124 | 177 |
| 125 final EnqueuerStrategy strategy; | 178 final EnqueuerStrategy strategy; |
| 126 final Set<ClassEntity> _recentClasses = new Setlet<ClassEntity>(); | 179 final Set<ClassEntity> _recentClasses = new Setlet<ClassEntity>(); |
| 127 final ResolutionWorldBuilderImpl _universe; | 180 final ResolutionWorldBuilderImpl _universe; |
| 128 final WorkItemBuilder _workItemBuilder; | 181 final WorkItemBuilder _workItemBuilder; |
| 182 final DiagnosticReporter _reporter; |
| 129 | 183 |
| 130 bool queueIsClosed = false; | 184 bool queueIsClosed = false; |
| 131 | 185 |
| 132 WorldImpactVisitor _impactVisitor; | 186 WorldImpactVisitor _impactVisitor; |
| 133 | 187 |
| 134 /// All declaration elements that have been processed by the resolver. | 188 /// All declaration elements that have been processed by the resolver. |
| 135 final Set<Entity> _processedEntities = new Set<Entity>(); | 189 final Set<Entity> _processedEntities = new Set<Entity>(); |
| 136 | 190 |
| 137 final Queue<WorkItem> _queue = new Queue<WorkItem>(); | 191 final Queue<WorkItem> _queue = new Queue<WorkItem>(); |
| 138 | 192 |
| 139 /// Queue of deferred resolution actions to execute when the resolution queue | 193 /// Queue of deferred resolution actions to execute when the resolution queue |
| 140 /// has been emptied. | 194 /// has been emptied. |
| 141 final Queue<_DeferredAction> _deferredQueue = new Queue<_DeferredAction>(); | 195 final Queue<_DeferredAction> _deferredQueue = new Queue<_DeferredAction>(); |
| 142 | 196 |
| 143 ResolutionEnqueuer(this.task, this._options, Resolution resolution, | 197 ResolutionEnqueuer( |
| 144 this.strategy, this._globalDependencies, JavaScriptBackend backend, | 198 this.task, |
| 145 [this.name = 'resolution enqueuer']) | 199 this._options, |
| 146 : this.backend = backend, | 200 this._reporter, |
| 147 this._resolution = resolution, | 201 this.strategy, |
| 148 this.nativeEnqueuer = backend.nativeResolutionEnqueuer(), | 202 this._globalDependencies, |
| 149 _universe = new ResolutionWorldBuilderImpl( | 203 this._listener, |
| 150 backend, resolution, const OpenWorldStrategy()), | 204 this.nativeEnqueuer, |
| 151 _workItemBuilder = new ResolutionWorkItemBuilder(resolution) { | 205 this._universe, |
| 206 this._workItemBuilder, |
| 207 [this.name = 'resolution enqueuer']) { |
| 152 _impactVisitor = new EnqueuerImplImpactVisitor(this); | 208 _impactVisitor = new EnqueuerImplImpactVisitor(this); |
| 153 } | 209 } |
| 154 | 210 |
| 155 ResolutionWorldBuilder get worldBuilder => _universe; | 211 ResolutionWorldBuilder get worldBuilder => _universe; |
| 156 | 212 |
| 157 bool get queueIsEmpty => _queue.isEmpty; | 213 bool get queueIsEmpty => _queue.isEmpty; |
| 158 | 214 |
| 159 DiagnosticReporter get _reporter => _resolution.reporter; | |
| 160 | |
| 161 Iterable<ClassEntity> get processedClasses => _universe.processedClasses; | 215 Iterable<ClassEntity> get processedClasses => _universe.processedClasses; |
| 162 | 216 |
| 163 void applyImpact(WorldImpact worldImpact, {var impactSource}) { | 217 void applyImpact(WorldImpact worldImpact, {var impactSource}) { |
| 164 if (worldImpact.isEmpty) return; | 218 if (worldImpact.isEmpty) return; |
| 165 impactStrategy.visitImpact( | 219 impactStrategy.visitImpact( |
| 166 impactSource, worldImpact, _impactVisitor, impactUse); | 220 impactSource, worldImpact, _impactVisitor, impactUse); |
| 167 } | 221 } |
| 168 | 222 |
| 169 void _registerInstantiatedType(ResolutionInterfaceType type, | 223 void _registerInstantiatedType(ResolutionInterfaceType type, |
| 170 {ConstructorElement constructor, | 224 {ConstructorElement constructor, |
| 171 bool mirrorUsage: false, | 225 bool mirrorUsage: false, |
| 172 bool nativeUsage: false, | 226 bool nativeUsage: false, |
| 173 bool globalDependency: false, | 227 bool globalDependency: false, |
| 174 bool isRedirection: false}) { | 228 bool isRedirection: false}) { |
| 175 task.measure(() { | 229 task.measure(() { |
| 176 _universe.registerTypeInstantiation(type, _applyClassUse, | 230 _universe.registerTypeInstantiation(type, _applyClassUse, |
| 177 constructor: constructor, | 231 constructor: constructor, |
| 178 byMirrors: mirrorUsage, | 232 byMirrors: mirrorUsage, |
| 179 isRedirection: isRedirection); | 233 isRedirection: isRedirection); |
| 180 if (globalDependency && !mirrorUsage) { | 234 if (globalDependency && !mirrorUsage) { |
| 181 _globalDependencies.registerDependency(type.element); | 235 _globalDependencies.registerDependency(type.element); |
| 182 } | 236 } |
| 183 if (nativeUsage) { | 237 if (nativeUsage) { |
| 184 nativeEnqueuer.onInstantiatedType(type); | 238 nativeEnqueuer.onInstantiatedType(type); |
| 185 } | 239 } |
| 186 backend.registerInstantiatedType(type); | 240 _listener.registerInstantiatedType(type); |
| 187 }); | 241 }); |
| 188 } | 242 } |
| 189 | 243 |
| 190 bool checkNoEnqueuedInvokedInstanceMethods() { | 244 bool checkNoEnqueuedInvokedInstanceMethods() { |
| 191 return strategy.checkEnqueuerConsistency(this); | 245 return strategy.checkEnqueuerConsistency(this); |
| 192 } | 246 } |
| 193 | 247 |
| 194 void checkClass(ClassEntity cls) { | 248 void checkClass(ClassEntity cls) { |
| 195 _universe.processClassMembers(cls, | 249 _universe.processClassMembers(cls, |
| 196 (MemberEntity member, EnumSet<MemberUse> useSet) { | 250 (MemberEntity member, EnumSet<MemberUse> useSet) { |
| 197 if (useSet.isNotEmpty) { | 251 if (useSet.isNotEmpty) { |
| 198 _reporter.internalError(member, | 252 _reporter.internalError(member, |
| 199 'Unenqueued use of $member: ${useSet.iterable(MemberUse.values)}'); | 253 'Unenqueued use of $member: ${useSet.iterable(MemberUse.values)}'); |
| 200 } | 254 } |
| 201 }); | 255 }); |
| 202 } | 256 } |
| 203 | 257 |
| 204 /// Callback for applying the use of a [member]. | 258 /// Callback for applying the use of a [member]. |
| 205 void _applyMemberUse(Entity member, EnumSet<MemberUse> useSet) { | 259 void _applyMemberUse(Entity member, EnumSet<MemberUse> useSet) { |
| 206 if (useSet.contains(MemberUse.NORMAL)) { | 260 if (useSet.contains(MemberUse.NORMAL)) { |
| 207 _addToWorkList(member); | 261 _addToWorkList(member); |
| 208 } | 262 } |
| 209 if (useSet.contains(MemberUse.CLOSURIZE_INSTANCE)) { | 263 if (useSet.contains(MemberUse.CLOSURIZE_INSTANCE)) { |
| 210 _registerClosurizedMember(member); | 264 _registerClosurizedMember(member); |
| 211 } | 265 } |
| 212 if (useSet.contains(MemberUse.CLOSURIZE_STATIC)) { | 266 if (useSet.contains(MemberUse.CLOSURIZE_STATIC)) { |
| 213 applyImpact(backend.registerGetOfStaticFunction()); | 267 applyImpact(_listener.registerGetOfStaticFunction()); |
| 214 } | 268 } |
| 215 } | 269 } |
| 216 | 270 |
| 217 /// Callback for applying the use of a [cls]. | 271 /// Callback for applying the use of a [cls]. |
| 218 void _applyClassUse(ClassEntity cls, EnumSet<ClassUse> useSet) { | 272 void _applyClassUse(ClassEntity cls, EnumSet<ClassUse> useSet) { |
| 219 if (useSet.contains(ClassUse.INSTANTIATED)) { | 273 if (useSet.contains(ClassUse.INSTANTIATED)) { |
| 220 _recentClasses.add(cls); | 274 _recentClasses.add(cls); |
| 221 _universe.processClassMembers(cls, _applyMemberUse); | 275 _universe.processClassMembers(cls, _applyMemberUse); |
| 222 // We only tell the backend once that [cls] was instantiated, so | 276 // We only tell the backend once that [cls] was instantiated, so |
| 223 // any additional dependencies must be treated as global | 277 // any additional dependencies must be treated as global |
| 224 // dependencies. | 278 // dependencies. |
| 225 applyImpact(backend.registerInstantiatedClass(cls, forResolution: true)); | 279 applyImpact( |
| 280 _listener.registerInstantiatedClass(cls, forResolution: true)); |
| 226 } | 281 } |
| 227 if (useSet.contains(ClassUse.IMPLEMENTED)) { | 282 if (useSet.contains(ClassUse.IMPLEMENTED)) { |
| 228 applyImpact(backend.registerImplementedClass(cls, forResolution: true)); | 283 applyImpact(_listener.registerImplementedClass(cls, forResolution: true)); |
| 229 } | 284 } |
| 230 } | 285 } |
| 231 | 286 |
| 232 void processDynamicUse(DynamicUse dynamicUse) { | 287 void processDynamicUse(DynamicUse dynamicUse) { |
| 233 task.measure(() { | 288 task.measure(() { |
| 234 _universe.registerDynamicUse(dynamicUse, _applyMemberUse); | 289 _universe.registerDynamicUse(dynamicUse, _applyMemberUse); |
| 235 }); | 290 }); |
| 236 } | 291 } |
| 237 | 292 |
| 238 void processStaticUse(StaticUse staticUse) { | 293 void processStaticUse(StaticUse staticUse) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 type = _universe.registerIsCheck(type); | 347 type = _universe.registerIsCheck(type); |
| 293 // Even in checked mode, type annotations for return type and argument | 348 // Even in checked mode, type annotations for return type and argument |
| 294 // types do not imply type checks, so there should never be a check | 349 // types do not imply type checks, so there should never be a check |
| 295 // against the type variable of a typedef. | 350 // against the type variable of a typedef. |
| 296 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); | 351 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); |
| 297 } | 352 } |
| 298 | 353 |
| 299 void _registerClosurizedMember(MemberElement element) { | 354 void _registerClosurizedMember(MemberElement element) { |
| 300 assert(element.isInstanceMember); | 355 assert(element.isInstanceMember); |
| 301 if (element.type.containsTypeVariables) { | 356 if (element.type.containsTypeVariables) { |
| 302 applyImpact(backend.registerClosureWithFreeTypeVariables(element, | 357 applyImpact(_listener.registerClosureWithFreeTypeVariables(element, |
| 303 forResolution: true)); | 358 forResolution: true)); |
| 304 _universe.closuresWithFreeTypeVariables.add(element); | 359 _universe.closuresWithFreeTypeVariables.add(element); |
| 305 } | 360 } |
| 306 applyImpact(backend.registerBoundClosure()); | 361 applyImpact(_listener.registerBoundClosure()); |
| 307 _universe.closurizedMembers.add(element); | 362 _universe.closurizedMembers.add(element); |
| 308 } | 363 } |
| 309 | 364 |
| 310 void forEach(void f(WorkItem work)) { | 365 void forEach(void f(WorkItem work)) { |
| 311 do { | 366 do { |
| 312 while (_queue.isNotEmpty) { | 367 while (_queue.isNotEmpty) { |
| 313 // TODO(johnniwinther): Find an optimal process order. | 368 // TODO(johnniwinther): Find an optimal process order. |
| 314 WorkItem work = _queue.removeLast(); | 369 WorkItem work = _queue.removeLast(); |
| 315 if (!_processedEntities.contains(work.element)) { | 370 if (!_processedEntities.contains(work.element)) { |
| 316 strategy.processWorkItem(f, work); | 371 strategy.processWorkItem(f, work); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 void _addToWorkList(MemberEntity entity) { | 412 void _addToWorkList(MemberEntity entity) { |
| 358 if (hasBeenProcessed(entity)) return; | 413 if (hasBeenProcessed(entity)) return; |
| 359 WorkItem workItem = _workItemBuilder.createWorkItem(entity); | 414 WorkItem workItem = _workItemBuilder.createWorkItem(entity); |
| 360 if (workItem == null) return; | 415 if (workItem == null) return; |
| 361 | 416 |
| 362 if (queueIsClosed) { | 417 if (queueIsClosed) { |
| 363 throw new SpannableAssertionFailure( | 418 throw new SpannableAssertionFailure( |
| 364 entity, "Resolution work list is closed. Trying to add $entity."); | 419 entity, "Resolution work list is closed. Trying to add $entity."); |
| 365 } | 420 } |
| 366 | 421 |
| 367 applyImpact(backend.registerUsedElement(entity, forResolution: true)); | 422 applyImpact(_listener.registerUsedElement(entity, forResolution: true)); |
| 368 _universe.registerUsedElement(entity); | 423 _universe.registerUsedElement(entity); |
| 369 _queue.add(workItem); | 424 _queue.add(workItem); |
| 370 } | 425 } |
| 371 | 426 |
| 372 /// Adds an action to the deferred task queue. | 427 /// Adds an action to the deferred task queue. |
| 373 /// The action is performed the next time the resolution queue has been | 428 /// The action is performed the next time the resolution queue has been |
| 374 /// emptied. | 429 /// emptied. |
| 375 /// | 430 /// |
| 376 /// The queue is processed in FIFO order. | 431 /// The queue is processed in FIFO order. |
| 377 void addDeferredAction(Entity entity, void action()) { | 432 void addDeferredAction(Entity entity, void action()) { |
| 378 if (queueIsClosed) { | 433 if (queueIsClosed) { |
| 379 throw new SpannableAssertionFailure( | 434 throw new SpannableAssertionFailure( |
| 380 entity, | 435 entity, |
| 381 "Resolution work list is closed. " | 436 "Resolution work list is closed. " |
| 382 "Trying to add deferred action for $entity"); | 437 "Trying to add deferred action for $entity"); |
| 383 } | 438 } |
| 384 _deferredQueue.add(new _DeferredAction(entity, action)); | 439 _deferredQueue.add(new _DeferredAction(entity, action)); |
| 385 } | 440 } |
| 386 | 441 |
| 387 /// [_onQueueEmpty] is called whenever the queue is drained. [recentClasses] | 442 /// [_onQueueEmpty] is called whenever the queue is drained. [recentClasses] |
| 388 /// contains the set of all classes seen for the first time since | 443 /// contains the set of all classes seen for the first time since |
| 389 /// [_onQueueEmpty] was called last. A return value of [true] indicates that | 444 /// [_onQueueEmpty] was called last. A return value of [true] indicates that |
| 390 /// the [recentClasses] have been processed and may be cleared. If [false] is | 445 /// the [recentClasses] have been processed and may be cleared. If [false] is |
| 391 /// returned, [_onQueueEmpty] will be called once the queue is empty again (or | 446 /// returned, [_onQueueEmpty] will be called once the queue is empty again (or |
| 392 /// still empty) and [recentClasses] will be a superset of the current value. | 447 /// still empty) and [recentClasses] will be a superset of the current value. |
| 393 bool _onQueueEmpty(Iterable<ClassEntity> recentClasses) { | 448 bool _onQueueEmpty(Iterable<ClassEntity> recentClasses) { |
| 394 _emptyDeferredQueue(); | 449 _emptyDeferredQueue(); |
| 395 | 450 |
| 396 return backend.onQueueEmpty(this, recentClasses); | 451 return _listener.onQueueEmpty(this, recentClasses); |
| 397 } | 452 } |
| 398 | 453 |
| 399 void emptyDeferredQueueForTesting() => _emptyDeferredQueue(); | 454 void emptyDeferredQueueForTesting() => _emptyDeferredQueue(); |
| 400 | 455 |
| 401 void _emptyDeferredQueue() { | 456 void _emptyDeferredQueue() { |
| 402 while (!_deferredQueue.isEmpty) { | 457 while (!_deferredQueue.isEmpty) { |
| 403 _DeferredAction task = _deferredQueue.removeFirst(); | 458 _DeferredAction task = _deferredQueue.removeFirst(); |
| 404 _reporter.withCurrentElement(task.element, task.action); | 459 _reporter.withCurrentElement(task.element, task.action); |
| 405 } | 460 } |
| 406 } | 461 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 @override | 574 @override |
| 520 WorkItem createWorkItem(MemberElement element) { | 575 WorkItem createWorkItem(MemberElement element) { |
| 521 assert(invariant(element, element.isDeclaration)); | 576 assert(invariant(element, element.isDeclaration)); |
| 522 if (element.isMalformed) return null; | 577 if (element.isMalformed) return null; |
| 523 | 578 |
| 524 assert(invariant(element, element is AnalyzableElement, | 579 assert(invariant(element, element is AnalyzableElement, |
| 525 message: 'Element $element is not analyzable.')); | 580 message: 'Element $element is not analyzable.')); |
| 526 return _resolution.createWorkItem(element); | 581 return _resolution.createWorkItem(element); |
| 527 } | 582 } |
| 528 } | 583 } |
| OLD | NEW |