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

Side by Side Diff: pkg/compiler/lib/src/enqueue.dart

Issue 2318593003: Split Universe into ResolutionUniverse and CodegenUniverse (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
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.enqueue;
6 6
7 import 'dart:collection' show Queue; 7 import 'dart:collection' show Queue;
8 8
9 import 'common/names.dart' show Identifiers; 9 import 'common/names.dart' show Identifiers;
10 import 'common/resolution.dart' show Resolution; 10 import 'common/resolution.dart' show Resolution;
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 class ResolutionEnqueuer extends Enqueuer { 124 class ResolutionEnqueuer extends Enqueuer {
125 final String name; 125 final String name;
126 final Compiler compiler; // TODO(ahe): Remove this dependency. 126 final Compiler compiler; // TODO(ahe): Remove this dependency.
127 final EnqueuerStrategy strategy; 127 final EnqueuerStrategy strategy;
128 final Map<String, Set<Element>> instanceMembersByName = 128 final Map<String, Set<Element>> instanceMembersByName =
129 new Map<String, Set<Element>>(); 129 new Map<String, Set<Element>>();
130 final Map<String, Set<Element>> instanceFunctionsByName = 130 final Map<String, Set<Element>> instanceFunctionsByName =
131 new Map<String, Set<Element>>(); 131 new Map<String, Set<Element>>();
132 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); 132 final Set<ClassElement> _processedClasses = new Set<ClassElement>();
133 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); 133 Set<ClassElement> recentClasses = new Setlet<ClassElement>();
134 final Universe universe = new Universe(const TypeMaskStrategy()); 134 final ResolutionUniverseImpl _universe =
135 new ResolutionUniverseImpl(const TypeMaskStrategy());
135 136
136 static final TRACE_MIRROR_ENQUEUING = 137 static final TRACE_MIRROR_ENQUEUING =
137 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); 138 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING");
138 139
139 bool queueIsClosed = false; 140 bool queueIsClosed = false;
140 141
141 bool hasEnqueuedReflectiveElements = false; 142 bool hasEnqueuedReflectiveElements = false;
142 bool hasEnqueuedReflectiveStaticFields = false; 143 bool hasEnqueuedReflectiveStaticFields = false;
143 144
144 WorldImpactVisitor impactVisitor; 145 WorldImpactVisitor impactVisitor;
145 146
146 ResolutionEnqueuer(Compiler compiler, this.strategy) 147 ResolutionEnqueuer(Compiler compiler, this.strategy)
147 : this.name = 'resolution enqueuer', 148 : this.name = 'resolution enqueuer',
148 this.compiler = compiler, 149 this.compiler = compiler,
149 processedElements = new Set<AstElement>(), 150 processedElements = new Set<AstElement>(),
150 queue = new Queue<ResolutionWorkItem>(), 151 queue = new Queue<ResolutionWorkItem>(),
151 deferredQueue = new Queue<_DeferredAction>() { 152 deferredQueue = new Queue<_DeferredAction>() {
152 impactVisitor = new _EnqueuerImpactVisitor(this); 153 impactVisitor = new _EnqueuerImpactVisitor(this);
153 } 154 }
154 155
155 // TODO(johnniwinther): Move this to [ResolutionEnqueuer]. 156 // TODO(johnniwinther): Move this to [ResolutionEnqueuer].
156 Resolution get resolution => compiler.resolution; 157 Resolution get resolution => compiler.resolution;
157 158
159 ResolutionUniverse get universe => _universe;
160
158 bool get queueIsEmpty => queue.isEmpty; 161 bool get queueIsEmpty => queue.isEmpty;
159 162
160 QueueFilter get filter => compiler.enqueuerFilter; 163 QueueFilter get filter => compiler.enqueuerFilter;
161 164
162 DiagnosticReporter get reporter => compiler.reporter; 165 DiagnosticReporter get reporter => compiler.reporter;
163 166
164 bool isClassProcessed(ClassElement cls) => _processedClasses.contains(cls); 167 bool isClassProcessed(ClassElement cls) => _processedClasses.contains(cls);
165 168
166 Iterable<ClassElement> get processedClasses => _processedClasses; 169 Iterable<ClassElement> get processedClasses => _processedClasses;
167 170
(...skipping 16 matching lines...) Expand all
184 void applyImpact(Element element, WorldImpact worldImpact) { 187 void applyImpact(Element element, WorldImpact worldImpact) {
185 compiler.impactStrategy 188 compiler.impactStrategy
186 .visitImpact(element, worldImpact, impactVisitor, impactUse); 189 .visitImpact(element, worldImpact, impactVisitor, impactUse);
187 } 190 }
188 191
189 void registerInstantiatedType(InterfaceType type, {bool mirrorUsage: false}) { 192 void registerInstantiatedType(InterfaceType type, {bool mirrorUsage: false}) {
190 task.measure(() { 193 task.measure(() {
191 ClassElement cls = type.element; 194 ClassElement cls = type.element;
192 cls.ensureResolved(resolution); 195 cls.ensureResolved(resolution);
193 bool isNative = compiler.backend.isNative(cls); 196 bool isNative = compiler.backend.isNative(cls);
194 universe.registerTypeInstantiation(type, 197 _universe.registerTypeInstantiation(type,
195 isNative: isNative, 198 isNative: isNative,
196 byMirrors: mirrorUsage, onImplemented: (ClassElement cls) { 199 byMirrors: mirrorUsage, onImplemented: (ClassElement cls) {
197 compiler.backend 200 compiler.backend
198 .registerImplementedClass(cls, this, compiler.globalDependencies); 201 .registerImplementedClass(cls, this, compiler.globalDependencies);
199 }); 202 });
200 // TODO(johnniwinther): Share this reasoning with [Universe]. 203 // TODO(johnniwinther): Share this reasoning with [Universe].
201 if (!cls.isAbstract || isNative || mirrorUsage) { 204 if (!cls.isAbstract || isNative || mirrorUsage) {
202 processInstantiatedClass(cls); 205 processInstantiatedClass(cls);
203 } 206 }
204 }); 207 });
(...skipping 16 matching lines...) Expand all
221 if (member.isField) { 224 if (member.isField) {
222 // The obvious thing to test here would be "member.isNative", 225 // The obvious thing to test here would be "member.isNative",
223 // however, that only works after metadata has been parsed/analyzed, 226 // however, that only works after metadata has been parsed/analyzed,
224 // and that may not have happened yet. 227 // and that may not have happened yet.
225 // So instead we use the enclosing class, which we know have had 228 // So instead we use the enclosing class, which we know have had
226 // its metadata parsed and analyzed. 229 // its metadata parsed and analyzed.
227 // Note: this assumes that there are no non-native fields on native 230 // Note: this assumes that there are no non-native fields on native
228 // classes, which may not be the case when a native class is subclassed. 231 // classes, which may not be the case when a native class is subclassed.
229 if (compiler.backend.isNative(cls)) { 232 if (compiler.backend.isNative(cls)) {
230 compiler.openWorld.registerUsedElement(member); 233 compiler.openWorld.registerUsedElement(member);
231 if (universe.hasInvokedGetter(member, compiler.openWorld) || 234 if (_universe.hasInvokedGetter(member, compiler.openWorld) ||
232 universe.hasInvocation(member, compiler.openWorld)) { 235 _universe.hasInvocation(member, compiler.openWorld)) {
233 addToWorkList(member); 236 addToWorkList(member);
234 return; 237 return;
235 } 238 }
236 if (universe.hasInvokedSetter(member, compiler.openWorld)) { 239 if (_universe.hasInvokedSetter(member, compiler.openWorld)) {
237 addToWorkList(member); 240 addToWorkList(member);
238 return; 241 return;
239 } 242 }
240 // Native fields need to go into instanceMembersByName as they 243 // Native fields need to go into instanceMembersByName as they
241 // are virtual instantiation points and escape points. 244 // are virtual instantiation points and escape points.
242 } else { 245 } else {
243 // All field initializers must be resolved as they could 246 // All field initializers must be resolved as they could
244 // have an observable side-effect (and cannot be tree-shaken 247 // have an observable side-effect (and cannot be tree-shaken
245 // away). 248 // away).
246 addToWorkList(member); 249 addToWorkList(member);
247 return; 250 return;
248 } 251 }
249 } else if (member.isFunction) { 252 } else if (member.isFunction) {
250 FunctionElement function = member; 253 FunctionElement function = member;
251 function.computeType(resolution); 254 function.computeType(resolution);
252 if (function.name == Identifiers.noSuchMethod_) { 255 if (function.name == Identifiers.noSuchMethod_) {
253 registerNoSuchMethod(function); 256 registerNoSuchMethod(function);
254 } 257 }
255 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { 258 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) {
256 registerCallMethodWithFreeTypeVariables(function); 259 registerCallMethodWithFreeTypeVariables(function);
257 } 260 }
258 // If there is a property access with the same name as a method we 261 // If there is a property access with the same name as a method we
259 // need to emit the method. 262 // need to emit the method.
260 if (universe.hasInvokedGetter(function, compiler.openWorld)) { 263 if (_universe.hasInvokedGetter(function, compiler.openWorld)) {
261 registerClosurizedMember(function); 264 registerClosurizedMember(function);
262 addToWorkList(function); 265 addToWorkList(function);
263 return; 266 return;
264 } 267 }
265 // Store the member in [instanceFunctionsByName] to catch 268 // Store the member in [instanceFunctionsByName] to catch
266 // getters on the function. 269 // getters on the function.
267 instanceFunctionsByName 270 instanceFunctionsByName
268 .putIfAbsent(memberName, () => new Set<Element>()) 271 .putIfAbsent(memberName, () => new Set<Element>())
269 .add(member); 272 .add(member);
270 if (universe.hasInvocation(function, compiler.openWorld)) { 273 if (_universe.hasInvocation(function, compiler.openWorld)) {
271 addToWorkList(function); 274 addToWorkList(function);
272 return; 275 return;
273 } 276 }
274 } else if (member.isGetter) { 277 } else if (member.isGetter) {
275 FunctionElement getter = member; 278 FunctionElement getter = member;
276 getter.computeType(resolution); 279 getter.computeType(resolution);
277 if (universe.hasInvokedGetter(getter, compiler.openWorld)) { 280 if (_universe.hasInvokedGetter(getter, compiler.openWorld)) {
278 addToWorkList(getter); 281 addToWorkList(getter);
279 return; 282 return;
280 } 283 }
281 // We don't know what selectors the returned closure accepts. If 284 // We don't know what selectors the returned closure accepts. If
282 // the set contains any selector we have to assume that it matches. 285 // the set contains any selector we have to assume that it matches.
283 if (universe.hasInvocation(getter, compiler.openWorld)) { 286 if (_universe.hasInvocation(getter, compiler.openWorld)) {
284 addToWorkList(getter); 287 addToWorkList(getter);
285 return; 288 return;
286 } 289 }
287 } else if (member.isSetter) { 290 } else if (member.isSetter) {
288 FunctionElement setter = member; 291 FunctionElement setter = member;
289 setter.computeType(resolution); 292 setter.computeType(resolution);
290 if (universe.hasInvokedSetter(setter, compiler.openWorld)) { 293 if (_universe.hasInvokedSetter(setter, compiler.openWorld)) {
291 addToWorkList(setter); 294 addToWorkList(setter);
292 return; 295 return;
293 } 296 }
294 } 297 }
295 298
296 // The element is not yet used. Add it to the list of instance 299 // The element is not yet used. Add it to the list of instance
297 // members to still be processed. 300 // members to still be processed.
298 instanceMembersByName 301 instanceMembersByName
299 .putIfAbsent(memberName, () => new Set<Element>()) 302 .putIfAbsent(memberName, () => new Set<Element>())
300 .add(member); 303 .add(member);
(...skipping 26 matching lines...) Expand all
327 ClassElement superclass = cls; 330 ClassElement superclass = cls;
328 while (superclass != null) { 331 while (superclass != null) {
329 processClass(superclass); 332 processClass(superclass);
330 superclass = superclass.superclass; 333 superclass = superclass.superclass;
331 } 334 }
332 }); 335 });
333 } 336 }
334 337
335 void registerDynamicUse(DynamicUse dynamicUse) { 338 void registerDynamicUse(DynamicUse dynamicUse) {
336 task.measure(() { 339 task.measure(() {
337 if (universe.registerDynamicUse(dynamicUse)) { 340 if (_universe.registerDynamicUse(dynamicUse)) {
338 handleUnseenSelector(dynamicUse); 341 handleUnseenSelector(dynamicUse);
339 } 342 }
340 }); 343 });
341 } 344 }
342 345
343 void logEnqueueReflectiveAction(action, [msg = ""]) { 346 void logEnqueueReflectiveAction(action, [msg = ""]) {
344 if (TRACE_MIRROR_ENQUEUING) { 347 if (TRACE_MIRROR_ENQUEUING) {
345 print("MIRROR_ENQUEUE (R): $action $msg"); 348 print("MIRROR_ENQUEUE (R): $action $msg");
346 } 349 }
347 } 350 }
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
563 * Invariant: [element] must be a declaration element. 566 * Invariant: [element] must be a declaration element.
564 */ 567 */
565 void registerStaticUse(StaticUse staticUse) { 568 void registerStaticUse(StaticUse staticUse) {
566 strategy.processStaticUse(this, staticUse); 569 strategy.processStaticUse(this, staticUse);
567 } 570 }
568 571
569 void registerStaticUseInternal(StaticUse staticUse) { 572 void registerStaticUseInternal(StaticUse staticUse) {
570 Element element = staticUse.element; 573 Element element = staticUse.element;
571 assert(invariant(element, element.isDeclaration, 574 assert(invariant(element, element.isDeclaration,
572 message: "Element ${element} is not the declaration.")); 575 message: "Element ${element} is not the declaration."));
573 universe.registerStaticUse(staticUse); 576 _universe.registerStaticUse(staticUse);
574 compiler.backend.registerStaticUse(element, this); 577 compiler.backend.registerStaticUse(element, this);
575 bool addElement = true; 578 bool addElement = true;
576 switch (staticUse.kind) { 579 switch (staticUse.kind) {
577 case StaticUseKind.STATIC_TEAR_OFF: 580 case StaticUseKind.STATIC_TEAR_OFF:
578 compiler.backend.registerGetOfStaticFunction(this); 581 compiler.backend.registerGetOfStaticFunction(this);
579 break; 582 break;
580 case StaticUseKind.FIELD_GET: 583 case StaticUseKind.FIELD_GET:
581 case StaticUseKind.FIELD_SET: 584 case StaticUseKind.FIELD_SET:
582 case StaticUseKind.CLOSURE: 585 case StaticUseKind.CLOSURE:
583 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and 586 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and
(...skipping 28 matching lines...) Expand all
612 if (compiler.options.enableTypeAssertions) { 615 if (compiler.options.enableTypeAssertions) {
613 _registerIsCheck(type); 616 _registerIsCheck(type);
614 } 617 }
615 break; 618 break;
616 case TypeUseKind.TYPE_LITERAL: 619 case TypeUseKind.TYPE_LITERAL:
617 break; 620 break;
618 } 621 }
619 } 622 }
620 623
621 void _registerIsCheck(DartType type) { 624 void _registerIsCheck(DartType type) {
622 type = universe.registerIsCheck(type, compiler); 625 type = _universe.registerIsCheck(type, compiler);
623 // Even in checked mode, type annotations for return type and argument 626 // Even in checked mode, type annotations for return type and argument
624 // types do not imply type checks, so there should never be a check 627 // types do not imply type checks, so there should never be a check
625 // against the type variable of a typedef. 628 // against the type variable of a typedef.
626 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); 629 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef);
627 } 630 }
628 631
629 void registerCallMethodWithFreeTypeVariables(Element element) { 632 void registerCallMethodWithFreeTypeVariables(Element element) {
630 compiler.backend.registerCallMethodWithFreeTypeVariables( 633 compiler.backend.registerCallMethodWithFreeTypeVariables(
631 element, this, compiler.globalDependencies); 634 element, this, compiler.globalDependencies);
632 universe.callMethodsWithFreeTypeVariables.add(element); 635 _universe.callMethodsWithFreeTypeVariables.add(element);
633 } 636 }
634 637
635 void registerClosurizedMember(TypedElement element) { 638 void registerClosurizedMember(TypedElement element) {
636 assert(element.isInstanceMember); 639 assert(element.isInstanceMember);
637 if (element.computeType(resolution).containsTypeVariables) { 640 if (element.computeType(resolution).containsTypeVariables) {
638 compiler.backend.registerClosureWithFreeTypeVariables( 641 compiler.backend.registerClosureWithFreeTypeVariables(
639 element, this, compiler.globalDependencies); 642 element, this, compiler.globalDependencies);
643 _universe.closuresWithFreeTypeVariables.add(element);
640 } 644 }
641 compiler.backend.registerBoundClosure(this); 645 compiler.backend.registerBoundClosure(this);
642 universe.closurizedMembers.add(element); 646 _universe.closurizedMembers.add(element);
643 } 647 }
644 648
645 void forEach(void f(WorkItem work)) { 649 void forEach(void f(WorkItem work)) {
646 do { 650 do {
647 while (queue.isNotEmpty) { 651 while (queue.isNotEmpty) {
648 // TODO(johnniwinther): Find an optimal process order. 652 // TODO(johnniwinther): Find an optimal process order.
649 filter.processWorkItem(f, queue.removeLast()); 653 filter.processWorkItem(f, queue.removeLast());
650 } 654 }
651 List recents = recentClasses.toList(growable: false); 655 List recents = recentClasses.toList(growable: false);
652 recentClasses.clear(); 656 recentClasses.clear();
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 void emptyDeferredQueueForTesting() => _emptyDeferredQueue(); 806 void emptyDeferredQueueForTesting() => _emptyDeferredQueue();
803 807
804 void _emptyDeferredQueue() { 808 void _emptyDeferredQueue() {
805 while (!deferredQueue.isEmpty) { 809 while (!deferredQueue.isEmpty) {
806 _DeferredAction task = deferredQueue.removeFirst(); 810 _DeferredAction task = deferredQueue.removeFirst();
807 reporter.withCurrentElement(task.element, task.action); 811 reporter.withCurrentElement(task.element, task.action);
808 } 812 }
809 } 813 }
810 814
811 void forgetElement(Element element) { 815 void forgetElement(Element element) {
812 universe.forgetElement(element, compiler); 816 _universe.forgetElement(element, compiler);
813 _processedClasses.remove(element); 817 _processedClasses.remove(element);
814 instanceMembersByName[element.name]?.remove(element); 818 instanceMembersByName[element.name]?.remove(element);
815 instanceFunctionsByName[element.name]?.remove(element); 819 instanceFunctionsByName[element.name]?.remove(element);
816 processedElements.remove(element); 820 processedElements.remove(element);
817 } 821 }
818 } 822 }
819 823
820 /// Parameterizes filtering of which work items are enqueued. 824 /// Parameterizes filtering of which work items are enqueued.
821 class QueueFilter { 825 class QueueFilter {
822 bool checkNoEnqueuedInvokedInstanceMethods(Enqueuer enqueuer) { 826 bool checkNoEnqueuedInvokedInstanceMethods(Enqueuer enqueuer) {
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 } 905 }
902 906
903 typedef void _DeferredActionFunction(); 907 typedef void _DeferredActionFunction();
904 908
905 class _DeferredAction { 909 class _DeferredAction {
906 final Element element; 910 final Element element;
907 final _DeferredActionFunction action; 911 final _DeferredActionFunction action;
908 912
909 _DeferredAction(this.element, this.action); 913 _DeferredAction(this.element, this.action);
910 } 914 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698