| 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 | 16 show AnalyzableElement, ClassElement, MemberElement; |
| 17 AnalyzableElement, | |
| 18 ClassElement, | |
| 19 ConstructorElement, | |
| 20 Element, | |
| 21 MemberElement; | |
| 22 import 'elements/entities.dart'; | 17 import 'elements/entities.dart'; |
| 23 import 'elements/resolution_types.dart' | 18 import 'elements/resolution_types.dart' show ResolutionTypedefType; |
| 24 show ResolutionDartType, ResolutionInterfaceType; | 19 import 'elements/types.dart'; |
| 25 import 'elements/types.dart' show InterfaceType; | |
| 26 import 'native/native.dart' as native; | 20 import 'native/native.dart' as native; |
| 27 import 'universe/world_builder.dart'; | 21 import 'universe/world_builder.dart'; |
| 28 import 'universe/use.dart' | 22 import 'universe/use.dart' |
| 29 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; | 23 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; |
| 30 import 'universe/world_impact.dart' | 24 import 'universe/world_impact.dart' |
| 31 show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor; | 25 show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor; |
| 32 import 'util/enumset.dart'; | 26 import 'util/enumset.dart'; |
| 33 import 'util/util.dart' show Setlet; | 27 import 'util/util.dart' show Setlet; |
| 34 | 28 |
| 35 class EnqueueTask extends CompilerTask { | 29 class EnqueueTask extends CompilerTask { |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 } | 220 } |
| 227 | 221 |
| 228 Iterable<ClassEntity> get processedClasses => _worldBuilder.processedClasses; | 222 Iterable<ClassEntity> get processedClasses => _worldBuilder.processedClasses; |
| 229 | 223 |
| 230 void applyImpact(WorldImpact worldImpact, {var impactSource}) { | 224 void applyImpact(WorldImpact worldImpact, {var impactSource}) { |
| 231 if (worldImpact.isEmpty) return; | 225 if (worldImpact.isEmpty) return; |
| 232 impactStrategy.visitImpact( | 226 impactStrategy.visitImpact( |
| 233 impactSource, worldImpact, _impactVisitor, impactUse); | 227 impactSource, worldImpact, _impactVisitor, impactUse); |
| 234 } | 228 } |
| 235 | 229 |
| 236 void _registerInstantiatedType(ResolutionInterfaceType type, | 230 void _registerInstantiatedType(InterfaceType type, |
| 237 {ConstructorElement constructor, | 231 {ConstructorEntity constructor, |
| 238 bool mirrorUsage: false, | 232 bool mirrorUsage: false, |
| 239 bool nativeUsage: false, | 233 bool nativeUsage: false, |
| 240 bool globalDependency: false, | 234 bool globalDependency: false, |
| 241 bool isRedirection: false}) { | 235 bool isRedirection: false}) { |
| 242 task.measure(() { | 236 task.measure(() { |
| 243 _worldBuilder.registerTypeInstantiation(type, _applyClassUse, | 237 _worldBuilder.registerTypeInstantiation(type, _applyClassUse, |
| 244 constructor: constructor, | 238 constructor: constructor, |
| 245 byMirrors: mirrorUsage, | 239 byMirrors: mirrorUsage, |
| 246 isRedirection: isRedirection); | 240 isRedirection: isRedirection); |
| 247 if (nativeUsage) { | 241 if (nativeUsage) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 constructor: staticUse.element, | 309 constructor: staticUse.element, |
| 316 globalDependency: false, | 310 globalDependency: false, |
| 317 isRedirection: true); | 311 isRedirection: true); |
| 318 break; | 312 break; |
| 319 default: | 313 default: |
| 320 break; | 314 break; |
| 321 } | 315 } |
| 322 } | 316 } |
| 323 | 317 |
| 324 void processTypeUse(TypeUse typeUse) { | 318 void processTypeUse(TypeUse typeUse) { |
| 325 ResolutionDartType type = typeUse.type; | 319 DartType type = typeUse.type; |
| 326 switch (typeUse.kind) { | 320 switch (typeUse.kind) { |
| 327 case TypeUseKind.INSTANTIATION: | 321 case TypeUseKind.INSTANTIATION: |
| 328 _registerInstantiatedType(type, globalDependency: false); | 322 _registerInstantiatedType(type, globalDependency: false); |
| 329 break; | 323 break; |
| 330 case TypeUseKind.MIRROR_INSTANTIATION: | 324 case TypeUseKind.MIRROR_INSTANTIATION: |
| 331 _registerInstantiatedType(type, | 325 _registerInstantiatedType(type, |
| 332 mirrorUsage: true, globalDependency: false); | 326 mirrorUsage: true, globalDependency: false); |
| 333 break; | 327 break; |
| 334 case TypeUseKind.NATIVE_INSTANTIATION: | 328 case TypeUseKind.NATIVE_INSTANTIATION: |
| 335 _registerInstantiatedType(type, | 329 _registerInstantiatedType(type, |
| 336 nativeUsage: true, globalDependency: true); | 330 nativeUsage: true, globalDependency: true); |
| 337 break; | 331 break; |
| 338 case TypeUseKind.IS_CHECK: | 332 case TypeUseKind.IS_CHECK: |
| 339 case TypeUseKind.AS_CAST: | 333 case TypeUseKind.AS_CAST: |
| 340 case TypeUseKind.CATCH_TYPE: | 334 case TypeUseKind.CATCH_TYPE: |
| 341 _registerIsCheck(type); | 335 _registerIsCheck(type); |
| 342 break; | 336 break; |
| 343 case TypeUseKind.CHECKED_MODE_CHECK: | 337 case TypeUseKind.CHECKED_MODE_CHECK: |
| 344 if (_options.enableTypeAssertions) { | 338 if (_options.enableTypeAssertions) { |
| 345 _registerIsCheck(type); | 339 _registerIsCheck(type); |
| 346 } | 340 } |
| 347 break; | 341 break; |
| 348 case TypeUseKind.TYPE_LITERAL: | 342 case TypeUseKind.TYPE_LITERAL: |
| 349 if (type.isTypedef) { | 343 if (type.isTypedef) { |
| 350 worldBuilder.registerTypedef(type.element); | 344 ResolutionTypedefType typedef = type; |
| 345 worldBuilder.registerTypedef(typedef.element); |
| 351 } | 346 } |
| 352 break; | 347 break; |
| 353 } | 348 } |
| 354 } | 349 } |
| 355 | 350 |
| 356 void _registerIsCheck(ResolutionDartType type) { | 351 void _registerIsCheck(DartType type) { |
| 357 type = _worldBuilder.registerIsCheck(type); | 352 _worldBuilder.registerIsCheck(type); |
| 358 // Even in checked mode, type annotations for return type and argument | |
| 359 // types do not imply type checks, so there should never be a check | |
| 360 // against the type variable of a typedef. | |
| 361 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); | |
| 362 } | 353 } |
| 363 | 354 |
| 364 void _registerClosurizedMember(MemberElement element) { | 355 void _registerClosurizedMember(MemberEntity element) { |
| 365 assert(element.isInstanceMember); | 356 assert(element.isInstanceMember); |
| 366 applyImpact(listener.registerClosurizedMember(element)); | 357 applyImpact(listener.registerClosurizedMember(element)); |
| 367 _worldBuilder.registerClosurizedMember(element); | 358 _worldBuilder.registerClosurizedMember(element); |
| 368 } | 359 } |
| 369 | 360 |
| 370 void forEach(void f(WorkItem work)) { | 361 void forEach(void f(WorkItem work)) { |
| 371 do { | 362 do { |
| 372 while (_queue.isNotEmpty) { | 363 while (_queue.isNotEmpty) { |
| 373 // TODO(johnniwinther): Find an optimal process order. | 364 // TODO(johnniwinther): Find an optimal process order. |
| 374 WorkItem work = _queue.removeLast(); | 365 WorkItem work = _queue.removeLast(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 392 | 383 |
| 393 String toString() => 'Enqueuer($name)'; | 384 String toString() => 'Enqueuer($name)'; |
| 394 | 385 |
| 395 Iterable<Entity> get processedEntities => _processedEntities; | 386 Iterable<Entity> get processedEntities => _processedEntities; |
| 396 | 387 |
| 397 ImpactUseCase get impactUse => IMPACT_USE; | 388 ImpactUseCase get impactUse => IMPACT_USE; |
| 398 | 389 |
| 399 bool get isResolutionQueue => true; | 390 bool get isResolutionQueue => true; |
| 400 | 391 |
| 401 /// Returns `true` if [element] has been processed by the resolution enqueuer. | 392 /// Returns `true` if [element] has been processed by the resolution enqueuer. |
| 402 // TODO(johnniwinther): Move this to the [OpenWorld]/[ResolutionWorldBuilder]. | 393 // TODO(johnniwinther): Remove this together with the resolver. |
| 403 bool hasBeenProcessed(MemberElement element) { | 394 bool hasBeenProcessed(MemberElement element) { |
| 404 assert(invariant(element, element == element.analyzableElement.declaration, | 395 assert(invariant(element, element == element.analyzableElement.declaration, |
| 405 message: "Unexpected element $element")); | 396 message: "Unexpected element $element")); |
| 406 return _processedEntities.contains(element); | 397 return _processedEntities.contains(element); |
| 407 } | 398 } |
| 408 | 399 |
| 409 /// Registers [entity] as processed by the resolution enqueuer. Used only for | 400 /// Registers [entity] as processed by the resolution enqueuer. Used only for |
| 410 /// testing. | 401 /// testing. |
| 411 void registerProcessedElementInternal(Entity entity) { | 402 void registerProcessedElementInternal(Entity entity) { |
| 412 _processedEntities.add(entity); | 403 _processedEntities.add(entity); |
| 413 } | 404 } |
| 414 | 405 |
| 415 /// Create a [WorkItem] for [entity] and add it to the work list if it has not | 406 /// Create a [WorkItem] for [entity] and add it to the work list if it has not |
| 416 /// already been processed. | 407 /// already been processed. |
| 417 void _addToWorkList(MemberEntity entity) { | 408 void _addToWorkList(MemberEntity entity) { |
| 418 if (hasBeenProcessed(entity)) return; | 409 if (_processedEntities.contains(entity)) return; |
| 419 WorkItem workItem = _workItemBuilder.createWorkItem(entity); | 410 WorkItem workItem = _workItemBuilder.createWorkItem(entity); |
| 420 if (workItem == null) return; | 411 if (workItem == null) return; |
| 421 | 412 |
| 422 if (queueIsClosed) { | 413 if (queueIsClosed) { |
| 423 throw new SpannableAssertionFailure( | 414 throw new SpannableAssertionFailure( |
| 424 entity, "Resolution work list is closed. Trying to add $entity."); | 415 entity, "Resolution work list is closed. Trying to add $entity."); |
| 425 } | 416 } |
| 426 | 417 |
| 427 applyImpact(listener.registerUsedElement(entity)); | 418 applyImpact(listener.registerUsedElement(entity)); |
| 428 _worldBuilder.registerUsedElement(entity); | 419 _worldBuilder.registerUsedElement(entity); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 | 542 |
| 552 @override | 543 @override |
| 553 void visitTypeUse(TypeUse typeUse) { | 544 void visitTypeUse(TypeUse typeUse) { |
| 554 enqueuer.strategy.processTypeUse(enqueuer, typeUse); | 545 enqueuer.strategy.processTypeUse(enqueuer, typeUse); |
| 555 } | 546 } |
| 556 } | 547 } |
| 557 | 548 |
| 558 typedef void _DeferredActionFunction(); | 549 typedef void _DeferredActionFunction(); |
| 559 | 550 |
| 560 class _DeferredAction { | 551 class _DeferredAction { |
| 561 final Element element; | 552 final Entity element; |
| 562 final _DeferredActionFunction action; | 553 final _DeferredActionFunction action; |
| 563 | 554 |
| 564 _DeferredAction(this.element, this.action); | 555 _DeferredAction(this.element, this.action); |
| 565 } | 556 } |
| 566 | 557 |
| 567 /// Interface for creating work items for enqueued member entities. | 558 /// Interface for creating work items for enqueued member entities. |
| 568 abstract class WorkItemBuilder { | 559 abstract class WorkItemBuilder { |
| 569 WorkItem createWorkItem(MemberEntity entity); | 560 WorkItem createWorkItem(MemberEntity entity); |
| 570 } | 561 } |
| 571 | 562 |
| 572 /// Builder that creates work item necessary for the resolution of a | 563 /// Builder that creates work item necessary for the resolution of a |
| 573 /// [MemberElement]. | 564 /// [MemberElement]. |
| 574 class ResolutionWorkItemBuilder extends WorkItemBuilder { | 565 class ResolutionWorkItemBuilder extends WorkItemBuilder { |
| 575 final Resolution _resolution; | 566 final Resolution _resolution; |
| 576 | 567 |
| 577 ResolutionWorkItemBuilder(this._resolution); | 568 ResolutionWorkItemBuilder(this._resolution); |
| 578 | 569 |
| 579 @override | 570 @override |
| 580 WorkItem createWorkItem(MemberElement element) { | 571 WorkItem createWorkItem(MemberElement element) { |
| 581 assert(invariant(element, element.isDeclaration)); | 572 assert(invariant(element, element.isDeclaration)); |
| 582 if (element.isMalformed) return null; | 573 if (element.isMalformed) return null; |
| 583 | 574 |
| 584 assert(invariant(element, element is AnalyzableElement, | 575 assert(invariant(element, element is AnalyzableElement, |
| 585 message: 'Element $element is not analyzable.')); | 576 message: 'Element $element is not analyzable.')); |
| 586 return _resolution.createWorkItem(element); | 577 return _resolution.createWorkItem(element); |
| 587 } | 578 } |
| 588 } | 579 } |
| OLD | NEW |