Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: pkg/compiler/lib/src/js_backend/enqueuer.dart

Issue 2296153002: Use backend-specific enqueuer. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/compiler/lib/src/js_backend/backend.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/backend.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698