Chromium Code Reviews| 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; | 13 import 'compiler.dart' show Compiler; |
| 14 import 'options.dart'; | 14 import 'options.dart'; |
| 15 import 'elements/elements.dart' | 15 import 'elements/elements.dart' |
| 16 show AnalyzableElement, ClassElement, MemberElement; | 16 show AnalyzableElement, ClassElement, MemberElement; |
| 17 import 'elements/entities.dart'; | 17 import 'elements/entities.dart'; |
| 18 import 'elements/resolution_types.dart' show ResolutionTypedefType; | 18 import 'elements/resolution_types.dart' show ResolutionTypedefType; |
| 19 import 'elements/types.dart'; | 19 import 'elements/types.dart'; |
| 20 import 'native/native.dart' as native; | |
| 21 import 'universe/world_builder.dart'; | 20 import 'universe/world_builder.dart'; |
| 22 import 'universe/use.dart' | 21 import 'universe/use.dart' |
| 23 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; | 22 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; |
| 24 import 'universe/world_impact.dart' | 23 import 'universe/world_impact.dart' |
| 25 show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor; | 24 show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor; |
| 26 import 'util/enumset.dart'; | 25 import 'util/enumset.dart'; |
| 27 import 'util/util.dart' show Setlet; | 26 import 'util/util.dart' show Setlet; |
| 28 | 27 |
| 29 class EnqueueTask extends CompilerTask { | 28 class EnqueueTask extends CompilerTask { |
| 30 ResolutionEnqueuer _resolution; | 29 ResolutionEnqueuer _resolution; |
| 31 Enqueuer _codegen; | 30 Enqueuer _codegen; |
| 32 final Compiler compiler; | 31 final Compiler compiler; |
| 33 | 32 |
| 34 String get name => 'Enqueue'; | 33 String get name => 'Enqueue'; |
| 35 | 34 |
| 36 EnqueueTask(Compiler compiler) | 35 EnqueueTask(Compiler compiler) |
| 37 : this.compiler = compiler, | 36 : this.compiler = compiler, |
| 38 super(compiler.measurer) { | 37 super(compiler.measurer) { |
| 39 _resolution = new ResolutionEnqueuer( | 38 _resolution = new ResolutionEnqueuer( |
| 40 this, | 39 this, |
| 41 compiler.options, | 40 compiler.options, |
| 42 compiler.reporter, | 41 compiler.reporter, |
| 43 compiler.options.analyzeOnly && compiler.options.analyzeMain | 42 compiler.options.analyzeOnly && compiler.options.analyzeMain |
| 44 ? const DirectEnqueuerStrategy() | 43 ? const DirectEnqueuerStrategy() |
| 45 : const TreeShakingEnqueuerStrategy(), | 44 : const TreeShakingEnqueuerStrategy(), |
| 46 compiler.backend.resolutionEnqueuerListener, | 45 compiler.backend.resolutionEnqueuerListener, |
| 47 compiler.backend.nativeResolutionEnqueuer(), | |
| 48 new ElementResolutionWorldBuilder( | 46 new ElementResolutionWorldBuilder( |
| 49 compiler.backend, compiler.resolution, const OpenWorldStrategy()), | 47 compiler.backend, compiler.resolution, const OpenWorldStrategy()), |
| 50 new ResolutionWorkItemBuilder(compiler.resolution)); | 48 new ResolutionWorkItemBuilder(compiler.resolution)); |
| 51 _codegen = compiler.backend.createCodegenEnqueuer(this, compiler); | 49 _codegen = compiler.backend.createCodegenEnqueuer(this, compiler); |
| 52 } | 50 } |
| 53 | 51 |
| 54 ResolutionEnqueuer get resolution => _resolution; | 52 ResolutionEnqueuer get resolution => _resolution; |
| 55 Enqueuer get codegen => _codegen; | 53 Enqueuer get codegen => _codegen; |
| 56 } | 54 } |
| 57 | 55 |
| 58 abstract class Enqueuer { | 56 abstract class Enqueuer { |
| 59 WorldBuilder get worldBuilder; | 57 WorldBuilder get worldBuilder; |
| 60 native.NativeEnqueuer get nativeEnqueuer; | |
| 61 ImpactStrategy get impactStrategy; | 58 ImpactStrategy get impactStrategy; |
| 62 | 59 |
| 63 void open(ImpactStrategy impactStrategy, FunctionEntity mainMethod, | 60 void open(ImpactStrategy impactStrategy, FunctionEntity mainMethod, |
| 64 Iterable<LibraryEntity> libraries); | 61 Iterable<LibraryEntity> libraries); |
| 65 void close(); | 62 void close(); |
| 66 | 63 |
| 67 /// Returns [:true:] if this enqueuer is the resolution enqueuer. | 64 /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
| 68 bool get isResolutionQueue; | 65 bool get isResolutionQueue; |
| 69 | 66 |
| 70 bool queueIsClosed; | 67 bool queueIsClosed; |
| 71 | 68 |
| 72 bool get queueIsEmpty; | 69 bool get queueIsEmpty; |
| 73 | 70 |
| 74 ImpactUseCase get impactUse; | 71 ImpactUseCase get impactUse; |
| 75 | 72 |
| 76 void forEach(void f(WorkItem work)); | 73 void forEach(void f(WorkItem work)); |
| 77 | 74 |
| 78 /// Apply the [worldImpact] to this enqueuer. If the [impactSource] is | 75 /// Apply the [worldImpact] to this enqueuer. If the [impactSource] is |
| 79 /// provided the impact strategy will remove it from the element impact cache, | 76 /// provided the impact strategy will remove it from the element impact cache, |
| 80 /// if it is no longer needed. | 77 /// if it is no longer needed. |
| 81 void applyImpact(WorldImpact worldImpact, {var impactSource}); | 78 void applyImpact(WorldImpact worldImpact, {var impactSource}); |
| 82 bool checkNoEnqueuedInvokedInstanceMethods(); | 79 bool checkNoEnqueuedInvokedInstanceMethods(); |
| 83 | 80 |
| 84 /// Check the enqueuer queue is empty or fail otherwise. | 81 /// Check the enqueuer queue is empty or fail otherwise. |
| 85 void checkQueueIsEmpty(); | 82 void checkQueueIsEmpty(); |
| 86 void logSummary(log(message)); | 83 void logSummary(void log(String message)); |
| 87 | 84 |
| 88 Iterable<Entity> get processedEntities; | 85 Iterable<Entity> get processedEntities; |
| 89 | 86 |
| 90 Iterable<ClassEntity> get processedClasses; | 87 Iterable<ClassEntity> get processedClasses; |
| 91 } | 88 } |
| 92 | 89 |
| 93 abstract class EnqueuerListener { | 90 abstract class EnqueuerListener { |
| 94 /// Called to instruct to the backend that [type] has been instantiated. | 91 /// Called to instruct to the backend that [type] has been instantiated. |
| 95 void registerInstantiatedType(InterfaceType type, {bool isGlobal}); | 92 void registerInstantiatedType(InterfaceType type, |
| 93 {bool isGlobal: false, bool nativeUsage: false}); | |
| 96 | 94 |
| 97 /// Called to notify to the backend that a class is being instantiated. Any | 95 /// Called to notify to the backend that a class is being instantiated. Any |
| 98 /// backend specific [WorldImpact] of this is returned. | 96 /// backend specific [WorldImpact] of this is returned. |
| 99 WorldImpact registerInstantiatedClass(ClassEntity cls); | 97 WorldImpact registerInstantiatedClass(ClassEntity cls); |
| 100 | 98 |
| 101 /// Called to notify to the backend that a class is implemented by an | 99 /// Called to notify to the backend that a class is implemented by an |
| 102 /// instantiated class. Any backend specific [WorldImpact] of this is | 100 /// instantiated class. Any backend specific [WorldImpact] of this is |
| 103 /// returned. | 101 /// returned. |
| 104 WorldImpact registerImplementedClass(ClassEntity cls); | 102 WorldImpact registerImplementedClass(ClassEntity cls); |
| 105 | 103 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 128 /// A return value of `true` indicates that [recentClasses] has been | 126 /// A return value of `true` indicates that [recentClasses] has been |
| 129 /// processed and its elements do not need to be seen in the next round. When | 127 /// processed and its elements do not need to be seen in the next round. When |
| 130 /// `false` is returned, [onQueueEmpty] will be called again once the | 128 /// `false` is returned, [onQueueEmpty] will be called again once the |
| 131 /// resolution queue has drained and [recentClasses] will be a superset of the | 129 /// resolution queue has drained and [recentClasses] will be a superset of the |
| 132 /// current value. | 130 /// current value. |
| 133 /// | 131 /// |
| 134 /// There is no guarantee that a class is only present once in | 132 /// There is no guarantee that a class is only present once in |
| 135 /// [recentClasses], but every class seen by the [enqueuer] will be present in | 133 /// [recentClasses], but every class seen by the [enqueuer] will be present in |
| 136 /// [recentClasses] at least once. | 134 /// [recentClasses] at least once. |
| 137 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses); | 135 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses); |
| 136 | |
| 137 /// Called when to the queue is emptied. | |
|
Siggi Cherem (dart-lang)
2017/03/14 03:10:50
mmm... "when to the"?
Johnni Winther
2017/03/15 09:02:58
Good English not?
| |
| 138 void logSummary(void log(String message)); | |
| 138 } | 139 } |
| 139 | 140 |
| 140 abstract class EnqueuerImpl extends Enqueuer { | 141 abstract class EnqueuerImpl extends Enqueuer { |
| 141 CompilerTask get task; | 142 CompilerTask get task; |
| 142 EnqueuerStrategy get strategy; | 143 EnqueuerStrategy get strategy; |
| 143 void checkClass(ClassEntity cls); | 144 void checkClass(ClassEntity cls); |
| 144 void processStaticUse(StaticUse staticUse); | 145 void processStaticUse(StaticUse staticUse); |
| 145 void processTypeUse(TypeUse typeUse); | 146 void processTypeUse(TypeUse typeUse); |
| 146 void processDynamicUse(DynamicUse dynamicUse); | 147 void processDynamicUse(DynamicUse dynamicUse); |
| 147 EnqueuerListener get listener; | 148 EnqueuerListener get listener; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 166 | 167 |
| 167 /// [Enqueuer] which is specific to resolution. | 168 /// [Enqueuer] which is specific to resolution. |
| 168 class ResolutionEnqueuer extends EnqueuerImpl { | 169 class ResolutionEnqueuer extends EnqueuerImpl { |
| 169 static const ImpactUseCase IMPACT_USE = | 170 static const ImpactUseCase IMPACT_USE = |
| 170 const ImpactUseCase('ResolutionEnqueuer'); | 171 const ImpactUseCase('ResolutionEnqueuer'); |
| 171 | 172 |
| 172 final CompilerTask task; | 173 final CompilerTask task; |
| 173 final String name; | 174 final String name; |
| 174 final CompilerOptions _options; | 175 final CompilerOptions _options; |
| 175 final EnqueuerListener listener; | 176 final EnqueuerListener listener; |
| 176 final native.NativeEnqueuer nativeEnqueuer; | |
| 177 | 177 |
| 178 final EnqueuerStrategy strategy; | 178 final EnqueuerStrategy strategy; |
| 179 final Set<ClassEntity> _recentClasses = new Setlet<ClassEntity>(); | 179 final Set<ClassEntity> _recentClasses = new Setlet<ClassEntity>(); |
| 180 final ResolutionEnqueuerWorldBuilder _worldBuilder; | 180 final ResolutionEnqueuerWorldBuilder _worldBuilder; |
| 181 final WorkItemBuilder _workItemBuilder; | 181 final WorkItemBuilder _workItemBuilder; |
| 182 final DiagnosticReporter _reporter; | 182 final DiagnosticReporter _reporter; |
| 183 | 183 |
| 184 bool queueIsClosed = false; | 184 bool queueIsClosed = false; |
| 185 | 185 |
| 186 WorldImpactVisitor _impactVisitor; | 186 WorldImpactVisitor _impactVisitor; |
| 187 | 187 |
| 188 /// All declaration elements that have been processed by the resolver. | 188 /// All declaration elements that have been processed by the resolver. |
| 189 final Set<Entity> _processedEntities = new Set<Entity>(); | 189 final Set<Entity> _processedEntities = new Set<Entity>(); |
| 190 | 190 |
| 191 final Queue<WorkItem> _queue = new Queue<WorkItem>(); | 191 final Queue<WorkItem> _queue = new Queue<WorkItem>(); |
| 192 | 192 |
| 193 /// Queue of deferred resolution actions to execute when the resolution queue | 193 /// Queue of deferred resolution actions to execute when the resolution queue |
| 194 /// has been emptied. | 194 /// has been emptied. |
| 195 final Queue<_DeferredAction> _deferredQueue = new Queue<_DeferredAction>(); | 195 final Queue<_DeferredAction> _deferredQueue = new Queue<_DeferredAction>(); |
| 196 | 196 |
| 197 ResolutionEnqueuer( | 197 ResolutionEnqueuer(this.task, this._options, this._reporter, this.strategy, |
| 198 this.task, | 198 this.listener, this._worldBuilder, this._workItemBuilder, |
| 199 this._options, | |
| 200 this._reporter, | |
| 201 this.strategy, | |
| 202 this.listener, | |
| 203 this.nativeEnqueuer, | |
| 204 this._worldBuilder, | |
| 205 this._workItemBuilder, | |
| 206 [this.name = 'resolution enqueuer']) { | 199 [this.name = 'resolution enqueuer']) { |
| 207 _impactVisitor = new EnqueuerImplImpactVisitor(this); | 200 _impactVisitor = new EnqueuerImplImpactVisitor(this); |
| 208 } | 201 } |
| 209 | 202 |
| 210 ResolutionWorldBuilder get worldBuilder => _worldBuilder; | 203 ResolutionWorldBuilder get worldBuilder => _worldBuilder; |
| 211 | 204 |
| 212 bool get queueIsEmpty => _queue.isEmpty; | 205 bool get queueIsEmpty => _queue.isEmpty; |
| 213 | 206 |
| 214 @override | 207 @override |
| 215 void checkQueueIsEmpty() { | 208 void checkQueueIsEmpty() { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 231 {ConstructorEntity constructor, | 224 {ConstructorEntity constructor, |
| 232 bool mirrorUsage: false, | 225 bool mirrorUsage: false, |
| 233 bool nativeUsage: false, | 226 bool nativeUsage: false, |
| 234 bool globalDependency: false, | 227 bool globalDependency: false, |
| 235 bool isRedirection: false}) { | 228 bool isRedirection: false}) { |
| 236 task.measure(() { | 229 task.measure(() { |
| 237 _worldBuilder.registerTypeInstantiation(type, _applyClassUse, | 230 _worldBuilder.registerTypeInstantiation(type, _applyClassUse, |
| 238 constructor: constructor, | 231 constructor: constructor, |
| 239 byMirrors: mirrorUsage, | 232 byMirrors: mirrorUsage, |
| 240 isRedirection: isRedirection); | 233 isRedirection: isRedirection); |
| 241 if (nativeUsage) { | |
| 242 nativeEnqueuer.onInstantiatedType(type); | |
| 243 } | |
| 244 listener.registerInstantiatedType(type, | 234 listener.registerInstantiatedType(type, |
| 245 isGlobal: globalDependency && !mirrorUsage); | 235 isGlobal: globalDependency && !mirrorUsage, nativeUsage: nativeUsage); |
| 246 }); | 236 }); |
| 247 } | 237 } |
| 248 | 238 |
| 249 bool checkNoEnqueuedInvokedInstanceMethods() { | 239 bool checkNoEnqueuedInvokedInstanceMethods() { |
| 250 return strategy.checkEnqueuerConsistency(this); | 240 return strategy.checkEnqueuerConsistency(this); |
| 251 } | 241 } |
| 252 | 242 |
| 253 void checkClass(ClassEntity cls) { | 243 void checkClass(ClassEntity cls) { |
| 254 _worldBuilder.processClassMembers(cls, | 244 _worldBuilder.processClassMembers(cls, |
| 255 (MemberEntity member, EnumSet<MemberUse> useSet) { | 245 (MemberEntity member, EnumSet<MemberUse> useSet) { |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 369 } | 359 } |
| 370 } | 360 } |
| 371 List recents = _recentClasses.toList(growable: false); | 361 List recents = _recentClasses.toList(growable: false); |
| 372 _recentClasses.clear(); | 362 _recentClasses.clear(); |
| 373 if (!_onQueueEmpty(recents)) { | 363 if (!_onQueueEmpty(recents)) { |
| 374 _recentClasses.addAll(recents); | 364 _recentClasses.addAll(recents); |
| 375 } | 365 } |
| 376 } while (_queue.isNotEmpty || _recentClasses.isNotEmpty); | 366 } while (_queue.isNotEmpty || _recentClasses.isNotEmpty); |
| 377 } | 367 } |
| 378 | 368 |
| 379 void logSummary(log(message)) { | 369 void logSummary(void log(String message)) { |
| 380 log('Resolved ${_processedEntities.length} elements.'); | 370 log('Resolved ${_processedEntities.length} elements.'); |
| 381 nativeEnqueuer.logSummary(log); | 371 listener.logSummary(log); |
| 382 } | 372 } |
| 383 | 373 |
| 384 String toString() => 'Enqueuer($name)'; | 374 String toString() => 'Enqueuer($name)'; |
| 385 | 375 |
| 386 Iterable<Entity> get processedEntities => _processedEntities; | 376 Iterable<Entity> get processedEntities => _processedEntities; |
| 387 | 377 |
| 388 ImpactUseCase get impactUse => IMPACT_USE; | 378 ImpactUseCase get impactUse => IMPACT_USE; |
| 389 | 379 |
| 390 bool get isResolutionQueue => true; | 380 bool get isResolutionQueue => true; |
| 391 | 381 |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 570 @override | 560 @override |
| 571 WorkItem createWorkItem(MemberElement element) { | 561 WorkItem createWorkItem(MemberElement element) { |
| 572 assert(invariant(element, element.isDeclaration)); | 562 assert(invariant(element, element.isDeclaration)); |
| 573 if (element.isMalformed) return null; | 563 if (element.isMalformed) return null; |
| 574 | 564 |
| 575 assert(invariant(element, element is AnalyzableElement, | 565 assert(invariant(element, element is AnalyzableElement, |
| 576 message: 'Element $element is not analyzable.')); | 566 message: 'Element $element is not analyzable.')); |
| 577 return _resolution.createWorkItem(element); | 567 return _resolution.createWorkItem(element); |
| 578 } | 568 } |
| 579 } | 569 } |
| OLD | NEW |