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.js.enqueue; |
| 6 | 6 |
| 7 import 'dart:collection' show Queue; | 7 import 'dart:collection' show Queue; |
| 8 | 8 |
| 9 import 'common/codegen.dart' show CodegenWorkItem; | 9 import '../common/codegen.dart' show CodegenWorkItem; |
| 10 import 'common/names.dart' show Identifiers; | 10 import '../common/names.dart' show Identifiers; |
| 11 import 'common/resolution.dart' show Resolution; | 11 import '../common/resolution.dart' show Resolution; |
| 12 import 'common/resolution.dart' show ResolutionWorkItem; | 12 import '../common/resolution.dart' show ResolutionWorkItem; |
| 13 import 'common/tasks.dart' show CompilerTask; | 13 import '../common/tasks.dart' show CompilerTask; |
| 14 import 'common/work.dart' show ItemCompilationContext, WorkItem; | 14 import '../common/work.dart' show ItemCompilationContext, WorkItem; |
| 15 import 'common.dart'; | 15 import '../common.dart'; |
| 16 import 'compiler.dart' show Compiler; | 16 import '../compiler.dart' show Compiler; |
| 17 import 'dart_types.dart' show DartType, InterfaceType; | 17 import '../dart_types.dart' show DartType, InterfaceType; |
| 18 import 'elements/elements.dart' | 18 import '../elements/elements.dart' |
| 19 show | 19 show |
| 20 AnalyzableElement, | 20 AnalyzableElement, |
| 21 AstElement, | 21 AstElement, |
| 22 ClassElement, | 22 ClassElement, |
| 23 ConstructorElement, | 23 ConstructorElement, |
| 24 Element, | 24 Element, |
| 25 Elements, | 25 Elements, |
| 26 FunctionElement, | 26 FunctionElement, |
| 27 LibraryElement, | 27 LibraryElement, |
| 28 Member, | 28 Member, |
| 29 MemberElement, | 29 MemberElement, |
| 30 Name, | 30 Name, |
| 31 TypedElement, | 31 TypedElement, |
| 32 TypedefElement; | 32 TypedefElement; |
| 33 import 'js/js.dart' as js; | 33 import '../enqueue.dart' as enqueue; |
| 34 import 'native/native.dart' as native; | 34 import '../js/js.dart' as js; |
| 35 import 'types/types.dart' show TypeMaskStrategy; | 35 import '../native/native.dart' as native; |
| 36 import 'universe/selector.dart' show Selector; | 36 import '../types/types.dart' show TypeMaskStrategy; |
| 37 import 'universe/universe.dart'; | 37 import '../universe/selector.dart' show Selector; |
| 38 import 'universe/use.dart' | 38 import '../universe/universe.dart'; |
| 39 import '../universe/use.dart' | |
| 39 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; | 40 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; |
| 40 import 'universe/world_impact.dart' | 41 import '../universe/world_impact.dart' |
| 41 show ImpactUseCase, WorldImpact, WorldImpactVisitor; | 42 show ImpactUseCase, WorldImpact, WorldImpactVisitor; |
| 42 import 'util/util.dart' show Setlet; | 43 import '../util/util.dart' show Setlet; |
| 43 | 44 |
| 44 typedef ItemCompilationContext ItemCompilationContextCreator(); | 45 abstract class _Enqueuer implements enqueue.Enqueuer { |
| 45 | |
| 46 class EnqueueTask extends CompilerTask { | |
| 47 final ResolutionEnqueuer resolution; | |
| 48 final CodegenEnqueuer codegen; | |
| 49 final Compiler compiler; | |
| 50 | |
| 51 String get name => 'Enqueue'; | |
| 52 | |
| 53 EnqueueTask(Compiler compiler) | |
| 54 : compiler = compiler, | |
| 55 resolution = new ResolutionEnqueuer( | |
| 56 compiler, | |
| 57 compiler.backend.createItemCompilationContext, | |
| 58 compiler.options.analyzeOnly && compiler.options.analyzeMain | |
| 59 ? const EnqueuerStrategy() | |
| 60 : const TreeShakingEnqueuerStrategy()), | |
| 61 codegen = new CodegenEnqueuer( | |
| 62 compiler, | |
| 63 compiler.backend.createItemCompilationContext, | |
| 64 const TreeShakingEnqueuerStrategy()), | |
| 65 super(compiler.measurer) { | |
| 66 codegen.task = this; | |
| 67 resolution.task = this; | |
| 68 | |
| 69 codegen.nativeEnqueuer = compiler.backend.nativeCodegenEnqueuer(codegen); | |
| 70 resolution.nativeEnqueuer = | |
| 71 compiler.backend.nativeResolutionEnqueuer(resolution); | |
| 72 } | |
| 73 | |
| 74 void forgetElement(Element element) { | |
| 75 resolution.forgetElement(element); | |
| 76 codegen.forgetElement(element); | |
| 77 } | |
| 78 } | |
| 79 | |
| 80 abstract class Enqueuer { | |
| 81 final String name; | 46 final String name; |
| 82 final Compiler compiler; // TODO(ahe): Remove this dependency. | 47 final Compiler compiler; // TODO(ahe): Remove this dependency. |
| 83 final EnqueuerStrategy strategy; | 48 final enqueue.EnqueuerStrategy strategy; |
| 84 final ItemCompilationContextCreator itemCompilationContextCreator; | 49 final enqueue.ItemCompilationContextCreator itemCompilationContextCreator; |
| 85 final Map<String, Set<Element>> instanceMembersByName = | 50 final Map<String, Set<Element>> instanceMembersByName = |
| 86 new Map<String, Set<Element>>(); | 51 new Map<String, Set<Element>>(); |
| 87 final Map<String, Set<Element>> instanceFunctionsByName = | 52 final Map<String, Set<Element>> instanceFunctionsByName = |
| 88 new Map<String, Set<Element>>(); | 53 new Map<String, Set<Element>>(); |
| 89 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); | 54 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); |
| 90 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); | 55 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); |
| 91 final Universe universe = new Universe(const TypeMaskStrategy()); | 56 final Universe universe = new Universe(const TypeMaskStrategy()); |
| 92 | 57 |
| 93 static final TRACE_MIRROR_ENQUEUING = | 58 static final TRACE_MIRROR_ENQUEUING = |
| 94 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); | 59 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); |
| 95 | 60 |
| 96 bool queueIsClosed = false; | 61 bool queueIsClosed = false; |
| 97 EnqueueTask task; | 62 enqueue.EnqueueTask task; |
| 98 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask | 63 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask |
| 99 | 64 |
| 100 bool hasEnqueuedReflectiveElements = false; | 65 bool hasEnqueuedReflectiveElements = false; |
| 101 bool hasEnqueuedReflectiveStaticFields = false; | 66 bool hasEnqueuedReflectiveStaticFields = false; |
| 102 | 67 |
| 103 WorldImpactVisitor impactVisitor; | 68 WorldImpactVisitor impactVisitor; |
| 104 | 69 |
| 105 Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator, | 70 _Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator, |
| 106 this.strategy) { | 71 this.strategy) { |
| 107 impactVisitor = new _EnqueuerImpactVisitor(this); | 72 impactVisitor = new _EnqueuerImpactVisitor(this); |
| 108 } | 73 } |
| 109 | 74 |
| 110 // TODO(johnniwinther): Move this to [ResolutionEnqueuer]. | 75 // TODO(johnniwinther): Move this to [ResolutionEnqueuer]. |
| 111 Resolution get resolution => compiler.resolution; | 76 Resolution get resolution => compiler.resolution; |
| 112 | 77 |
| 113 Queue<WorkItem> get queue; | 78 Queue<WorkItem> get queue; |
| 114 bool get queueIsEmpty => queue.isEmpty; | 79 bool get queueIsEmpty => queue.isEmpty; |
| 115 | 80 |
| 116 /// Returns [:true:] if this enqueuer is the resolution enqueuer. | 81 /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
| 117 bool get isResolutionQueue => false; | 82 bool get isResolutionQueue => false; |
| 118 | 83 |
| 119 QueueFilter get filter => compiler.enqueuerFilter; | 84 enqueue.QueueFilter get filter => compiler.enqueuerFilter; |
| 120 | 85 |
| 121 DiagnosticReporter get reporter => compiler.reporter; | 86 DiagnosticReporter get reporter => compiler.reporter; |
| 122 | 87 |
| 123 /// Returns [:true:] if [member] has been processed by this enqueuer. | 88 /// Returns [:true:] if [member] has been processed by this enqueuer. |
| 124 bool isProcessed(Element member); | 89 bool isProcessed(Element member); |
| 125 | 90 |
| 126 bool isClassProcessed(ClassElement cls) => _processedClasses.contains(cls); | 91 bool isClassProcessed(ClassElement cls) => _processedClasses.contains(cls); |
| 127 | 92 |
| 128 Iterable<ClassElement> get processedClasses => _processedClasses; | 93 Iterable<ClassElement> get processedClasses => _processedClasses; |
| 129 | 94 |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 671 String toString() => 'Enqueuer($name)'; | 636 String toString() => 'Enqueuer($name)'; |
| 672 | 637 |
| 673 void forgetElement(Element element) { | 638 void forgetElement(Element element) { |
| 674 universe.forgetElement(element, compiler); | 639 universe.forgetElement(element, compiler); |
| 675 _processedClasses.remove(element); | 640 _processedClasses.remove(element); |
| 676 instanceMembersByName[element.name]?.remove(element); | 641 instanceMembersByName[element.name]?.remove(element); |
| 677 instanceFunctionsByName[element.name]?.remove(element); | 642 instanceFunctionsByName[element.name]?.remove(element); |
| 678 } | 643 } |
| 679 } | 644 } |
| 680 | 645 |
| 681 /// [Enqueuer] which is specific to resolution. | |
| 682 class ResolutionEnqueuer extends Enqueuer { | |
| 683 /// All declaration elements that have been processed by the resolver. | |
| 684 final Set<AstElement> processedElements; | |
| 685 | |
| 686 final Queue<ResolutionWorkItem> queue; | |
| 687 | |
| 688 /// Queue of deferred resolution actions to execute when the resolution queue | |
| 689 /// has been emptied. | |
| 690 final Queue<_DeferredAction> deferredQueue; | |
| 691 | |
| 692 static const ImpactUseCase IMPACT_USE = | |
| 693 const ImpactUseCase('ResolutionEnqueuer'); | |
| 694 | |
| 695 ImpactUseCase get impactUse => IMPACT_USE; | |
| 696 | |
| 697 ResolutionEnqueuer( | |
| 698 Compiler compiler, | |
| 699 ItemCompilationContext itemCompilationContextCreator(), | |
| 700 EnqueuerStrategy strategy) | |
| 701 : super('resolution enqueuer', compiler, itemCompilationContextCreator, | |
| 702 strategy), | |
| 703 processedElements = new Set<AstElement>(), | |
| 704 queue = new Queue<ResolutionWorkItem>(), | |
| 705 deferredQueue = new Queue<_DeferredAction>(); | |
| 706 | |
| 707 bool get isResolutionQueue => true; | |
| 708 | |
| 709 bool isProcessed(Element member) => processedElements.contains(member); | |
| 710 | |
| 711 /// Returns `true` if [element] has been processed by the resolution enqueuer. | |
| 712 bool hasBeenProcessed(Element element) { | |
| 713 return processedElements.contains(element.analyzableElement.declaration); | |
| 714 } | |
| 715 | |
| 716 /// Registers [element] as processed by the resolution enqueuer. | |
| 717 void registerProcessedElement(AstElement element) { | |
| 718 processedElements.add(element); | |
| 719 compiler.backend.onElementResolved(element); | |
| 720 } | |
| 721 | |
| 722 /** | |
| 723 * Decides whether an element should be included to satisfy requirements | |
| 724 * of the mirror system. | |
| 725 * | |
| 726 * During resolution, we have to resort to matching elements against the | |
| 727 * [MirrorsUsed] pattern, as we do not have a complete picture of the world, | |
| 728 * yet. | |
| 729 */ | |
| 730 bool shouldIncludeElementDueToMirrors(Element element, | |
| 731 {bool includedEnclosing}) { | |
| 732 return includedEnclosing || | |
| 733 compiler.backend.requiredByMirrorSystem(element); | |
| 734 } | |
| 735 | |
| 736 bool internalAddToWorkList(Element element) { | |
| 737 if (element.isMalformed) return false; | |
| 738 | |
| 739 assert(invariant(element, element is AnalyzableElement, | |
| 740 message: 'Element $element is not analyzable.')); | |
| 741 if (hasBeenProcessed(element)) return false; | |
| 742 if (queueIsClosed) { | |
| 743 throw new SpannableAssertionFailure( | |
| 744 element, "Resolution work list is closed. Trying to add $element."); | |
| 745 } | |
| 746 | |
| 747 compiler.world.registerUsedElement(element); | |
| 748 | |
| 749 ResolutionWorkItem workItem = compiler.resolution | |
| 750 .createWorkItem(element, itemCompilationContextCreator()); | |
| 751 queue.add(workItem); | |
| 752 | |
| 753 // Enable isolate support if we start using something from the isolate | |
| 754 // library, or timers for the async library. We exclude constant fields, | |
| 755 // which are ending here because their initializing expression is compiled. | |
| 756 LibraryElement library = element.library; | |
| 757 if (!compiler.hasIsolateSupport && (!element.isField || !element.isConst)) { | |
| 758 String uri = library.canonicalUri.toString(); | |
| 759 if (uri == 'dart:isolate') { | |
| 760 enableIsolateSupport(); | |
| 761 } else if (uri == 'dart:async') { | |
| 762 if (element.name == '_createTimer' || | |
| 763 element.name == '_createPeriodicTimer') { | |
| 764 // The [:Timer:] class uses the event queue of the isolate | |
| 765 // library, so we make sure that event queue is generated. | |
| 766 enableIsolateSupport(); | |
| 767 } | |
| 768 } | |
| 769 } | |
| 770 | |
| 771 if (element.isGetter && element.name == Identifiers.runtimeType_) { | |
| 772 // Enable runtime type support if we discover a getter called runtimeType. | |
| 773 // We have to enable runtime type before hitting the codegen, so | |
| 774 // that constructors know whether they need to generate code for | |
| 775 // runtime type. | |
| 776 compiler.enabledRuntimeType = true; | |
| 777 // TODO(ahe): Record precise dependency here. | |
| 778 compiler.backend.registerRuntimeType(this, compiler.globalDependencies); | |
| 779 } else if (compiler.commonElements.isFunctionApplyMethod(element)) { | |
| 780 compiler.enabledFunctionApply = true; | |
| 781 } | |
| 782 | |
| 783 return true; | |
| 784 } | |
| 785 | |
| 786 void registerNoSuchMethod(Element element) { | |
| 787 compiler.backend.registerNoSuchMethod(element); | |
| 788 } | |
| 789 | |
| 790 void enableIsolateSupport() { | |
| 791 compiler.hasIsolateSupport = true; | |
| 792 compiler.backend.enableIsolateSupport(this); | |
| 793 } | |
| 794 | |
| 795 /** | |
| 796 * Adds an action to the deferred task queue. | |
| 797 * | |
| 798 * The action is performed the next time the resolution queue has been | |
| 799 * emptied. | |
| 800 * | |
| 801 * The queue is processed in FIFO order. | |
| 802 */ | |
| 803 void addDeferredAction(Element element, void action()) { | |
| 804 if (queueIsClosed) { | |
| 805 throw new SpannableAssertionFailure( | |
| 806 element, | |
| 807 "Resolution work list is closed. " | |
| 808 "Trying to add deferred action for $element"); | |
| 809 } | |
| 810 deferredQueue.add(new _DeferredAction(element, action)); | |
| 811 } | |
| 812 | |
| 813 bool onQueueEmpty(Iterable<ClassElement> recentClasses) { | |
| 814 _emptyDeferredQueue(); | |
| 815 return super.onQueueEmpty(recentClasses); | |
| 816 } | |
| 817 | |
| 818 void emptyDeferredQueueForTesting() => _emptyDeferredQueue(); | |
| 819 | |
| 820 void _emptyDeferredQueue() { | |
| 821 while (!deferredQueue.isEmpty) { | |
| 822 _DeferredAction task = deferredQueue.removeFirst(); | |
| 823 reporter.withCurrentElement(task.element, task.action); | |
| 824 } | |
| 825 } | |
| 826 | |
| 827 void _logSpecificSummary(log(message)) { | |
| 828 log('Resolved ${processedElements.length} elements.'); | |
| 829 } | |
| 830 | |
| 831 void forgetElement(Element element) { | |
| 832 super.forgetElement(element); | |
| 833 processedElements.remove(element); | |
| 834 } | |
| 835 } | |
| 836 | |
| 837 /// [Enqueuer] which is specific to code generation. | 646 /// [Enqueuer] which is specific to code generation. |
| 838 class CodegenEnqueuer extends Enqueuer { | 647 class CodegenEnqueuer extends _Enqueuer implements enqueue.CodegenEnqueuer { |
|
sra1
2016/08/31 17:45:03
Why do we need an abstract base class that contain
Johnni Winther
2016/09/01 10:18:57
It's in the follow-up CL.
| |
| 839 final Queue<CodegenWorkItem> queue; | 648 final Queue<CodegenWorkItem> queue; |
| 840 final Map<Element, js.Expression> generatedCode = <Element, js.Expression>{}; | 649 final Map<Element, js.Expression> generatedCode = <Element, js.Expression>{}; |
| 841 | 650 |
| 842 final Set<Element> newlyEnqueuedElements; | 651 final Set<Element> newlyEnqueuedElements; |
| 843 | 652 |
| 844 final Set<DynamicUse> newlySeenSelectors; | 653 final Set<DynamicUse> newlySeenSelectors; |
| 845 | 654 |
| 846 bool enabledNoSuchMethod = false; | 655 bool enabledNoSuchMethod = false; |
| 847 | 656 |
| 848 static const ImpactUseCase IMPACT_USE = | 657 static const ImpactUseCase IMPACT_USE = |
| 849 const ImpactUseCase('CodegenEnqueuer'); | 658 const ImpactUseCase('CodegenEnqueuer'); |
| 850 | 659 |
| 851 ImpactUseCase get impactUse => IMPACT_USE; | 660 ImpactUseCase get impactUse => IMPACT_USE; |
| 852 | 661 |
| 853 CodegenEnqueuer( | 662 CodegenEnqueuer( |
| 854 Compiler compiler, | 663 Compiler compiler, |
| 855 ItemCompilationContext itemCompilationContextCreator(), | 664 ItemCompilationContext itemCompilationContextCreator(), |
| 856 EnqueuerStrategy strategy) | 665 enqueue.EnqueuerStrategy strategy) |
| 857 : queue = new Queue<CodegenWorkItem>(), | 666 : queue = new Queue<CodegenWorkItem>(), |
| 858 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), | 667 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), |
| 859 newlySeenSelectors = compiler.cacheStrategy.newSet(), | 668 newlySeenSelectors = compiler.cacheStrategy.newSet(), |
| 860 super('codegen enqueuer', compiler, itemCompilationContextCreator, | 669 super('codegen enqueuer', compiler, itemCompilationContextCreator, |
| 861 strategy); | 670 strategy); |
| 862 | 671 |
| 863 bool isProcessed(Element member) => | 672 bool isProcessed(Element member) => |
| 864 member.isAbstract || generatedCode.containsKey(member); | 673 member.isAbstract || generatedCode.containsKey(member); |
| 865 | 674 |
| 866 /** | 675 /** |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 926 } | 735 } |
| 927 | 736 |
| 928 void handleUnseenSelector(DynamicUse dynamicUse) { | 737 void handleUnseenSelector(DynamicUse dynamicUse) { |
| 929 if (compiler.options.hasIncrementalSupport) { | 738 if (compiler.options.hasIncrementalSupport) { |
| 930 newlySeenSelectors.add(dynamicUse); | 739 newlySeenSelectors.add(dynamicUse); |
| 931 } | 740 } |
| 932 super.handleUnseenSelector(dynamicUse); | 741 super.handleUnseenSelector(dynamicUse); |
| 933 } | 742 } |
| 934 } | 743 } |
| 935 | 744 |
| 936 /// Parameterizes filtering of which work items are enqueued. | |
| 937 class QueueFilter { | |
| 938 bool checkNoEnqueuedInvokedInstanceMethods(Enqueuer enqueuer) { | |
| 939 enqueuer.task.measure(() { | |
| 940 // Run through the classes and see if we need to compile methods. | |
| 941 for (ClassElement classElement | |
| 942 in enqueuer.universe.directlyInstantiatedClasses) { | |
| 943 for (ClassElement currentClass = classElement; | |
| 944 currentClass != null; | |
| 945 currentClass = currentClass.superclass) { | |
| 946 enqueuer.processInstantiatedClassMembers(currentClass); | |
| 947 } | |
| 948 } | |
| 949 }); | |
| 950 return true; | |
| 951 } | |
| 952 | |
| 953 void processWorkItem(void f(WorkItem work), WorkItem work) { | |
| 954 f(work); | |
| 955 } | |
| 956 } | |
| 957 | |
| 958 void removeFromSet(Map<String, Set<Element>> map, Element element) { | 745 void removeFromSet(Map<String, Set<Element>> map, Element element) { |
| 959 Set<Element> set = map[element.name]; | 746 Set<Element> set = map[element.name]; |
| 960 if (set == null) return; | 747 if (set == null) return; |
| 961 set.remove(element); | 748 set.remove(element); |
| 962 } | 749 } |
| 963 | 750 |
| 964 /// Strategy used by the enqueuer to populate the world. | |
| 965 // TODO(johnniwinther): Merge this interface with [QueueFilter]. | |
| 966 class EnqueuerStrategy { | |
| 967 const EnqueuerStrategy(); | |
| 968 | |
| 969 /// Process a class instantiated in live code. | |
| 970 void processInstantiatedClass(Enqueuer enqueuer, ClassElement cls) {} | |
| 971 | |
| 972 /// Process a static use of and element in live code. | |
| 973 void processStaticUse(Enqueuer enqueuer, StaticUse staticUse) {} | |
| 974 | |
| 975 /// Process a dynamic use for a call site in live code. | |
| 976 void processDynamicUse(Enqueuer enqueuer, DynamicUse dynamicUse) {} | |
| 977 } | |
| 978 | |
| 979 class TreeShakingEnqueuerStrategy implements EnqueuerStrategy { | |
| 980 const TreeShakingEnqueuerStrategy(); | |
| 981 | |
| 982 @override | |
| 983 void processInstantiatedClass(Enqueuer enqueuer, ClassElement cls) { | |
| 984 cls.implementation.forEachMember(enqueuer.processInstantiatedClassMember); | |
| 985 } | |
| 986 | |
| 987 @override | |
| 988 void processStaticUse(Enqueuer enqueuer, StaticUse staticUse) { | |
| 989 enqueuer.registerStaticUseInternal(staticUse); | |
| 990 } | |
| 991 | |
| 992 @override | |
| 993 void processDynamicUse(Enqueuer enqueuer, DynamicUse dynamicUse) { | |
| 994 enqueuer.handleUnseenSelectorInternal(dynamicUse); | |
| 995 } | |
| 996 } | |
| 997 | |
| 998 class _EnqueuerImpactVisitor implements WorldImpactVisitor { | 751 class _EnqueuerImpactVisitor implements WorldImpactVisitor { |
| 999 final Enqueuer enqueuer; | 752 final _Enqueuer enqueuer; |
| 1000 | 753 |
| 1001 _EnqueuerImpactVisitor(this.enqueuer); | 754 _EnqueuerImpactVisitor(this.enqueuer); |
| 1002 | 755 |
| 1003 @override | 756 @override |
| 1004 void visitDynamicUse(DynamicUse dynamicUse) { | 757 void visitDynamicUse(DynamicUse dynamicUse) { |
| 1005 enqueuer.registerDynamicUse(dynamicUse); | 758 enqueuer.registerDynamicUse(dynamicUse); |
| 1006 } | 759 } |
| 1007 | 760 |
| 1008 @override | 761 @override |
| 1009 void visitStaticUse(StaticUse staticUse) { | 762 void visitStaticUse(StaticUse staticUse) { |
| 1010 enqueuer.registerStaticUse(staticUse); | 763 enqueuer.registerStaticUse(staticUse); |
| 1011 } | 764 } |
| 1012 | 765 |
| 1013 @override | 766 @override |
| 1014 void visitTypeUse(TypeUse typeUse) { | 767 void visitTypeUse(TypeUse typeUse) { |
| 1015 enqueuer.registerTypeUse(typeUse); | 768 enqueuer.registerTypeUse(typeUse); |
| 1016 } | 769 } |
| 1017 } | 770 } |
| 1018 | |
| 1019 typedef void _DeferredActionFunction(); | |
| 1020 | |
| 1021 class _DeferredAction { | |
| 1022 final Element element; | |
| 1023 final _DeferredActionFunction action; | |
| 1024 | |
| 1025 _DeferredAction(this.element, this.action); | |
| 1026 } | |
| OLD | NEW |